Trusting custom or self-signed certificates (Docker/Podman)
Overview
Starting with 3.6.1-funcrel, CAST Imaging is delivered as hardened Docker/Podman images - minimal images that contain only what is required to run the application. Because these images do not include a shell or package manager, you cannot import certificates into them interactively.
This page explains how to build a Java trust store from the certificates already bundled in the image, add your own certificate to it, and mount it into the relevant CAST Imaging components. Do this when the components need to trust an internal or self-signed certificate authority (CA) for outbound connections, for example:
- a Nexus/Maven or .NET artifact repository,
- an intercepting HTTPS proxy,
- AIP SSO,
- CAST Extend.
The instructions apply to the Imaging Services components (control-panel, console, auth-service, gateway) and to the analysis-node.
This page covers outbound trust only. It does not cover inbound browser HTTPS (see HTTPS configuration) or certificate-based database authentication (see Configuring and using an encrypted database instance), both of which should use signed certificates in production.
Prerequisites
- A certificate to trust, referred to as
self_signed_cert.crtbelow. This can be the public certificate of the associated key or a CA certificate. - Access to the Docker (or Podman) CLI, and the ability to pull a CAST Imaging image locally.
- The ability to mount a local folder into a container.
Every docker command below works with podman. If you use Podman with SELinux enabled, see the SELinux notes in each step.
Step 1 - Build the trust store
Start a container with a local folder mounted, and call the bundled keytool to create a new trust store from the cacerts file inside the image:
$ docker run --rm -it --entrypoint keytool -v ./:/certs docker.io/castimaging/auth-service:<version> -importkeystore -srckeystore /usr/lib/jvm/temurin-25/lib/security/cacerts -destkeystore /certs/new_trust_store.p12 -srcstoretype PKCS12 -deststoretype PKCS12
You are prompted three times - twice to set and confirm the password for the new trust store, and once for the current password of the source cacerts (which defaults to changeit):
Enter destination keystore password:
Re-enter new password:
Enter source keystore password:
This creates a new_trust_store.p12 file in the current folder containing a copy of the certificates from the image’s Java distribution.
Replace <version> with your installed release, and adjust the cacerts path to match the JDK bundled in that release. The path follows the pattern /usr/lib/jvm/temurin-<major>/lib/security/cacerts:
- 3.6.1-funcrel to 3.6.3-funcrel use OpenJDK 21:
/usr/lib/jvm/temurin-21/lib/security/cacerts - 3.6.4-funcrel and later use OpenJDK 25:
/usr/lib/jvm/temurin-25/lib/security/cacerts
Notes:
- Podman with SELinux: mounting
./may fail. Instead, create a named volume (podman volume create my_volume_name) and mount it in place of./in the command above. Usepodman inspect my_volume_nameto locate the volume on disk if you want to copy the trust store out, or keep it in the volume to mount into the other containers later. - The certificates in
cacertseventually expire. If trust errors start occurring, rebuild the trust store. Tools such askeytoolcan list certificates and their expiry dates.
Step 2 - Import your certificate
Reuse the bundled keytool to import your certificate into the trust store created above:
$ docker run --rm -it --entrypoint keytool -v ./:/certs docker.io/castimaging/auth-service:<version> -importcert -alias nexus-cert -file /certs/self_signed_cert.crt -keystore /certs/new_trust_store.p12
You are prompted for the trust store password and whether to trust the certificate. Sample (trimmed) output:
Enter keystore password:
Owner: CN=, OU=, O=, L=, ST=, C=
Issuer: CN=, OU=, O=, L=, ST=, C=
Serial number: 4acf945a4c5a3c51
...
Trust this certificate? [no]: yes
Certificate was added to keystore
Notes:
- Accepted certificate file extensions are
.pem,.crt, and.cer. Other extensions may work but have not been tested. - If you have another trust store rather than a single certificate, you can merge the two together - see the
keytooldocumentation. - Podman with SELinux: copy your certificate into the volume folder before running the command. Use
podman inspect my_volume_nameto find the folder location.
Step 3 - Mount the trust store for Imaging Services
To make the components use the new trust store, add the trust store folder and JVM options to the .env file, then reference them from a docker-compose.override.yml file so that your changes persist across updates. See also Managing docker-compose.yml files and Managing .env files.
Edit /opt/cast/installation/imaging-services/.env and add:
# Path to the folder containing the new_trust_store (or the volume name)
JAVA_SSL_HOST_FOLDER=/path/to/folder
# Java options to customize the trust store used by the JVM
JAVA_SSL_OPTIONS="-Djavax.net.ssl.trustStore=/certs/new_trust_store.p12 -Djavax.net.ssl.trustStorePassword=********** -Djavax.net.ssl.trustStoreType=pkcs12"
Replace /path/to/folder with your host folder (or volume name), and set trustStorePassword to the trust store password you chose in Step 1.
Then create (or edit) /opt/cast/installation/imaging-services/docker-compose.override.yml and enable the trust store for the services that need it:
services:
control-panel:
volumes:
- ${JAVA_SSL_HOST_FOLDER}:/certs
environment:
- JDK_JAVA_OPTIONS=${JAVA_SSL_OPTIONS}
# auth-service:
# volumes:
# - ${JAVA_SSL_HOST_FOLDER}:/certs
# environment:
# - JDK_JAVA_OPTIONS=${JAVA_SSL_OPTIONS}
# gateway:
# volumes:
# - ${JAVA_SSL_HOST_FOLDER}:/certs
# environment:
# - JDK_JAVA_OPTIONS=${JAVA_SSL_OPTIONS}
console:
volumes:
- ${JAVA_SSL_HOST_FOLDER}:/certs
environment:
- JDK_JAVA_OPTIONS=${JAVA_SSL_OPTIONS}
Enable only the services that need the certificate. In this example auth-service and gateway are commented out because a Nexus repository is reached by control-panel and console. For a certificate used elsewhere (for example a self-signed certificate in AIP SSO), uncomment auth-service and gateway as required.
Restart the components so the change is taken into account:
$ cd /opt/cast/installation/imaging-services # navigate to the installation folder
$ sudo docker compose down # stop the containers
$ sudo docker compose up -d # start the containers in detached mode
$ sudo docker ps # check the containers are running
Step 4 - Mount the trust store for the Analysis Node
The procedure is the same as for Imaging Services - only the folder changes.
Edit /opt/cast/installation/imaging-node/.env and add the same two variables:
# Path to the folder containing the new_trust_store (or the volume name)
JAVA_SSL_HOST_FOLDER=/path/to/folder
# Java options to customize the trust store used by the JVM
JAVA_SSL_OPTIONS="-Djavax.net.ssl.trustStore=/certs/new_trust_store.p12 -Djavax.net.ssl.trustStorePassword=********** -Djavax.net.ssl.trustStoreType=pkcs12"
Then create (or edit) /opt/cast/installation/imaging-node/docker-compose.override.yml:
services:
analysis-node:
volumes:
- ${JAVA_SSL_HOST_FOLDER}:/certs
environment:
- JDK_JAVA_OPTIONS=${JAVA_SSL_OPTIONS}
Restart the node with the same docker compose down / docker compose up -d sequence shown above, run from /opt/cast/installation/imaging-node.
Verify
Start the components and confirm that the target connection now works - for example that the Nexus repository is reachable from CAST Imaging - and that no TLS or PKIX path building failed errors appear in the logs of the affected services.