Renewal with P10CR or KUR¶
cert-manager decides when to renew a Certificate. cmp-issuer decides which CMP operation performs that renewal through spec.protocol.renewal.
spec:
endpoint:
url: https://ca.example.test/cmp/initial
renewalUrl: https://ca.example.test/cmp/key-update
protocol:
initialEnrollment: P10CR
renewal: KUR
renewalUrl is optional. Omit it when one CMP endpoint accepts both P10CR and KUR.
cert-manager renewal¶
When a Certificate nears expiry cert-manager creates a new CertificateRequest. Revision one uses initialEnrollment. Later revisions use renewal, which follows initialEnrollment when omitted: P10CR after P10CR and KUR after IR.
renewal |
CMP operation | Workload key access | Server requirement |
|---|---|---|---|
P10CR or omitted after P10CR |
Fresh P10CR | None | Repeat enrollment for the same identity |
KUR or omitted after IR |
Certificate-authenticated KUR | Current and staged keys | KUR enabled for the existing certificate |
P10CR compatibility renewal¶
P10CR is the default for compatibility. It was exercised against Nokia NCM 26.7 through cert-manager with both values of privateKey.rotationPolicy:
rotationPolicy |
What the renewal sends | Result |
|---|---|---|
Always |
A new key, so a new public key in the CSR | New certificate, new serial |
Never |
The existing key, so the same public key in the CSR | New certificate, new serial |
Each renewal is a new CMP transaction with a fresh identifier. It is not a retransmission of the earlier transaction. The controller reads no workload private key in this mode.
True KUR renewal¶
KUR proves two things before the server updates the certificate:
- The current valid certificate and private key protect the CMP message.
- The requested private key signs CRMF proof of possession.
The certificate template repeats the subject of the current certificate exactly as it is encoded there. For a certificate named only in its SANs, that subject is an empty name (NULL-DN), as RFC 9483 requires.
Each KUR also carries the recommended CRMF oldCertID control with the current certificate's exact issuer and serial number. This lets a server select the certificate being replaced even after repeated same-key updates have created several certificates for the same subject and public key.
With rotationPolicy: Always these are different keys. With rotationPolicy: Never the same key makes both proofs and the server profile must allow same-key update.
The keys may be RSA, ECDSA, Ed25519 or ML-DSA. An ML-DSA tls.key must be in the seed-only PKCS #8 form, see Known limitations.
cmp-issuer rejects KUR before network traffic when the current certificate is expired, its key does not match, its Key Usage extension forbids digital signatures, the staged key does not match the CSR or the subject or SAN values changed. The CA must reject a revoked current certificate.
A certificate originally issued through P10CR or IR can later be renewed through KUR. The enrollment request used for the old certificate does not change the KUR proof or oldCertID. Server policy still decides whether that certificate is eligible for key update.
With requestedValidity: Duration the KUR template also asks for a validity. See Requested validity.
The updated certificate must get a new validity. When the CA returns the notBefore and notAfter of the certificate being updated, cert-manager finds the renewal time already passed and renews again at once. cmp-issuer rejects such a certificate in certConf and fails the request. Configure the CA to compute a new validity on key update or use renewal: P10CR. NCM needs a policy setting for this, see Tested PKIs.
The selected operation is recorded before the first send and every retry uses the same operation and transaction identifier. A KUR that was sent never changes to another operation.
Missing or expired current certificate¶
KUR authenticates with the current certificate. It cannot do so after the Certificate Secret was deleted or emptied or after renewals kept failing until the certificate expired. By default the request then fails:
| Current certificate | Result with renewalFallback: None |
|---|---|
Secret deleted or without tls.crt |
Permanent failure that names the Secret and the ways to recover |
| Expired | Permanent badTime failure before any CMP traffic |
Set renewalFallback: InitialEnrollment to renew with the initialEnrollment operation instead:
spec:
protocol:
initialEnrollment: IR
renewalFallback: InitialEnrollment
An IR issuer then renews with IR. An issuer with initialEnrollment: P10CR and renewal: KUR renews with P10CR. The fallback goes to endpoint.url rather than renewalUrl and the issuer credentials protect it. The CMP server must accept an initial enrollment for an identity that already holds a certificate. The old certificate is not revoked.
A Secret that exists falls back only when cert-manager wrote it for the Certificate, so its cert-manager.io/certificate-name annotation must name the Certificate. A Secret written by another tool fails as it does for KUR. A certificate that is not yet valid, does not match its key or no longer matches the CSR identity still renews with KUR and fails with the KUR error.
The choice is made once before the first CMP message. The CMPTransaction records the operation in spec.operation and the reason in spec.renewalFallback, which is CurrentCertificateMissing or CurrentCertificateExpired. A retry uses the recorded operation even when the certificate returns. A transaction that started as KUR never falls back, so a certificate that expires during an unfinished KUR does not change the operation. The controller logs the fallback and records a RenewalFallback Warning Event on the CertificateRequest:
kubectl describe certificaterequest <name> -n <namespace>
Without the fallback, set renewal: P10CR or delete and recreate the Certificate, whose first revision uses initialEnrollment.
Response validation profiles¶
spec.protocol.validationProfile defaults to Interoperable. This accepts KUP caPubs because CMP
servers including EJBCA and Nokia NCM can legitimately be configured to deliver CA certificates there.
Those certificates are untrusted chain candidates only. They cannot add a trust root and the issued
chain must still terminate at spec.cmpTrust.
Use the RFC 9483 receiver rules for the implemented operations with:
spec:
protocol:
validationProfile: RFC9483
This pins P10CR CP certReqId to -1, requires MAC-based responses throughout a MAC-protected
operation and requires KUP caPubs absent. Tested NCM and EJBCA versions return P10CR certReqId 0,
so the complete profile rejects their initial enrollment behavior. Use the default profile with a
focused setting when only one rule is required:
spec:
protocol:
kurResponseCaPubs: RequireAbsent
The focused values are kurResponseCaPubs: Accept | RequireAbsent,
macResponseProtection: AllowSignature | Strict and p10crResponseCertReqId: -1 | 0.
Both profiles accept responses signed by a configured trust anchor when the server omits its
certificate from extraCerts. The RFC9483 profile does not enforce the first-response certificate
presence rule. See message protection.
Workload Secret authorization¶
KUR does not trust cert-manager.io/private-key-secret-name by itself. Before reading either key cmp-issuer verifies the controlling Certificate, owner UID, immediately previous revision, issuer reference, current output Secret, status.nextPrivateKeySecretName, staged Secret owner and label, CSR signature and public-key equality.
The current output Secret must carry cert-manager's cert-manager.io/certificate-name annotation naming the owning Certificate. cert-manager writes it whenever it stores an issued certificate. A Secret controlled by a different Certificate is refused, which matters when cert-manager runs with --enable-certificate-owner-ref.
The current and staged Secret UIDs and a digest of their consumed key material are included in the transaction configuration digest. Key rotation during an unfinished KUR stops it before more CMP traffic. A metadata-only write to either Secret leaves the transaction valid.
See Private-key handling and Credential Secret access.
Nokia NCM REST renewal¶
Some Nokia deployments expose certificate renewal through NCM REST APIs. That path is unrelated to CMP KUR and is unsupported by cmp-issuer.
Support matrix¶
| Operation | Status |
|---|---|
| P10CR initial enrollment | Implemented |
| P10CR re-enrollment | Server dependent. Verified against NCM 26.7 for both rotation policies |
| KUR | Implemented for unchanged subject and SANs. Verified against NCM 26.7, EJBCA 9.3.7 and OpenSSL 3.6.3 with both rotation policies |
| IR initial enrollment | Implemented. Verified against NCM 26.7, EJBCA 9.3.7 and OpenSSL 3.6.5 with both protection modes. NCM and EJBCA renewed the IR certificate through KUR |
Renewal fallback to initialEnrollment |
Implemented. Verified after the Certificate Secret was deleted with IR and P10CR against NCM 26.7 and with IR against EJBCA 9.3.7 in RA mode |
| Nokia NCM REST renewal | Unsupported |
See Tested PKIs for server-specific validation and configuration.