{"record":{"id":"c6063b20b13df124","repo":"gravitational/teleport","slug":"certificate-or-public-key-required","errorCode":null,"errorMessage":"certificate or public key required","messagePattern":"certificate or public key required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/subca/parsed.go","lineNumber":257,"sourceCode":"\t\t}\n\t\twantPublicKey = HashCertificatePublicKey(cert)\n\t}\n\n\t// PublicKey.\n\tif co.GetPublicKey() != \"\" {\n\t\tif !certificateOverridePublicKeyRE.MatchString(co.GetPublicKey()) {\n\t\t\treturn nil, \"\", errors.New(\"invalid public key\")\n\t\t}\n\t\tif wantPublicKey != \"\" && NormalizePublicKey(co.GetPublicKey()) != wantPublicKey {\n\t\t\treturn nil, \"public_key\", fmt.Errorf(\"certificate public key mismatch (want %q)\", wantPublicKey)\n\t\t}\n\t}\n\n\t// Validate \"required\" fields now that we know both Certificate and PublicKey\n\t// are valid.\n\tswitch {\n\tcase co.GetDisabled() && co.GetPublicKey() == \"\" && co.GetCertificate() == \"\":\n\t\treturn nil, \"\", errors.New(\"certificate or public key required\")\n\tcase co.GetDisabled():\n\t\t// OK, determined above to have either PublicKey or Certificate.\n\tcase co.GetCertificate() == \"\":\n\t\treturn nil, \"\", errors.New(\"certificate required\")\n\t}\n\n\t// Chain.\n\tvar chain []*x509.Certificate\n\tif len(co.GetChain()) > 0 {\n\t\tif cert == nil {\n\t\t\treturn nil, \"\", errors.New(\"chain not allowed with an empty certificate\")\n\t\t}\n\n\t\t// The exact number is arbitrary, the fact that a cap exists isn't.\n\t\tconst maxChainLength = 10\n\t\tif len(co.GetChain()) > maxChainLength {\n\t\t\treturn nil, \"chain\", fmt.Errorf(\n\t\t\t\t\"certificate chain has too many entries (%d > %d)\", len(co.GetChain()), maxChainLength)","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/subca/parsed.go#L239-L275","documentation":"A disabled certificate override must still identify what it disables. validateCertificateOverride requires that if co.Disabled is true, at least one of PublicKey or Certificate is set; otherwise it cannot pin which key/certificate is being disabled and returns this error.","triggerScenarios":"Creating/updating a SubCA certificate override with disabled: true but neither certificate nor public_key populated, reaching the switch in validateCertificateOverride.","commonSituations":"Disabling an override by only setting disabled:true while clearing the key fields; template-generated specs where the key material got stripped.","solutions":["Include the certificate or public key of the CA being disabled along with disabled: true","If you meant to remove the override entirely, delete the override resource instead of disabling an empty one"],"exampleFix":"// before\noverride:\n  disabled: true\n// after\noverride:\n  disabled: true\n  public_key: |\n    -----BEGIN PUBLIC KEY-----\n    ...\n    -----END PUBLIC KEY-----","handlingStrategy":"validation","validationCode":"if override.GetDisabled() && override.GetCertificate() == \"\" && override.GetPublicKey() == \"\" {\n    return trace.BadParameter(\"disabled override still requires certificate or public_key\")\n}","typeGuard":"func isCompleteDisabledOverride(o *subcav1.CertificateOverride) bool {\n    return o != nil && o.GetDisabled() && (o.GetCertificate() != \"\" || o.GetPublicKey() != \"\")\n}","tryCatchPattern":"if _, _, err := ValidateAndParseCAOverride(clusterName, co); err != nil {\n    if strings.Contains(err.Error(), \"certificate or public key required\") {\n        return trace.BadParameter(\"set certificate or public_key on the disabled override\")\n    }\n    return trace.Wrap(err)\n}","preventionTips":["When disabling an override, keep the key/certificate fields populated","Delete the override entirely if it should no longer exist","Lint SubCA specs for disabled overrides missing key material"],"tags":["subca","validation","config"],"backgroundTag":"certificate-override-required-field","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}