Deploy EJBCA as CA with automation
ENTERPRISE
This outlines how to deploy a Certificate Authority (CA) using the EJBCA Enterprise configuration export/import tool EJBCA ConfigDump. The following sections provide examples of how to use Helm to create Certificate Authorities (CAs), configure roles, enable required protocols such as REST and OCSP, and customize ConfigDump-supported resources.
Prerequisites
Before you begin, you should be familiar with how to deploy EJBCA CA in Kubernetes.
EJBCA installation with ConfigDump import does not support replication during the installation stage. Instead, use helm install
with ConfigDump and replicaCount: 1
. After installation, perform a helm upgrade
to the desired replicaCount
.
Prepare database and credentials
Prepare a database in Kubernetes or externally.
Create secrets containing the username and password.
Configure these essential values in values.yaml:
The database URL
The database credential secrets
Ingress URL
Prepare configuration dump
ConfigDump objects used in the following examples were created using the EJBCA ConfigDump REST Interface. The provided samples will demonstrate how to initialize an EJBCA instance with:
Crypto Tokens: Two soft crypto tokens with authentication codes provided using Kubernetes secrets.
Certification Authorities (CAs): Two CAs created using supplied subjectDN, validity, etc.
End Entity Profile: An End Entity Profile for issuing server certificates with up to four DNS Names.
Roles and Role Members: Roles used for certificate authentication with CN (common name) SuperAdmin and AutomationAdmin.
Protocols: Configuration that enables REST, ACME and other protocols.
Separate confidential data and create Kubernetes secrets
Sensitive data in ConfigDump exports can be replaced with references to Kubernetes Secret keys.
For example, given a configuration dump snippet with an Authentication Code supperSecretPassword
:
"crypto-tokens": {
"ManagementCA": {
"Object Type": "Crypto Token",
"Authentication Code": "supperSecretPassword",
...
}
}
You can first create a secret to store the Authentication Code using an arbitrary key, for example, AUTHENTICATION_CODE
:
kubectl create secret generic configdump-secrets \
--from-literal=AUTHENTICATION_CODE=supperSecretPassword
Then, reference this key in an inline or mounted ConfigDump file when deploying EJBCA:
"crypto-tokens": {
"ManagementCA": {
"Object Type": "Crypto Token",
"Authentication Code": "${AUTHENTICATION_CODE}",
...
}
}
Subsequent sections of this guide will use a Kubernetes secret with the following content:
kubectl create secret generic configdump-secrets \
--from-literal=CA_TOKEN_PASSWORD=foo123 \
--from-literal=PEER_TOKEN_PASSWORD=bar123
Prepare configuration dump as a Kubernetes ConfigMap
Prepare a Kubernetes ConfigMap with your EJBCA configuration files.
Example filename: ejbca-ca-init-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ejbca-ca-init-configmap
data:
after-deployed-pre.sh: |
#!/bin/bash
cd /opt/keyfactor
bin/ejbca.sh cryptotoken create --token CaToken001 --pin "$CA_TOKEN_PASSWORD" --autoactivate --type SoftCryptoToken
bin/ejbca.sh cryptotoken generatekey --token CaToken001 --alias signkey001 --keyspec 2048
bin/ejbca.sh cryptotoken generatekey --token CaToken001 --alias defaultkey001 --keyspec 2048 --key-usage SIGN_ENCRYPT
bin/ejbca.sh cryptotoken generatekey --token CaToken001 --alias signkey002 --keyspec 2048
bin/ejbca.sh cryptotoken generatekey --token CaToken001 --alias defaultkey002 --keyspec 2048 --key-usage SIGN_ENCRYPT
bin/ejbca.sh cryptotoken generatekey --token CaToken001 --alias testkey --keyspec 2048
echo "web.reqcert=false" >> /opt/keyfactor/ejbca/conf/web.properties
configdump.json: |
{
"crypto-tokens": {
"PeerToken": {
"Object Type": "Crypto Token",
"Version": 2,
"Name": "PeerToken",
"Used": true,
"Key Pair Info": [],
"Authentication Code": "${PEER_TOKEN_PASSWORD}",
"Type": "SoftCryptoToken",
"Active": true,
"Auto Activation": true
}
},
"certification-authorities": {
"ManagementCA": {
"Object Type": "Certification Authority",
"Version": 2,
"Name": "ManagementCA",
"Type of CA": "X.509",
"Serial Number Octet Size": 20,
"Pre-produce OCSP Responses": false,
"Microsoft CA Compatible Mode Used": false,
"Store responses on-demand": false,
"Pre-produce OCSP Responses Upon certificate issuance/revocation": false,
"Certificate Profile": "ROOTCA",
"Default Certificate Profile": "Not used",
"Use Append-Only Table": false,
"CA Token": {
"Signature Algorithm": "SHA256WithRSA",
"Encryption Algorithm": "SHA256WithRSA",
"Crypto Token": "CaToken001",
"Default Key": "defaultkey001",
"Certificate Signing Key": "signkey001",
"CRL Signing Key": "signkey001",
"Key Encryption Key": "defaultkey001",
"Test Key": "testkey",
"Key Sequence Format": "Numeric",
"Key Sequence": "00000"
},
"Enforce Unique Public Keys": false,
"Enforce key renewal": false,
"Enforce Unique DN": false,
"User Storage": true,
"Certificate Storage": true,
"Accept Revocations for Non-Existing Entries": false,
"Subject DN": "CN=ManagementCA,OU=SomeOrg",
"Signed By": "Self Signed",
"Validity": "20y",
"Subject Alternative Name": "None",
"Use UTF-8 in Policy Notice Text": true,
"LDAP DN Order": true,
"Authority Key Id Used": true,
"CRL Number Used": true,
"Partitioned CRL Used": false,
"CRL Expiration Period": "1d",
"CRL Issue Interval": "0m",
"CRL Overlap Time": "10m",
"Delta CRL Period": "0m",
"Generate CRL Upon Revocation": false,
"Allow Changing Revocation Reason": false,
"Finish User": true,
"CA Healthcheck Enabled": true,
"Request Processor": null
},
"RootCA": {
"Object Type": "Certification Authority",
"Version": 2,
"Name": "RootCA",
"Type of CA": "X.509",
"Serial Number Octet Size": 20,
"Pre-produce OCSP Responses": false,
"Microsoft CA Compatible Mode Used": false,
"Store responses on-demand": false,
"Pre-produce OCSP Responses Upon certificate issuance/revocation": false,
"Certificate Profile": "ROOTCA",
"Default Certificate Profile": "Not used",
"Use Append-Only Table": false,
"CA Token": {
"Signature Algorithm": "SHA256WithRSA",
"Encryption Algorithm": "SHA256WithRSA",
"Crypto Token": "CaToken001",
"Default Key": "defaultkey002",
"Certificate Signing Key": "signkey002",
"CRL Signing Key": "signkey002",
"Key Encryption Key": "defaultkey002",
"Test Key": "testkey",
"Key Sequence Format": "Numeric",
"Key Sequence": "00000"
},
"Enforce Unique Public Keys": false,
"Enforce key renewal": false,
"Enforce Unique DN": false,
"User Storage": true,
"Certificate Storage": true,
"Accept Revocations for Non-Existing Entries": false,
"Subject DN": "CN=RootCA,C=SE",
"Signed By": "Self Signed",
"Validity": "20y",
"Subject Alternative Name": "None",
"Use UTF-8 in Policy Notice Text": true,
"LDAP DN Order": true,
"Authority Key Id Used": true,
"CRL Number Used": true,
"Partitioned CRL Used": false,
"CRL Expiration Period": "1d",
"CRL Issue Interval": "0m",
"CRL Overlap Time": "10m",
"Delta CRL Period": "0m",
"Generate CRL Upon Revocation": false,
"Allow Changing Revocation Reason": false,
"Finish User": true,
"CA Healthcheck Enabled": true,
"Request Processor": null
}
},
"end-entity-profiles": {
"eep001": {
"Object Type": "End Entity Profile",
"Version": 1,
"Name": "ServerEndEntityProfile",
"Description": "",
"Default CA": "ManagementCA",
"Available CAs": ["ManagementCA", "RootCA"],
"Default Certificate Profile": "SERVER",
"Available Certificate Profiles": ["SERVER"],
"Default Token Type": "PEM File",
"Available Token Types": [
"User Generated",
"PKCS12 File",
"BCFKS File",
"JKS File",
"PEM File"
],
"Subject DN": {
"CN": [
{
"Required": true
}
]
},
"Subject Alternative Name": {
"DNSNAME": [
{
"Required": false
},
{
"Required": false
},
{
"Required": false
},
{
"Required": false
}
]
}
}
},
"available-protocols": {
"available-protocol-configuration": {
"Object Type": "Available Protocols",
"Version": 1,
"Name": "available-protocol-configuration",
"ACME": true,
"Certstore": true,
"CMP": true,
"CRLstore": true,
"EST": true,
"MSAE": true,
"OCSP": true,
"SCEP": true,
"RA Web": true,
"REST CA Management": true,
"REST Certificate Management": true,
"REST Coap Management": true,
"REST Crypto Token Management": true,
"REST End Entity Management": true,
"REST End Entity Management V2": true,
"REST Configdump": true,
"REST Certificate Management V2": true,
"REST SSH V1": true,
"REST System V1": true,
"Webdist": true,
"Web Service": true,
"ITS Certificate Management": false,
"Custom header name for REST calls from browser": "X-Keyfactor-Requested-With"
}
},
"admin-roles": {
"Super Administrator Role": {
"Object Type": "Role",
"Version": 1,
"Name": "Super Administrator Role",
"Role Members": [
{
"Token Type": "CertificateAuthenticationToken",
"Issuer": "ManagementCA",
"Match With": "WITH_COMMONNAME",
"Match Value": "AutomationAdmin"
},
{
"Token Type": "CertificateAuthenticationToken",
"Issuer": "ManagementCA",
"Match With": "WITH_COMMONNAME",
"Match Value": "SuperAdmin"
},
{
"Token Type": "CliAuthenticationToken",
"Issuer": null,
"Match With": "USERNAME",
"Match Value": "ejbca"
},
{
"Token Type": "PublicAccessAuthenticationToken",
"Issuer": null,
"Match With": "TRANSPORT_CONFIDENTIAL",
"Match Value": ""
}
],
"Namespace": "",
"RA Style Id": 0,
"Access Rules": {
"/": "Allow"
}
}
}
}
Create the ConfigMap:
kubectl apply -f ejbca-ca-init-configmap.yaml
Configure Deployment
The following shows an example Helm chart values file modified to deploy the EJBCA CA.
Example filename: ejbca-ca-values.yaml
ejbca:
env:
DATABASE_JDBC_URL: "jdbc:mariadb://mariadb:3306/ejbca?characterEncoding=utf8"
DATABASE_USER: ejbca
LOG_AUDIT_TO_DB: true
envRaw:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-passwords
key: mariadb-password
envFrom:
- secretRef:
name: configdump-secrets
configdumpImport:
enabled: true
initialize: true
configMapName: ejbca-ca-init-configmap
configMapKey: configdump.json
volumes:
- name: after-deployed-pre
configMap:
name: ejbca-ca-init-configmap
defaultMode: 0777
items:
- key: "after-deployed-pre.sh"
path: "after-deployed-pre.sh"
# Extra volume mounts to be added to the deployment
volumeMounts:
- name: after-deployed-pre
mountPath: /opt/keyfactor/bin/internal/after-deployed-pre.sh
subPath: after-deployed-pre.sh
ingress:
enabled: true
hosts:
- host: "ejbca.example.com"
paths:
- path: /
pathType: Prefix
#imagePullSecrets:
# - name: keyfactor-registry
Install EJBCA
Deploy EJBCA to a Kubernetes cluster using the previously prepared Helm chart values file:
helm install ejbca-ca -f ejbca-ca-values.yaml \
oci://repo.keyfactor.com/charts/ejbca --version <version>
Secure EJBCA
Once EJBCA is deployed, enroll a Super Administrator certificate, create a TLS server certificate, and configure EJBCA to use them with client certificate authentication.
Issue SuperAdmin certificate
To issue a certificate for the SuperAdmin:
In EJBCA, click RA Web to access the EJBCA RA user interface.
Select Enroll > Make New Request and specify the following:
For Certificate Type, i applicable, select EMPTY.
For Certificate subtype, select ENDUSER.
For CA, select ManagementCA.
For Key-pair generation, select By the CA.
For Key algorithm, select for example, RSA-2048.
For the Required Subject DN Attributes, Common Name (CN), specify SuperAdmin.
For Provide User Credentials, enter a username and password.
Click Download PKCS#12 to download the certificate.
Your certificate is saved as a SuperAdmin.p12 file.
Configure TLS and client certificate authentication
Steps describing how to secure access to EJBCA using a TLS server certificate with client certificate authentication are outlined on the Deploy CA in Kubernetes page.
To configure EJBCA, do the following:
Access EJBCA Admin Web by navigating your browser to the host configured in
ejbca-ca-values.yaml
.On the CA Structure & CRLs page, click Download PEM file to download the
ManagementCA.cacert.pem
file.Proceed to the Deploy CA in Kubernetes page and follow the guide starting from section Enroll server TLS certificate.