The EJBCA Issuer for cert-manager is a CertificateRequest controller that issues certificates using EJBCA.
In the Keyfactor Community, we welcome contributions. Keyfactor Community software is open-source and community-supported, meaning that no SLA is applicable. Keyfactor will address issues as resources become available.
- To report a problem or suggest a new feature, go to Issues.
- If you want to contribute bug fixes or proposed enhancements, see the Contributing Guidelines and create a Pull request.
Commercial support is available for EJBCA Enterprise.
Before starting, ensure that the following requirements are met:
- Supported version of EJBCA Community or EJBCA Enterprise
- EJBCA must be properly configured according to the product docs.
- The "REST Certificate Management" protocol must be enabled under System Configuration > Protocol Configuration. The following endpoints must be available:
/ejbca/ejbca-rest-api/v1/certificate/pkcs10enroll/ejbca/ejbca-rest-api/v1/certificate/status
- Kubernetes >= v1.19
- Kubernetes, Minikube, Kind, etc.
You must have permission to create Custom Resource Definitions in your Kubernetes cluster.
- Supported cert-manager release installed in your cluster. Please see the cert-manager installation for details.
- Supported version of Helm for your Kubernetes version
EJBCA Issuer enrolls certificates by creating or updating an End Entity via the PKCS10 Enroll REST request. Before using EJBCA Issuer, you must create or identify an End Entity Profile and a Certificate Profile suitable for your usecase.
-
Create or identify a Certificate Profile
Certificate Profiles in EJBCA define the properties and constraints of the certificates being issued. This includes settings like key usage, extended key usage, validity period, allowed key algorithms, and signature algorithms.
- If you haven't created a Certificate Profile before, this guide walks you through how to create a Certificate Profile in the EJBCA AdminWeb.
You should make careful note of the allowed Key Types and Key Sizes on the Certificate Profile. When creating cert-manager Certificates, you must make sure that the key
algorithmandsizeare allowed by your Certificate Profile in EJBCA. -
Create or identify an End Entity Profile
End Entity Profiles in EJBCA define the rules for managing certificate requesters (end entities) and their associated data. They define which fields are required, optional, or hidden during the certificate enrollment process (e.g., common name, email, organization, SANs). End Entity Profiles control the type of information that end entities must provide and how that information is validated before issuing certificates.
- If you haven't created an End Entity Profile before, this guide walks you through how to create an End Entity Profile in the EJBCA AdminWeb.
You should make careful note of the Subject DN Attributes and Other Subject Attributes specified by your End Entity Profile. When creating cert-manager Certificates, you must make sure that the
subject,commonName,dnsNames, etc. are allowed and/or configured correctly by your End Entity Profile in EJBCA. -
Configure EJBCA Roles and Access Rules
Roles define groups of users or administrators with specific permissions. In EJBCA, users and administrators are identified by being members of a particular role. Access Rules are permissions that dictate what actions a role can perform and what parts of the system it can interact with.
- If you haven't created Roles and Access rules before, this guide provides a primer on these concepts in EJCBA.
If your security policy requires fine-grain access control, EJBCA Issuer requires the following Access Rules.
Regular Access Rules Permission /ra_functionality/approve_end_entity/Allow /ra_functionality/create_end_entity/Allow /ra_functionality/edit_end_entity/Allow CA Access Rules Permission /ca/<your CA name>/Allow End Entity Profile Access Rules Permission /endentityprofilesrules/<your End Entity Profile Name>/Allow
EJBCA Issuer is installed using a Helm chart. The chart is available in the EJBCA cert-manager Helm repository.
-
Verify that at least one Kubernetes node is running
kubectl get nodes
-
Add the Helm repository:
helm repo add ejbca-issuer https://keyfactor.github.io/ejbca-cert-manager-issuer helm repo update
-
Then, install the chart:
helm install ejbca-cert-manager-issuer ejbca-issuer/ejbca-cert-manager-issuer \ --namespace ejbca-issuer-system \ --create-namespace \ # --set image.pullPolicy=Never # Only required if using a local image
The Helm chart installs the EJBCA Issuer CRDs by default. The CRDs can be installed manually with the
make installtarget.
EJBCA Issuer supports authentication to EJBCA using mTLS (client certificate & key) or the OAuth 2.0 "client credentials" token flow (sometimes called two-legged OAuth 2.0).
Credentials must be configured using a Kubernetes Secret. By default, the secret is expected to exist in the same namespace as the issuer controller (ejbca-issuer-system by default).
EJBCA Issuer can read secrets in the Issuer namespace if
--set "secretConfig.useClusterRoleForSecretAccess=true"flag is set when installing the Helm chart.
Create a K8s TLS secret containing the client certificate and key to authenticate with EJBCA:
kubectl -n ejbca-issuer-system create secret tls ejbca-secret --cert=client.crt --key=client.keyCreate an Opaque secret containing the client ID and client secret to authenticate with EJBCA:
token_url="<token url>"
client_id="<client id>"
client_secret="<client secret>"
audience="<audience>"
scopes="<scopes>" # comma separated list of scopes
kubectl -n ejbca-issuer-system create secret generic ejbca-secret \
"--from-literal=tokenUrl=$token_url" \
"--from-literal=clientId=$client_id" \
"--from-literal=clientSecret=$client_secret" \
"--from-literal=audience=$audience" \
"--from-literal=scopes=$scopes"Audience and Scopes are optional
If the EJBCA API is configured to use a self-signed certificate or with a certificate that isn't publically trusted, the CA certificate must be provided as a Kubernetes secret.
kubectl -n ejbca-issuer-system create secret generic ejbca-ca-secret --from-file=ca.crtThe ejbca-issuer.keyfactor.com/v1alpha1 API version supports Issuer and ClusterIssuer resources. The Issuer resource is namespaced, while the ClusterIssuer resource is cluster-scoped.
For example, ClusterIssuer resources can be used to issue certificates for resources in multiple namespaces, whereas Issuer resources can only be used to issue certificates for resources in the same namespace.
-
Prepare the
specexport HOSTNAME="<hostname>" export EJBCA_CA_NAME="<certificateAuthorityName>" export CERTIFICATE_PROFILE_NAME="<certificateProfileName>" export END_ENTITY_PROFILE_NAME="<endEntityProfileName>"
The
specfield of both the Issuer and ClusterIssuer resources use the following fields:Field Name Description hostname The hostname of the EJBCA instance ejbcaSecretName The name of the Kubernetes secret containing the client certificate and key or OAuth 2.0 credentials certificateAuthorityName The name of the EJBCA certificate authority to use. For example, ManagementCAcertificateProfileName The name of the EJBCA certificate profile to use. For example, ENDUSERendEntityProfileName The name of the EJBCA end entity profile to use. For example, istiocaBundleSecretName The name of the Kubernetes secret containing the CA certificate. Optional, required if using a self-signed or untrusted root certificate endEntityName The name of the end entity to use. Optional. Refer to the EJBCA End Entity Name Configuration section for more details on how this field is used If a different combination of hostname/certificate authority/certificate profile/end entity profile is required, a new Issuer or ClusterIssuer resource must be created. Each resource instantiation represents a single configuration.
-
Create an Issuer or ClusterIssuer
-
Issuer
Create an Issuer resource using the environment variables prepared in step 1.
cat <<EOF > ./issuer.yaml apiVersion: ejbca-issuer.keyfactor.com/v1alpha1 kind: Issuer metadata: name: issuer-sample namespace: default spec: hostname: "$HOSTNAME" ejbcaSecretName: "ejbca-secret" # references the secret created above caBundleSecretName: "ejbca-ca-secret" # references the secret created above certificateAuthorityName: "$EJBCA_CA_NAME" certificateProfileName: "$CERTIFICATE_PROFILE_NAME" endEntityProfileName: "$END_ENTITY_PROFILE_NAME" endEntityName: "" EOF kubectl -n default apply -f issuer.yaml
-
ClusterIssuer
Create a ClusterIssuer resource using the environment variables prepared in step 1.
cat <<EOF > ./clusterissuer.yaml apiVersion: ejbca-issuer.keyfactor.com/v1alpha1 kind: ClusterIssuer metadata: name: clusterissuer-sample spec: hostname: "$HOSTNAME" ejbcaSecretName: "ejbca-secret" # references the secret created above caBundleSecretName: "ejbca-ca-secret" # references the secret created above certificateAuthorityName: "$EJBCA_CA_NAME" certificateProfileName: "$CERTIFICATE_PROFILE_NAME" endEntityProfileName: "$END_ENTITY_PROFILE_NAME" endEntityName: "" EOF kubectl apply -f clusterissuer.yaml
NOTE
The
endEntityNamefield in the Issuer and ClusterIssuer spec is described here -
Once an Issuer or ClusterIssuer resource is created, they can be used to issue certificates using cert-manager. The two most important concepts are Certificate and CertificateRequest resources.
Certificateresources represent a single X.509 certificate and its associated attributes. cert-manager maintains the corresponding certificate, including renewal when appropriate.- When
Certificateresources are created, cert-manager creates a correspondingCertificateRequestthat targets a specific Issuer or ClusterIssuer to actually issue the certificate.
To learn more about cert-manager, see the cert-manager documentation.
The following is an example of a Certificate resource. This resource will create a corresponding CertificateRequest resource, and will use the issuer-sample Issuer resource to issue the certificate. Once issued, the certificate will be stored in a Kubernetes secret named ejbca-certificate.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ejbca-certificate
spec:
issuerRef:
name: issuer-sample
group: ejbca-issuer.keyfactor.com
kind: Issuer
commonName: example.com
secretName: ejbca-certificateCertificate resources support many more fields than the above example. See the Certificate resource documentation for more information.
Similarly, a CertificateRequest resource can be created directly. The following is an example of a CertificateRequest resource.
apiVersion: cert-manager.io/v1
kind: CertificateRequest
metadata:
name: ejbca-certificate
spec:
issuerRef:
name: issuer-sample
group: ejbca-issuer.keyfactor.com
kind: Issuer
request: <csr>All fields in EJBCA Issuer and ClusterIssuer
speccan be overridden by applying Kubernetes Annotations to Certificates and CertificateRequests. See runtime customization for more
Unless the cert-manager internal approver automatically approves the request, newly created CertificateRequest resources
will be in a Pending state until they are approved. CertificateRequest resources can be approved manually by using
cmctl. The following is an example
of approving a CertificateRequest resource named ejbca-certificate in the ejbca-issuer-system namespace.
cmctl -n ejbca-issuer-system approve ejbca-certificateOnce a certificate request has been approved, the certificate will be issued and stored in the secret specified in the CertificateRequest resource. The following is an example of retrieving the certificate from the secret.
kubectl get secret ejbca-certificate -n ejbca-issuer-system -o jsonpath='{.data.tls\.crt}' | base64 -dTo learn more about certificate approval and RBAC configuration, see the cert-manager documentation.
For license information, see LICENSE.
See all Keyfactor EJBCA GitHub projects.