Skip to main content

EJBCA Community Edition - Docker Compose Stack, build Certification Authority, issue Server TLS Certificate, test the secure TLS encryption

1142 words·
EJBCA Docker-Compose MariaDB Certification Authority

Here is my testing playground for a EJBCA based CA. This is not on production level since I did not deploy a Subordinate CA, instead I issued the server certificate directly with the root CA.

So far I think EJBCA is a very powerful tool but the documentation for the community edition is partly outdated. Also the environment variable TLS_SETUP_ENABLED=true was missing in the Docker Compose documentation, without that variable it’s not possible to issue the SuperAdmin certificate.

EJBCA Community Edition - Docker Compose Stack
#

Folder Structure
#

# Create folder structure
sudo mkdir -p /opt/ejbca/mariadb && cd /opt/ejbca

DNS Entry
#

# Create a DNS record for ejbca
192.168.30.91 ejbca.jklug.local

Docker Compose
#

# Create Docker Compose file
sudo vi docker-compose.yml
version: '3.9'
services:

  mariadb:
    image: mariadb:latest
    container_name: ejbca-database
    environment:
      - MYSQL_ROOT_PASSWORD=foo123
      - MYSQL_DATABASE=ejbca
      - MYSQL_USER=ejbca
      - MYSQL_PASSWORD=ejbca
    volumes:
      - ./mariadb:/var/lib/mysql:rw
    restart: unless-stopped

  ejbca-ce:
    hostname: ejbca.jklug.local
    container_name: ejbca-ce
    image: keyfactor/ejbca-ce:latest
    depends_on:
      - mariadb
    environment:
      - DATABASE_JDBC_URL=jdbc:mariadb://ejbca-database:3306/ejbca?characterEncoding=UTF-8
      - LOG_LEVEL_APP=INFO
      - LOG_LEVEL_SERVER=INFO
      - TLS_SETUP_ENABLED=simple
      - TLS_SETUP_ENABLED=true
    ports:
      - "80:8080"
      - "443:8443"
    restart: unless-stopped

Start Container
#

# Start container
sudo docker compose up -d

Check Logs
#

Check the container logs and wait till the end where the URL and password are listed:

# Check logs
sudo docker compose logs -f
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) ***********************************************************************************************
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *                                                                                             *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) * A fresh installation was detected and a ManagementCA was created for your initial           *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) * administration of the system.                                                               *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *                                                                                             *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) * Initial SuperAdmin client certificate enrollment URL (adapt port to your mapping):          *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *                                                                                             *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *   URL:      https://ejbca.jklug.local:443/ejbca/ra/enrollwithusername.xhtml?username=superadmin *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *   Password: QOVHATeCTRXi3EcqJLJDd4Xg                                                        *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *                                                                                             *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) * Once the P12 is downloaded, use "QOVHATeCTRXi3EcqJLJDd4Xg" to import it.                    *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) *                                                                                             *
ejbca-ce        | 2024-01-26 22:29:49,823+0000 INFO  [/opt/keyfactor/bin/start.sh] (process:1) ***********************************************************************************************

Issue SuperAdmin certificate
#

The following SuperAdmin certificate is password protected and later used to access the actual EJBCA webinterface. It’s necessary to import the SuperAdmin certificate into the browser.

Use the URL and password from the Docker logs:

# Open the webinterface in a browser
https://192.168.30.91:443/ejbca/ra/enrollwithusername.xhtml?username=superadmin

# Password:
QOVHATeCTRXi3EcqJLJDd4Xg

Import Certificate
#

# Open browser settings: Firefox
about:preferences#privacy
  • Import the SuperAdmin.p12 certificate
  • Enter the password QOVHATeCTRXi3EcqJLJDd4Xg

Access EJBCA CA UI
#

https://ejbca.jklug.local/ejbca/adminweb/

Create Root Certificate Authority
#

Certificate Profiles
#

Create a “JKW-RootCA-Profile”

  • Disable Authority Key ID > Use
  • Disable Subject Alternative Name > Use
  • Disable Issuer Alternative Name > Use
  • Disable LDAP DN order > Use

Crypto Tokens
#

  • Create a CryptoToken “JKW-RootCA-CryptoToken”

  • Type SOFT stores the keys encrypted in the database

  • Define authentication code. After the container reboot the crypto token must be activated using the authentication code

  • Optional: Check “Auto-activation” to automatically activate the crypto token after a container reboot

  • Create a sign key “JKW-RootCA-SignKey0001” for the crypto token
  • Create a encryption key “JKW-RootCA-EncryptKey0001” for the crypto token
  • Create a test key “Testkey” for the crypto token

c

Certification Authorities
#

  • Create new Certification Authoritie “JKW-RootCA”
  • Select Crypto Token > JKW-RootCA-CryptoToken

  • Select defaultKey > JKW-RootCA-EncryptKey0001

  • Select certSignKey > JKW-RootCA-SignKey0001

  • Select testKey > Testkey

  • Define Subject DN > CN=JKW-RootCA,O=JKW,C=AT

  • Define Validity > 30 years 30y

  • Disable LDAP DN order > Use

  • Define CRL Expire Period (Certificate Revocation List) > three months 3mo
  • Create certification authority

