kubernetes/kops · error
client certificate chain does not match universe ID
Error message
client certificate chain does not match universe ID
What it means
After the cert chain verifies cryptographically, AuthenticateClientToUniverse requires the universe ID to match at least one certificate in the verified chain (typically the root CA). No chain contained a certificate whose identity equals the universe ID, so the client is not a member of this universe and authentication is rejected.
Source
Thrown at discovery/pkg/discovery/auth.go:85
}
verifiedChains = chains
}
// The universe ID must match at least one of the certificates in the chain (typically the root CA).
var matchingChain []*x509.Certificate
for _, verifiedChain := range verifiedChains {
for _, cert := range verifiedChain {
hash := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
calculatedUniverseID := hex.EncodeToString(hash[:])
if calculatedUniverseID == universeID {
matchingChain = verifiedChain
break
}
}
}
if matchingChain == nil {
return nil, fmt.Errorf("client certificate chain does not match universe ID")
}
clientID := matchingChain[0].Subject.CommonName
if clientID == "" {
return nil, fmt.Errorf("client certificate missing Common Name")
}
return &UserInfo{
UniverseID: universeID,
ClientID: clientID,
}, nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Issue the client a certificate signed by the CA whose identity (subject) matches the target universeID.
- Verify the universeID passed to AuthenticateClientToUniverse matches the universe the cert was issued for.
- Re-provision or re-issue client credentials after a universe/cluster rebuild so the root CA matches.
Example fix
// before: cert from universe-a presented to universe-b AuthenticateClientToUniverse(ctx, universeBID, tlsConn) // after: use credentials issued for the target universe AuthenticateClientToUniverse(ctx, universeBID, connWithUniverseBCert)
Defensive patterns
Strategy: validation
Validate before calling
func certMatchesUniverse(chain []*x509.Certificate, universeID string) bool {
for _, c := range chain {
if c.Subject.CommonName == universeID || c.Subject.Organization[0] == universeID {
return true
}
}
return false
}
// call before authenticating
if !certMatchesUniverse(peerCertificates, universeID) { /* reject early */ } Type guard
func isUniverseCert(cert *x509.Certificate, universeID string) bool {
return cert != nil && (cert.Subject.CommonName == universeID || slices.Contains(cert.Subject.Organization, universeID))
} Prevention
- Store per-universe credential bundles separately and load the one matching the target universe.
- Regenerate credentials after any universe/cluster rebuild.
- Log the cert issuer/subject on auth failure for fast diagnosis.
When it happens
Trigger: Calling AuthenticateClientToUniverse with a certificate chain that verifies against a valid CA but whose chain contains no certificate matching the expected universeID (e.g. wrong universe's cert presented).
Common situations: Client configured with credentials from a different cluster/universe; server's expected universeID changed after a re-provision; stale or copied kubeconfig/cert bundle pointing at another universe.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- client certificate missing Common Name
- reading %q certificate: %v
- error issuing certificate: %v
- error reading user provided cert %q: %v
- error loading certificate %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/8142c9879e03cd8c.
Report an issue: GitHub.