Răsfoiți Sursa

posture: add get serial support for macOS

Updates #5902

Signed-off-by: Kristoffer Dalby <[email protected]>
Kristoffer Dalby 2 ani în urmă
părinte
comite
d0b8bdf8f7

+ 74 - 0
posture/serialnumber_macos.go

@@ -0,0 +1,74 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+//go:build cgo && darwin && !ios
+
+package posture
+
+// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit
+// #include <CoreFoundation/CoreFoundation.h>
+// #include <IOKit/IOKitLib.h>
+//
+// #if __MAC_OS_X_VERSION_MIN_REQUIRED < 120000
+// #define kIOMainPortDefault kIOMasterPortDefault
+// #endif
+//
+// const char *
+// getSerialNumber()
+// {
+//     CFMutableDictionaryRef matching = IOServiceMatching("IOPlatformExpertDevice");
+//     if (!matching) {
+//         return "err: failed to create dictionary to match IOServices";
+//     }
+//
+//     io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, matching);
+//     if (!service) {
+//         return "err: failed to look up registered IOService objects that match a matching dictionary";
+//     }
+//
+//     CFStringRef serialNumberRef = IORegistryEntryCreateCFProperty(
+//         service,
+//         CFSTR("IOPlatformSerialNumber"),
+//         kCFAllocatorDefault,
+//         0
+//     );
+//     if (!serialNumberRef) {
+//         return "err: failed to look up serial number in IORegistry";
+//     }
+//
+//     CFIndex length = CFStringGetLength(serialNumberRef);
+//     CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
+//     char *serialNumberBuf = (char *)malloc(max_size);
+//
+//     bool result = CFStringGetCString(serialNumberRef, serialNumberBuf, max_size, kCFStringEncodingUTF8);
+//
+//     CFRelease(serialNumberRef);
+//     IOObjectRelease(service);
+//
+//     if (!result) {
+//         free(serialNumberBuf);
+//
+//         return "err: failed to convert serial number reference to string";
+//     }
+//
+//     return serialNumberBuf;
+// }
+import "C"
+import (
+	"fmt"
+	"strings"
+
+	"tailscale.com/types/logger"
+)
+
+// GetSerialNumber returns the platform serial sumber as reported by IOKit.
+func GetSerialNumbers(_ logger.Logf) ([]string, error) {
+	csn := C.getSerialNumber()
+	serialNumber := C.GoString(csn)
+
+	if err, ok := strings.CutPrefix(serialNumber, "err: "); ok {
+		return nil, fmt.Errorf("failed to get serial number from IOKit: %s", err)
+	}
+
+	return []string{serialNumber}, nil
+}

+ 37 - 0
posture/serialnumber_macos_test.go

@@ -0,0 +1,37 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+//go:build cgo && darwin && !ios
+
+package posture
+
+import (
+	"fmt"
+	"testing"
+
+	"tailscale.com/types/logger"
+	"tailscale.com/util/cibuild"
+)
+
+func TestGetSerialNumberMac(t *testing.T) {
+	// Do not run this test on CI, it can only be ran on macOS
+	// and we currenty only use Linux runners.
+	if cibuild.On() {
+		t.Skip()
+	}
+
+	sns, err := GetSerialNumbers(logger.Discard)
+	if err != nil {
+		t.Fatalf("failed to get serial number: %s", err)
+	}
+
+	if len(sns) != 1 {
+		t.Errorf("expected list of one serial number, got %v", sns)
+	}
+
+	if len(sns[0]) <= 0 {
+		t.Errorf("expected a serial number with more than zero characters, got %s", sns[0])
+	}
+
+	fmt.Printf("serials: %v\n", sns)
+}

+ 3 - 3
posture/serialnumber_stub.go

@@ -1,14 +1,14 @@
 // Copyright (c) Tailscale Inc & AUTHORS
 // SPDX-License-Identifier: BSD-3-Clause
 
-// darwin: not implemented
-// andoird: not implemented
+// 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 darwin || android || js || plan9 || solaris
+//go:build ios || android || solaris || plan9 || js || wasm || (darwin && !cgo)
 
 package posture