4

I have to add a custom root certificate to the Java trust store inside a docker environment. So I added the following command to my dockerfile:

RUN $JAVA_HOME/bin/keytool -import -file /opt/custom/certs/mycert.pem -alias mycert -keystore $JAVA_HOME/jre/lib/security/cacerts -trustcacerts -storepass changeit -noprompt

I get the following output when building the docker image:

Step 10/10 : RUN $JAVA_HOME/bin/keytool -import -file /opt/custom/certs/mycert.pem -alias mycert -keystore $JAVA_HOME/jre/lib/security/cacerts -trustcacerts -storepass changeit -noprompt
 ---> Running in cbc2a547797e
Certificate was added to keystore
keytool error: java.io.FileNotFoundException: /opt/java/openjdk/jre/lib/security/cacerts (No such file or directory)
The command '/bin/sh -c $JAVA_HOME/bin/keytool -import -file /opt/custom/certs/mycert.pem -alias mycert -keystore $JAVA_HOME/jre/lib/security/cacerts -trustcacerts -storepass changeit -noprompt' returned a non-zero code: 1

I'm baffled by the following facts:

  • the output Certificate was added to keystore seems to indicate a successful execution of keytool
  • at the same time, I get keytool error and a non-zero return-code, so no success
  • the file that is claimed not to exist, does in fact exist (could it be an access problem?)

What I've checked:

  • %JAVA_HOME seems to be available, as the error message displays the correct path
  • When I build the image without above RUN command, then issue the exact same command inside the docker container, it works perfectly
  • I checked the same using /bin/sh as the shell to make sure it's not the shell - worked
  • There's no dependency on the current directory, as all pathes are absolute

Now I don't have any more ideas how to track this issue down.

not2savvy
  • 2,902
  • 3
  • 22
  • 37

3 Answers3

3

It is probably a permission issue, what I'm guessing is that the base image you use changed the user from root and you need to be root to access the file. You should be able to do the following :

USER root
RUN $JAVA_HOME/bin/keytool -import -file /opt/custom/certs/mycert.pem -alias mycert -keystore $JAVA_HOME/jre/lib/security/cacerts -trustcacerts -storepass changeit -noprompt
USER originaluser

You can find the original user by using:

docker history yourbaseimagename:tag
jeanpic
  • 481
  • 3
  • 15
  • Thanks for your answer. However, I tried inserting `USER root` before the `RUN`, but it did not change the outcome. May I also mention that the RUN before the problem RUN does some `apt-get install` (and it's successful), so I'm pretty sure it has root access. Could you elaborate on the `docker history`? I tried this, but I don't see any user information there. – not2savvy Jun 29 '21 at 17:43
  • `RUN whoami` in the dockerfile returns `root` when built. – not2savvy Jun 29 '21 at 17:53
2

Turned out that the problem was my fault™️

There were a few things that had confused me:

  1. keytool displays Certificate was added to keystore even though that had actually failed – stupid
  2. I checked if the command works in the docker container, but I missed that I was testing in another version of the image that had Java installed in a different way
  3. The Java keystore is not always located in the same path – it may be $JAVA_PATH/lib/security/cacerts or it may be $JAVA_PATH/jre/lib/security/cacerts – obviously depending on whether a JRE or JDK is installed

So my solution was to write a bash script:

  1. Is Java version 9 or better? Then import using -cacerts option which will automatically take care of the keystore location
  2. Else: does the $JAVA_HOME/jre directory exist? Then use -keystore $JAVA_PATH/jre/lib/security/cacerts
  3. Else: use -keystore $JAVA_PATH/lib/security/cacerts
not2savvy
  • 2,902
  • 3
  • 22
  • 37
0

I am using https://hub.docker.com/r/jenkins/jenkins and in my case the problem was caused by the new OpenJDK 11 installation which removes the jre from the path used previously. I changed

$JAVA_HOME/jre/lib/security/cacerts

into

$JAVA_HOME/lib/security/cacerts
lainatnavi
  • 1,453
  • 1
  • 14
  • 22