mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 16:26:38 +00:00
Compare commits
1 Commits
trigger-pr
...
feature/di
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
279e96e6b1 |
22
client/system/disk_encryption.go
Normal file
22
client/system/disk_encryption.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
// DiskEncryptionVolume represents encryption status of a single volume.
|
||||||
|
type DiskEncryptionVolume struct {
|
||||||
|
Path string
|
||||||
|
Encrypted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiskEncryptionInfo holds disk encryption detection results.
|
||||||
|
type DiskEncryptionInfo struct {
|
||||||
|
Volumes []DiskEncryptionVolume
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEncrypted returns true if the volume at the given path is encrypted.
|
||||||
|
func (d DiskEncryptionInfo) IsEncrypted(path string) bool {
|
||||||
|
for _, v := range d.Volumes {
|
||||||
|
if v.Path == path {
|
||||||
|
return v.Encrypted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
35
client/system/disk_encryption_darwin.go
Normal file
35
client/system/disk_encryption_darwin.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//go:build darwin && !ios
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// detectDiskEncryption detects FileVault encryption status on macOS.
|
||||||
|
func detectDiskEncryption(ctx context.Context) DiskEncryptionInfo {
|
||||||
|
info := DiskEncryptionInfo{}
|
||||||
|
|
||||||
|
cmdCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
cmd := exec.CommandContext(cmdCtx, "fdesetup", "status")
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("execute fdesetup: %v", err)
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypted := strings.Contains(string(output), "FileVault is On")
|
||||||
|
info.Volumes = append(info.Volumes, DiskEncryptionVolume{
|
||||||
|
Path: "/",
|
||||||
|
Encrypted: encrypted,
|
||||||
|
})
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
98
client/system/disk_encryption_linux.go
Normal file
98
client/system/disk_encryption_linux.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
//go:build linux && !android
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// detectDiskEncryption detects LUKS encryption status on Linux by reading sysfs.
|
||||||
|
func detectDiskEncryption(ctx context.Context) DiskEncryptionInfo {
|
||||||
|
info := DiskEncryptionInfo{}
|
||||||
|
|
||||||
|
encryptedDevices := findEncryptedDevices()
|
||||||
|
mountPoints := parseMounts(encryptedDevices)
|
||||||
|
|
||||||
|
info.Volumes = mountPoints
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
// findEncryptedDevices scans /sys/block for dm-crypt (LUKS) encrypted devices.
|
||||||
|
func findEncryptedDevices() map[string]bool {
|
||||||
|
encryptedDevices := make(map[string]bool)
|
||||||
|
|
||||||
|
sysBlock := "/sys/block"
|
||||||
|
entries, err := os.ReadDir(sysBlock)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("read /sys/block: %v", err)
|
||||||
|
return encryptedDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
dmUuidPath := filepath.Join(sysBlock, entry.Name(), "dm", "uuid")
|
||||||
|
data, err := os.ReadFile(dmUuidPath)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
uuid := strings.TrimSpace(string(data))
|
||||||
|
if strings.HasPrefix(uuid, "CRYPT-") {
|
||||||
|
dmNamePath := filepath.Join(sysBlock, entry.Name(), "dm", "name")
|
||||||
|
if nameData, err := os.ReadFile(dmNamePath); err == nil {
|
||||||
|
dmName := strings.TrimSpace(string(nameData))
|
||||||
|
encryptedDevices["/dev/mapper/"+dmName] = true
|
||||||
|
}
|
||||||
|
encryptedDevices["/dev/"+entry.Name()] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return encryptedDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseMounts reads /proc/mounts and maps devices to mount points with encryption status.
|
||||||
|
func parseMounts(encryptedDevices map[string]bool) []DiskEncryptionVolume {
|
||||||
|
var volumes []DiskEncryptionVolume
|
||||||
|
|
||||||
|
mountsFile, err := os.Open("/proc/mounts")
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("open /proc/mounts: %v", err)
|
||||||
|
return volumes
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := mountsFile.Close(); err != nil {
|
||||||
|
log.Debugf("close /proc/mounts: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(mountsFile)
|
||||||
|
for scanner.Scan() {
|
||||||
|
fields := strings.Fields(scanner.Text())
|
||||||
|
if len(fields) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
device, mountPoint := fields[0], fields[1]
|
||||||
|
|
||||||
|
encrypted := encryptedDevices[device]
|
||||||
|
|
||||||
|
if !encrypted && strings.HasPrefix(device, "/dev/mapper/") {
|
||||||
|
for encDev := range encryptedDevices {
|
||||||
|
if device == encDev {
|
||||||
|
encrypted = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes = append(volumes, DiskEncryptionVolume{
|
||||||
|
Path: mountPoint,
|
||||||
|
Encrypted: encrypted,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return volumes
|
||||||
|
}
|
||||||
10
client/system/disk_encryption_stub.go
Normal file
10
client/system/disk_encryption_stub.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
//go:build android || ios || freebsd || js
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// detectDiskEncryption is a stub for unsupported platforms.
|
||||||
|
func detectDiskEncryption(_ context.Context) DiskEncryptionInfo {
|
||||||
|
return DiskEncryptionInfo{}
|
||||||
|
}
|
||||||
41
client/system/disk_encryption_windows.go
Normal file
41
client/system/disk_encryption_windows.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/yusufpapurcu/wmi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Win32EncryptableVolume represents the WMI class for BitLocker status.
|
||||||
|
type Win32EncryptableVolume struct {
|
||||||
|
DriveLetter string
|
||||||
|
ProtectionStatus uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// detectDiskEncryption detects BitLocker encryption status on Windows via WMI.
|
||||||
|
func detectDiskEncryption(_ context.Context) DiskEncryptionInfo {
|
||||||
|
info := DiskEncryptionInfo{}
|
||||||
|
|
||||||
|
var volumes []Win32EncryptableVolume
|
||||||
|
query := "SELECT DriveLetter, ProtectionStatus FROM Win32_EncryptableVolume"
|
||||||
|
|
||||||
|
err := wmi.QueryNamespace(query, &volumes, `root\CIMV2\Security\MicrosoftVolumeEncryption`)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("query BitLocker status: %v", err)
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, vol := range volumes {
|
||||||
|
driveLetter := strings.TrimSuffix(vol.DriveLetter, "\\")
|
||||||
|
info.Volumes = append(info.Volumes, DiskEncryptionVolume{
|
||||||
|
Path: driveLetter,
|
||||||
|
Encrypted: vol.ProtectionStatus == 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ type Info struct {
|
|||||||
SystemManufacturer string
|
SystemManufacturer string
|
||||||
Environment Environment
|
Environment Environment
|
||||||
Files []File // for posture checks
|
Files []File // for posture checks
|
||||||
|
DiskEncryption DiskEncryptionInfo
|
||||||
|
|
||||||
RosenpassEnabled bool
|
RosenpassEnabled bool
|
||||||
RosenpassPermissive bool
|
RosenpassPermissive bool
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
SystemSerialNumber: serial(),
|
SystemSerialNumber: serial(),
|
||||||
SystemProductName: productModel(),
|
SystemProductName: productModel(),
|
||||||
SystemManufacturer: productManufacturer(),
|
SystemManufacturer: productManufacturer(),
|
||||||
|
DiskEncryption: detectDiskEncryption(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
return gio
|
return gio
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
SystemProductName: si.SystemProductName,
|
SystemProductName: si.SystemProductName,
|
||||||
SystemManufacturer: si.SystemManufacturer,
|
SystemManufacturer: si.SystemManufacturer,
|
||||||
Environment: si.Environment,
|
Environment: si.Environment,
|
||||||
|
DiskEncryption: detectDiskEncryption(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
systemHostname, _ := os.Hostname()
|
systemHostname, _ := os.Hostname()
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
UIVersion: extractUserAgent(ctx),
|
UIVersion: extractUserAgent(ctx),
|
||||||
KernelVersion: osInfo[1],
|
KernelVersion: osInfo[1],
|
||||||
Environment: env,
|
Environment: env,
|
||||||
|
DiskEncryption: detectDiskEncryption(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
sysName := extractOsName(ctx, "sysName")
|
sysName := extractOsName(ctx, "sysName")
|
||||||
swVersion := extractOsVersion(ctx, "swVersion")
|
swVersion := extractOsVersion(ctx, "swVersion")
|
||||||
|
|
||||||
gio := &Info{Kernel: sysName, OSVersion: swVersion, Platform: "unknown", OS: sysName, GoOS: runtime.GOOS, CPUs: runtime.NumCPU(), KernelVersion: swVersion}
|
gio := &Info{Kernel: sysName, OSVersion: swVersion, Platform: "unknown", OS: sysName, GoOS: runtime.GOOS, CPUs: runtime.NumCPU(), KernelVersion: swVersion, DiskEncryption: detectDiskEncryption(ctx)}
|
||||||
gio.Hostname = extractDeviceName(ctx, "hostname")
|
gio.Hostname = extractDeviceName(ctx, "hostname")
|
||||||
gio.NetbirdVersion = version.NetbirdVersion()
|
gio.NetbirdVersion = version.NetbirdVersion()
|
||||||
gio.UIVersion = extractUserAgent(ctx)
|
gio.UIVersion = extractUserAgent(ctx)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func UpdateStaticInfoAsync() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetInfo retrieves system information for WASM environment
|
// GetInfo retrieves system information for WASM environment
|
||||||
func GetInfo(_ context.Context) *Info {
|
func GetInfo(ctx context.Context) *Info {
|
||||||
info := &Info{
|
info := &Info{
|
||||||
GoOS: runtime.GOOS,
|
GoOS: runtime.GOOS,
|
||||||
Kernel: runtime.GOARCH,
|
Kernel: runtime.GOARCH,
|
||||||
@@ -25,6 +25,7 @@ func GetInfo(_ context.Context) *Info {
|
|||||||
Hostname: "wasm-client",
|
Hostname: "wasm-client",
|
||||||
CPUs: runtime.NumCPU(),
|
CPUs: runtime.NumCPU(),
|
||||||
NetbirdVersion: version.NetbirdVersion(),
|
NetbirdVersion: version.NetbirdVersion(),
|
||||||
|
DiskEncryption: detectDiskEncryption(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
collectBrowserInfo(info)
|
collectBrowserInfo(info)
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
SystemProductName: si.SystemProductName,
|
SystemProductName: si.SystemProductName,
|
||||||
SystemManufacturer: si.SystemManufacturer,
|
SystemManufacturer: si.SystemManufacturer,
|
||||||
Environment: si.Environment,
|
Environment: si.Environment,
|
||||||
|
DiskEncryption: detectDiskEncryption(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
return gio
|
return gio
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ func GetInfo(ctx context.Context) *Info {
|
|||||||
SystemProductName: si.SystemProductName,
|
SystemProductName: si.SystemProductName,
|
||||||
SystemManufacturer: si.SystemManufacturer,
|
SystemManufacturer: si.SystemManufacturer,
|
||||||
Environment: si.Environment,
|
Environment: si.Environment,
|
||||||
|
DiskEncryption: detectDiskEncryption(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
addrs, err := networkAddresses()
|
addrs, err := networkAddresses()
|
||||||
|
|||||||
@@ -470,6 +470,16 @@ func extractPeerMeta(ctx context.Context, meta *proto.PeerSystemMeta) nbpeer.Pee
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diskEncryptionVolumes := make([]nbpeer.DiskEncryptionVolume, 0)
|
||||||
|
if meta.GetDiskEncryption() != nil {
|
||||||
|
for _, vol := range meta.GetDiskEncryption().GetVolumes() {
|
||||||
|
diskEncryptionVolumes = append(diskEncryptionVolumes, nbpeer.DiskEncryptionVolume{
|
||||||
|
Path: vol.GetPath(),
|
||||||
|
Encrypted: vol.GetEncrypted(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nbpeer.PeerSystemMeta{
|
return nbpeer.PeerSystemMeta{
|
||||||
Hostname: meta.GetHostname(),
|
Hostname: meta.GetHostname(),
|
||||||
GoOS: meta.GetGoOS(),
|
GoOS: meta.GetGoOS(),
|
||||||
@@ -501,6 +511,9 @@ func extractPeerMeta(ctx context.Context, meta *proto.PeerSystemMeta) nbpeer.Pee
|
|||||||
LazyConnectionEnabled: meta.GetFlags().GetLazyConnectionEnabled(),
|
LazyConnectionEnabled: meta.GetFlags().GetLazyConnectionEnabled(),
|
||||||
},
|
},
|
||||||
Files: files,
|
Files: files,
|
||||||
|
DiskEncryption: nbpeer.DiskEncryptionInfo{
|
||||||
|
Volumes: diskEncryptionVolumes,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,27 @@ type File struct {
|
|||||||
ProcessIsRunning bool
|
ProcessIsRunning bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiskEncryptionVolume represents encryption status of a volume.
|
||||||
|
type DiskEncryptionVolume struct {
|
||||||
|
Path string
|
||||||
|
Encrypted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiskEncryptionInfo holds encryption info for all volumes.
|
||||||
|
type DiskEncryptionInfo struct {
|
||||||
|
Volumes []DiskEncryptionVolume `gorm:"serializer:json"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEncrypted returns true if the volume at path is encrypted.
|
||||||
|
func (d DiskEncryptionInfo) IsEncrypted(path string) bool {
|
||||||
|
for _, v := range d.Volumes {
|
||||||
|
if v.Path == path {
|
||||||
|
return v.Encrypted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Flags defines a set of options to control feature behavior
|
// Flags defines a set of options to control feature behavior
|
||||||
type Flags struct {
|
type Flags struct {
|
||||||
RosenpassEnabled bool
|
RosenpassEnabled bool
|
||||||
@@ -127,9 +148,10 @@ type PeerSystemMeta struct { //nolint:revive
|
|||||||
SystemSerialNumber string
|
SystemSerialNumber string
|
||||||
SystemProductName string
|
SystemProductName string
|
||||||
SystemManufacturer string
|
SystemManufacturer string
|
||||||
Environment Environment `gorm:"serializer:json"`
|
Environment Environment `gorm:"serializer:json"`
|
||||||
Flags Flags `gorm:"serializer:json"`
|
Flags Flags `gorm:"serializer:json"`
|
||||||
Files []File `gorm:"serializer:json"`
|
Files []File `gorm:"serializer:json"`
|
||||||
|
DiskEncryption DiskEncryptionInfo `gorm:"serializer:json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
|
func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
|
||||||
@@ -159,6 +181,19 @@ func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.Slice(p.DiskEncryption.Volumes, func(i, j int) bool {
|
||||||
|
return p.DiskEncryption.Volumes[i].Path < p.DiskEncryption.Volumes[j].Path
|
||||||
|
})
|
||||||
|
sort.Slice(other.DiskEncryption.Volumes, func(i, j int) bool {
|
||||||
|
return other.DiskEncryption.Volumes[i].Path < other.DiskEncryption.Volumes[j].Path
|
||||||
|
})
|
||||||
|
equalDiskEncryption := slices.EqualFunc(p.DiskEncryption.Volumes, other.DiskEncryption.Volumes, func(vol DiskEncryptionVolume, oVol DiskEncryptionVolume) bool {
|
||||||
|
return vol.Path == oVol.Path && vol.Encrypted == oVol.Encrypted
|
||||||
|
})
|
||||||
|
if !equalDiskEncryption {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return p.Hostname == other.Hostname &&
|
return p.Hostname == other.Hostname &&
|
||||||
p.GoOS == other.GoOS &&
|
p.GoOS == other.GoOS &&
|
||||||
p.Kernel == other.Kernel &&
|
p.Kernel == other.Kernel &&
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const (
|
|||||||
GeoLocationCheckName = "GeoLocationCheck"
|
GeoLocationCheckName = "GeoLocationCheck"
|
||||||
PeerNetworkRangeCheckName = "PeerNetworkRangeCheck"
|
PeerNetworkRangeCheckName = "PeerNetworkRangeCheck"
|
||||||
ProcessCheckName = "ProcessCheck"
|
ProcessCheckName = "ProcessCheck"
|
||||||
|
DiskEncryptionCheckName = "DiskEncryptionCheck"
|
||||||
|
|
||||||
CheckActionAllow string = "allow"
|
CheckActionAllow string = "allow"
|
||||||
CheckActionDeny string = "deny"
|
CheckActionDeny string = "deny"
|
||||||
@@ -58,6 +59,7 @@ type ChecksDefinition struct {
|
|||||||
GeoLocationCheck *GeoLocationCheck `json:",omitempty"`
|
GeoLocationCheck *GeoLocationCheck `json:",omitempty"`
|
||||||
PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:",omitempty"`
|
PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:",omitempty"`
|
||||||
ProcessCheck *ProcessCheck `json:",omitempty"`
|
ProcessCheck *ProcessCheck `json:",omitempty"`
|
||||||
|
DiskEncryptionCheck *DiskEncryptionCheck `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of a checks definition.
|
// Copy returns a copy of a checks definition.
|
||||||
@@ -110,6 +112,13 @@ func (cd ChecksDefinition) Copy() ChecksDefinition {
|
|||||||
}
|
}
|
||||||
copy(cdCopy.ProcessCheck.Processes, processCheck.Processes)
|
copy(cdCopy.ProcessCheck.Processes, processCheck.Processes)
|
||||||
}
|
}
|
||||||
|
if cd.DiskEncryptionCheck != nil {
|
||||||
|
cdCopy.DiskEncryptionCheck = &DiskEncryptionCheck{
|
||||||
|
LinuxPath: cd.DiskEncryptionCheck.LinuxPath,
|
||||||
|
DarwinPath: cd.DiskEncryptionCheck.DarwinPath,
|
||||||
|
WindowsPath: cd.DiskEncryptionCheck.WindowsPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
return cdCopy
|
return cdCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,6 +162,9 @@ func (pc *Checks) GetChecks() []Check {
|
|||||||
if pc.Checks.ProcessCheck != nil {
|
if pc.Checks.ProcessCheck != nil {
|
||||||
checks = append(checks, pc.Checks.ProcessCheck)
|
checks = append(checks, pc.Checks.ProcessCheck)
|
||||||
}
|
}
|
||||||
|
if pc.Checks.DiskEncryptionCheck != nil {
|
||||||
|
checks = append(checks, pc.Checks.DiskEncryptionCheck)
|
||||||
|
}
|
||||||
return checks
|
return checks
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,6 +220,10 @@ func buildPostureCheck(postureChecksID string, name string, description string,
|
|||||||
postureChecks.Checks.ProcessCheck = toProcessCheck(processCheck)
|
postureChecks.Checks.ProcessCheck = toProcessCheck(processCheck)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if diskEncryptionCheck := checks.DiskEncryptionCheck; diskEncryptionCheck != nil {
|
||||||
|
postureChecks.Checks.DiskEncryptionCheck = toDiskEncryptionCheck(diskEncryptionCheck)
|
||||||
|
}
|
||||||
|
|
||||||
return &postureChecks, nil
|
return &postureChecks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +258,10 @@ func (pc *Checks) ToAPIResponse() *api.PostureCheck {
|
|||||||
checks.ProcessCheck = toProcessCheckResponse(pc.Checks.ProcessCheck)
|
checks.ProcessCheck = toProcessCheckResponse(pc.Checks.ProcessCheck)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pc.Checks.DiskEncryptionCheck != nil {
|
||||||
|
checks.DiskEncryptionCheck = toDiskEncryptionCheckResponse(pc.Checks.DiskEncryptionCheck)
|
||||||
|
}
|
||||||
|
|
||||||
return &api.PostureCheck{
|
return &api.PostureCheck{
|
||||||
Id: pc.ID,
|
Id: pc.ID,
|
||||||
Name: pc.Name,
|
Name: pc.Name,
|
||||||
@@ -386,3 +406,25 @@ func toProcessCheck(check *api.ProcessCheck) *ProcessCheck {
|
|||||||
Processes: processes,
|
Processes: processes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toDiskEncryptionCheck(check *api.DiskEncryptionCheck) *DiskEncryptionCheck {
|
||||||
|
d := &DiskEncryptionCheck{}
|
||||||
|
if check.LinuxPath != nil {
|
||||||
|
d.LinuxPath = *check.LinuxPath
|
||||||
|
}
|
||||||
|
if check.DarwinPath != nil {
|
||||||
|
d.DarwinPath = *check.DarwinPath
|
||||||
|
}
|
||||||
|
if check.WindowsPath != nil {
|
||||||
|
d.WindowsPath = *check.WindowsPath
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func toDiskEncryptionCheckResponse(check *DiskEncryptionCheck) *api.DiskEncryptionCheck {
|
||||||
|
return &api.DiskEncryptionCheck{
|
||||||
|
LinuxPath: &check.LinuxPath,
|
||||||
|
DarwinPath: &check.DarwinPath,
|
||||||
|
WindowsPath: &check.WindowsPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
52
management/server/posture/disk_encryption.go
Normal file
52
management/server/posture/disk_encryption.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package posture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DiskEncryptionCheck verifies that specified volumes are encrypted.
|
||||||
|
type DiskEncryptionCheck struct {
|
||||||
|
LinuxPath string
|
||||||
|
DarwinPath string
|
||||||
|
WindowsPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Check = (*DiskEncryptionCheck)(nil)
|
||||||
|
|
||||||
|
// Name returns the name of the check.
|
||||||
|
func (d *DiskEncryptionCheck) Name() string {
|
||||||
|
return DiskEncryptionCheckName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check performs the disk encryption verification for the given peer.
|
||||||
|
func (d *DiskEncryptionCheck) Check(_ context.Context, peer nbpeer.Peer) (bool, error) {
|
||||||
|
var pathToCheck string
|
||||||
|
|
||||||
|
switch peer.Meta.GoOS {
|
||||||
|
case "linux":
|
||||||
|
pathToCheck = d.LinuxPath
|
||||||
|
case "darwin":
|
||||||
|
pathToCheck = d.DarwinPath
|
||||||
|
case "windows":
|
||||||
|
pathToCheck = d.WindowsPath
|
||||||
|
default:
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathToCheck == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return peer.Meta.DiskEncryption.IsEncrypted(pathToCheck), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the configuration of the disk encryption check.
|
||||||
|
func (d *DiskEncryptionCheck) Validate() error {
|
||||||
|
if d.LinuxPath == "" && d.DarwinPath == "" && d.WindowsPath == "" {
|
||||||
|
return fmt.Errorf("%s at least one path must be configured", d.Name())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
306
management/server/posture/disk_encryption_test.go
Normal file
306
management/server/posture/disk_encryption_test.go
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
package posture
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDiskEncryptionCheck_Check(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input peer.Peer
|
||||||
|
check DiskEncryptionCheck
|
||||||
|
wantErr bool
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "linux with encrypted root",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "linux",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "/", Encrypted: true},
|
||||||
|
{Path: "/home", Encrypted: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "linux with unencrypted root",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "linux",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "/", Encrypted: false},
|
||||||
|
{Path: "/home", Encrypted: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "linux with no volume info",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "linux",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "darwin with encrypted root",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "darwin",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "/", Encrypted: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
DarwinPath: "/",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "darwin with unencrypted root",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "darwin",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "/", Encrypted: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
DarwinPath: "/",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "windows with encrypted C drive",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "windows",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "C:", Encrypted: true},
|
||||||
|
{Path: "D:", Encrypted: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "windows with unencrypted C drive",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "windows",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "C:", Encrypted: false},
|
||||||
|
{Path: "D:", Encrypted: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported ios operating system",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "ios",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
DarwinPath: "/",
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported android operating system",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "android",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
DarwinPath: "/",
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "linux peer with no linux path configured passes",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "linux",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "/", Encrypted: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
DarwinPath: "/",
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "darwin peer with no darwin path configured passes",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "darwin",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "/", Encrypted: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "windows peer with no windows path configured passes",
|
||||||
|
input: peer.Peer{
|
||||||
|
Meta: peer.PeerSystemMeta{
|
||||||
|
GoOS: "windows",
|
||||||
|
DiskEncryption: peer.DiskEncryptionInfo{
|
||||||
|
Volumes: []peer.DiskEncryptionVolume{
|
||||||
|
{Path: "C:", Encrypted: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
DarwinPath: "/",
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
isValid: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
isValid, err := tt.check.Check(context.Background(), tt.input)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.isValid, isValid)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiskEncryptionCheck_Validate(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
check DiskEncryptionCheck
|
||||||
|
expectedError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid linux, darwin and windows paths",
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
DarwinPath: "/",
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid linux path only",
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
LinuxPath: "/",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid darwin path only",
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
DarwinPath: "/",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid windows path only",
|
||||||
|
check: DiskEncryptionCheck{
|
||||||
|
WindowsPath: "C:",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid empty paths",
|
||||||
|
check: DiskEncryptionCheck{},
|
||||||
|
expectedError: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := tc.check.Validate()
|
||||||
|
if tc.expectedError {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiskEncryptionCheck_Name(t *testing.T) {
|
||||||
|
check := DiskEncryptionCheck{}
|
||||||
|
assert.Equal(t, DiskEncryptionCheckName, check.Name())
|
||||||
|
}
|
||||||
@@ -550,6 +550,14 @@ func infoToMetaData(info *system.Info) *proto.PeerSystemMeta {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diskEncryptionVolumes := make([]*proto.DiskEncryptionVolume, 0, len(info.DiskEncryption.Volumes))
|
||||||
|
for _, vol := range info.DiskEncryption.Volumes {
|
||||||
|
diskEncryptionVolumes = append(diskEncryptionVolumes, &proto.DiskEncryptionVolume{
|
||||||
|
Path: vol.Path,
|
||||||
|
Encrypted: vol.Encrypted,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return &proto.PeerSystemMeta{
|
return &proto.PeerSystemMeta{
|
||||||
Hostname: info.Hostname,
|
Hostname: info.Hostname,
|
||||||
GoOS: info.GoOS,
|
GoOS: info.GoOS,
|
||||||
@@ -585,5 +593,8 @@ func infoToMetaData(info *system.Info) *proto.PeerSystemMeta {
|
|||||||
|
|
||||||
LazyConnectionEnabled: info.LazyConnectionEnabled,
|
LazyConnectionEnabled: info.LazyConnectionEnabled,
|
||||||
},
|
},
|
||||||
|
DiskEncryption: &proto.DiskEncryptionInfo{
|
||||||
|
Volumes: diskEncryptionVolumes,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1232,6 +1232,8 @@ components:
|
|||||||
$ref: '#/components/schemas/PeerNetworkRangeCheck'
|
$ref: '#/components/schemas/PeerNetworkRangeCheck'
|
||||||
process_check:
|
process_check:
|
||||||
$ref: '#/components/schemas/ProcessCheck'
|
$ref: '#/components/schemas/ProcessCheck'
|
||||||
|
disk_encryption_check:
|
||||||
|
$ref: '#/components/schemas/DiskEncryptionCheck'
|
||||||
NBVersionCheck:
|
NBVersionCheck:
|
||||||
description: Posture check for the version of NetBird
|
description: Posture check for the version of NetBird
|
||||||
type: object
|
type: object
|
||||||
@@ -1346,6 +1348,22 @@ components:
|
|||||||
description: Path to the process executable file in a Windows operating system
|
description: Path to the process executable file in a Windows operating system
|
||||||
type: string
|
type: string
|
||||||
example: "C:\ProgramData\NetBird\netbird.exe"
|
example: "C:\ProgramData\NetBird\netbird.exe"
|
||||||
|
DiskEncryptionCheck:
|
||||||
|
description: Posture check for disk encryption status
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
linux_path:
|
||||||
|
description: Mount path to check on Linux (e.g., "/", "/home")
|
||||||
|
type: string
|
||||||
|
example: "/"
|
||||||
|
darwin_path:
|
||||||
|
description: Mount path to check on macOS (e.g., "/")
|
||||||
|
type: string
|
||||||
|
example: "/"
|
||||||
|
windows_path:
|
||||||
|
description: Drive letter to check on Windows (e.g., "C:", "D:")
|
||||||
|
type: string
|
||||||
|
example: "C:"
|
||||||
Location:
|
Location:
|
||||||
description: Describe geographical location information
|
description: Describe geographical location information
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -370,6 +370,9 @@ type AvailablePorts struct {
|
|||||||
|
|
||||||
// Checks List of objects that perform the actual checks
|
// Checks List of objects that perform the actual checks
|
||||||
type Checks struct {
|
type Checks struct {
|
||||||
|
// DiskEncryptionCheck Posture check for disk encryption status
|
||||||
|
DiskEncryptionCheck *DiskEncryptionCheck `json:"disk_encryption_check,omitempty"`
|
||||||
|
|
||||||
// GeoLocationCheck Posture check for geo location
|
// GeoLocationCheck Posture check for geo location
|
||||||
GeoLocationCheck *GeoLocationCheck `json:"geo_location_check,omitempty"`
|
GeoLocationCheck *GeoLocationCheck `json:"geo_location_check,omitempty"`
|
||||||
|
|
||||||
@@ -476,6 +479,18 @@ type DNSSettings struct {
|
|||||||
DisabledManagementGroups []string `json:"disabled_management_groups"`
|
DisabledManagementGroups []string `json:"disabled_management_groups"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiskEncryptionCheck Posture check for disk encryption status
|
||||||
|
type DiskEncryptionCheck struct {
|
||||||
|
// DarwinPath Mount path to check on macOS (e.g., "/")
|
||||||
|
DarwinPath *string `json:"darwin_path,omitempty"`
|
||||||
|
|
||||||
|
// LinuxPath Mount path to check on Linux (e.g., "/", "/home")
|
||||||
|
LinuxPath *string `json:"linux_path,omitempty"`
|
||||||
|
|
||||||
|
// WindowsPath Drive letter to check on Windows (e.g., "C:", "D:")
|
||||||
|
WindowsPath *string `json:"windows_path,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Event defines model for Event.
|
// Event defines model for Event.
|
||||||
type Event struct {
|
type Event struct {
|
||||||
// Activity The activity that occurred during the event
|
// Activity The activity that occurred during the event
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -154,6 +154,19 @@ message Flags {
|
|||||||
bool disableSSHAuth = 15;
|
bool disableSSHAuth = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiskEncryptionVolume represents encryption status of a single volume.
|
||||||
|
message DiskEncryptionVolume {
|
||||||
|
// Mount path (Linux/macOS) or drive letter (Windows)
|
||||||
|
string path = 1;
|
||||||
|
// Whether the volume is encrypted
|
||||||
|
bool encrypted = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiskEncryptionInfo holds disk encryption detection results.
|
||||||
|
message DiskEncryptionInfo {
|
||||||
|
repeated DiskEncryptionVolume volumes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// PeerSystemMeta is machine meta data like OS and version.
|
// PeerSystemMeta is machine meta data like OS and version.
|
||||||
message PeerSystemMeta {
|
message PeerSystemMeta {
|
||||||
string hostname = 1;
|
string hostname = 1;
|
||||||
@@ -173,6 +186,7 @@ message PeerSystemMeta {
|
|||||||
Environment environment = 15;
|
Environment environment = 15;
|
||||||
repeated File files = 16;
|
repeated File files = 16;
|
||||||
Flags flags = 17;
|
Flags flags = 17;
|
||||||
|
DiskEncryptionInfo diskEncryption = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LoginResponse {
|
message LoginResponse {
|
||||||
|
|||||||
Reference in New Issue
Block a user