Compare commits

...

1 Commits

Author SHA1 Message Date
mlsmaycon
279e96e6b1 add disk encryption check 2026-01-17 19:56:50 +01:00
23 changed files with 1637 additions and 760 deletions

View 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
}

View 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
}

View 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
}

View 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{}
}

View 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
}

View File

@@ -59,6 +59,7 @@ type Info struct {
SystemManufacturer string
Environment Environment
Files []File // for posture checks
DiskEncryption DiskEncryptionInfo
RosenpassEnabled bool
RosenpassPermissive bool

View File

@@ -44,6 +44,7 @@ func GetInfo(ctx context.Context) *Info {
SystemSerialNumber: serial(),
SystemProductName: productModel(),
SystemManufacturer: productManufacturer(),
DiskEncryption: detectDiskEncryption(ctx),
}
return gio

View File

@@ -62,6 +62,7 @@ func GetInfo(ctx context.Context) *Info {
SystemProductName: si.SystemProductName,
SystemManufacturer: si.SystemManufacturer,
Environment: si.Environment,
DiskEncryption: detectDiskEncryption(ctx),
}
systemHostname, _ := os.Hostname()

View File

@@ -55,6 +55,7 @@ func GetInfo(ctx context.Context) *Info {
UIVersion: extractUserAgent(ctx),
KernelVersion: osInfo[1],
Environment: env,
DiskEncryption: detectDiskEncryption(ctx),
}
}

View File

