Skip to content

cert-manager private-key handling

cmp-issuer integrates with cert-manager external issuers. Private-key access depends on the selected CMP operation.

P10CR: no workload private-key access

For P10CR initial enrollment cert-manager signs a PKCS #10 CSR with the workload private key and passes only the CSR bytes to the external issuer.

cmp-issuer:

  • Forwards the signed CSR in P10CR
  • Never reads the workload private key
  • Never reads cert-manager's staging private-key Secret
  • Does not interpret cert-manager.io/private-key-secret-name

The end-to-end suite covers this boundary: a crafted annotation pointing at a sentinel Secret leaves that Secret unchanged while enrollment still succeeds.

RBAC reinforces the boundary. The controller ClusterRole grants no default Secret read access in workload namespaces. Only explicitly authorized issuer credential namespaces are readable.

IR: one narrowly authorized key proof

IR reads the staged requested key only after it authenticates cert-manager's ownership chain. It validates the exact controlling Certificate name and UID, revision one with no earlier revision in Certificate.status, issuer reference, status.nextPrivateKeySecretName, staged Secret owner and next-key label, CSR signature and public-key equality.

A later revision uses IR only as a renewal fallback under renewalFallback: InitialEnrollment. It then requires the immediately previous revision in Certificate.status, as KUR does. Before it falls back, the controller reads the current output Secret once and parses only its tls.crt to find the certificate missing or expired. See Missing or expired current certificate.

The staged key signs CRMF proof of possession. The issuer's own credentials protect the CMP message, so IR reads no other workload key. Only tls.key is parsed from the staged Secret. Its UID and a digest of tls.key are bound into the durable transaction configuration digest.

KUR: two narrowly authorized key proofs

KUR reads the current workload key and the staged requested key only after it authenticates cert-manager's ownership chain. It validates the exact controlling Certificate name and UID, immediately previous revision, issuer reference, current output Secret, status.nextPrivateKeySecretName, staged Secret owner and next-key label, CSR signature and public-key equality.

The current output Secret is accepted only when cert-manager's cert-manager.io/certificate-name annotation names the owning Certificate, and a controller owner reference on it must name that same Certificate. cert-manager sets the annotation on every issuance and adds the owner reference only with --enable-certificate-owner-ref.

The current key protects the CMP message with the certificate being updated. The requested key signs CRMF proof of possession. With rotationPolicy: Never both roles can use the same key material.

Only tls.key is parsed from the staged Secret. The current Secret contributes tls.crt and tls.key. Each Secret's UID and a digest of exactly those data keys are bound into the durable transaction configuration digest, so a change to the key material stops an unfinished transaction while a metadata-only write does not.

Annotation is not authorization

cert-manager.io/private-key-secret-name names where cert-manager stores the workload key. It is not permission for the external issuer to read that Secret. cmp-issuer uses it only after the value matches the authenticated Certificate.status.nextPrivateKeySecretName and the Secret's owner and label.