Skip to main content
Skip table of contents

Configure EJBCA Cloud with an AWS Application Load Balancer

This page outlines the configuration of EJBCA Cloud with an AWS Application Load Balancer (ALB), enabling TLS termination and forwarding of client certificates to EJBCA.

Overview

This guide assumes a deployment with two clustered EJBCA nodes connected to an external database. The Management CA certificate must be trusted in the browser accessing the load-balanced endpoint.

The target configuration uses an AWS Application Load Balancer (ALB) to terminate TLS and pass the SuperAdmin certificate through to EJBCA, with the following flow:

CODE
Client (mTLS)
      ↓
AWS ALB (mTLS terminates)
      ↓  (X-Amzn-Mtls-Clientcert header)
Apache httpd
      ↓  (SSL_CLIENT_CERT header)
WildFly (Undertow proxy-http)
      ↓
EJBCA Admin Web

For additional information on mTLS setup on an ALB, refer to the AWS documentation Configuring mutual TLS on an Application Load Balancer - Elastic Load Balancing.

Step 1 - Configure Health Check

To configure EJBCA Health Check service, do the following:

  1. Edit the /opt/ejbca/conf/ejbca.properties file on all the nodes to be load balanced, to allow health checks from external URLs.

  2. Add the following line to the ejbca.properties file:

    CODE
    healthcheck.authorizedips=ANY

    You can later change this to be the load balancer IP once you have it configured. You can get this from the AWS console or from the logs of Apache once the ALB is configured.

  3. Restart EJBCA with:

    CODE
    systemctl restart wildfly
  4. To validate that the health check works, go to the URL:

    CODE
    http://<HOST_FQDN>/ejbca/publicweb/healthcheck/ejbcahealth

You should see “ALLOK” if the health check works and the node is healthy.

Step 2 - Create a Target Group in EC2

To create a target group in the EC2 Console, do the following:

  1. In the EC2 Console, create a Target Group and specify the following:

    • Target group name

    • Protocol: HTTP

    • Port: 80

    • VPC: Same as EC2 Nodes

    • Health check protocol: HTTP

    • Health check path: Specify the path /ejbca/publicweb/healthcheck/ejbcahealth

    • Advanced health check settings:

      • Timeout: 60 seconds (health checks can slow when systems are under heavy loads - adjust accordingly).

      • Ensure the Interval is greater than the timeout value.

  2. Click Next and then select the EJBCA nodes that will be load balanced to.

    image-20260424-172532.png
  3. Click Include as pending below, then click Next and Create target group.

    image-20260424-172801.png
  4. Once the target group is created, select the target group, click the attributes tab, and select Edit.

  5. Under Target selection configuration, select Turn on stickiness and select the duration for 1 hour.

    image-20260424-212647.png

Step 3 - Configure Apache

AWS ALBs send the certificate header as:

CODE
X-Amzn-Mtls-Clientcert

Encoded like:

CODE
-----BEGIN%20CERTIFICATE-----%0A...

Yet, EJBCA requires:

CODE
-----BEGIN CERTIFICATE-----
...

