{"record":{"id":"332dd699c2199b75","repo":"gravitational/teleport","slug":"unable-to-sign-with-requested-key","errorCode":null,"errorMessage":"unable to sign with requested key","messagePattern":"unable to sign with requested key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/auth/keystore/manager.go","lineNumber":457,"sourceCode":"\t\t\treturn ssh.NewSignerWithAlgorithms(algorithmSigner, []string{ssh.KeyAlgoECDSA256})\n\t\tcase elliptic.P384():\n\t\t\treturn ssh.NewSignerWithAlgorithms(algorithmSigner, []string{ssh.KeyAlgoECDSA384})\n\t\tcase elliptic.P521():\n\t\t\treturn ssh.NewSignerWithAlgorithms(algorithmSigner, []string{ssh.KeyAlgoECDSA521})\n\t\tdefault:\n\t\t\treturn nil, trace.BadParameter(\"SSH CA: ECDSA curve: %s\", pub.Curve.Params().Name)\n\t\t}\n\tcase ed25519.PublicKey:\n\t\t// This is the current default, but let's set it explicitly so\n\t\t// golang.org/x/crypto/ssh can't change it in an update and break some\n\t\t// HSM or KMS that wouldn't support the new default.\n\t\treturn ssh.NewSignerWithAlgorithms(algorithmSigner, []string{ssh.KeyAlgoED25519})\n\tdefault:\n\t\treturn nil, trace.BadParameter(\"SSH CA: unsupported key type: %s\", sshSigner.PublicKey().Type())\n\t}\n}\n\nvar ErrUnusableKey = errors.New(\"unable to sign with requested key\")\n\n// TLSSigner returns a crypto.Signer for the given TLSKeyPair.\n// It returns ErrUnusableKey if unable to create a signer from the given keypair,\n// e.g. if it is stored in an HSM or KMS this auth service is not configured to use.\nfunc (m *Manager) TLSSigner(ctx context.Context, keypair *types.TLSKeyPair) (crypto.Signer, error) {\n\tfor _, backend := range m.usableBackends {\n\t\tcanUse, err := backend.canUseKey(ctx, keypair.Key, keypair.KeyType)\n\t\tif err != nil {\n\t\t\treturn nil, trace.Wrap(err)\n\t\t}\n\t\tif !canUse {\n\t\t\tcontinue\n\t\t}\n\t\tpub, err := publicKeyFromTLSCertPem(keypair.Cert)\n\t\tif err != nil {\n\t\t\treturn nil, trace.Wrap(err)\n\t\t}\n\t\tsigner, err := backend.getSigner(ctx, keypair.Key, pub)","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/auth/keystore/manager.go#L439-L475","documentation":"Manager.TLSSigner (and SSH signing paths) iterate usable key-store backends trying to build a signer from a stored TLS key pair. ErrUnusableKey is returned when no backend can produce a signer for the given key — e.g. the key lives in an HSM/KMS this auth server is not configured to use. It is an expected, sentinel error: callers like lib/auth/init.go treat it as non-fatal (no warning) because a different signer may still exist.","triggerScenarios":"Calling keystore Manager.TLSSigner(ctx, keypair) where the key pair was created by a keystore backend (HSM, KMS, PKCS#11) that is absent from the current auth server's usableBackends configuration, so all backends decline and manager.go:483 returns ErrUnusableKey.","commonSituations":"Auth servers scaled out with different keystore configs (some with HSM/KMS, some without) reading CAs signed elsewhere; HA deployments after migrating CA keys into HSM but not updating all auth servers' keystore config; restore of CA data without the matching keystore plugin configuration.","solutions":["Configure the auth server with the keystore backend that holds the key (add the HSM/KMS/PKCS#11 section to auth config) so usableBackends includes it.","Verify errors.Is(err, keystore.ErrUnusableKey) to distinguish expected incompatibility from real failures, as lib/auth/init.go:918 does, and skip silently.","Re-sign or re-issue the CA key pair with a keystore type available to this auth server."],"exampleFix":"// before\nsigner, err := keyStore.TLSSigner(ctx, kp)\nif err != nil {\n    return trace.Wrap(err)\n}\n// after\nsigner, err := keyStore.TLSSigner(ctx, kp)\nif err != nil {\n    if errors.Is(err, keystore.ErrUnusableKey) {\n        return nil // key managed by an unavailable backend; another signer may cover it\n    }\n    return trace.Wrap(err)\n}","handlingStrategy":"type-guard","validationCode":"if !keyStore.SupportsKeyPair(kp) { /* skip; key managed by an unavailable backend */ }","typeGuard":"if errors.Is(err, keystore.ErrUnusableKey) { /* expected: backend mismatch, not a failure */ }","tryCatchPattern":"signer, err := keyStore.TLSSigner(ctx, kp)\nswitch {\ncase errors.Is(err, keystore.ErrUnusableKey):\n    return nil // benign: another configured signer covers this CA\ncase err != nil:\n    return trace.Wrap(err)\n}","preventionTips":["Keep keystore configuration identical across all auth servers in an HA cluster.","When migrating CA keys to HSM/KMS, update every auth server's keystore config first.","Treat ErrUnusableKey as a sentinel (errors.Is), never as a generic failure in logs or alerts."],"tags":["keystore","hsm","kms","tls"],"backgroundTag":"key-unsuitable-for-backend","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}