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:
- Suported 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
algorithm
andsize
are 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 install
target.
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.key
Create 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.crt
The 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
spec
export HOSTNAME="<hostname>" export EJBCA_CA_NAME="<certificateAuthorityName>" export CERTIFICATE_PROFILE_NAME="<certificateProfileName>" export END_ENTITY_PROFILE_NAME="<endEntityProfileName>"
The
spec
field 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, ManagementCA
certificateProfileName The name of the EJBCA certificate profile to use. For example, ENDUSER
endEntityProfileName The name of the EJBCA end entity profile to use. For example, istio
caBundleSecretName 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
endEntityName
field 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.
Certificate
resources represent a single X.509 certificate and its associated attributes. cert-manager maintains the corresponding certificate, including renewal when appropriate.- When
Certificate
resources are created, cert-manager creates a correspondingCertificateRequest
that 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-certificate
Certificate 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
spec
can 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-certificate
Once 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 -d
To learn more about certificate approval and RBAC configuration, see the cert-manager documentation.
For license information, see LICENSE.
See all Keyfactor EJBCA GitHub projects.