Chapter 5. Use custom CA certificates
If containers communicate with services secured by a private Certificate Authority (CA), you must add the root CA certificates to the container image. This ensures that the container can verify the identity of internal endpoints and establish secure, encrypted TLS connections.
5.1. Use OpenSSL-based images with custom CA certificates Copy linkLink copied to clipboard!
In OpenSSL-based container images, such as curl and nginx, you can make your custom root Certificate Authority (CA) certificates available to the image. Your application can then establish secure TLS connections to services that use certificates signed by your company’s CA.
5.1.1. Replace system CA certificates in OpenSSL-based images by using Podman Copy linkLink copied to clipboard!
Use the Podman volume mount option to override the image’s Certificate Authority (CA) bundle if you require only a custom certificate bundle in an OpenSSL-based image. The application in your image then uses only the custom bundle.
Prerequisites
-
The
podmanpackage is installed. - You have the CA certificate bundle in PEM format.
Procedure
When you start the container, use a bind mount to pass the certificate bundle to the container. For example:
$ podman run \ --rm \ --volume <path_to_certificate_bundle>.pem:/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:ro,Z \ registry.access.redhat.com/hi/<image>ImportantThis approach replaces the image’s built-in CA certificate bundle. If you require that your container trusts multiple CAs, ensure that all required CA certificates are part of the file that you mount to the container.
5.1.2. Replace system CA certificates by injecting the cluster-wide CA bundle in OpenSSL-based images on OpenShift Container Platform Copy linkLink copied to clipboard!
If you require only a custom certificate bundle in an OpenSSL-based image, you can use an OpenShift Container Platform ConfigMap to override the image’s Certificate Authority (CA) bundle. The application in your image then uses only the custom bundle.
Prerequisites
- You have access to OpenShift Container Platform CLI.
- The cluster administrator added the custom CA bundle to the cluster-wide proxy.
- You have the permissions to create ConfigMaps and modify Pod specifications in the target namespace.
Procedure
Display the name of the ConfigMap that contains the cluster-wide trusted certificates:
$ oc get proxy/cluster -o jsonpath='{.spec.trustedCA.name}'ca-bundleCreate a YAML configuration file that both requests the cluster-wide CA bundle and defines the volume mount necessary for your application to access it:
apiVersion: v1 kind: ConfigMap metadata: name: trusted-ca labels: config.openshift.io/inject-trusted-cabundle: "true" --- apiVersion: v1 kind: Pod spec: containers: - name: app image: registry.access.redhat.com/hi/<image>:latest volumeMounts: - name: trusted-ca mountPath: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem subPath: ca-bundle.crt readOnly: true volumes: - name: trusted-ca configMap: name: trusted-caThis configuration uses the
config.openshift.io/inject-trusted-cabundle: "true"label to trigger the automatic injection of the cluster CA bundle into the ConfigMap. ThesubPath: ca-bundle.crtproperty mounts the certificate at the path required by OpenSSL.Apply the configuration:
$ oc apply -f <configuration_file>.yaml
5.1.3. Replace system CA certificates by injecting a custom CA bundle in OpenSSL-based images on OpenShift Container Platform Copy linkLink copied to clipboard!
If you require only a custom certificate bundle in an OpenSSL-based image, you can use an OpenShift Container Platform ConfigMap to override the image’s Certificate Authority (CA) bundle. The application in your image then uses only the custom bundle.
Prerequisites
- You have access to OpenShift Container Platform CLI.
- You have the CA certificate bundle in PEM format.
- You have the permissions to create ConfigMaps and modify Pod specifications in the target namespace.
Procedure
Create a YAML configuration file that both defines the CA bundle and the volume mount necessary for your application to access it:
apiVersion: v1 kind: ConfigMap metadata: name: custom-ca-bundle data: tls-ca-bundle.pem: | -----BEGIN CERTIFICATE----- <certificate> -----END CERTIFICATE----- <more_certificates_if_needed> --- apiVersion: v1 kind: Pod spec: containers: - name: app image: registry.access.redhat.com/hi/<image>:latest volumeMounts: - name: custom-ca mountPath: /etc/pki/ca-trust/extracted/pem readOnly: true volumes: - name: custom-ca configMap: name: custom-ca-bundleApply the configuration:
$ oc apply -f <configuration_file>.yaml
5.1.4. Create a modified OpenSSL-based image to add custom root CA certificates Copy linkLink copied to clipboard!
If you require that an OpenSSL-based image trusts both your custom Certificate Authorities (CAs) and the image’s built-in default CAs, create a modified image to add the custom certificates.
Prerequisites
-
The
podmanpackage is installed.
Procedure
Create a project directory. For example:
$ mkdir ~/project/Copy the custom CA certificate to your project directory:
$ cp <path>/custom-root-ca.pem ~/project/Create a file named
~/project/Containerfile, that references the Red Hat Hardened Images in theFROMinstructions. For example:# Build stage: FROM registry.access.redhat.com/hi/curl:latest-builder AS builder # Copy the certificate to the image COPY custom-root-ca.pem /tmp/ # Temporarily switch to root to add the CA certificate to the truststore USER root RUN trust anchor /tmp/custom-root-ca.pem USER ${CONTAINER_DEFAULT_USER} # Runtime stage: # Copy the truststore from the builder image to the runtime image FROM registry.access.redhat.com/hi/curl:latest COPY --from=builder /etc/pki/ca-trust/extracted /etc/pki/ca-trust/extractedBuild the custom image:
$ podman build -t <image_name> ~/project/The
-t <image_name>option specifies the name of the image after the build process.Optional: Display the list of images:
$ podman image listREPOSITORY TAG IMAGE ID CREATED SIZE localhost/<image_name> latest 2cd25ce7a7ef 2 minutes ago 51 MBCreate a container that uses the image. For example:
$ podman run --rm <image_name>:latest https://intranet.example.com
5.2. Use Python images with custom CA certificates Copy linkLink copied to clipboard!
You can make your custom root Certificate Authority (CA) certificates available to Python images. Your application can then establish secure TLS connections to services that use certificates signed by your company’s CA.
Python libraries search for trusted certificates in different locations:
The built-in
urlliblibrary reads the CAs from the following locations:-
/etc/pki/tls/cert.pem- the main CA bundle file -
/etc/pki/tls/certs/- a directory with hashed certificate symbolic links
-
The third-party
requestslibrary only uses the path defined in theREQUESTS_CA_BUNDLEenvironment variable.The
requestslibrary is not included in the standard Python image. If you want to use it, you must create a custom image.
5.2.1. Replace system CA certificates in Python images by using Podman Copy linkLink copied to clipboard!
Use the Podman volume mount option to override the image’s Certificate Authority (CA) bundle if you require only a custom certificate bundle in a Python image. The application in your image then uses only the custom bundle.
Prerequisites
-
The
podmanpackage is installed. - You have the CA certificate bundle in PEM format.
Procedure
When you start the container, use a bind mount to pass the certificate bundle to the container. For example:
$ podman run \ --rm \ --volume <path_to_certificate_bundle>.pem:/etc/pki/tls/cert.pem:ro,Z \ --tmpfs /etc/pki/tls/certs:notmpcopyup \ --env REQUESTS_CA_BUNDLE=/etc/pki/tls/cert.pem \ registry.access.redhat.com/hi/pythonThis command mounts your CA bundle to the
/etc/pki/tls/cert.pemfile, sets the$REQUESTS_CA_BUNDLEenvironment variable to it, and blocks the directory with the hashes by overriding it with an emptytmpfsoverlay.ImportantThis approach replaces the image’s built-in CA certificate bundle. If you require that your container trusts multiple CAs, ensure that all required CA certificates are part of the file that you mount to the container.
5.2.2. Replace system CA certificates by injecting the cluster-wide CA bundle in Python images on OpenShift Container Platform Copy linkLink copied to clipboard!
If you require only a custom certificate bundle in a Python image, you can use an OpenShift Container Platform ConfigMap to override the image’s Certificate Authority (CA) bundle. The application in your image then uses only the custom bundle.
Prerequisites
- You have access to OpenShift Container Platform CLI.
- The cluster administrator added the custom CA bundle to the cluster-wide proxy.
- You have the permissions to create ConfigMaps and modify Pod specifications in the target namespace.
Procedure
Display the name of the ConfigMap that contains the cluster-wide trusted certificates:
$ oc get proxy/cluster -o jsonpath='{.spec.trustedCA.name}'ca-bundleCreate a YAML configuration file that both defines the CA bundle and the volume mount necessary for your application to access it:
apiVersion: v1 kind: ConfigMap metadata: name: trusted-ca labels: config.openshift.io/inject-trusted-cabundle: "true" --- apiVersion: v1 kind: Pod spec: containers: - name: app # Use registry.access.redhat.com/hi/python if you require only urllib # Use your custom image with the requests library installed for both libraries image: registry.access.redhat.com/hi/python env: - name: REQUESTS_CA_BUNDLE value: /etc/pki/tls/cert.pem volumeMounts: - name: trusted-ca mountPath: /etc/pki/tls/cert.pem subPath: ca-bundle.crt readOnly: true - name: empty-certs mountPath: /etc/pki/tls/certs readOnly: true volumes: - name: trusted-ca configMap: name: trusted-ca - name: empty-certs emptyDir: {}Apply the configuration:
$ oc apply -f <configuration_file>.yaml
5.2.3. Replace system CA certificates by injecting a custom CA bundle in Python images on OpenShift Container Platform Copy linkLink copied to clipboard!
If you require only a custom certificate bundle in a Python image, you can use an OpenShift Container Platform ConfigMap to override the image’s Certificate Authority (CA) bundle. The application in your image then uses only the custom bundle.
Prerequisites
- You have access to OpenShift Container Platform CLI.
- You have the CA certificate bundle in PEM format.
- You have the permissions to create ConfigMaps and modify Pod specifications in the target namespace.
Procedure
Create a YAML configuration file that both defines the CA bundle and the volume mount necessary for your application to access it:
apiVersion: v1 kind: ConfigMap metadata: name: custom-ca-bundle data: cert.pem: | -----BEGIN CERTIFICATE----- <certificate> -----END CERTIFICATE----- <more_certificates_if_needed> --- apiVersion: v1 kind: Pod spec: containers: - name: app # Use registry.access.redhat.com/hi/python if you require only urllib # Use your custom image with the requests library installed for both libraries image: registry.access.redhat.com/hi/python env: - name: REQUESTS_CA_BUNDLE value: /etc/pki/tls/cert.pem volumeMounts: - name: custom-ca mountPath: /etc/pki/tls/cert.pem subPath: cert.pem readOnly: true - name: empty-certs mountPath: /etc/pki/tls/certs readOnly: true volumes: - name: custom-ca configMap: name: custom-ca-bundle - name: empty-certs emptyDir: {}Apply the configuration:
$ oc apply -f <configuration_file>.yaml
5.2.4. Add a custom CA bundle to Python images by using Podman Copy linkLink copied to clipboard!
If you require that a Python image trusts both your custom Certificate Authorities (CAs) and the image’s built-in default CAs, use the Podman volume mount option to mount the custom certificate to the image. The application in your image can then use all these certificates.
Prerequisites
-
The
podmanpackage is installed. - You have the CA certificate bundle in PEM format.
Procedure
Store the hash of the certificate’s subject name in a temporary environment variable:
$ CA_HASH=$(openssl x509 -noout -subject_hash -in <path_to_certificate>.pem)When you start the container, use a bind mount to pass the certificate to the container. For example:
$ podman run \ --rm \ --volume <path_to_certificate>.pem:/etc/pki/tls/certs/${CA_HASH}.0:ro,Z \ --env REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ \ registry.access.redhat.com/hi/pythonThis command uses the hash in the
CA_HASHenvironment variable to define the destination of the bind mount. Additionally, it sets theREQUESTS_CA_BUNDLEenvironment variable in the image to the/etc/pki/tls/certs/directory.
5.2.5. Add a custom CA bundle to Python images on OpenShift Container Platform Copy linkLink copied to clipboard!
If you require that a Python image trusts both your custom Certificate Authorities (CAs) and the image’s built-in default CAs, use an OpenShift Container Platform ConfigMap to mount the custom certificate to the image. The application in your image can then use all these certificates.
Prerequisites
- You have access to OpenShift Container Platform CLI.
- You have the CA certificate bundle in PEM format.
- You have the permissions to create ConfigMaps and modify Pod specifications in the target namespace.
Procedure
Display the hash of the certificate’s subject name:
$ openssl x509 -noout -subject_hash -in <path_to_certificate>.pem12abc456You require the hash when you mount the ConfigMap into the Pod specification.
Create a YAML configuration file that both defines the CA bundle and the volume mount necessary for your application to access it:
apiVersion: v1 kind: ConfigMap metadata: name: custom-ca data: ca.crt: | -----BEGIN CERTIFICATE----- <certificate> -----END CERTIFICATE----- <more_certificates_if_needed> --- apiVersion: v1 kind: Pod spec: containers: - name: app # Use registry.access.redhat.com/hi/python if you require only urllib # Use your custom image with the requests library installed for both libraries image: registry.access.redhat.com/hi/python env: - name: REQUESTS_CA_BUNDLE value: /etc/pki/tls/certs/ volumeMounts: - name: custom-ca # Append .0 to the hash mountPath: /etc/pki/tls/certs/<hash>.0 subPath: ca.crt readOnly: true volumes: - name: custom-ca configMap: name: custom-caApply the configuration:
$ oc apply -f <configuration_file>.yaml
5.3. Use Java images with custom CA certificates Copy linkLink copied to clipboard!
You can make your custom root Certificate Authority (CA) certificates available to Java images. Your application can then establish secure TLS connections to services that use certificates signed by your company’s CA.
Java uses the Java KeyStore (JKS) or Public-Key Cryptography Standards #12 (PKCS12) formats for key storage. However, you can import certificates in PEM files.
The key stores require a password for integrity checking. For the system truststore, the default password is changeit. This simple default password is intended for tamper detection and integrity verification rather than cryptographic confidentiality.
5.3.1. Add or replace custom CA certificates in Java images by using Podman Copy linkLink copied to clipboard!
To add a custom Certificate Authority (CA) bundle to a Java image, you can use an OpenShift Container Platform ConfigMap. You can select whether you want to add your custom CA bundle to the existing truststore or create a new truststore that contains only your CA bundle.
Procedure
Create a storage volume:
$ podman volume create <volume_name>Enter the Podman user namespace shell:
$ podman unshareMount the volume:
$ podman volume mount <volume_name>/home/<user>/.local/share/containers/storage/volumes/<volume_name>/_dataCopy your custom certificate to the volume:
# cp <path_to_certificate>.pem \ /home/<user>/.local/share/containers/storage/volumes/<volume_name>/_data/Exit the user namespace shell:
# exitIf you want to add your custom CA bundle to the existing truststore, you must first export it:
$ podman run \ --rm \ --volume <volume_name>:/work/:Z \ --user 0 registry.access.redhat.com/hi/openjdk:latest \ cp /etc/pki/ca-trust/extracted/java/cacerts /work/cacertsThe command extracts the CA certificates from the Java truststore and stores it in the
cacertsfile on the storage volume.Skip this step if you want to trust only your custom CAs.
Import the custom CA certificate into the Java truststore:
$ podman run \ --rm \ --volume <volume_name>:/work:Z \ registry.access.redhat.com/hi/openjdk:latest \ keytool \ -import \ -noprompt \ -trustcacerts \ -alias <unique_name> \ -file /work/<certificate_file_name>.pem \ -keystore /work/cacerts \ -storepass changeit \ -storetype JKSThe default password of the system truststore is
changeit. The-alias <unique_name>option sets the name for the certificate in the truststore. It can be any value.
Verification
Start an OpenJDK container and mount the storage volume with the truststore to the
/etc/pki/ca-trust/extracted/java/cacertsfile:# podman run --rm \ --volume <volume_name>/cacerts:/etc/pki/ca-trust/extracted/java/cacerts:ro,Z \ registry.access.redhat.com/hi/openjdk:latest \ java -jar <application>.jar
5.3.2. Add or replace custom CA certificates in Java images on OpenShift Container Platform Copy linkLink copied to clipboard!
Use an OpenShift Container Platform ConfigMap to add a custom Certificate Authority (CA) bundle to a Java image. You can select whether you want to add your custom CA bundle to the existing truststore or if you want to create a new truststore that contains only your CA bundle.
Prerequisites
- You have access to OpenShift Container Platform CLI.
- You have the CA certificate bundle in PEM format.
- You have the permissions to create ConfigMaps and modify Pod specifications in the target namespace.
Procedure
Create a YAML configuration file that both defines the CA bundle and the volume mount necessary for your application to access it:
apiVersion: v1 kind: ConfigMap metadata: name: custom-ca data: ca.crt: | -----BEGIN CERTIFICATE----- <certificate> -----END CERTIFICATE----- <more_certificates_if_needed> --- apiVersion: v1 kind: Pod spec: initContainers: - name: prepare-truststore image: quay.io/hummingbird/openjdk:latest command: ["sh", "-c"] args: - | # 1. Copy the default Java truststore to a writable location # Skip this step if you want to trust only your custom CAs cp /etc/pki/ca-trust/extracted/java/cacerts /truststore/cacerts chmod 666 /truststore/cacerts # 2. Import your file into the truststore (default password: changeit) keytool -import -noprompt -trustcacerts -alias custom-ca \ -file /ca/ca.crt -keystore /truststore/cacerts \ -storepass changeit -storetype JKS volumeMounts: - name: custom-ca mountPath: /ca - name: truststore mountPath: /truststore containers: - name: app image: registry.access.redhat.com/hi/openjdk:latest volumeMounts: - name: truststore mountPath: /etc/pki/ca-trust/extracted/java readOnly: true volumes: - name: custom-ca configMap: name: custom-ca - name: truststore emptyDir: {}Apply the configuration:
$ oc apply -f <configuration_file>.yaml
5.3.3. Create a modified Java image to add custom root CA certificates Copy linkLink copied to clipboard!
If you require that a Java image trusts both your custom Certificate Authorities (CAs) and the image’s built-in default CAs, create a modified image to add the custom certificates. This avoids the need to generate the truststore on each container startup.
Prerequisites
-
The
podmanpackage is installed.
Procedure
Create a project directory. For example:
$ mkdir ~/project/Copy the custom CA certificate to your project directory:
$ cp <path>/custom-root-ca.pem ~/project/Create a file named
~/project/Containerfile, that references the Red Hat Hardened Images in theFROMinstructions. For example:# Build stage: FROM registry.access.redhat.com/hi/openjdk:latest-builder AS builder # Copy the certificate to the image COPY custom-root-ca.pem /tmp/ # Temporarily switch to root to add the CA certificate to the truststore USER root RUN trust anchor /tmp/custom-root-ca.pem USER ${CONTAINER_DEFAULT_USER} # Runtime stage: # Copy the truststore from the builder image to the runtime image FROM registry.access.redhat.com/hi/openjdk:latest COPY --from=builder /etc/pki/ca-trust/extracted /etc/pki/ca-trust/extractedBuild the custom image:
$ podman build -t <image_name> ~/project/The
-t <image_name>option specifies the name of the image after the build process.Optional: Display the list of images:
$ podman image listREPOSITORY TAG IMAGE ID CREATED SIZE localhost/<image_name> latest 03ca4c30326a 4 seconds ago 343 MBCreate a container that uses the image. For example:
$ podman run --rm <image_name>:latest ...