Add docstrings to mdm_integration

This commit is contained in:
riccardom
2026-06-09 19:45:47 +02:00
parent d7f00b3beb
commit bd9fed41ad
13 changed files with 129 additions and 31 deletions
+10 -3
View File
@@ -85,7 +85,9 @@ type Policy struct {
// NewPolicy constructs a Policy from a key→value map. Pass nil or an empty
// NewPolicy constructs a Policy backed by the provided key→value map.
// If values is nil it is replaced with an empty map so the returned *Policy
// is always non-nil and represents no active MDM enforcement when empty.
// NewPolicy constructs a non-nil *Policy that wraps the provided key/value map.
// If values is nil it is replaced with an empty map so the returned Policy always
// represents "no MDM enforcement" when its values are empty.
func NewPolicy(values map[string]any) *Policy {
if values == nil {
values = map[string]any{}
@@ -102,7 +104,11 @@ func NewPolicy(values map[string]any) *Policy {
// - source present, zero keys: info "MDM enrolled (no managed keys)"
// LoadPolicy loads MDM-managed configuration from the platform and returns a Policy representing the managed settings.
// If the platform loader fails or returns nil, LoadPolicy returns a non-nil empty Policy.
// When the loaded map contains zero keys it logs that MDM is enrolled with no managed keys; when it contains keys it logs the count and a stable, sorted list of key names.
// LoadPolicy loads platform-managed MDM key/value pairs and returns a non-nil Policy.
// If the platform loader returns an error or a nil map, an empty Policy is returned.
// On loader error a trace-level message is emitted. When a map is returned, an
// informational message is logged either indicating enrollment with no managed keys
// or the count and a stable, sorted list of managed key names.
func LoadPolicy() *Policy {
values, err := loadPlatformPolicy()
if err != nil {
@@ -260,7 +266,8 @@ func (p *Policy) GetStringSlice(key string) ([]string, bool) {
// sortedKeys returns the keys of m as a deterministic, lexicographically
// sorted slice. Used internally by Policy.ManagedKeys and LoadPolicy's
// diagnostic log line so callers see a stable key order across runs
// It produces a deterministic ordering for a map regardless of Go's randomized iteration.
// sortedKeys returns the keys of m as a lexicographically sorted slice.
// The sorted order provides a deterministic key ordering for diagnostics and enumeration.
func sortedKeys(m map[string]any) []string {
out := make([]string, 0, len(m))
for k := range m {
+7 -1
View File
@@ -41,7 +41,13 @@ const policyPlistPath = "/Library/Managed Preferences/io.netbird.client.plist"
//
// If the plist file does not exist, it returns (nil, nil). It returns a wrapped error on open/stat/decode failures.
// The function refuses to read a world-writable plist and returns an error in that case.
// Top-level plist keys are canonicalized (case-insensitive) to the internal MDM key names; unknown keys are logged and skipped.
// loadPlatformPolicy reads the device-level managed-preferences plist and returns its recognized keys.
//
// It looks for the plist at policyPlistPath and, if present, decodes it into a map[string]any.
// Top-level plist keys are canonicalized case-insensitively to the package's internal MDM key names;
// unknown keys are logged and ignored. If the plist file does not exist, it returns (nil, nil).
// The function refuses to read the file if it is world-writable and returns a wrapped error for
// failures to open, stat, or decode the plist.
func loadPlatformPolicy() (map[string]any, error) {
f, err := os.Open(policyPlistPath)
if err != nil {
+3 -1
View File
@@ -9,7 +9,9 @@ package mdm
// builds and returns (nil, nil) — the platform-absent sentinel that
// LoadPolicy in policy.go treats as "no MDM source present".
//
//nolint:nilnil // (nil, nil) is the documented platform-absent sentinel; see LoadPolicy.
// loadPlatformPolicy reports the absence of a platform-managed configuration on mobile builds.
// It returns a nil policy map and a nil error as a sentinel value; the real managed-config
// dictionary is read by the native iOS/Android layer and injected into the Go process.
func loadPlatformPolicy() (map[string]any, error) {
return nil, nil
}
+2 -1
View File
@@ -9,7 +9,8 @@ package mdm
// source present"; an error here would just translate to the same
// outcome with an extra log line.
//
//nolint:nilnil // (nil, nil) is the documented platform-absent sentinel; see LoadPolicy.
// loadPlatformPolicy indicates that no platform MDM policy is available on this build target.
// It intentionally returns (nil, nil) as the documented platform-absent sentinel so callers treat MDM as not present.
func loadPlatformPolicy() (map[string]any, error) {
return nil, nil
}
+13 -1
View File
@@ -35,7 +35,9 @@ const policyRegistryPath = `Software\Policies\NetBird`
// If the registry key does not exist it returns (nil, nil).
// It returns a map whose keys are canonical policy names and whose values are coerced from registry types:
// REG_SZ/REG_EXPAND_SZ -> string, REG_DWORD/REG_QWORD -> int64, REG_MULTI_SZ -> []string.
// Unknown value names, unsupported value types, and per-value read errors are skipped and logged; failures opening the key or enumerating values are returned as errors.
// readRegistryValue reads the registry value named by name from key k and, when the value is successfully read and its type is supported, stores the coerced Go value in out[canonical].
//
// REG_SZ and REG_EXPAND_SZ are stored as string, REG_DWORD and REG_QWORD are stored as int64, and REG_MULTI_SZ is stored as []string; unknown value names, unsupported value types, and per-value read errors are logged and skipped.
func readRegistryValue(k registry.Key, name, canonical string, out map[string]any) {
_, valType, err := k.GetValue(name, nil)
if err != nil {
@@ -69,6 +71,16 @@ func readRegistryValue(k registry.Key, name, canonical string, out map[string]an
}
}
// loadPlatformPolicy loads MDM-managed NetBird policy values from the Windows
// registry at HKLM\Software\Policies\NetBird.
//
// It returns a map that maps canonical policy names to coerced Go values:
// string for REG_SZ/REG_EXPAND_SZ, int64 for REG_DWORD/REG_QWORD, and []string
// for REG_MULTI_SZ. If the policy registry key does not exist, it returns
// (nil, nil). It returns an error when opening or enumerating the registry
// key fails. Individual values that are unknown, of unsupported types, or that
// fail to read are skipped and produce logged warnings; registry close failures
// are also logged.
func loadPlatformPolicy() (map[string]any, error) {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, policyRegistryPath, registry.QUERY_VALUE)
if err != nil {
+14 -4
View File
@@ -26,7 +26,8 @@ const testReloadInterval = 1 * time.Second
// reloadInterval returns the production cadence, or the accelerated test
// cadence when running under `go test`. Centralising the choice here keeps
// reloadInterval selects the polling interval used to re-read the OS-native MDM policy.
// It returns testReloadInterval when tests are running (testing.Testing() == true) and defaultReloadInterval otherwise.
// reloadInterval selects the polling interval used for policy reloads.
// It returns testReloadInterval when running under `go test` (testing.Testing() == true), and defaultReloadInterval otherwise.
func reloadInterval() time.Duration {
if testing.Testing() {
return testReloadInterval
@@ -55,7 +56,11 @@ type Ticker struct {
// reloadInterval (production default, accelerated under `go test`); callers
// NewTicker creates a Ticker that polls the OS-native MDM policy at the package reload interval and invokes onChange when a policy change is detected.
// If onChange is nil the ticker will only log detected changes.
// The ticker's initial snapshot is populated by loading the current policy.
// NewTicker creates a Ticker that polls for policy changes and invokes onChange when a difference is detected.
//
// The provided onChange callback, if non-nil, is called with the previous and current Policy snapshots when a
// change is observed. The returned Ticker's polling interval is set via reloadInterval and its initial snapshot
// is populated by calling policyLoader.
func NewTicker(onChange func(prev, curr *Policy)) *Ticker {
return &Ticker{
interval: reloadInterval(),
@@ -94,7 +99,10 @@ func (t *Ticker) Run(ctx context.Context) {
}
// PoliciesEqual reports whether two Policy instances carry the same managed
// value maps for deep equality.
// PoliciesEqual reports whether two Policy instances represent the same policy.
// It returns true when both policies are empty, returns false if one pointer is nil
// while the other is not, and otherwise compares the policies' underlying value
// maps for deep equality.
func PoliciesEqual(a, b *Policy) bool {
if a.IsEmpty() && b.IsEmpty() {
return true
@@ -110,7 +118,7 @@ func PoliciesEqual(a, b *Policy) bool {
// The returned slices contain keys present only in `curr` (added), only in `prev` (removed),
// and present in both but whose values differ (changed). Each slice is sorted
// lexicographically for stable logging output; value differences are determined
// using deep equality.
// associated values differ by deep equality.
func diffPolicies(prev, curr *Policy) (added, removed, changed []string) {
prevKeys := mapOf(prev)
currKeys := mapOf(curr)
@@ -136,6 +144,8 @@ func diffPolicies(prev, curr *Policy) (added, removed, changed []string) {
// map of a Policy so callers outside this package can compare across the
// mapOf returns a non-nil copy of the given Policy's key/value map.
// If p is nil, mapOf returns an empty map; otherwise it returns a newly
// mapOf returns a non-nil copy of a Policy's values map.
// If p is nil it returns an empty map; otherwise it returns a newly
// allocated map containing the same key/value pairs as p.values.
func mapOf(p *Policy) map[string]any {
if p == nil {