Export / Import Certificates
#

Export Certificates
#

Export both the “ManagementCA” certificate that enables the secure connection to the https://ejbca.jklug.local/ejbca/adminweb/ interface and the newly create CA certificate:

ManagementCA: ManagementCA.crt

JKW-RootCA: JKWRootCA.crt

  • Go to the RA Web section
  • Go to CA Certificates and CRLs

  • Click Internet Explorer to export the certificates

ManagementCA certificate: JKWRootCA.crt

JKW-RootCA certificate: JKWRootCA.crt

Import Certificates
#

Open the MMC Certificate Manager for local computer:

# Run 
certlm.msc
  • Import both the “JKWRootCA.crt” and the “ManagementCA.crt” certificates:

TLS Server Certificate
#

Certificate Profiles
#

  • Create a new template: “JKW-TLS-Server-Profile”
  • Edit the profile
  • Define Available Key Algorithms

  • Define Available Bit Lengths

  • Define Validity or end date of the certificate

  • Disable Basic Constraints > Use...

  • Select Key Usage > Digital Signature & Key encipherment

  • Select Extended Key Usage > Server Authentication

  • Disable Issuer Alternative Name > Use...

Optional:

  • Enable CRL Distribution Points > Use...

  • Enable Use CA defined CRL Distribution Point > Use...

  • Enable Authority Information Access > Use...

  • Enable Use CA defined OCSP locator > Use...

  • Enable Use CA defined CA issuer > Use...

  • Disable LDAP DN order > Use

  • Define the CA: “JKW-Root-CA”


End Entity Profiles
#

  • Create a end entitity profile
  • Edit the profile
  • Disable End Entity E-mail > Use

  • Check CN, Common name > Required & Modifiable

  • Add O, Organization, Check Required

  • Add C, Country, Check Required

  • Add DNS Name: Check Use entity CN field

  • Add DNS Name: Blank DNS name

  • Define Available Certificate Profiles > JKW-TLS-Server-Profile

  • Define Available CAs > JKW-RootCA

  • Define Available Tokens > User Generated & PEM file

  • Save the profile

Server Certificate
#

  • Go to the RA Web section
  • Go to Enroll > Make New Request
  • Select the earlier created TLS Server Profile in the Certificate Type section
  • Define a Common Name and the DNS Name for the certificate
  • Define a Username and Password for the certificate enrollment

Nginx Certificate Test
#

TLS Server Certificate
#

# Create folder for the TLS server certificate
sudo mkdir -p /etc/certs/nginx.jklug.work
  • Add the newly created certificate
# Set permissions
sudo chmod 0400 /etc/certs/nginx.jklug.work/nginx.pem

HTML Test Website
#

# Create folder for website
sudo mkdir -p /var/www/nginx.jklug.local

# Change permissions
sudo chmod 0755 /var/www/nginx.jklug.local

# Create html file
sudo vi /var/www/nginx.jklug.local/index.html

# Change permissions
sudo chmod 644 /var/www/nginx.jklug.local/index.html
<!-- /var/www/nginx.jklug.local/index.html -->
<!DOCTYPE html>
<html>

<head>
	<title>EJBCA TLS Test</title>
</head>

<body>
	<h1>EJBCA TLS Test</h1>
</body>

</html>

Virtual Host Configuration
#

# Install nginx
sudo apt install nginx

# Copy the default virtual host configuration
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/nginx.jklug.local

# Edit the new virtual host configuration
sudo vi /etc/nginx/sites-available/nginx.jklug.local
server {
    listen 80;
    listen [::]:80;
    server_name nginx.jklug.local;
    return 302 https://$server_name$request_uri;
}

server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;


    ssl_certificate         /etc/certs/nginx.jklug.local/nginx.pem;
    ssl_certificate_key     /etc/certs/nginx.jklug.local/nginx.pem;

    server_name nginx.jklug.local;

    root /var/www/nginx.jklug.local;
    index index.html index.htm;


    location / {
            try_files $uri $uri/ =404;
    }
}

Note: EJBCA only exports one .pem certificate file that includes both the key and the chain. In the Nginx virtual host configuration just point both ssl_certificate and ssl_certificate_key to the same .pem certificate file.

# Disable default configuration
sudo rm /etc/nginx/sites-enabled/default

# Enable the virtual host configuration
sudo ln -s /etc/nginx/sites-available/nginx.jklug.local /etc/nginx/sites-enabled/

# Restart Nginx
sudo systemctl restart nginx

Test TLS Encryption
#


Links #

# Official Documentation
https://doc.primekey.com/ejbca/tutorials-and-guides/quick-start-guide-start-ejbca-container-with-client-certificate-authenticated-access

https://doc.primekey.com/ejbca/tutorials-and-guides/tutorial-start-out-with-ejbca-docker-container

https://doc.primekey.com/ejbca/tutorials-and-guides/tutorial-create-your-first-root-ca-using-ejbca

https://doc.primekey.com/ejbca/tutorials-and-guides/tutorial-create-a-pki-hierarchy-in-ejbca

https://doc.primekey.com/ejbca/tutorials-and-guides/tutorial-issue-tls-server-certificates-with-ejbca