From 6cd08920694b9d35fc441d8873b6e87c4a880f8d Mon Sep 17 00:00:00 2001 From: Nick Khyl Date: Thu, 20 Jun 2024 18:52:30 -0500 Subject: [PATCH] posture, util/syspolicy: append DeviceSerialNumber from syspolicy on Windows Some off-the-shelf motherboards come with bogus serial number values like "System Serial Number", "To Be Filled By O.E.M.", "Unknown", or similar. This updates posture.GetSerialNumbers to use DeviceSerialNumber syspolicy on Windows. If configured, its value will be appended to the list of serial numbers read from SMBIOS. Fixes #12566 Signed-off-by: Nick Khyl --- posture/serialnumber_notmacos.go | 31 +++++++++++++++++++++++---- util/syspolicy/policy_keys_windows.go | 1 + 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/posture/serialnumber_notmacos.go b/posture/serialnumber_notmacos.go index 69ad904b8..889013ffb 100644 --- a/posture/serialnumber_notmacos.go +++ b/posture/serialnumber_notmacos.go @@ -13,6 +13,7 @@ import ( "github.com/digitalocean/go-smbios/smbios" "tailscale.com/types/logger" + "tailscale.com/util/syspolicy" ) // getByteFromSmbiosStructure retrieves a 8-bit unsigned integer at the given specOffset. @@ -71,7 +72,31 @@ func init() { numOfTables = len(validTables) } -func GetSerialNumbers(logf logger.Logf) ([]string, error) { +func GetSerialNumbers(logf logger.Logf) (serials []string, err error) { + defer func() { + // Append an additional serial number if configured via the + // DeviceSerialNumber GP/MDM policy. This can be used as a workaround + // when the serial number is not available from SMBIOS, or hasn't been + // properly set by the OEM and has a bogus value like "System Serial Number", + // "To Be Filled By O.E.M.", "Unknown", or similar. + serial, policyErr := syspolicy.GetString("DeviceSerialNumber", "") + if policyErr != nil { + // Non-fatal, so we'll just return whatever we read from SMBIOS. + logf("failed to read DeviceSerialNumber from syspolicy: %v", policyErr) + } else if serial != "" { + serials = append(serials, serial) + if err != nil { + // Log the original error before we discard it. + logf("%v", err) + err = nil + } + } + + if err == nil { + logf("got serial numbers %v", serials) + } + }() + // Find SMBIOS data in operating system-specific location. rc, _, err := smbios.Stream() if err != nil { @@ -86,7 +111,7 @@ func GetSerialNumbers(logf logger.Logf) ([]string, error) { return nil, fmt.Errorf("failed to decode dmi/smbios structures: %w", err) } - serials := make([]string, 0, numOfTables) + serials = make([]string, 0, numOfTables) for _, s := range ss { switch s.Header.Type { @@ -99,7 +124,5 @@ func GetSerialNumbers(logf logger.Logf) ([]string, error) { } } - logf("got serial numbers %v", serials) - return serials, nil } diff --git a/util/syspolicy/policy_keys_windows.go b/util/syspolicy/policy_keys_windows.go index 5e9a71695..42f2fe166 100644 --- a/util/syspolicy/policy_keys_windows.go +++ b/util/syspolicy/policy_keys_windows.go @@ -28,6 +28,7 @@ var stringKeys = []Key{ ManagedByOrganizationName, ManagedByCaption, ManagedByURL, + DeviceSerialNumber, } var boolKeys = []Key{