Search code examples
javalinuxspring-bootdockersmtp

load server certificate and CA certificate to be used in a Linux container, with keytool


I have a server running linux, Red Hat, and in the server I have docker running in swarm mode, and the way I create the containers is using yaml files.

The containers have alpine with tomcat server. The tomcat server is used to deploy an application built with Java 8 and Spring Boot 2.6.6.

In the application exist a logic to send emails, and now I'm updating that to use a new email server that supports encryption and authentication.

I already added the required variables in spring boot: port, server, user, password, start encryption, and so on.

When I want to send an email I receive the below error:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target at 
sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)

Based on that error I pulled the certificate of the email server by using ssl tools, and as well I got the CA certificates.

In the yaml file I added the command key as shown below to import the certificates:

    command: bash -c "keytool -importcert -alias smtp-server -keystore truststore -file /sslfolder/email.crt -storepass changeit -noprompt &&
 keytool -importcert -trustcacerts -alias ca-cert-smtp -keystore cacerts -file /sslfolder/ca.pem -storepass changeit -noprompt &&
 keytool -importcert -alias ca1 -noprompt -file /sslfolder/ca1.pem -trustcacerts -storepass changeit -keystore cacerts &&
 keytool -importcert -alias ca2 -noprompt -file /sslfolder/ca2.pem -trustcacerts -storepass changeit -keystore cacerts &&
catalina.sh run"

And after that I'm still getting the error PKIX path building failed.

I also validated the certificates were imported by entering in the container and retrieving the certificates in truststore and cacerts, and they were imported.

Has anyone faced the same error?


Solution

  • I found what was happening and successfully loaded the certificates.

    First, the container has his own path to the cacerts, in /etc/ssl/cacerts. And the tomcat server (catalina) has his own version of cacerts, /usr/tomcat/cacerts.

    In the yaml file, as I mentioned before, in the volumes I added a reference to the path where in the host is placed the certificate of the CA authority:

        volumes:
            - /pathInthehostTotheSSL:sslPathInTheContainer
    

    And in the environment entry added the below

        environment:
            - -JAVA-OPTS=-Djavax.net.ssl.trustStore=/etc/ssl/cacerts
    

    in this way, catalina takes that as an argument an loads the certificate you added with keytool.

    In the command entry, the keytool command shall point to the cacerts path you´re passing in the JAVA-OPTS.

    command: bash -c "
     keytool -importcert -alias ca1 -noprompt -file /sslfolder/ca1.pem -trustcacerts -storepass changeit -keystore /etc/ssl/cacerts &&
     keytool -importcert -alias ca2 -noprompt -file /sslfolder/ca2.pem -trustcacerts -storepass changeit -keystore /etc/ssl/cacerts &&
    catalina.sh run"
    

    And with this in the configuration the application was able to do the handshake while calling a remote server through HTTPS.