You need to add a configuration file to decode it by performing the following steps:

  1. On each node to be load balanced, create the following file: /etc/httpd/conf.d/alb-mtls.lua.

  2. Add the following configuration to the file:

    CODE
    function alb_mtls_fixup(r)
        local cert = r.headers_in["X-Amzn-Mtls-Clientcert-Leaf"]
    
        if cert and cert ~= "" then
            -- Do NOT URL decode here.
            -- Undertow/WildFly certificate-forwarding expects SSL_CLIENT_CERT
            -- and can handle the URL-encoded cert value.
            cert = cert:gsub("%%(%x%x)", function(hex)
               return string.char(tonumber(hex, 16))
            end)
            r.headers_in["SSL_CLIENT_CERT"] = cert
    
            -- Optional debug
            r:warn("Set SSL_CLIENT_CERT from ALB mTLS header, first chars: " .. string.sub(cert, 1, 80))
        end
    
        return apache2.DECLINED
    end
  3. Enable the following modules in the Apache configuration:

    CODE
    vim /etc/httpd/conf.modules.d/00-base.conf
  4. Uncomment the following:

    CODE
    LoadModule headers_module modules/mod_headers.so
    LoadModule setenvif_module modules/mod_setenvif.so
  5. Edit the following file:

    CODE
    vim /etc/httpd/conf.modules.d/00-lua.conf
  6. Uncomment the following:

    CODE
    LoadModule lua_module modules/mod_lua.so
  7. Edit the following file:

    CODE
    vim /etc/httpd/conf.modules.d/00-proxy.conf
  8. Uncomment the following:

    CODE
    LoadModule proxy_http_module modules/mod_proxy_http.so
  9. Edit the configuration file for Apache/EJBCA:

    CODE
    vim /etc/httpd/extra/httpd-vhosts-app-nossl.conf
  10. Replace the content with the following:

    CODE
    Listen 80
    <VirtualHost *:80>
        DocumentRoot /var/www/html/
        ProxyPreserveHost On
        # Treat ALB-forwarded HTTPS as HTTPS for rewrite logic
        SetEnvIf X-Forwarded-Proto https HTTPS=on
    
        <Directory "/var/www/html">
            Header always set Content-Security-Policy "default-src 'self'"
            AllowOverride None
            Require all granted
        </Directory>
    
        LuaHookFixups /etc/httpd/conf.d/alb-mtls.lua alb_mtls_fixup
        RewriteEngine On
    
        # Disallow unsupported methods/protocols
        RewriteCond %{REQUEST_METHOD} !^(HEAD|GET|POST|PUT|DELETE)$ [NC,OR]
        RewriteCond %{THE_REQUEST} !HTTP/1\.[0,1]$
        RewriteRule .* - [F,L]
    
        # Allow encoded slashes for OCSP GET
        AllowEncodedSlashes On
    
        # If you want to go back to using AJP (default config-uncomment the next two lines and comment the two after)
        #ProxyPass /ejbca/ ajp://localhost:8009/ejbca/ keepalive=On ping=500ms retry=1 timeout=300 nocanon
        #ProxyPass        /ejbca/ http://127.0.0.1:8080/ejbca/ keepalive=On retry=1 timeout=300 nocanon
        ProxyPass        /ejbca/ http://127.0.0.1:8080/ejbca/ keepalive=On retry=1 timeout=300 nocanon
        ProxyPassReverse /ejbca/ http://127.0.0.1:8080/ejbca/
    
        ProxyPassReverse /ejbca/ http://127.0.0.1:8080/ejbca/
    
        ProxyPass /.well-known/ ajp://localhost:8009/.well-known/ keepalive=On ping=500ms retry=1 timeout=300
    
        # Keep these legacy redirects if you still want them
        RewriteRule ^/ejbca/publicweb/?$ / [R=302,L]
        RewriteRule ^/ejbca/?$ / [R=302,L]
    
        # Redirect admin and SOAP/API-style paths to HTTPS only when the original client request was not already HTTPS
        RewriteCond %{ENV:HTTPS} !=on
        RewriteRule ^/ejbca/adminweb(/.*)?$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
        RewriteCond %{ENV:HTTPS} !=on
        RewriteRule ^/ejbca/ejbcaws(/.*)?$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
        RewriteCond %{ENV:HTTPS} !=on
        RewriteRule ^/ejbca/ejbca-rest-api(/.*)?$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
        # Redirect non-proxied/non-static URLs to /
        RewriteRule !(^/favicon.ico$|^/img/.*|^/css/.*|^/index.html$|^/$|^/ejbca/.*|^/\.well-known/.*) / [L,R=301]
    
        ErrorDocument 404 /index.html
    
        # This is temporary so we can see the certificate come through in a log
        LogFormat "%h %l %u %t \"%r\" %>s mtls_leaf=\"%{X-Amzn-Mtls-Clientcert-Leaf}i\" ssl_client_cert=\"%{SSL_CLIENT_CERT}i\"" mtlsdebug
        CustomLog logs/mtls_access_log mtlsdebug
    </VirtualHost>
  11. Restart apache with:

    CODE
    systemctl restart httpd

Step 4 - Configure WildFly

To configure WildFly, do the following:

  1. Run the following command to edit the WildFly configuration to enable proxy-address and certificate forwarding:

    CODE
    /opt/wildfly/bin/jboss-cli.sh --connect <<'EOF'
    /subsystem=undertow/server=default-server/http-listener=remoting:write-attribute(name=proxy-address-forwarding,value=true)
    /subsystem=undertow/server=default-server/http-listener=remoting:write-attribute(name=certificate-forwarding,value=true)
    reload
    EOF

    This command will reload WildFly. Ensure that the server reloads successfully after the third command.

  2. Run the following commands to add a listener to WildFly for port 8080 so you can use http instead of AJP:

    CODE
    /opt/wildfly/bin/jboss-cli.sh --connect <<'EOF'
    /socket-binding-group=standard-sockets/socket-binding=proxy-http:add(interface=public,port=8080)
    /subsystem=undertow/server=default-server/http-listener=proxy-http:add(socket-binding=proxy-http,proxy-address-forwarding=true,certificate-forwarding=true,enable-http2=false)
    reload
    EOF

    This command will reload WildFly. Ensure that the server reloads successfully after the third command.

  3. Run the following to make sure the servlet request is marked as secure:

    CODE
    /opt/wildfly/bin/jboss-cli.sh --connect <<'EOF'
    /subsystem=undertow/server=default-server/http-listener=proxy-http:write-attribute(name=secure,value=true)
    reload
    EOF

    This command will reload WildFly. Ensure that the server reloads successfully after the third command.

