EJBCA Certificate Operations Using CMP

CMP automates certificate lifecycle management. EJBCA uses CMP aliases to associate enrollment parameters with a specific CA, certificate profile, and end entity profile.

This section shows how to use OpenSSL’s CMP client to enroll, renew, revoke, and check the status of certificates through an EJBCA CMP endpoint.

CMP uses two independent authentication layers:

  • TLS layer — The system-local-ca.pem file acts as the TLS trust anchor that verifies the EJBCA HTTPS endpoint. For mTLS authentication with the EJBCA service, you must provide the Super Administrator client certificate and private key.

  • CMP layer — Initial enrollment (ir) and RA-mode renewal use an HMAC shared secret for authentication. Key update requests (kur) use signature-based authentication with an existing certificate and private key.

Prerequisites

Before you begin, ensure the following are available:

  • A CMP alias configured in EJBCA (see EJBCA CLI Operations).

  • A certificate profile and end entity profile associated with the alias.

  • The HMAC shared secret configured for the alias.

  • OpenSSL 3.0+ with CMP support.

  • The system-local-ca.pem certificate for TLS verification.

  • The superadmin client certificate and key for mTLS authentication with the EJBCA service (the httpd proxy). See Export Superadmin Credentials.

  • Environment variables set for the EJBCA hostname, CMP alias, and credentials. See Environment Setup.

Export Superadmin Credentials

Export the superadmin certificate and key from the platform to your local machine:

~(keystone_admin)]$ kubectl get secret -n ejbca ejbca-superadmin-cert \
    -o jsonpath='{.data.tls\.crt}' | base64 -d > superadmin.crt.pem
~(keystone_admin)]$ kubectl get secret -n ejbca ejbca-superadmin-cert \
    -o jsonpath='{.data.tls\.key}' | base64 -d > superadmin.key.pem

Environment Setup

Set the following environment variables before running the commands in this topic:

$ export EJBCA_HOSTNAME="ejbca.example.com:7443"
$ export CMP_ALIAS="cmp-test-alias"
$ export CMP_HMAC_SECRET="changeit"
$ export CA_NAME="test-ca"
$ export SUPERADMIN_CERT="./superadmin.crt.pem"
$ export SUPERADMIN_KEY="./superadmin.key.pem"

Enroll a Certificate

Generate a key pair and CSR using the following commands, then enroll the certificate through a CMP initial request (ir):

$ export CERT="${CA_NAME}-cert"
$ export CERT_CN="${CA_NAME}-cert"
$ export KEY_FILE="${CERT}.key.pem"
$ export CSR_FILE="${CERT}.csr.pem"
$ export CERT_FILE="${CERT}.cert.pem"
$ export CA_FILE="${CA_NAME}.cert.pem"

# Generate private key
$ openssl genrsa -out ${KEY_FILE} 4096

# Generate CSR with SAN
$ openssl req -new -key ${KEY_FILE} \
    -subj "/CN=${CERT_CN}" \
    -addext "subjectAltName=DNS:${CERT_CN}" \
    -out "${CSR_FILE}"

# Enroll via CMP
$ openssl cmp -cmd ir \
    -server ${EJBCA_HOSTNAME} \
    -path /ejbca/publicweb/cmp/${CMP_ALIAS} \
    -tls_used \
    -tls_trusted ./system-local-ca.pem \
    -tls_cert ${SUPERADMIN_CERT} \
    -tls_key ${SUPERADMIN_KEY} \
    -ref "${CMP_ALIAS}" \
    -secret pass:${CMP_HMAC_SECRET} \
    -subject "/CN=${CERT_CN}" \
    -recipient "/CN=${CA_NAME}" \
    -newkey "${KEY_FILE}" \
    -csr "${CSR_FILE}" \
    -certout "${CERT_FILE}" \
    -cacertsout "${CA_FILE}"

Note

Both -csr and -newkey are required: the CSR provides subject and extensions, while -newkey provides the private key for Proof of Possession (POPO).

The -ref parameter is the CMP alias name (used as senderKID for HMAC lookup). The -recipient specifies the DN of the issuing CA.

Renew a Certificate

To renew a certificate, generate a new key pair and CSR, and then submit a new RA mode ir (initial request) using HMAC authentication. Use the same enrollment procedure that you used for the initial certificate request. EJBCA issues a new certificate for the same subject and does not require the existing certificate or private key.

Note

A true CMP key update (kur) uses signature-based authentication with the existing certificate and private key. You cannot authenticate a kur request with HMAC. The ir-based renewal method shown here provides a simpler alternative for RA mode deployments that use an HMAC shared secret.

# Generate new key and CSR
$ openssl genrsa -out ${CERT}-renewed.key.pem 4096
$ openssl req -new -key ${CERT}-renewed.key.pem \
    -subj "/CN=${CERT_CN}" \
    -addext "subjectAltName=DNS:${CERT_CN}" \
    -out "${CERT}-renewed.csr.pem"

# Re-enroll via CMP ir (same as initial enrollment)
$ openssl cmp -cmd ir \
    -server ${EJBCA_HOSTNAME} \
    -path /ejbca/publicweb/cmp/${CMP_ALIAS} \
    -tls_used \
    -tls_trusted ./system-local-ca.pem \
    -tls_cert ${SUPERADMIN_CERT} \
    -tls_key ${SUPERADMIN_KEY} \
    -ref "${CMP_ALIAS}" \
    -secret pass:${CMP_HMAC_SECRET} \
    -subject "/CN=${CERT_CN}" \
    -recipient "/CN=${CA_NAME}" \
    -newkey "${CERT}-renewed.key.pem" \
    -csr "${CERT}-renewed.csr.pem" \
    -certout "${CERT}-renewed.cert.pem" \
    -cacertsout "${CA_FILE}"

Revoke a Certificate

To revoke a certificate, submit a CMP revocation request (rr) using the ${CERT_FILE} certificate file generated during enrollment.

$ openssl cmp -cmd rr \
    -server ${EJBCA_HOSTNAME} \
    -path /ejbca/publicweb/cmp/${CMP_ALIAS} \
    -tls_used \
    -tls_trusted ./system-local-ca.pem \
    -tls_cert ${SUPERADMIN_CERT} \
    -tls_key ${SUPERADMIN_KEY} \
    -ref "${CMP_ALIAS}" \
    -secret pass:${CMP_HMAC_SECRET} \
    -recipient "/CN=${CA_NAME}" \
    -oldcert "${CERT_FILE}" \
    -revreason 0 \
    -unprotected_errors

The supported revocation reasons are:

  • 0 — unspecified

  • 1 — keyCompromise

  • 3 — affiliationChanged

  • 4 — superseded

  • 5 — cessationOfOperation

Note

Use the -unprotected_errors flag to display the actual error messages. Without this flag, EJBCA may return signature-protected error responses that you cannot verify without a trust anchor.

Check Certificate Status

To verify the status of an issued or revoked certificate, query the EJBCA OCSP responder:

$ openssl ocsp \
    -issuer ${CA_FILE} \
    -cert ${CERT_FILE} \
    -url https://${EJBCA_HOSTNAME}/ejbca/publicweb/status/ocsp \
    -CAfile ${CA_FILE} \
    -verify_other ${CA_FILE}

Note

For the complete CMP protocol reference, see: https://docs.keyfactor.com/ejbca/latest/protocols/ejbca-cmp

Related Information