How do I import a CA root certificate to trust store in JBoss EAP for OpenShift?

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 7.4
  • Red Hat OpenShift Container Platform (OCP)
    • 4

Issue

  • How do I import a CA root certificate to trust store in JBoss EAP for OpenShift?

  • update-ca-trust fails in a JBoss EAP Pod as follows. How do I update cacerts in the container?

    $ oc rsh <pod-name>
    sh-4.2$ update-ca-trust 
    p11-kit: couldn't create file: /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt: Permission denied
    p11-kit: couldn't create file: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem: Permission denied
    p11-kit: couldn't create file: /etc/pki/ca-trust/extracted/pem/email-ca-bundle.pem: Permission denied
    p11-kit: couldn't create file: /etc/pki/ca-trust/extracted/pem/objsign-ca-bundle.pem: Permission denied
    p11-kit: couldn't create file: /etc/pki/ca-trust/extracted/java/cacerts: Permission denied
    
  • keytool -import also fails in JBoss EAP Pod due to Permission denied:

    $ oc rsh <pod-name>
    sh-4.2$ keytool -import -keystore /usr/lib/jvm/java-1.8.0-openjdk/jre/lib/security/cacerts -trustcacerts -alias my-root-cert -file /opt/eap/standalone/configuration/root-ca.crt -storepass changeit -noprompt 
    Certificate was added to keystore
    keytool error: java.io.FileNotFoundException: /usr/lib/jvm/java-1.8.0-openjdk/jre/lib/security/cacerts (Permission denied)
    

Resolution

Option 1. Mount cacerts as a Secret - Runtime option:

Extract cacerts from the JBoss EAP container, add a root certificate to cacerts, and mount it as Secret. The sample steps are as follows.

NOTE: Updating the JBoss EAP container image will also update ca-certificates-<date-version>.el7_9.noarch package in the image. If you update the version of JBoss EAP image, you need to re-extract cacerts from the new version of the container image.

1. Deploy an arbitrary application to OpenShift

$ oc new-project eap74-test
$ oc create -f https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap74/templates/eap74-basic-s2i.json
$ oc create -f https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap74/eap74-openjdk8-image-stream.json

$ oc new-app --template=eap74-basic-s2i -p APPLICATION_NAME=helloworld -p IMAGE_STREAM_NAMESPACE=eap74-test -p EAP_IMAGE_NAME=jboss-eap74-openjdk8-openshift:7.4.0 -p EAP_RUNTIME_IMAGE_NAME=jboss-eap74-openjdk8-runtime-openshift:7.4.0 -p SOURCE_REPOSITORY_URL=https://github.com/jboss-developer/jboss-eap-quickstarts -p SOURCE_REPOSITORY_REF=7.4.x -p CONTEXT_DIR=helloworld-html5

$ oc get pod | grep Running
helloworld-1-mp7cl                   1/1     Running     0          19m

2. Extract the cacerts file from the pod

$ oc rsync helloworld-1-mp7cl:/etc/pki/ca-trust/extracted/java/cacerts .
$ ls
cacerts  root-ca.crt

3. Import a CA certificate to cacerts

$ chmod 744 cacerts
$ keytool -keystore cacerts -alias my-root-cert -import -file root-ca.crt -storepass changeit -noprompt
Certificate was added to keystore

4. Mount cacerts as a Secret

$ oc create secret generic cacerts --from-file=cacerts
$ oc set volume dc/helloworld --add --name=cacerts-vol -m /opt/eap/cert/ -t secret --secret-name=cacerts

5. Add -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword to replace default trusted store in the Pod

$ oc set env dc/helloworld JAVA_OPTS_APPEND="-Djavax.net.ssl.trustStore=/opt/eap/cert/cacerts -Djavax.net.ssl.trustStorePassword=changeit"

Option 2. Add a CA certification when building a container - Build time option:

If you have already created a custom EAP image with a Dockerfile, this is a simple option. The copy command will succeed given higher privileges at build time - see below:

USER root
COPY ./root-ca.crt /usr/share/pki/ca-trust-source/anchors/
RUN update-ca-trust 

Root Cause

  • update-ca-trust command requires privileges and cannot be run on JBoss EAP for OpenShift Pod.
  • The default java trust store /etc/pki/ca-trust/extracted/java/cacerts is read-only. We cannot update cacerts after JBoss EAP Pod has been started.
sh-4.2$ ls -l /etc/pki/ca-trust/extracted/java/cacerts
-r--r--r--. 1 root root 154622 Dec 13 05:57 /etc/pki/ca-trust/extracted/java/cacerts

The solution Injecting CA certificate inside OpenJDK container at runtime and build time, discuss a generalized approaches for this problem for OpenJDK containers including Service-CA Operator usage at runtime injection.

Components
Tags

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.