kubernetes/kops · critical

ca key for %q was not found; cannot issue certificates

Error message

ca key for %q was not found; cannot issue certificates

What it means

IssueCert looked up the signing CA via keystore.FindPrimaryKeypair and got a result whose private key is nil. Without the CA private key, kOps cannot sign new certificates, so it refuses rather than issuing a certificate it cannot sign.

Source

Thrown at pkg/pki/issue.go:126

			continue
		}
		if ip := net.ParseIP(san); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, san)
		}
	}

	var caPrivateKey *PrivateKey
	var signer *x509.Certificate
	if !template.IsCA {
		var err error
		caCertificate, caPrivateKey, err = keystore.FindPrimaryKeypair(ctx, request.Signer)
		if err != nil {
			return nil, nil, nil, err
		}
		if caPrivateKey == nil {
			return nil, nil, nil, fmt.Errorf("ca key for %q was not found; cannot issue certificates", request.Signer)
		}
		if caCertificate == nil {
			return nil, nil, nil, fmt.Errorf("ca certificate for %q was not found; cannot issue certificates", request.Signer)
		}
		signer = caCertificate.Certificate
	}

	privateKey := request.PrivateKey
	if request.PublicKey != nil {
		template.PublicKey = request.PublicKey
	} else if privateKey == nil {
		var err error
		privateKey, err = GeneratePrivateKey()
		if err != nil {
			return nil, nil, nil, err
		}
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Recreate or restore the CA keypair in the keystore (kops toolbox pki / re-run installPKI) so the private key exists.
  2. Restore the missing private key backing file in the state store keyset (e.g. under <cluster>/pki/private/...).
  3. Issue the certificate with a signer whose keypair is complete.
Defensive patterns

Strategy: validation

Validate before calling

cert, key, err := keystore.FindPrimaryKeypair(ctx, signer)
if err != nil { return err }
if key == nil {
    return fmt.Errorf("CA %s private key missing; restore keyset first", signer)
}

Type guard

func caReady(kp *pki.Keypair) bool {
    return kp != nil && kp.Certificate != nil && kp.PrivateKey != nil
}

Try / catch

if err := installPKI(...); err != nil {
    if strings.Contains(err.Error(), "ca key for") {
        // recreate/restore CA keyset, then retry once
    }
    return err
}

Prevention

When it happens

Trigger: Requesting issuance with request.Signer set to a CA name (e.g. "kubernetes-ca") whose keyset contains a certificate but no private key — e.g. the CA keypair was never created, or only the public part was imported/restored.

Common situations: Restoring a cluster state store from a backup that omitted private keys, manually importing CA certs into the keyset, or issuing certificates before installPKI created the CA.

Understand the failure class

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/47afb9b590449ebf. Report an issue: GitHub.