IntroductionA few days ago we set up a Jenkins installation for a new coworker of our company. Without going into too much detail (as this post is not intended to be a Jenkins course), Jenkins is a continuous integration software which for example helps to automate and document the build process in software development. For example it can listen to a Git repository, performs automated software tests once a developer pushes a new commit to it and then releases the update on the live server if all tests were completed successfully. In this workflow Jenkins offers a simple Email functionality which informs the user whenever a task is completed, failed or some other interesting stuff happens. To enable Jenkins to send these mails, you have to insert the information of your Email-SMTP-Server in the Jenkins settings.
So far, so good. Nowadays it is standard that SMTP uses SSL to encrypt messages. As Jenkins is a Java program, it uses the Java TrustStore for determining which SSL certificates it trusts. So if the certificate of your SMTP server is not part of the Java TrustStore, you will get an error when trying to send mails. The corresponding error message in Jenkins looked something like the following. You might get a similar error message with every other software that applies the Java TrustStore while trying to use a not trusted SSL certficate.
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) at java.security.cert.CertPathBuilder.build(Unknown Source) Caused: sun.security.validator.ValidatorException: PKIX path building failed at sun.security.validator.PKIXValidator.doBuild(Unknown Source) at sun.security.validator.PKIXValidator.engineValidate(Unknown Source) at sun.security.validator.Validator.validate(Unknown Source) at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) ...
Get SSL certificate from SMTP server with OpenSSLTo avoid the above mentioned error, we need to get the SSL certificate from our SMTP server and add it to the Java TrustStore. For this we will use OpenSSL that you can download from the official page and install it on your system. As we are working on Windows computers, the following description will be for the Windows operating system, but should be quite similar for Linux and Mac. After OpenSSL is applicable on your system, start the command line. You should now be able to perform the command openssl version to see the installed version of OpenSSL.
Now that we are sure that OpenSSL is working, we can get the SSL certificate from our server. For that we perform the following command in the command line:
openssl s_client -servername <server-address> -connect <server-address>:465 | openssl x509 –text
In this command it is assumed that our SMTP server is reachable on port 465. Let our SMTP server be example.com, then the above command would look like:
openssl s_client -servername example.com -connect example.com:465 | openssl x509 –text
This should print the certificate information to the console. The interesting part can be found between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.
We now simply create a new file for example with our favorite text editor and copy the above shown certificate information (including the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----) into this file. Then we save the file as a certificate with the extension .crt, for example as example.crt.
Add the certificate to the Java TrustStoreThis certificate now should be copied into the Security-Folder under your Java Development Kit. In general the path for this location looks something like C:\Program Files\Java\jdk1.8.0_131\jre\lib\security, for sure depending on the JDK version you are using. Now we navigate into this directory with our command line and add this certificate to our trusted certificates. To do so we execute the following command in the command line:
keytool -import -alias <alias> -file <cert-file> -keystore cacerts -storepass changeit
In there you have to specify an alias for your certificate, which is completely up to you. Furthermore you have to specify the name of the certificate that we had created before. In our example the certificate name is example.com and we will use example-cert as the alias:
keytool -import -alias example-cert -file example.crt -keystore cacerts -storepass changeit
After that the certificate should be added to our Java TrustStore. To check if everything worked correctly, we can list all certifcates in the TrustStore with:
keytool -keystore cacerts -storepass changeit -list
In this list you should find the certificate with the above created alias name. If the list of certificates is too long so that the command line will cut the output, you also can write it to a file with the following command:
keytool -keystore cacerts -storepass changeit -list > "C:\Users\<your-username>\Desktop\output.txt" 2>&1
This will create a file output.txt on the desktop with a list of all certificates in the TrustStore, for sure you have to set your user name appropriately. The SSL certificate of your SMTP server is now added to the Java TrustStore and you should get no more error while trying to send Emails.