EJBCA Integration with Kubernetes cert-manager

The ejbca-cert-manager-issuer integrates EJBCA with Kubernetes cert-manager, enabling EJBCA to automatically issue and renew certificates using standard cert-manager Certificate resources.

EJBCA cert-manager Resources

The app-ejbca deployment automatically installs the supporting resources needed for cert-manager integration:

  • ejbca-cert-manager-issuer — the issuer controller

  • cert-manager-approver-policy — the policy controller

  • A CertificateRequestPolicy (approve-ejbca-issuer) — approval policy

  • ClusterRoles and ClusterRoleBindings:

    • cert-manager-approver-policy — The base role/role binding for the approver-policy controller to evaluate CertificateRequests against policy rules

    • cert-manager-approver-policy:ejbca — The EJBCA-specific role/role binding granting the controller permissions to read EJBCA CRDs (EJBCAIssuer, EJBCAClusterIssuer) during evaluation

    • cert-manager-policy:ejbca — The EJBCA-specific role/role binding granting the requester cert-manager SA permission to “use” the approve-ejbca-issuer policy

  • CA bundle secret (ejbca-ca-bundle) — contains the system-local-ca bundle for the issuer to verify the EJBCA HTTPS endpoint

  • ejbca-superadmin-cert secret — contains the superadmin’s certificate and key that the issuer (and Admin GUI, CMP, REST API) uses for client authentication to the EJBCA service

Prerequisites

Before creating certificates, ensure the CA, certificate profile, and end entity profile exist in EJBCA. If they do not exist, create them using the CLI or Admin GUI. See EJBCA CLI Operations or EJBCA Admin GUI Access and Operations.

Create an EJBCA ClusterIssuer

To create a ClusterIssuer that connects to your EJBCA instance, complete the following steps:

  1. Set environment variables:

    $ export CA_NAME="test-ca"
    $ export CERT_PROFILE="test-cert-profile"
    $ export EE_PROFILE="test-entity-profile"
    $ export SVC_HOST="ejbca-httpd.ejbca.svc.cluster.local:443"
    
  2. Create the ClusterIssuer resource:

    $ cat > ejbca-clusterissuer.yaml << EOF
    apiVersion: ejbca-issuer.keyfactor.com/v1alpha1
    kind: ClusterIssuer
    metadata:
      name: ejbca-issuer
    spec:
      # Must match the internal service hostname
      hostname: "ejbca-httpd.ejbca.svc.cluster.local:443"
    
      # CA configuration (must match |EJBCA| setup)
      certificateAuthorityName: "${CA_NAME}"
      certificateProfileName: "${CERT_PROFILE}"
      endEntityProfileName: "${EE_PROFILE}"
    
      # Client certificate for |mTLS| authentication
      ejbcaSecretName: "ejbca-superadmin-cert"
    
      # CA bundle to trust |EJBCA| HTTPS endpoint
      caBundleSecretName: "ejbca-ca-bundle"
    
      # End entity naming strategy
      endEntityName: "cn"
    EOF
    
  3. Apply and verify:

    ~(keystone_admin)]$ kubectl apply -f ejbca-clusterissuer.yaml
    ~(keystone_admin)]$ kubectl get clusterissuers.ejbca-issuer.keyfactor.com
    

Issue a Certificate with EJBCA ClusterIssuer

To issue a certificate using the ClusterIssuer, do the following:

  1. Create a cert-manager Certificate resource:

    $ cat > test-certificate.yaml << EOF
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: test-ejbca-cert
      namespace: default
    spec:
      secretName: test-ejbca-cert
      commonName: test.example.com
      dnsNames:
        - test.example.com
      privateKey:
        algorithm: RSA
        size: 4096
      duration: 8760h    # 1 year
      renewBefore: 720h  # 30 days before expiry
      issuerRef:
        name: ejbca-issuer
        kind: ClusterIssuer
        group: ejbca-issuer.keyfactor.com
    EOF
    

    Important

    The privateKey.size must match the allowed key lengths in the EJBCA certificate profile. If the profile only allows 4096-bit keys, requesting 2048-bit (cert-manager’s default) will fail with: “Illegal key length, not authorized by certificate profile: 2048”

  2. Apply the Certificate resource and verify that it was issued and the certificate secret was created:

    ~(keystone_admin)]$ kubectl apply -f test-certificate.yaml
    ~(keystone_admin)]$ kubectl get certificate test-ejbca-cert
    ~(keystone_admin)]$ kubectl get secret test-ejbca-cert
    

Renew a Certificate Using EJBCA ClusterIssuer

cert-manager handles renewal automatically based on the renewBefore field. To manually trigger renewal and confirm the certificate was renewed:

~(keystone_admin)]$ kubectl cert-manager renew test-ejbca-cert
~(keystone_admin)]$ kubectl get certificaterequest -o wide

Related Information