From a2d8e21552bdb808fc344e6befcdf8c06f9c4012 Mon Sep 17 00:00:00 2001 From: AlbertSun Date: Tue, 23 Jun 2026 17:26:51 +0800 Subject: [PATCH] fix(doctor): report macOS keychain signer as present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The keychain signer lacked a HardwareProber, so probeHardware() returned ok=false and doctor printed "no TEE signer in this build" on macOS — a false negative, since the signer is registered and private_key_jwt works. Implement ProbeHardware on keychainSigner (reports backend=keychain, available when /usr/bin/security is present; no key access, no prompt) so doctor shows 'keychain TEE available'. --- extension/keysigner/signer_keychain_darwin.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/extension/keysigner/signer_keychain_darwin.go b/extension/keysigner/signer_keychain_darwin.go index 056a01b31..57c6d9a00 100644 --- a/extension/keysigner/signer_keychain_darwin.go +++ b/extension/keysigner/signer_keychain_darwin.go @@ -259,6 +259,22 @@ type keychainSigner struct{} func init() { Register(keychainSigner{}) } +// ProbeHardware reports the macOS Keychain backend backing this signer. The +// keychain signer is compiled into every darwin build and needs no special +// hardware, so it reports available whenever the Security tooling is present. +// It performs no key access, so it never prompts. Implementing HardwareProber +// is what lets `doctor` report the signer as present rather than treating the +// (prober-less) signer as "no TEE signer in this build". +func (keychainSigner) ProbeHardware(_ context.Context) (HardwareInfo, error) { + info := HardwareInfo{Backend: "keychain", VendorName: "macOS Keychain"} + if _, err := os.Stat(securityBin); err != nil { + info.Reason = securityBin + " not found" + return info, nil + } + info.Available = true + return info, nil +} + func (keychainSigner) EnsureKey(_ context.Context, ref KeyRef) (crypto.PublicKey, error) { if md, err := readKeyMetadata(ref.Label); err == nil { return decodePublicKey(md.PublicKey)