posture: add get serial support for macOS

Updates #5902

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
pull/9684/head
Kristoffer Dalby 9 months ago committed by Kristoffer Dalby
parent 9eedf86563
commit d0b8bdf8f7

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

@ -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)
}

@ -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

Loading…
Cancel
Save