gravitational/teleport · error

certificate or public key required

Error message

certificate or public key required

What it means

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.

Source

Thrown at lib/subca/parsed.go:257

		}
		wantPublicKey = HashCertificatePublicKey(cert)
	}

	// PublicKey.
	if co.GetPublicKey() != "" {
		if !certificateOverridePublicKeyRE.MatchString(co.GetPublicKey()) {
			return nil, "", errors.New("invalid public key")
		}
		if wantPublicKey != "" && NormalizePublicKey(co.GetPublicKey()) != wantPublicKey {
			return nil, "public_key", fmt.Errorf("certificate public key mismatch (want %q)", wantPublicKey)
		}
	}

	// Validate "required" fields now that we know both Certificate and PublicKey
	// are valid.
	switch {
	case co.GetDisabled() && co.GetPublicKey() == "" && co.GetCertificate() == "":
		return nil, "", errors.New("certificate or public key required")
	case co.GetDisabled():
		// OK, determined above to have either PublicKey or Certificate.
	case co.GetCertificate() == "":
		return nil, "", errors.New("certificate required")
	}

	// Chain.
	var chain []*x509.Certificate
	if len(co.GetChain()) > 0 {
		if cert == nil {
			return nil, "", errors.New("chain not allowed with an empty certificate")
		}

		// The exact number is arbitrary, the fact that a cap exists isn't.
		const maxChainLength = 10
		if len(co.GetChain()) > maxChainLength {
			return nil, "chain", fmt.Errorf(
				"certificate chain has too many entries (%d > %d)", len(co.GetChain()), maxChainLength)

View on GitHub (pinned to 1283425b60)

Solutions

  1. Include the certificate or public key of the CA being disabled along with disabled: true
  2. If you meant to remove the override entirely, delete the override resource instead of disabling an empty one

Example fix

// before
override:
  disabled: true
// after
override:
  disabled: true
  public_key: |
    -----BEGIN PUBLIC KEY-----
    ...
    -----END PUBLIC KEY-----
Defensive patterns

Strategy: validation

Validate before calling

if override.GetDisabled() && override.GetCertificate() == "" && override.GetPublicKey() == "" {
    return trace.BadParameter("disabled override still requires certificate or public_key")
}

Type guard

func isCompleteDisabledOverride(o *subcav1.CertificateOverride) bool {
    return o != nil && o.GetDisabled() && (o.GetCertificate() != "" || o.GetPublicKey() != "")
}

Try / catch

if _, _, err := ValidateAndParseCAOverride(clusterName, co); err != nil {
    if strings.Contains(err.Error(), "certificate or public key required") {
        return trace.BadParameter("set certificate or public_key on the disabled override")
    }
    return trace.Wrap(err)
}

Prevention

When it happens

Trigger: Creating/updating a SubCA certificate override with disabled: true but neither certificate nor public_key populated, reaching the switch in validateCertificateOverride.

Common situations: Disabling an override by only setting disabled:true while clearing the key fields; template-generated specs where the key material got stripped.

Understand the failure class

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/c6063b20b13df124. Report an issue: GitHub.