# Transparently Distributing Your Private CA to Java Applications > **Warning**: This tutorial requires an unreleased version of trust-manager that adds support for JKS: https://github.com/cert-manager/trust-manager/pull/122. In this example, we will be configuring a pod that runs a Java application to transparently trust a private CA. This tutorial works with Java applications running in Debian images. It needs to be adapted when using other distributions. The first step is to install cert-manager and trust-manager: ```bash helm upgrade -i -n cert-manager cert-manager jetstack/cert-manager --set installCRDs=true --wait --create-namespace helm upgrade -i -n cert-manager trust-manager jetstack/trust-manager --wait ``` We will use a fake Jenkins server served over HTTPS using a certificate signed by a private CA managed by cert-maanger. Since deploying Jenkins requires lots of moving parts, we won't be deploying a real Jenkins instance. Instead, we will be creating an HTTP server that responds "I am a fake server". We will be using Caddy for that. To deploy our fake Jenkins server, apply the following manifests: ```yaml apiVersion: v1 kind: Service metadata: name: fakejenkins namespace: cert-manager spec: selector: name: fakejenkins ports: - protocol: TCP port: 8443 targetPort: 8443 --- apiVersion: v1 kind: Pod metadata: name: fakejenkins namespace: cert-manager labels: name: fakejenkins spec: containers: - name: fakejenkins image: caddy ports: - containerPort: 8443 volumeMounts: - name: fakejenkinsfile mountPath: /etc/Caddyfile subPath: Caddyfile - name: ca mountPath: /var/run/secrets/ca command: ["caddy", "run", "--config", "/etc/Caddyfile", "--adapter", "caddyfile"] volumes: - name: fakejenkinsfile configMap: name: fakejenkinsfile - name: ca secret: secretName: trust-manager-example-ca-secret items: - key: tls.crt path: tls.crt - key: tls.key path: tls.key --- apiVersion: v1 kind: ConfigMap metadata: name: fakejenkinsfile namespace: cert-manager data: Caddyfile: | { skip_install_trust auto_https disable_redirects } https://fakejenkins.cert-manager.svc.cluster.local:8443 { tls /var/run/secrets/ca/tls.crt /var/run/secrets/ca/tls.key respond /cli* "I am a fake server" 200 header { Content-Type "text/html" X-Jenkins "2.387.2" X-Hudson "1.395" } } --- apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: trust-manager-selfsigned-issuer spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: trust-manager-example-ca namespace: cert-manager spec: isCA: true commonName: fakejenkins.cert-manager.svc.cluster.local dnsNames: [fakejenkins.cert-manager.svc.cluster.local] secretName: trust-manager-example-ca-secret privateKey: algorithm: ECDSA size: 256 issuerRef: name: trust-manager-selfsigned-issuer kind: ClusterIssuer group: cert-manager.io ``` Now, let us create a bundle to distribute our private CA. ```yaml apiVersion: trust.cert-manager.io/v1alpha1 kind: Bundle metadata: name: example-bundle spec: sources: - secret: name: trust-manager-example-ca-secret key: tls.crt target: configMap: key: "trust-bundle.pem" additionalFormats: jks: key: trust-bundle.jks ``` > **Note**: The public CAs present in the container won't be available anymore. You have the possibility to distribute the public CAs along with your private CA by adding the source `useDefaultCAs: true`: > > ```yaml > sources: > - useDefaultCAs: true > ``` Now, let us run a pod with `jenkins-cli.jar`. This pod relies on Java 8. Java 8 doesn't support loading PEM-encoded certificates. It only became possible to use PEM-encoded certificates with Java 11 and earlier. ```yaml apiVersion: v1 kind: Pod metadata: name: jenkins labels: name: jenkins spec: volumes: - name: trust-bundle-jks configMap: name: example-bundle items: - key: trust-bundle.jks path: cacerts terminationGracePeriodSeconds: 1 containers: - name: jenkins image: dynamictivity/jenkins-cli env: - name: JENKINS_URL value: https://fakejenkins.cert-manager.svc.cluster.local:8443 volumeMounts: - name: trust-bundle-jks mountPath: /etc/ssl/certs/java/cacerts subPath: cacerts command: ["bash", "-c", "sleep 1000000"] ``` Let us see if the HTTPS connection works: ```bash $ kubectl exec -it jenkins -- ./jenkins-cli-wrapper.sh There's no Jenkins running at https://fakejenkins.cert-manager.svc.cluster.local:8443/cli?remoting=false, or is not serving the HTTP Duplex transport ``` This means that the TLS connection was successfully established. We can now check the contents of the Java trust store: ```bash $ kubectl exec -i jenkins -- keytool -list -keystore /etc/ssl/certs/java/cacerts -storepass "changeit" Keystore type: JKS Keystore provider: SUN Your keystore contains 1 entry cn=fakejenkins.cert-manager.svc.cluster.local, Apr 14, 2023, trustedCertEntry, Certificate fingerprint (SHA1): CC:63:19:3E:BA:58:17:23:64:2F:34:42:53:47:7D:41:2C:A7:95:5C ``` > **Warning**: right now, the JKS implementation uses a fixed password `changeit`. >