'Using Keytool in InitContainer

I am trying to import corporate certificate, so that Java/Spark will be correctly authorizing to access the corporate Cluster.

For this I'm building an Image in Docker and deploy it with kubernetes. I don't want to copy the file in the Dockerfile, because I think it should be a secret file. Thus I'm forcing myself to not execute keytool inside my dockerfile.

Also, I don't want to run as root my application container, in case if there is a security issue, the usee could potentially access to everything as root.

I'm trying to use an InitContainer to load the certificate. This it is a totally separate container that would run as root to execute keytool. By default it will save the new file at ~/.keystore. Since it's a separate container, it won't be find by my applicative container. So I try to change the default directory for keytool and to point it to a mounted volume.

Part of Dockerfile:

FROM Our_corporate_base_image

ENV JAVA_HOME="/opt/jdk"
ENV _JAVA_OPTIONS="-Djavax.net.ssl.keyStore=/work-dir/keystore.jks -Djavax.net.ssl.trustStore=/work-dir/truststore.jks"
USER root
WORKDIR /opt

RUN curl -L -o openjdk.tar.gz https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz \
  && mkdir jdk \
  && tar zxf openjdk.tar.gz -C jdk --strip-components=1 \
  && rm -rf openjdk.tar.gz \
  && apt-get -y --purge autoremove curl \
  && ln -sf /opt/jdk/bin/* /usr/local/bin/ \
  && rm -rf /var/lib/apt/lists/* \
  && java  --version \
  && javac --version \
  && jlink --version 

When building the image, it tells me the JVM does take into account my _JAVA_OPTIONS (I think I should use JAVA_TOOL_OPTIONS)

19:02:23 Picked up _JAVA_OPTIONS: -Djavax.net.ssl.keyStore=/work-dir/keystore.jks -Djavax.net.ssl.trustStore=/work-dir/truststore.jks
19:02:23 openjdk 11.0.1 2018-10-16
19:02:23 OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
19:02:23 OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
19:02:23 Picked up _JAVA_OPTIONS: -Djavax.net.ssl.keyStore=/work-dir/keystore.jks -Djavax.net.ssl.trustStore=/work-dir/truststore.jks
19:02:24 javac 11.0.1
19:02:24 Picked up _JAVA_OPTIONS: -Djavax.net.ssl.keyStore=/work-dir/keystore.jks -Djavax.net.ssl.trustStore=/work-dir/truststore.jks
19:02:24 11.0.1

/work-dir/ is a mounted volume in my app container and init container:

  initContainers:
  - name: "{{ k8s.deploy.name }}-init"
    image: imageRepo
    imagePullPolicy: "Always"
    securityContext:
      runAsUser: 0
    command: ['/bin/bash']
    args: ['-c', "env && keytool -import -alias ca-bundle -file {{ k8s.mountpath.secret }}/ca-bundle.crt -keypass changeit -storepass changeit -noprompt"]
    volumeMounts:
    - name: "{{ k8s.volumemounts.secret }}"
      mountPath: "{{ k8s.mountpath.secret }}/"
    - name: workdir
      mountPath: "/work-dir"
  containers:
  - name: "{{ k8s.deploy.name }}-app"
    image: imageRepo
    imagePullPolicy: "Always"
    // Lot of other stuff to set app and variables and launch a script for the app
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"

When I deploy the solution, the Init container does launch and execute the command as root. In kubectl I get logs saving it is at least importing the java options and the cert file:

Picked up _JAVA_OPTIONS: -Djavax.net.ssl.keyStore=/work-dir/keystore.jks -Djavax.net.ssl.trustStore=/work-dir/truststore.jks
Certificate was added to keystore

When I run a bash in the app container to keytool -list:

Picked up _JAVA_OPTIONS: -Djavax.net.ssl.keyStore=/work-dir/keystore.jks -Djavax.net.ssl.trustStore=/work-dir/truststore.jks
keytool error: java.lang.Exception: Keystore file does not exist: /home/user/.keystore

So I'm kind of confuse on how keytool works since the documentation does explicitly says that I need to modify Djavax.net.ssl.keyStore and Djavax.net.ssl.trustStore to change the default location of keytool https://docs.oracle.com/cd/E19830-01/819-4712/ablqy/index.html

Is it that my JVM does not take into account the options? I don't want to use the -keystore option in keytool to specify the location of the file while importing the cert file. Else I don't think java will load it nativly.

Should I try to mount a volume at /home/user/?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source