package originclient import ( "errors" "os" "path/filepath" "strings" "github.com/google/uuid" ) // errMachineIDUnavailable is returned by the OS-specific machineID() when // no real machine ID could be read. var errMachineIDUnavailable = errors.New("originclient: OS machine id unavailable") // machineIDFunc is a variable indirection over the OS-specific machineID() // so tests can stub OS machine-id lookup without depending on the actual // host's state. var machineIDFunc = machineID // ResolveMachineID returns the unique install ID to report to Origin, in // priority order: // // 1. explicit, if non-empty — a caller-supplied override. // 2. the real OS machine ID (/etc/machine-id on Linux, IOPlatformUUID on // macOS, MachineGuid on Windows), if readable. // 3. the ID already persisted at path, if present. // 4. a newly generated UUID, which ResolveMachineID attempts to persist to // path for future runs. // // OS-ID and persistence failures are logged as warnings, not returned as // errors: ResolveMachineID always returns a usable ID, falling back to one // that only lives for this process if it cannot be read from the OS or // saved to disk. logger may be nil. func ResolveMachineID(explicit, path string, logger Logger) string { if logger == nil { logger = noopLogger{} } if id := strings.TrimSpace(explicit); id != "" { return id } if id, err := machineIDFunc(); err == nil { if id = strings.TrimSpace(id); id != "" { return id } } else { logger.Warn("machine id: OS machine id unavailable, falling back to a generated id", err) } if path == "" { path = defaultInstallIDPath() } if data, err := os.ReadFile(path); err == nil { if id := strings.TrimSpace(string(data)); id != "" { return id } } id := uuid.NewString() if err := persistInstallID(path, id); err != nil { logger.Warn("machine id: failed to persist generated id, using an ephemeral id for this run", err) } return id } func persistInstallID(path, id string) error { if dir := filepath.Dir(path); dir != "." && dir != "" { if err := os.MkdirAll(dir, 0o750); err != nil { return err } } return os.WriteFile(path, []byte(id+"\n"), 0o600) } // defaultInstallIDPath returns the fallback-UUID persistence path used when // Config.InstallIDPath is unset: the OS user-config directory, or the OS // temp directory if that cannot be determined. func defaultInstallIDPath() string { dir, err := os.UserConfigDir() if err != nil || dir == "" { dir = os.TempDir() } return filepath.Join(dir, "origin-client", "install-id") }