Step 5 - Create a Security Group

To create a Security Group to allow the Load Balancer to talk to the EJBCA nodes and allow outbound traffic, do the following:

  1. Click Security Groups, then click Create.

  2. Get the internal IP addresses for the EJBCA nodes to be load balanced to, in this example 172.16.1.10 and 172.16.1.14.

  3. Create the security group according to the following example, by adding HTTP and HTTPS to each node.

image-20260424-183700.png

Step 6 - Create the Load Balancer

To create the load balancer, do the following:

  1. In the EC2 Console, click Load Balancer > Create Load Balancer, and select Create under Application Load Balancer:

    image-20260424-181847.png
  2. Provide values for the following:

    • Load balancer name: Specify a DNS name for the load balancer

    • VPC: Use current VPC the EJBCA Cloud nodes are on.

    • Select two Availability Zones.

    • Select the Security Group Created above.

    • Under Listeners and Routing:

      • Listener HTTP: 80.

      • Protocol: HTTP.

      • Port: 80.

      • Select the Target Group created previously.

      • Select Target Group Stickiness.

  3. Click Create Load Balancer.

Step 7 - Create certificate for ALB in EJBCA

To create a certificate for ALB in EJBCA, do the following:

  1. Go to the EJBCA RA Web and click Make new request.

  2. For Certificate Type: select the SslServerProfile.

  3. For Key-pair generation, select By the CA.

    image-20260424-191615.png
  4. Select a Key Algorithm such as RSA 4096.

  5. Locate the following FQDNs of the ALB and EJBCA nodes. For example:

    • ejbcacloud-15648816.us-east-1.elb.amazonaws.com

    • ec2-54-80-249-79.compute-1.amazonaws.com

    • ec2-98-93-144-174.compute-1.amazonaws.com
      Enter those values into the RA Web interface. Use the ALB FQDN as the Common Name (CN) of the certificate.

  6. Select Show more optional fields under Optional Subject Alternative Name Attributes section to allow for more DNS Names and add the ALB FQDN as the first value in the SAN and the two EJBCA node FQDNs in the next two fields.

    image-20260424-191736.png
  7. Enter a username and enrollment code.

  8. Select Download as PEM once the values are complete.

Step 8 - Create a Trust Store Bucket in S3

When configuring the ALB’s trust store, the only selectable method is to select a certificate stored in an S3 bucket. In this section, you will add the Management CA certificate to an S3 bucket so that you can select it in the ALB.

To create a trust store bucket in Amazon S3, do the following:

  1. Go to the AWS console and select Amazon S3.

  2. Create an S3 bucket using the defaults.

  3. To download the Management CA public certificate from the EJBCA Admin Web, select CA Functions > CA Structure and CRLs, and click Download PEM file.

    image-20260424-205434.png
  4. Upload the downloaded certificate to the newly created S3 bucket.

Step 9 - Configure an HTTPS Listener

To configure an HTTPS Listener, do the following:

  1. Select the Load Balancer previously created.

  2. Click Add Listener.

  3. Select the Protocol as HTTPS and ensure the Port = 443.

  4. Select the Target Group created previously.

  5. Under Target Group Stickiness, select Turn on target group stickiness.

    image-20260424-192152.png
  6. In the secure listener settings, select Import Certificate.

  7. Open the certificate generated in EJBCA in a text editor and paste the private key, certificate, and chain into the fields.

    image-20260424-185621.png
  8. Under Client certificate handling, select Mutual authentication and then select Verify with trust store.

  9. Under Trust store, select New trust store and provide a Trust store name.

    image-20260424-210538.png
  10. Under Certificate authority bundle, click Browse S3.

  11. Find and select the S3 bucket created, select the circle next to the PEM file uploaded earlier, and click Choose.

    image-20260424-210325.png
  12. Click Save Changes.

  13. Load the ALB URL in your browser. It should prompt for a certificate and load the user interface.

  14. Once all is working, comment out the log lines at the bottom of the /etc/httpd/extra/httpd-vhosts-app-nossl.conf file and restart Apache.

After completing these steps, EJBCA Cloud is accessible through the AWS Application Load Balancer with TLS termination and client certificate forwarding enabled.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.