Enrollment¶
Initial enrollment sends a protected P10CR with cert-manager's signed PKCS #10 CSR or a protected IR with a CRMF request built from that CSR. It completes when the server returns a validated CP or IP.
Flow¶
sequenceDiagram
participant CM as cert-manager
participant CI as cmp-issuer
participant CA as CMP server
CM->>CI: CertificateRequest with CSR
CI->>CA: protected P10CR or IR
CA->>CI: protected CP or IP
CI->>CA: protected certConf
CA->>CI: protected pkiConf
CI->>CM: issued certificate chain
When the server grants implicit confirmation the certConf / pkiConf exchange may be omitted.
Prerequisites¶
- cert-manager installed and approving requests
- cmp-issuer controller Ready
- Issuer credential and CMP trust Secrets readable
- For
CMPIssuer: the issuer namespace authorized for credential reads, see Credential Secret access - CMP server profile allowing P10CR or IR with the chosen protection mode
Configure the issuer¶
See CMPIssuer or CMPClusterIssuer. Set protocol.initialEnrollment to P10CR or IR.
initialEnrollment |
Request | Workload key access |
|---|---|---|
P10CR |
cert-manager's signed CSR | None |
IR |
CRMF template with the CSR subject, public key and extensions. The staged private key signs proof of possession | The staged key of the Certificate |
IR builds its proof of possession with the private key cert-manager staged for revision one of a Certificate, so it needs a CertificateRequest that cert-manager created for that Certificate. A hand-written CertificateRequest fails before any CMP traffic. The issuer's own credentials protect the IR message, as they protect a P10CR. See Private-key handling.
An issuer that enrolls with IR renews with KUR unless protocol.renewal says otherwise. See Renewal with P10CR or KUR.
Request a certificate¶
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: workload-tls
spec:
secretName: workload-tls
issuerRef:
name: my-cmp-issuer
kind: CMPIssuer
group: certmanager.misiektoja.github.io
commonName: workload.example.com
dnsNames:
- workload.example.com
cert-manager creates a CertificateRequest. cmp-issuer reconciles it after approval. For ML-DSA, check the build requirements and key usages.
Inspect progress¶
kubectl describe certificaterequest <name>
kubectl get cmptransactions -n <namespace>
kubectl describe cmptransaction <name>
A CMPTransaction appears as soon as an enrollment starts and reports Enrolling, Polling, Confirming or Issued. It records the enrolled CSR digest, the issuer that served it and, once the server answers, the validated chain. It is removed with the CertificateRequest that owns it.
The controller log carries the same lifecycle as text. Each enrollment ends in one line naming the issuer, the endpoint, the CMP transaction and the issued certificate, and each wait, resumption and failure is logged as it happens. See reading the controller log.
Requested validity¶
By default the CA chooses the validity of the certificate. With protocol.requestedValidity: Duration an IR or KUR asks for a notAfter of the transaction start plus the CertificateRequest spec.duration, which cert-manager copies from Certificate.spec.duration. A request without a duration asks for no validity.
spec:
protocol:
initialEnrollment: IR
requestedValidity: Duration
The CA decides the validity it grants and may shorten or ignore the request. A CA that replaces the requested validity may answer grantedWithMods, which fails the request under the default policy.grantedModifications: Reject. A PKCS #10 request cannot carry a validity, so P10CR never asks for one and Duration needs initialEnrollment: IR or renewal: KUR. See how the tested servers answer.
P10CR certReqId¶
RFC 9810 and RFC 9483 require certReqId -1 in P10CR CP responses. Tested servers may return 0. By default cmp-issuer accepts either value and echoes it in certConf. Pin a value with spec.protocol.p10crResponseCertReqId when needed.
Confirmation hash¶
The certConf hash follows the issued certificate's signature algorithm. For a certificate signed with ML-DSA, certConf names SHA-512 in hashAlg, which RFC 9810 section 5.3.18 allows only in CMPv3, so that certConf is sent as CMPv3. A CMPv2 or CMPv3 answer to it is accepted.
Granted modifications¶
When spec.policy.grantedModifications is Reject, certificates issued with grantedWithMods fail. Unless the server granted implicit confirmation, cmp-issuer also rejects them in certConf. Set Accept only when server-side field changes are expected and acceptable.
Asynchronous enrollment¶
Servers that answer waiting trigger polling until a certificate arrives or limits expire. See Transaction recovery.