kubernetes/kops · error
failed to verify client certificate chain: %w
Error message
failed to verify client certificate chain: %w
What it means
AuthenticateClientToUniverse validates an mTLS client certificate against the universe's CA. The certificate chain verification via crypto/x509 Cert.Verify failed, so the client's certificate cannot be trusted as issued by the universe CA. The underlying x509 error (unknown authority, expired, etc.) is wrapped with %w.
Source
Thrown at discovery/pkg/discovery/auth.go:66
opts := x509.VerifyOptions{
Roots: x509.NewCertPool(),
Intermediates: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
for i := 1; i < len(peerCertificates); i++ {
if i == len(peerCertificates)-1 {
// Last cert is the root
opts.Roots.AddCert(peerCertificates[i])
} else {
opts.Intermediates.AddCert(peerCertificates[i])
}
}
chains, err := peerCertificates[0].Verify(opts)
if err != nil {
return nil, fmt.Errorf("failed to verify client certificate chain: %w", err)
}
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 {View on GitHub (pinned to 4c8573c808)
Solutions
- Regenerate the client certificate signed by the universe's CA.
- Ensure the client sends its full chain (leaf + intermediates) during the TLS handshake.
- Check certificate expiry (openssl x509 -noout -dates) and renew if expired.
- Confirm the server's trust pool (RootCAs in opts) contains the universe root CA that actually signed the client cert.
Example fix
// before: client presents only the leaf cert
conn cert = leaf
// after: client loads the full chain
tls.LoadX509KeyPair("client.crt", "client.key")
tlsConfig.Certificates[0] = tls.Certificate{Certificate: append([][]byte{leafDER}, intermediates...)} Defensive patterns
Strategy: validation
Validate before calling
// verify the client cert before presenting it
leaf, _ := x509.ParseCertificate(certDER)
opts := x509.VerifyOptions{Roots: universeCAPool, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}}
if _, err := leaf.Verify(opts); err != nil {
return fmt.Errorf("client cert will not verify against universe CA: %w", err)
} Type guard
func hasValidClientCert(leaf *x509.Certificate, roots *x509.CertPool) bool {
_, err := leaf.Verify(x509.VerifyOptions{Roots: roots, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}})
return err == nil
} Prevention
- Automate client cert rotation before expiry.
- Always load the full chain (leaf + intermediates) on the client side.
- Keep server trust pool in sync with the universe CA.
When it happens
Trigger: Calling AuthenticateClientToUniverse with a TLS peer whose leaf certificate fails x509.Verify: signed by an unknown CA, expired/not-yet-valid, wrong key usage, or intermediates not supplied in peerCertificates.
Common situations: Client presents a cert from a different universe/CA than the server trusts; expired client certificate; missing intermediate certs in the TLS handshake; incorrect RootCAs pool loaded in verification opts.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- error reading client keypair: %v
- no TLS connection
- no client certificate presented
- unable to build client-cert CA pools
- building kube client: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/91d74c24e35176b8.
Report an issue: GitHub.