Charts: [stable/jenkins] Add Custom Trusted CA certificates

Created on 28 Jul 2020  路  4Comments  路  Source: helm/charts

Is your feature request related to a problem? Please describe.
I am looking for an ability to add/inject custom trustful CA certificates to the Jenkins installation so that Jenkins itself and its plugins can connect via TLS to servers using certificates signed by these CAs.

Describe the solution you'd like
The CA certificates should be added (at least) to the following locations:

  • To the jenkins/jenkins:lts container's trusted CA certificates (probably under /etc/ssl/certs/ca-certificates.crt)
  • To the Java cacerts keystore (probably under /usr/local/openjdk-8/jre/lib/security/cacerts)

The CA certificates should be configurable as helm values (i.e. as base64 encoded list of strings). The values could be used to create a config map/secret which is mounted into the Jenkins container. During initialization, the certificates should be picked up by a script that adds/imports the CA certificates to the required locations/files.

In addition, but maybe out of scope, it would be also desirable to have the same approach for the JNLP container that is created from jenkins/inbound-agent whenever a new build is started.

Most helpful comment

@fwilhelm92 Thanks for your recommendation. I was not aware of the postStart option. However, I would prefer to start Jenkins as non-root container if somehow possible.

My current workaround uses an alternative approach to yours:

  1. Create a emptyDir volume as shared space: cacerts-share
  2. Use a custom init container based on the jenkins/jenkins:lts container.
  3. Copy the original /etc/ssl/certs/ca-certificates.crt and /usr/local/openjdk-8/jre/lib/security/cacerts to the shared volume.
  4. Read the custom CA certs from an environment variable CA_CERTS_BASE64 and add them to the copied files.
  5. Mount the modifed files into the Jenkins container to override the default files.

Here is an example values.yaml file to achieve this:

master:
  customInitContainers:
  - name: add-ca-certs
    image: "jenkins/jenkins:lts"
    imagePullPolicy: Always
    env:
    - name: CA_CERTS_BASE64
      value: "..."
    command: 
    - "sh"
    - "-c"
    - >
      echo $CA_CERTS_BASE64 | base64 -d > /tmp/custom-ca-certs.crt
      && cat /etc/ssl/certs/ca-certificates.crt /tmp/custom-ca-certs.crt > /cacerts-share/ca-certificates.crt
      && cp ${JAVA_HOME}/jre/lib/security/cacerts /cacerts-share/cacerts 
      && chmod 644 /cacerts-share/cacerts
      && ${JAVA_HOME}/bin/keytool -import -trustcacerts -alias custom-ca-certs -keystore /cacerts-share/cacerts -file /tmp/custom-ca-certs.crt -noprompt -storepass changeit
    volumeMounts:
    - name: cacerts-share
      mountPath: /cacerts-share
persistence:
  volumes:
  - name: cacerts-share
    emptyDir: {}
  mounts:
  - mountPath: /etc/ssl/certs/ca-certificates.crt
    name: cacerts-share
    subPath: ca-certificates.crt
  - mountPath: /usr/local/openjdk-8/jre/lib/security/cacerts
    name: cacerts-share
    subPath: cacerts

However, I am not totally satisfied with the solution. I would like to have that feature available out of the box to keep things cleaner.

All 4 comments

Not sure if it will solve your problem, but some suggestions/hints:

Mounting a secret into a Jenkins container

After creating your (k8s-)secret you can mount it into the jenkins container by using persistence (https://github.com/helm/charts/blob/master/stable/jenkins/values.yaml#L589), e.g.:


persistence:
  enabled: true
  volumes:
    - name: name
      secret:
        secretName: secretName
        defaultMode: 0600
  mounts:
    - mountPath: /path/to/destination
      name: name
      readOnly: false

Adding certificates to the java-keystore

As already stated, I am not sure if this is the most feasible solution, but you could use the postStart-command (https://github.com/helm/charts/blob/master/stable/jenkins/values.yaml#L73). However, to use the postStart-command to add the certificates into the java-keystore requires the Jenkins to run as root.
In this example the certificates are downloaded in advance to use it in a pipeline. However, I am sure you can modify this to solve your problem.
(The second and third part of the command downloads the certificates, places them into a chosen directory, and executes update-ca-certifactes.)


master:
  lifecycle:
    postStart:
      exec:
        command: [
          "/bin/bash",
          "-c",
          "curl -s url-to-certificate-name.crt | 
          ${JAVA_HOME}/bin/keytool -keystore
            ${JAVA_HOME}/jre/lib/security/cacerts -import -alias certificate-name
            -noprompt -storepass changeit &&
          curl --create-dirs url-to-certificate-name.crt
            -o /path/to/destination/certificate-name.crt && 
          update-ca-certificates"
         ]

  runAsUser: 0
  fsGroup: 1000

@fwilhelm92 Thanks for your recommendation. I was not aware of the postStart option. However, I would prefer to start Jenkins as non-root container if somehow possible.

My current workaround uses an alternative approach to yours:

  1. Create a emptyDir volume as shared space: cacerts-share
  2. Use a custom init container based on the jenkins/jenkins:lts container.
  3. Copy the original /etc/ssl/certs/ca-certificates.crt and /usr/local/openjdk-8/jre/lib/security/cacerts to the shared volume.
  4. Read the custom CA certs from an environment variable CA_CERTS_BASE64 and add them to the copied files.
  5. Mount the modifed files into the Jenkins container to override the default files.

Here is an example values.yaml file to achieve this:

master:
  customInitContainers:
  - name: add-ca-certs
    image: "jenkins/jenkins:lts"
    imagePullPolicy: Always
    env:
    - name: CA_CERTS_BASE64
      value: "..."
    command: 
    - "sh"
    - "-c"
    - >
      echo $CA_CERTS_BASE64 | base64 -d > /tmp/custom-ca-certs.crt
      && cat /etc/ssl/certs/ca-certificates.crt /tmp/custom-ca-certs.crt > /cacerts-share/ca-certificates.crt
      && cp ${JAVA_HOME}/jre/lib/security/cacerts /cacerts-share/cacerts 
      && chmod 644 /cacerts-share/cacerts
      && ${JAVA_HOME}/bin/keytool -import -trustcacerts -alias custom-ca-certs -keystore /cacerts-share/cacerts -file /tmp/custom-ca-certs.crt -noprompt -storepass changeit
    volumeMounts:
    - name: cacerts-share
      mountPath: /cacerts-share
persistence:
  volumes:
  - name: cacerts-share
    emptyDir: {}
  mounts:
  - mountPath: /etc/ssl/certs/ca-certificates.crt
    name: cacerts-share
    subPath: ca-certificates.crt
  - mountPath: /usr/local/openjdk-8/jre/lib/security/cacerts
    name: cacerts-share
    subPath: cacerts

However, I am not totally satisfied with the solution. I would like to have that feature available out of the box to keep things cleaner.

@azbpa thank you very much for your solution. Helped me a great deal!

馃摙 stable/jenkins has moved to https://github.com/jenkinsci/helm-charts. If still applicable, please reopen the issue there. Thanks!

Was this page helpful?
0 / 5 - 0 ratings