Browse Source

xcode/iOS: support serial number collection via MDM on iOS (#11429)

Fixes tailscale/corp#18366.

This PR provides serial number collection on iOS, by allowing system administrators to pass a `DeviceSerialNumber` MDM key which can be read by the `posture` package in Go.

Signed-off-by: Andrea Gottardo <[email protected]>
Andrea Gottardo 1 year ago
parent
commit
e8ca30a5c7
4 changed files with 32 additions and 3 deletions
  1. 25 0
      posture/serialnumber_ios.go
  2. 1 2
      posture/serialnumber_stub.go
  3. 2 1
      tailcfg/tailcfg.go
  4. 4 0
      util/syspolicy/policy_keys.go

+ 25 - 0
posture/serialnumber_ios.go

@@ -0,0 +1,25 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package posture
+
+import (
+	"fmt"
+
+	"tailscale.com/types/logger"
+	"tailscale.com/util/syspolicy"
+)
+
+// GetSerialNumbers returns the serial number of the iOS/tvOS device as reported by an
+// MDM solution. It requires configuration via the DeviceSerialNumber system policy.
+// This is the only way to gather serial numbers on iOS and tvOS.
+func GetSerialNumbers(_ logger.Logf) ([]string, error) {
+	s, err := syspolicy.GetString("DeviceSerialNumber", "")
+	if err != nil {
+		return nil, fmt.Errorf("failed to get serial number from MDM: %v", err)
+	}
+	if s != "" {
+		return []string{s}, nil
+	}
+	return nil, nil
+}

+ 1 - 2
posture/serialnumber_stub.go

@@ -1,14 +1,13 @@
 // Copyright (c) Tailscale Inc & AUTHORS
 // SPDX-License-Identifier: BSD-3-Clause
 
-// ios: Apple does not allow getting serials on iOS
 // android: not implemented
 // js: not implemented
 // plan9: not implemented
 // solaris: currently unsupported by go-smbios:
 // https://github.com/digitalocean/go-smbios/pull/21
 
-//go:build ios || android || solaris || plan9 || js || wasm || (darwin && !cgo) || tamago || aix
+//go:build android || solaris || plan9 || js || wasm || tamago || aix || (darwin && !cgo && !ios)
 
 package posture
 

+ 2 - 1
tailcfg/tailcfg.go

@@ -138,7 +138,8 @@ type CapabilityVersion int
 //   - 95: 2024-05-06: Client uses NodeAttrUserDialUseRoutes to change DNS dialing behavior.
 //   - 96: 2024-05-29: Client understands NodeAttrSSHBehaviorV1
 //   - 97: 2024-06-06: Client understands NodeAttrDisableSplitDNSWhenNoCustomResolvers
-const CurrentCapabilityVersion CapabilityVersion = 97
+//   - 98: 2024-06-13: iOS/tvOS clients may provide serial number as part of posture information
+const CurrentCapabilityVersion CapabilityVersion = 98
 
 type StableID string
 

+ 4 - 0
util/syspolicy/policy_keys.go

@@ -76,6 +76,10 @@ const (
 	// Key is a string value that specifies an option: "always", "never", "user-decides".
 	// The default is "user-decides" unless otherwise stated.
 	PostureChecking Key = "PostureChecking"
+	// DeviceSerialNumber is the serial number of the device that is running Tailscale.
+	// This is used on iOS/tvOS to allow IT administrators to manually give us a serial number via MDM.
+	// We are unable to programmatically get the serial number from IOKit due to sandboxing restrictions.
+	DeviceSerialNumber Key = "DeviceSerialNumber"
 
 	// ManagedByOrganizationName indicates the name of the organization managing the Tailscale
 	// install. It is displayed inside the client UI in a prominent location.