@@ -19,7 +19,7 @@ func GetInfo(ctx context.Context) *Info {
sysName := extractOsName(ctx, "sysName")
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.NetbirdVersion = version.NetbirdVersion()
gio.UIVersion = extractUserAgent(ctx)

View File

@@ -15,7 +15,7 @@ func UpdateStaticInfoAsync() {
}
// GetInfo retrieves system information for WASM environment
func GetInfo(_ context.Context) *Info {
func GetInfo(ctx context.Context) *Info {
info := &Info{
GoOS: runtime.GOOS,
Kernel: runtime.GOARCH,
@@ -25,6 +25,7 @@ func GetInfo(_ context.Context) *Info {
Hostname: "wasm-client",
CPUs: runtime.NumCPU(),
NetbirdVersion: version.NetbirdVersion(),
DiskEncryption: detectDiskEncryption(ctx),
}
collectBrowserInfo(info)

View File

@@ -73,6 +73,7 @@ func GetInfo(ctx context.Context) *Info {
SystemProductName: si.SystemProductName,
SystemManufacturer: si.SystemManufacturer,
Environment: si.Environment,
DiskEncryption: detectDiskEncryption(ctx),
}
return gio

View File

@@ -35,6 +35,7 @@ func GetInfo(ctx context.Context) *Info {
SystemProductName: si.SystemProductName,
SystemManufacturer: si.SystemManufacturer,
Environment: si.Environment,
DiskEncryption: detectDiskEncryption(ctx),
}
addrs, err := networkAddresses()

View File

@@ -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{
Hostname: meta.GetHostname(),
GoOS: meta.GetGoOS(),
@@ -501,6 +511,9 @@ func extractPeerMeta(ctx context.Context, meta *proto.PeerSystemMeta) nbpeer.Pee
LazyConnectionEnabled: meta.GetFlags().GetLazyConnectionEnabled(),
},
Files: files,
DiskEncryption: nbpeer.DiskEncryptionInfo{
Volumes: diskEncryptionVolumes,
},
}
}

View File

@@ -95,6 +95,27 @@ type File struct {
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
type Flags struct {
RosenpassEnabled bool
@@ -127,9 +148,10 @@ type PeerSystemMeta struct { //nolint:revive
SystemSerialNumber string
SystemProductName string
SystemManufacturer string
Environment Environment `gorm:"serializer:json"`
Flags Flags `gorm:"serializer:json"`
Files []File `gorm:"serializer:json"`
Environment Environment `gorm:"serializer:json"`
Flags Flags `gorm:"serializer:json"`
Files []File `gorm:"serializer:json"`
DiskEncryption DiskEncryptionInfo `gorm:"serializer:json"`
}
func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
@@ -159,6 +181,19 @@ func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
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 &&
p.GoOS == other.GoOS &&
p.Kernel == other.Kernel &&

View File

@@ -18,6 +18,7 @@ const (
GeoLocationCheckName = "GeoLocationCheck"
PeerNetworkRangeCheckName = "PeerNetworkRangeCheck"
ProcessCheckName = "ProcessCheck"
DiskEncryptionCheckName = "DiskEncryptionCheck"
CheckActionAllow string = "allow"
CheckActionDeny string = "deny"
@@ -58,6 +59,7 @@ type ChecksDefinition struct {
GeoLocationCheck *GeoLocationCheck `json:",omitempty"`
PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:",omitempty"`
ProcessCheck *ProcessCheck `json:",omitempty"`
DiskEncryptionCheck *DiskEncryptionCheck `json:",omitempty"`
}
// Copy returns a copy of a checks definition.
@@ -110,6 +112,13 @@ func (cd ChecksDefinition) Copy() ChecksDefinition {
}
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
}
@@ -153,6 +162,9 @@ func (pc *Checks) GetChecks() []Check {
if pc.Checks.ProcessCheck != nil {
checks = append(checks, pc.Checks.ProcessCheck)
}
if pc.Checks.DiskEncryptionCheck != nil {
checks = append(checks, pc.Checks.DiskEncryptionCheck)
}
return checks
}
@@ -208,6 +220,10 @@ func buildPostureCheck(postureChecksID string, name string, description string,
postureChecks.Checks.ProcessCheck = toProcessCheck(processCheck)
}
if diskEncryptionCheck := checks.DiskEncryptionCheck; diskEncryptionCheck != nil {
postureChecks.Checks.DiskEncryptionCheck = toDiskEncryptionCheck(diskEncryptionCheck)
}
return &postureChecks, nil
}
@@ -242,6 +258,10 @@ func (pc *Checks) ToAPIResponse() *api.PostureCheck {
checks.ProcessCheck = toProcessCheckResponse(pc.Checks.ProcessCheck)
}
if pc.Checks.DiskEncryptionCheck != nil {
checks.DiskEncryptionCheck = toDiskEncryptionCheckResponse(pc.Checks.DiskEncryptionCheck)
}
return &api.PostureCheck{
Id: pc.ID,
Name: pc.Name,
@@ -386,3 +406,25 @@ func toProcessCheck(check *api.ProcessCheck) *ProcessCheck {
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,
}
}

View 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
}

View 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())
}

View File

@@ -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{
Hostname: info.Hostname,
GoOS: info.GoOS,
@@ -585,5 +593,8 @@ func infoToMetaData(info *system.Info) *proto.PeerSystemMeta {
LazyConnectionEnabled: info.LazyConnectionEnabled,
},
DiskEncryption: &proto.DiskEncryptionInfo{
Volumes: diskEncryptionVolumes,
},
}
}

View File

@@ -1232,6 +1232,8 @@ components:
$ref: '#/components/schemas/PeerNetworkRangeCheck'
process_check:
$ref: '#/components/schemas/ProcessCheck'
disk_encryption_check:
$ref: '#/components/schemas/DiskEncryptionCheck'
NBVersionCheck:
description: Posture check for the version of NetBird
type: object
@@ -1346,6 +1348,22 @@ components:
description: Path to the process executable file in a Windows operating system
type: string
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:
description: Describe geographical location information
type: object

View File

@@ -370,6 +370,9 @@ type AvailablePorts struct {
// Checks List of objects that perform the actual checks
type Checks struct {
// DiskEncryptionCheck Posture check for disk encryption status
DiskEncryptionCheck *DiskEncryptionCheck `json:"disk_encryption_check,omitempty"`
// GeoLocationCheck Posture check for geo location
GeoLocationCheck *GeoLocationCheck `json:"geo_location_check,omitempty"`
@@ -476,6 +479,18 @@ type DNSSettings struct {
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.
type Event struct {
// Activity The activity that occurred during the event

File diff suppressed because it is too large Load Diff

View File

@@ -154,6 +154,19 @@ message Flags {
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.
message PeerSystemMeta {
string hostname = 1;
@@ -173,6 +186,7 @@ message PeerSystemMeta {
Environment environment = 15;
repeated File files = 16;
Flags flags = 17;
DiskEncryptionInfo diskEncryption = 18;
}
message LoginResponse {