Tutorial - Deploy EJBCA container in MicroK8s
Learn how to deploy the EJBCA container in the Kubernetes distribution MicroK8s.
This tutorial shows you how to use Ingress for external access to EJBCA and deploy Apache HTTPD for internal services to access EJBCA. The power of EJBCA is leveraged by deploying in Kubernetes to use internally in the Kubernetes cluster as well as externally.
In this tutorial, you will learn how to:
- Deploy the EJBCA container into a Kubernetes runtime
- Use Ingress for external access to EJBCA
- Deploy Apache HTTPD container for containers inside of the Kubernetes cluster to access EJBCA
- Configure certificates issued from the EJBCA container to terminate TLS for accessing EJBCA
Prerequisites
- Before you begin, you need MicroK8s installed and configured. To learn how to install and configure the Kubernetes distribution MicroK8s to deploy the EJBCA container, follow the tutorial Install MicroK8s to run EJBCA.
- a PKI Hierarchy in EJBCA, i
- Additionally, you should be familiar with the YAML format and have a basic understanding of how to use the Kubernetes command line tool kubectl.
Step 1 - Create a namespace and secrets for EJBCA and MariaDB
In Kubernetes, namespaces provide a mechanism for isolating groups of resources within a single cluster and are used in environments with many users spread across multiple teams, or projects. A Kubernetes Secret is an object intended to hold confidential data and contains a small amount of sensitive data such as a password, a token, or a key. Using a Secret means that you do not need to include confidential data in your application code.
To isolate resources into a group in a Kubernetes cluster and create secrets for the database passwords, follow these steps:
- SSH to the MicroK8s server.
In your terminal, enter the following to create a namespace:
CODE$ kubectl create namespace ejbca-k8s
Create a secret for the MariaDB root password:
CODE$ kubectl create secret generic -n ejbca-k8s mariadb-secret --from-literal=mariadb-root-password=ejbca
Create a secret for the EJBCA MariaDB user account:
CODE$ kubectl create secret generic -n ejbca-k8s ejbca-mariadb-secret --from-literal=ejbca-db-password=ejbca
Step 2 - Create Load Balancer Ingress Service
To configure external access to EJBCA, the Metal LB load balancer is leveraged by creating an Ingress service type.
To create a load balancer Ingress service, follow these steps:
Use a text editor such as vim to create the ingress service file ingress-service.yml:
CODE$ vim ingress-service.yml
Add the following to the file:
YMLapiVersion: v1 kind: Service metadata: name: ejbca-node1 namespace: ingress spec: selector: name: nginx-ingress-microk8s type: LoadBalancer # loadBalancerIP is optional. MetalLB will automatically allocate an IP from its pool if not # specified. You can also specify one manually. # loadBalancerIP: x.y.z.a ports: - name: http protocol: TCP port: 80 targetPort: 80 - name: https protocol: TCP port: 443 targetPort: 443
Save and close the file:
CODE:wq
Apply the YAML file to create the Ingress service:
CODE$ kubectl apply -f ingress-service.yml
Check what external IP the ingress service is using:
CODE$ kubectl get all,ingress -n ingress
- Record this IP Address that can be added to the hosts file with the name ejbca-node1 for accessing the EJBCA.
Continue to the next step to create a persistent volume claim for the MariaDB database container.
Step 3 - Create a Persistent Volume Claim for the MariaDB container
To maintain the database state when the MariaDB container is stopped or upgraded, a Persistent Volume Claim (PVC) is used to store the DB data in a persistent storage location. For more information on PVCs, refer to the Kubernetes documentation topic Persistent Volumes.
To create a PVC, follow these steps:
Use a text editor such as vim to create the PVC file ejbca-pvc.yml:
CODE$ vim ejbca-pvc.yml
Add the following to the file:
YMLapiVersion: v1 kind: PersistentVolumeClaim metadata: name: mariadb-pvc namespace: ejbca-k8s spec: accessModes: [ReadWriteOnce] resources: { requests: { storage: 100M } }
Save and close the file:
CODE:wq
Apply the YAML file to create the PVC:
CODE$ kubectl apply -f ejbca-pvc.yml
Continue with creating the services required for accessing the database and EJBCA.
Step 4 - Create services for the database and EJBCA
EJBCA needs to connect to the MariaDB database container. A service is used to allocate an IP address and port for the connection. EJBCA requires a service for Ingress and Apache HTTPD to connect with using AJP.
To create the two services, follow these steps:
Use a text editor such as vim to create the services file ejbca-svc.yml:
CODE$ vim ejbca-svc.yml
Add the following to the file:
YMLapiVersion: v1 kind: Service metadata: name: ejbca-database-service namespace: ejbca-k8s labels: app: mariadb spec: type: ClusterIP ports: - name: database-port port: 3306 targetPort: 3306 selector: app: mariadb --- apiVersion: v1 kind: Service metadata: name: ejbca-service namespace: ejbca-k8s labels: app: ejbca spec: type: ClusterIP ports: - name: ajp port: 8009 targetPort: 8009 selector: app: ejbca
Save and close the file:
CODE:wq
Apply the YAML file to create the services:
CODE$ kubectl apply -f ejbca-svc.yml
The services are now created and you can continue to the next step to deploy the MariaDB container.
Step 5 - Create deployment for the MariaDB container
The EJBCA container supports MariaDB, Microsoft SQL Server, Oracle, and PostgreSQL databases. Deploying the EJBCA container with an external database stores the state and configuration. That means if the EJBCA container is stopped or restarted, the PKI configuration is not lost and requires everything to be configured all over again. A deployment is used to deploy the MariaDB container that will use the PVC and service created in the previous steps.
To deploy MariaDB in a container, follow these steps:
Use a text editor such as vim to create the MariaDB deployment file ejbca-db.yml:
CODE$ vim ejbca-db.yml
Add the following to the file:
YMLapiVersion: apps/v1 kind: Deployment # what to create? metadata: name: mariadb-deployment namespace: ejbca-k8s labels: app: mariadb spec: # specification for deployment resource replicas: 1 # how many replicas of pods we want to create selector: matchLabels: app: mariadb template: # blueprint for pods metadata: labels: app: mariadb # service will look for this label spec: # specification for pods volumes: - name: datadir persistentVolumeClaim: claimName: mariadb-pvc containers: - name: mariadb image: mariadb:latest ports: - containerPort: 3306 #default one env: - name: MARIADB_ROOT_PASSWORD valueFrom: secretKeyRef: name: mariadb-secret key: mariadb-root-password - name: MARIADB_PASSWORD valueFrom: secretKeyRef: name: ejbca-mariadb-secret key: ejbca-db-password - name: MARIADB_DATABASE value: ejbca - name: MARIADB_USER value: ejbca volumeMounts: - name: datadir mountPath: /var/lib/mysql/
Save and close the file:
CODE:wq
Apply the YAML file to create the MariaDB deployment:
CODE$ kubectl apply -f ejbca-db.yml
A deployment of MariaDB running in a container is now being deployed. Continue to the next step to deploy the EJBCA container.
Step 6 - Create deployment for the EJBCA container
As the pieces to support deploying EJBCA in Kubernetes were completed in previous steps, it's now time to create a deployment for the EJBCA container.
To deploy the EJBCA container, follow these steps:
Use a text editor such as vim to create the EJBCA deployment file ejbca-ca.yml:
CODE$ vim ejbca-ca.yml
Add the following to the file:
YMLapiVersion: apps/v1 kind: Deployment metadata: name: ejbca-deployment namespace: ejbca-k8s labels: app: ejbca spec: replicas: 1 selector: matchLabels: app: ejbca template: metadata: labels: app: ejbca spec: containers: - name: ejbca-node1 image: keyfactor/ejbca-ce:latest imagePullPolicy: Always resources: limits: cpu: "16" memory: "4096Mi" requests: cpu: 1000m memory: "2048Mi" ports: - containerPort: 8009 name: ejbca-ajp env: - name: DATABASE_JDBC_URL value: "jdbc:mariadb://ejbca-database-service:3306/ejbca?characterEncoding=utf8" - name: DATABASE_USER value: ejbca - name: PROXY_AJP_BIND value: "0.0.0.0" - name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: ejbca-mariadb-secret key: ejbca-db-password - name: LOG_AUDIT_TO_DB value: "true"
Save and close the file:
CODE:wq
Apply the YAML file to create the EJBCA deployment:
CODE$ kubectl apply -f ejbca-ca.yml
EJBCA is deploying and the next step is to configure ingress for external access to EJBCA.
Step 7 - Create Ingress for external access to EJBCA
To configure external access to EJBCA using Ingress, follow these steps:
Use a text editor such as vim to create the EJBCA Ingress file ejbca-ingress.yml
CODE$ vim ejbca-ingress.yml
Add the following the file:
YMLapiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: # Use AJP with appserver nginx.ingress.kubernetes.io/backend-protocol: AJP nginx.ingress.kubernetes.io/auth-tls-verify-client: "optional_no_ca" nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true" name: ejbca-node1 namespace: ejbca-k8s spec: ingressClassName: public rules: - host: ejbca-node1 http: paths: - path: / pathType: Prefix backend: service: name: ejbca-service port: number: 8009 tls: - hosts: - ejbca-node1.ejbca-k8s secretName: tls-secret
Save and close the file:
CODE:wq
Apply the YAML file to create the EJBCA Ingress:
CODE$ kubectl apply -f ejbca-ingress.yml
Query the Ingress IP to use for accessing EJBCA:
CODE$ kubectl -n ingress get services -o json | jq -r '.items[] |.status.loadBalancer?|.ingress[]?|.ip ' | cut -d : -f 2
Create a hosts file entry in /etc/hosts file or applicable file if using a none Linux OS with the IP from step 5. and the hostname ejbca-node1.ejbca-k8s, for example:
CODE# Add to the hosts file: 172.16.170.187 ejbca-node1.ejbca-k8s
External access to EJBCA using Ingress is now configured.
Step 8 - Issue TLS certificates for EJBCA external and internal access
The following provides steps for updating the current TLS server end entity profile and certificate profile to use the Management CA and RSA key type. Once updated, two certificates will be issued to use for TLS termination to access EJBCA
a PKI Hierarchy in EJBCA,
To update the profiles and issue the two TLS certificates to use with the MicroK8s EJBCA deployment, follow these steps:
- Log in to EJBCA and click Certificate Profiles under CA Functions.
- To edit the server profile values to fit your needs, find the TLS Server Profile in the list and click Edit.
- On the Edit page, update the following:
Add RSA to the selection of Available Key Algorithms, ECDSA and RSA should both be selected.
- Select 2040 bits - 4096 bits for the Available Bit Lengths.
Scroll down to the Available CAs and additionally select ManagementCA, so that ManagementCA and MyPKISubCA-G1 are both selected.
- Click Save.
- Next, to add the Management CA to the End Entity Profile, click End Entity Profiles under RA Functions.
- Select TLS Server Profile, then click Edit End Entity Profile
- Scroll down to the Available CAs and additionally select ManagementCA, so that ManagementCA and MyPKISubCA-G1 are both selected.
- Click Save.
- In EJBCA, click RA Web to access the EJBCA RA UI.
- Select Make New Request from the Enroll menu.
- For Certificate Type, select your TLS Server Profile.
- For CA, select ManagementCA.
- For Key-pair generation, select By the CA.
- For Key Algorithm, select RSA 2048 bits.
- Specify the following information to be used in the certificate:
- For CN, Common Name, specify a name, in this example ejbca-node1.
- For the second DNS Name in the Subject Alternative Name Attributes, specify the full cluster name ejbca-node1.ejbca-k8s.
- For Username, add ejbca-node1 to register the user under the username identical to the common name. The Username is the name that will go into the database and is often the same as the Common Name.
- For Enrollment code, enter a password twice.
- Click Download PEM to download and save the ejbca-node1.pem file.
- For CN, Common Name, specify a name, in this example ejbca-node1.
- To create a second internal certificate, scroll up and specify the following information to be used in the certificate:
- For CN, Common Name, specify a name, in this example ejbca-internal.
- For the second DNS Name in the Subject Alternative Name Attributes, specify the full cluster name ejbca-internal.ejbca-k8s.
- For Username, add ejbca-internal to register the user under the username identical to the common name. The Username is the name that will go into the database and is often the same as the Common Name.
- For Enrollment code, enter a password twice.
- Click Download PEM to download and save the ejbca-internal.pem file.
- For CN, Common Name, specify a name, in this example ejbca-internal.
TLS certificates have been issued from the Management CA that will be used to terminate TLS to the EJBCA container. Continue to the steps below to configure these certificates to use.
Step 9 - Create Kubernetes Secret and ConfigMap for the TLS certificates
Next, the two certificates issued in the previous step must be configured to be used with Ingress and Apache HTTPD.
You will create a Kubernetes Secret and ConfigMap for the TLS certificates:
- A Kubernetes Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key. Using a Secret means that you do not need to include confidential data in your application code.
- A ConfigMap is an API object used to store non-confidential data in key-value pairs. A ConfigMap allows you to decouple environment-specific configuration from your container images so that your applications are easily portable.
Secrets are similar to ConfigMaps but are specifically intended to hold confidential data. For more information, refer to the Kubernetes documentation topics Secrets and ConfigMaps.
To prepare Ingress and HTTPD to use certificates issued from EJBCA, follow these steps:
- Open a new SSH session to the server.
- To create the Kubernetes Secret, create three separate files for the ejbca-node1 certificate, key, and CA certificate:
- Open the ejbca-node1.pem file with a text editor of your choice.
- To create a server.crt file:
Use a text editor such as vim to create the server.crt file:
CODE$ vim server.crt
Add the ejbca-node1 certificate to the file from the ejbca-node1.pem file opened in the text editor. The following shows an example certificate:
CODE-----BEGIN CERTIFICATE----- MIIEnDCCAoSgAwIBAgIUC/uQvaEzLXFrULutwEFoXMdvPekwDQYJKoZIhvcNAQEL BQAwQjEVMBMGA1UEAwwMTWFuYWdlbWVudENBMRwwGgYDVQQKDBNLZXlmYWN0b3Ig Q29tbXVuaXR5MQswCQYDVQQGEwJTRTAeFw0yMzAzMTkxNzI2NDZaFw0yNDAzMTQx NzI2NDVaMEExCzAJBgNVBAYTAlNFMRwwGgYDVQQKDBNLZXlmYWN0b3IgQ29tbXVu aXR5MRQwEgYDVQQDDAtlamJjYS1ub2RlMTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAInoar+qRCeeLiuYknOSPjqboJ93W1YxBdYTScnDdXqRut2uDn0L oDijfP9CF3yWS4pvUkoBteOkIWs7eFi+7XA5JWQqrXzMo6dChdhI4tEnQ5XEVj+I SlAjFydTBXM4vNr8RKVMYHVvWLfT3Px6WX6BszueWMGkxwipdTwX4I7SBOt4gt9v njIvkdIsSGExuzi7h8u+JPhj/6vqgcflHhwWjCqVrEyy3aj7KN1zUJlXHxZ6Jp64 WNHPHd7brUCIPr8H+OT30LCZa1QYfMZK5ozHjlYOXJ+gE95NwR5oR2k/pHmqTwK6 YhvSiVt33RefQuGXt3ho2rCC7kiMsfm98A0CAwEAAaOBijCBhzAfBgNVHSMEGDAW gBTX/jGUQ0k8X6G7Xv4FgAQsBPOg0jAgBgNVHREEGTAXghVlamJjYS1ub2RlMS5l amJjYS1rOHMwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYEFEI3cF7EhrqN ZjlafvuMan1gR604MA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAgEA Nrdbh+9tIpL+UqNwsqnXgFGCsdDROrIv6ZAfdt1q0UM3iHAaRWT9DF105Nk4J7j2 tXacE8vkv35aCwBGJuG1uWoHm/H0+/fOs8pRW/9M4sjfpe/KM/hFjRXGVJfDlfVl rrvn2ixh240V9SkLStb0jStA0Jc4+fm3pnDppyGGYUFyk5gL0JNT67C7i2MR1vmA nHl3Z8Mq+FfteEuDSgYbf7Q5eCbnPOpGs4D6/msw4fEK2YiFPpgcnBR5RYFSLugF iI9p3RPWrfuOamkY43et3K1Ky37WvmrV1KJ7XquLn7xPJc6oOX9WGSvmXOUpZP4t iwqo1Ml7VXkQxtC0/zZjX6OK5d4B/H6TzqJBDDI+jrlNiTevtyieouhnQMx4PtjO GgNbaHpkbbVxFxrB0GgF0XPoKw6rDG7XDruO/6KgrsWYNZ4jJTu7pCIZNfrJPQXI YwsJBE2jNMG5Hpuj87XhM29M0eO2GYXE3fkjnTlz+5NHF0dR2tOQB9ZsCB4OEO8m lJeR5aRVJF+M3+/Lth1lWfZj4p4hHhGX3Bf609YWkrEXkllcMMx1D6hPK0PIMVRI gS1ZbY9vqs+nO3SP+FK0JuN/dpr24yyLnbH68zfToo7oggDlcKOiu4LFdOp51cUB 8mcVkwTsNCX1Y3kon2I1CmC7i4wBfSReh6gI1lL6FOY= -----END CERTIFICATE-----
Save and close the file:
CODE:wq
To create a server.key file:
Use a text editor such as vim to create the server.key file:
CODE$ vim server.key
Add the ejbca-node1 private key to the file from the ejbca-node1.pem file opened in the text editor. The following shows an example private key:
CODE-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCJ6Gq/qkQnni4r mJJzkj46m6Cfd1tWMQXWE0nJw3V6kbrdrg59C6A4o3z/Qhd8lkuKb1JKAbXjpCFr O3hYvu1wOSVkKq18zKOnQoXYSOLRJ0OVxFY/iEpQIxcnUwVzOLza/ESlTGB1b1i3 09z8ell+gbM7nljBpMcIqXU8F+CO0gTreILfb54yL5HSLEhhMbs4u4fLviT4Y/+r 6oHH5R4cFowqlaxMst2o+yjdc1CZVx8WeiaeuFjRzx3e261AiD6/B/jk99CwmWtU GHzGSuaMx45WDlyfoBPeTcEeaEdpP6R5qk8CumIb0olbd90Xn0Lhl7d4aNqwgu5I jLH5vfANAgMBAAECggEAFO+bBxpk6uPNbBJnR1LQDisyrQrca58ZHPkEJnR9KPyn MwC509t4OSj+sKy6rpANi0hfpHsSfyrbZPFcEZL4rmUKi2ScPlo9zQZhFebowipV DQ9HrbD14SkWmoJ0zRtztkX+cN7BtQpQnGW2QoEbhYRQrrAZFtq6WZMKSHNyhJPe G+VPaR1kgmbqV6sambmdvwQ8ZO3Q+PU5TWrKiNc3iUC03iNMuQpt5coA9Mxwumox vO9j4HWz9SoSn49Ik5M89N8A9D5te2FBoA+Nne6NbT+U1pMJlPSFCFuYzE21Ht4p 6IgSLoYiO2fnzpaPdjX2rfW5GHTY1cbvBeqFIotI4QKBgQC+SJEbBdtxJnAffA1y EulN1+w6Lle5CPo6igpMu6otHiB9z1un/v1Kq/I+xwAYDPHGnxOGNeMqzlHPBSQ7 dpRbPdWjRgUtKo+mqgQVnRZYrSyZ8Al9fZoU8WBlYSB3f6RpHYiD3UUlir6C58qy bA5YV0cLF0RQ6WzcxVXLQbVSIQKBgQC5iTHZZqHrWR8jiMqymJztXxytZi1FJU6n +31j4WbSVbcq3Qh55XvPg5Ujx98dbp8ESRUhO8hpvoFITHH5j1fbjRXNwc2Mevls OF8lT3MOsuD/XlxnLVeetYnsyQUbigkiCTWU0FH5AOzvWjaHMmIlsMCwpWhOF6eU eokkLLr4bQKBgFydQVMfxLEL/mK0pG6zWa6zu5yN1dCP2AsKCP1UEf4nvbS+amQY LfxcOGnpvdf25O7BmmUmcUzyYssaO4pdqtPGAueXOwnCv2xlL9u9O5UppJ3AQT49 FfO/kCWH4p+HFuS6pSlZV0BwiU15uCSjh0/kGwYA6xVep8fEnH9zmedBAoGAS7/U x2Lctt7DFNnzj+k5ILzVU4JE91cc/v5xmkbbmQJ/7xMhM8taukWJrXsb/8M7Tx+b bd8fmvS5idAUNISupSe8AC6hAjru/J0jU3NVkWm87OYUqddcT6LktfT4jd7Ujb3e z2wiG5yiH7LgUmBiq+q3MSfHJyMHO1qwBUHx8B0CgYAYQJQDv3MMtrev6QobFxNc sWFrqzUN9CYJA8OtS5zubPuFoage9P9LUOqqR4VCo4AoIj7xUunrDh0jUDgZ0KRA akfJm2mg7PULx0n4CKfd9gQociNFfQHlwvX9UobsEfNNIxYTHcixMaWOOjBKIXpB gpi9cRgUlgV60HdiVe5jwg== -----END PRIVATE KEY-----
Save and close the file:
CODE:wq
To create a ca.crt file:
Use a text editor such as vim to create the ca.crt file:
CODE$ vim ca.crt
Add the Management CA certificate to the file from the ejbca-node1.pem file opened in the text editor. The following shows an example Management CA certificate:
CODE-----BEGIN CERTIFICATE----- MIIFdTCCA12gAwIBAgIUWpEFjDfFuGU6I5s/zCpuXrVmZIswDQYJKoZIhvcNAQEL BQAwQjEVMBMGA1UEAwwMTWFuYWdlbWVudENBMRwwGgYDVQQKDBNLZXlmYWN0b3Ig Q29tbXVuaXR5MQswCQYDVQQGEwJTRTAeFw0yMzAxMTgwODM0MDJaFw0zMzAxMTUw ODM0MDFaMEIxFTATBgNVBAMMDE1hbmFnZW1lbnRDQTEcMBoGA1UECgwTS2V5ZmFj dG9yIENvbW11bml0eTELMAkGA1UEBhMCU0UwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDIf6n+++qldacqGvWlgiPx7AnSMuremYdrRhoylF+3kJbDFiMp KpVzEaeguionS4uXqErZAzgzcbu6huf4bRscYk04nCgXsFAMItsiEZ314oE4thv8 fbPPu4K1joeDgdHv0QhA3dkRUNorH54wOR6gLDzn6nBwePJAoKxhc/WoaONta2/O tHeTemYZOLt+uMY+Hj3o2sMeTm3B/B/ED5BWzVMSPOCCV6qk5/cW/P2YvWfFHUja 8xqqbBuuDZHTuX4X58BsHH+o8bgZjWhdwcZb8Oe2VajFX6DpiBZcESQL+0ir0ZqG zALBc8jADv0VZC0u1Pxj39p19Xosm46jelcH3CBD+65I+1Kg5aQ1tIpBHLvdJEuT X6WkNPMmi0VqawxtlgshlF10kLsHm/r+dlGTQ78EA23JkgglBPovCmWSb6+KJyk/ q6dWElqrbdHwieuajb2D9s/P7RDU7h9gSf6C4nbIX1x5H/mpVCdZWDuqL0Y7tn9K kvhh3TNXZf1TiryJkw3GDxHS88mh+pGEZsnC3hH5rLKj/JFVQtbWeu1QdhI5fFlh PtUjIWeFHbgvMisd4qjouJfhuF2LRfpdn/u52MHTVntVGtGYNV3uUVpVR6YkFH0q GfAqP5clv1qSF5gRANIPVQSpF0wcvTHvgWdv9bOy7a9BLvWFg46Ys4HKWQIDAQAB o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNf+MZRDSTxfobte/gWA BCwE86DSMB0GA1UdDgQWBBTX/jGUQ0k8X6G7Xv4FgAQsBPOg0jAOBgNVHQ8BAf8E BAMCAYYwDQYJKoZIhvcNAQELBQADggIBAC17+M739nb2AG3bpKObDDlW+fYMdEhX tjQcOvHIUrITKryX3lmHyWDFFgFTeTYcoxq8ywFvpvXz4pHgeFWRZYQw7cSWwH8n JfLE+EJlpYU2yUGto/S8NPXV54dAYNsvQQncQixsIYgxsmX7yIzBt1+v3sLmQlp5 CfZRCOxj+2fa9jb/jygdQC3AAS5uT86gYz0YcB5VXQ0+jYWsL7MDwgb8ORcmiugd uZ0kgBXd40Qg9bJhfz0N+BKWPTbS4dFst4ey5dndLp4QxWXzTt+gbmOMBpiwB6xx H3hw/LrRBEs7hrhVIlJ76cMx/f/5wERD0qS3uPXpCCtcKDBqHFruOI/NMNEVRFwi VxVD8w1jWYXDUyNVErU0LzqGOkyDuRwEDN8svaKn8+WdyumDB21tTWEbYPbFWc9R 2epNj8moBVcfnxwsVP5TCXk6tEEOMkCVLNC3JBUWSfGJjg/2PDEdo2cPYCXYU4Hu eE/SnoUbRh0M34BfaHHt8S/vcEZWSkctJUmRZbTju57FKMlIHcgE5FHN5ahDAiSc GgncvFfPKXcEPFh5bhKdhT6FzbKysCoRw16rwhzfsm4X42jvzBEOKpUcFDpRuBJs zTk30lhAdmROkG5UTemobyKgDVw50VcFKbMk3Q5Gzs9TZ+uRAWJA7rF6MSc+cSlP qMN+i82CAMeU -----END CERTIFICATE-----
Save and close the file:
CODE:wq
- To create a server.crt file:
Create Kubernetes Secret for the ejbca-node1 certificate, key, and a secret for the CA certificate file that Ingress will use to terminate TLS to the EJBCA container:
CODE$ kubectl create secret tls -n ejbca-k8s tls-ejbca-node1 --cert server.crt --key server.key $ kubectl create secret generic -n ejbca-k8s mtls-trust-chain --from-file=ca.crt=ca.crt
- To create the Kubernetes ConfigMap, create two separate files for the ejbca-node1 certificate and key (the CA certificate file ca.crt will be reused for the Management CA certificate).
- Open the ejbca-internal.pem file with a text editor.
- To create a ejbca-internal.crt file:
Use a text editor such as vim to create the ejbca-internal.crt file:
CODE$ vim ejbca-internal.crt
Add the ejbca-internal certificate to the file from the ejbca-internal.pem file opened in the text editor. The following shows an example certificate:
CODE-----BEGIN CERTIFICATE----- MIIEojCCAoqgAwIBAgIUPaLkQD5t3sJyXqyDZ9oakKCef4IwDQYJKoZIhvcNAQEL BQAwQjEVMBMGA1UEAwwMTWFuYWdlbWVudENBMRwwGgYDVQQKDBNLZXlmYWN0b3Ig Q29tbXVuaXR5MQswCQYDVQQGEwJTRTAeFw0yMzAzMTkxNzI3MTJaFw0yNDAzMTQx NzI3MTFaMEQxCzAJBgNVBAYTAlNFMRwwGgYDVQQKDBNLZXlmYWN0b3IgQ29tbXVu aXR5MRcwFQYDVQQDDA5lamJjYS1pbnRlcm5hbDCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAIxh+0WaKmw+Yrim+/2c7Li/gWDJKdsd+mS170V6rnHSfRDd qfcW1q9ADwRZyu3Pc3s+w6UmjSciwOtvovPOfC5D0dUog4bgQ/1cSWuVUC8gd/Xy xb7DuKqbGtg8kB5BMD7O3oF89b2iGisfw4Ei9Njf1hrgl9DWuFfQ6+/d5luUXCRv cKYeQl05ZRii8LwLc8vvb613HbQi4n47QbLHMDgQDqdiqvefhyDE8gdgJyOBM5nV dsc2/6sxsKDNTMV86N1POWSXBrM9b4T/jFAik76dGjcCv/WTY/3VbPCuGypB5SaL ++8/eLCEmZDgBovZT8WJIGK5odrdFbnSvtCwhZ0CAwEAAaOBjTCBijAfBgNVHSME GDAWgBTX/jGUQ0k8X6G7Xv4FgAQsBPOg0jAjBgNVHREEHDAaghhlamJjYS1pbnRl cm5hbC5lamJjYS1rOHMwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYEFJtU ZTtTpL9zsDKstua4doISNMo5MA4GA1UdDwEB/wQEAwIFoDANBgkqhkiG9w0BAQsF AAOCAgEAkTxtIref9DVm4fcB2jzNdaiLPpWQbhREWgdg8oGaaams832JnoiCJjga lBnp8wNb8M9AxgEIU15il0xdw9oOoHAhz04Z3DV6snS1wmPs1u+un9zN0ZdBEEbC zchc/tUg4lVYLlKieTjUcg8Dy/wVBegwBYxDXfzbabhMe8GFCs0qXll2hIetjesq XtILq3Y5L7qVL7CaEeD2SX+Eb9Zz89xl069Jh3wWc34rBTI9L1f+ysBX0FhUyqqg mU8xUjLDaDXpkF+tQH1tIxtu3A1J1k1aRp8jDb2w6urxERy3+Huxl50wrb80HJRg /IdccIckpoFzga76hxV5l/mKlyxerr7Uev9prnTGeGSNF58dkJrGkwenvaYQC/Pk I5MdqmrielVy56/o8ldS+12a1BtejMRE7I/KkPFF7ZIcTdh214NQe+FksaU8Wui4 ozAb8ULYjodMbrvU798TnXht8ySF0PPdTJ7B7gA9oUGZsnYTKO/M6OP6NHte4ezm t3qvQpzsYeUOILz0+YeBZfCZrn2lJzQSkzaoernYO2igAEv/EGqJQ43hDKBnKKtJ WMAHqzfaJuSnJfRnRIg1iDvQ+8XsTyMIY0uGgBWJt0qPAUxpgLBsjN+X9uu6DKuu CEQLNQ0oAbNYKjgqMU7yxf2YkhMP6nppS/I0JgVR9PKyMptyGJ0= -----END CERTIFICATE-----
Save and close the file:
CODE:wq
To create a ejbca-internal.key file:
Use a text editor such as vim to create the ejbca-internal.key file:
CODE$ vim ejbca-internal.key
Add the ejbca-internal private key to the file from the ejbca-internal.pem file opened in the text editor. The following shows an example private key:
CODE-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCMYftFmipsPmK4 pvv9nOy4v4FgySnbHfpkte9Feq5x0n0Q3an3FtavQA8EWcrtz3N7PsOlJo0nIsDr b6LzznwuQ9HVKIOG4EP9XElrlVAvIHf18sW+w7iqmxrYPJAeQTA+zt6BfPW9ohor H8OBIvTY39Ya4JfQ1rhX0Ovv3eZblFwkb3CmHkJdOWUYovC8C3PL72+tdx20IuJ+ O0GyxzA4EA6nYqr3n4cgxPIHYCcjgTOZ1XbHNv+rMbCgzUzFfOjdTzlklwazPW+E /4xQIpO+nRo3Ar/1k2P91WzwrhsqQeUmi/vvP3iwhJmQ4AaL2U/FiSBiuaHa3RW5 0r7QsIWdAgMBAAECggEACG3wv+DuN7I2TNawDm5AE6biLqzdn8vox2faTn57n5eP TXY1+MGNEhhjXnRC2G1KxqWB63aJZsZyNaDuNLwbHk8RuD42yaBJTNsgCH7+gdnu Ah16DMalXc8y+TWHxN1Ot5LF7xoRCnpDnn/JhkVSVPx514LRcueVyaYgqLZXGPwU lLsEzZjy87w+wWYdkaUL0FlZPjJSsUcpDgTo4IVyLHYgKijwKa6GGAC1LRaF7xnG IX7SHhAr8Aec26jd5GNWecJaftSh22GP7o6eaf2IJMc1r7JQE21T+nG//hLHZ9hI nwHdKXXjStKpnqLfwZsEt/gOwCJ7MQk+UPo0t+b9MQKBgQDFCOOQ3iU3CPjoyK5b eR0XRHdtHNwLFOFP7bMpkwQuS86TUxFau2VOE3yPOU3UI+eWNXU6tHD9J4ep+BWn kqjdeehdBSmZePtGjsktmXf96rVZR3801Lfpar2tMfB8b4ngdIJcBCdsFNUY9VFh U0vO9xDflag5w3GONiiwaJ5GUQKBgQC2ZOdJqebkJ7n9MHY8Yc67anX4m9sLGhX7 Sc4U8OLjGAAxXJrutoPYUPeUFGWwMfQvpXbydQRtnG4Jw42qnSino69xhwUqvhPS ZqMTU4NEq5DQBIrT9LV2Ih0BkvE9sdfQsvtZzXWDl7yMm1R2YlCwozlZTBn9GCf3 EOBxs/VbjQKBgBr4k4YCEqAM912OEufslUHZGmvyNmDB8/Gn/Q1k1X6s29Mo3MhJ vJ1KZ5OHaZLvc0UJfkmR56GPpq9qiTRODBV9GYSaL06V0/edlgZK6rT0Suy0r8IA mEg4V0x8+IlgD0SNTkbgPrE5zM3EzuX+q/LhuQqSBtwZV9L6sOks+PVxAoGADSiK Zw4S0jLrgBCW9xQ3Td4IVL8ptktTeqWAcJJQTAHXQbhklQQlzt1Ify5Zh7SS4T0W r7cxcpbueVXaSoy7+hwc9BvBi6va0jsFWMeVmMan09oACfqFfNhJL2via4kBANVo vLnN2IiB2cL6/O9q0tNzt7V9ynyLpY9aIdnRwaECgYBe67DpIIF+6o7+epHogfmN SLu/UdGhsBtJqbg9WJv7mXzpHWk+Vmx2HwYn6H9a8YW35C6E2GygVriuB72Ov5GV YPzw/mJ2YNLz1of0iBaH0Skru2kHP5fVNd4bpCz7Wt7WdB6ZEUfZerUEcprY30wr PkZVKHoa6btaotnw2IwNsQ== -----END PRIVATE KEY-----
Save and close the file:
CODE:wq
- To create a ejbca-internal.crt file:
Create a Kubernetes ConfigMap for the ejbca-internal certificate and key, and re-use the CA certificate file created for the Kubernetes Secret (since the certificates are issued off the same CA) to use HTTPD to terminate TLS to the EJBCA container:
CODE$ kubectl -n ejbca-k8s create configmap httpd-certs-configmap --from-file=ejbca-internal.crt=ejbca-internal.crt --from-file=ejbca-internal.key=ejbca-internal.key --from-file=ca.crt=ca.crt
The certificates, keys, and Management CA certificate are now configured to use for TLS by Apache HTTPD and Ingress. Continue to the next step to swap the TLS certificate used by Ingress.
Step 10 - Update EJBCA Ingress configuration to use new TLS certificate
Ingress has been using a self-signed certificate for terminating TLS to access the EJBCA CA UI and RA UI. The following outlines how to update the Ingress configuration to use and trust the certificate issued from the EJBCA Management CA.
To change the TLS certificate used by Ingress to access EJBCA, follow these steps:
Use a text editor such as vim to create the EJBCA Mutual TLS (mTLS) Ingress file ejbca-mtls-ingress.yml
CODE$ vim ejbca-mtls-ingress.yml
Add the following to the file:
YMLapiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: # Use AJP with appserver nginx.ingress.kubernetes.io/backend-protocol: AJP nginx.ingress.kubernetes.io/auth-tls-verify-client: "optional" nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true" nginx.ingress.kubernetes.io/auth-tls-secret: "ejbca-k8s/mtls-trust-chain" name: ejbca-node1 namespace: ejbca-k8s spec: ingressClassName: public rules: - host: ejbca-node1 http: paths: - path: / pathType: Prefix backend: service: name: ejbca-service port: number: 8009 tls: - hosts: - ejbca-node1.ejbca-k8s secretName: tls-ejbca-node1
Save and close the file:
CODE:wq
Remove the current EJBCA Ingress configuration:
CODE$ kubectl delete -f ejbca-ingress.yml
Apply the YAML file to create the EJBCA mTLS Ingress:
CODE$ kubectl apply -f ejbca-mtls-ingress.yml
Ingress is now using a certificate issued from the EJBCA Management CA. Continue to the next step to deploy and configure Apache HTTPD.
Step 11 - Deploy Apache HTTPD for internal Kubernetes cluster access
Apache HTTPD is used as a reverse proxy to terminate TLS and provide access to EJBCA for internal cluster access. Containers, service mesh, or whatever else needs to access EJBCA within the cluster will use Apache HTTPD.
To deploy and configure Apache HTTPD, follow these steps:
Use a text editor such as vim to create the EJBCA HTTPD file ejbca-httpd.yml
CODE$ vim ejbca-httpd.yml
Add the following to the file:
YML--- apiVersion: v1 kind: Service metadata: name: ejbca-internal namespace: ejbca-k8s labels: app: ejbca-httpd spec: type: ClusterIP ports: - name: apache port: 443 targetPort: 443 - name: open port: 80 targetPort: 80 selector: app: ejbca-httpd --- apiVersion: v1 data: httpd.conf: |+ LoadModule mpm_event_module modules/mod_mpm_event.so LoadModule headers_module modules/mod_headers.so LoadModule authz_core_module modules/mod_authz_core.so LoadModule access_compat_module modules/mod_access_compat.so LoadModule log_config_module modules/mod_log_config.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule unixd_module modules/mod_unixd.so LoadModule filter_module modules/mod_filter.so LoadModule substitute_module modules/mod_substitute.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so LoadModule ssl_module modules/mod_ssl.so MaxKeepAliveRequests 1000 KeepAlive On KeepAliveTimeout 180 # Don't think we need this # Include conf/extra/httpd-ssl.conf <IfModule unixd_module> User daemon Group daemon </IfModule> ErrorLog /proc/self/fd/2 LogLevel info <IfModule log_config_module> LogFormat "%h %A:%p %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %A:%p %l %u %t \"%r\" %>s %b" common CustomLog /proc/self/fd/1 common </IfModule> ServerRoot "/usr/local/apache2" Listen 443 Listen 80 <Directory /> AllowOverride none Require all denied </Directory> <VirtualHost *:443> DocumentRoot /var/www/html/ # Disallow any HTTP method that is not HEAD, GET or POST RewriteEngine On RewriteCond %{REQUEST_METHOD} !^(HEAD|GET|POST|PUT)$ [NC] RewriteRule .* - [F,L] SSLEngine on SSLCipherSuite HIGH:!ADH:!aDSS:!aDH SSLProtocol all -SSLv2 -SSLv3 -TLSv1 +TLSv1.2 -TLSv1.3 # SSLProtocol -all +TLSv1.2 SSLOptions +ExportCertData +StdEnvVars SSLCertificateFile /etc/httpd/ssl/ejbca-internal.crt SSLCertificateKeyFile /etc/httpd/ssl/ejbca-internal.key SSLVerifyClient optional SSLVerifyDepth 3 SSLCACertificateFile /etc/httpd/ssl/ca.crt <Location /ejbca/ejbcaws> SSLVerifyClient require </Location> <Location /ejbca/adminweb> SSLVerifyClient require </Location> # Allow encoded slashes for OCSP GET AllowEncodedSlashes On ProxyPass /ejbca/ ajp://ejbca-service:8009/ejbca/ keepalive=On ping=500ms retry=1 timeout=300 #Add ProxyPass for EST and .well-known URLs ProxyPass /.well-known/ ajp://ejbca-service:8009/.well-known/ keepalive=On ping=500ms retry=1 timeout=300 # Redirect /, /ejbca, /signserver and non-proxied URLs to /ejbca/ RewriteCond %{THE_REQUEST} !(/ejbca/.*|/.well-known/.*) RewriteRule (.*) https://%{HTTP_HOST}/ejbca/ </VirtualHost> <VirtualHost *:80> DocumentRoot /var/www/html/ # Disallow any HTTP method that is not HEAD, GET or POST RewriteEngine On RewriteCond %{REQUEST_METHOD} !^(HEAD|GET|POST)$ [NC] RewriteRule .* - [F,L] # Redirect legacy EJBCA enrollment to HTTPS RewriteCond %{HTTPS} !=on RewriteRule ^/?ejbca/enrol/(.*) https://%{SERVER_NAME}/ejbca/enrol/$1 [R,L] # Allow encoded slashes for OCSP GET AllowEncodedSlashes On ProxyPass /ejbca/ ajp://ejbca-service:8009/ejbca/ keepalive=On ping=500ms retry=1 timeout=300 nocanon ProxyPass /signserver/ ajp://ejbca-service:8009/signserver/ keepalive=On ping=500ms retry=1 timeout=300 # Redirect /, /ejbca, /signserver and non-proxied URLs to /ejbca/ RewriteCond %{THE_REQUEST} !(/signserver/.*|/ejbca/.*) [OR] RewriteCond %{THE_REQUEST} (/ejbca/ejbcaws.*) RewriteRule (.*) http://%{HTTP_HOST}/ejbca/ RewriteCond %{THE_REQUEST} (/ejbca/ejbcaws.*|/ejbca/adminweb.*) RewriteRule (.*) https://%{HTTP_HOST}/ejbca/ </VirtualHost> kind: ConfigMap metadata: namespace: ejbca-k8s name: config-httpd-configmap --- apiVersion: apps/v1 kind: Deployment metadata: name: ejbca-httpd namespace: ejbca-k8s labels: app: ejbca-httpd spec: replicas: 1 selector: matchLabels: app: ejbca-httpd template: metadata: labels: app: ejbca-httpd spec: containers: - name: httpd image: library/httpd:latest ports: - containerPort: 443 name: httpd-http - containerPort: 80 name: http volumeMounts: - name: config-httpd-volume mountPath: /usr/local/apache2/conf/ - name: certificates-volume mountPath: /etc/httpd/ssl volumes: - name: config-httpd-volume configMap: name: config-httpd-configmap - name: certificates-volume configMap: name: httpd-certs-configmap
Save and close the file:
CODE:wq
Apply the YAML file to deploy and configure the Apache HTTPD container:
CODE$ kubectl apply -f ejbca-httpd.yml
Apache HTTPD is now deployed and configured for internal cluster resources to access.
Next steps
In this tutorial, you learned how to deploy EJBCA in MicroK8s using MariaDB as the database and configure access to EJBCA internally and externally.
To learn how to use a service mesh to issue mutual TLS certificates with EJBCA running in Kubernetes., follow the tutorial Deploy EJBCA container to issue certificates to an Istio service mesh.