Self-signed certificates with Jenkins
Handmade
Whether you are new to continuous integration/continuous deployment (CI/CD) pipelines and the world of DevOps or fully familiar with such practices, one name always comes to the fore when discussing the automation of processes: Jenkins [1]. The highly popular automation server is open source, and although capable of fulfilling many types of complex tasks, it is equally accessible to novice users through its straightforward user interface (UI). In this article, I look at how I solved a recent headache on a project in which I was running Jenkins as a Docker container for the demonstration of a vendor-supplied Jenkins plugin.
Although I haven't used Jenkins much in the past, the quandary I faced and, most importantly, resolved could affect novice and advanced users alike. The problem was that once I had figured out how to update Jenkins plugins online, I couldn't connect a plugin to remote software as a service (SaaS) because it was using self-signed security certificates that were not recognized by Jenkins.
The Version
According to my relatively cursory inspection of the provided Docker containers, the first thing to note about Jenkins is that the version you use can be the difference between documentation immediately solving a problem or compounding it further. From the container perspective, I opted to look at two versions in particular: the very latest and greatest weekly release called jenkins/jenkins:latest
and the jenkins/jenkins:lts
, where lts
stands for the long-term support stable version.
The reason the version seems to matter so much is that Jenkins is developed at great speed and is constantly evolving. Admirable and fantastic as that is, every now and again trying to solve an issue on a version that hasn't been written about much online is tricky at best. This situation applies to most modern software and definitely not just the pervasive-for-good-reason Jenkins.
Although Jenkins provides a carefully considered and slick UI, in this article I focus on the container side and a number of command-line interface (CLI) options. Again with reference to the importance of versioning, the issue I encountered when trying to figure out UI options was that several version changes ago a number of menu options were deprecated. Nonetheless, with some trial and error I settled with the LTS version of the container image and the plugin working as hoped. The results can be reproduced easily to accommodate other online services that Jenkins doesn't immediately work with out of the box because the certificate authority isn't recognized.
The Installation
I prefer to save complex Docker run
commands in a small script, as shown in the run_jenkins.sh
file shown in Listing 1. (Remember to run
chmod +x run_jenkins.sh
to make it executable.)
Listing 1
run_jenkins.sh
docker run -d \ --name jenkins-lts \ --user root \ -p 0.0.0.0:8080:8080 \ -p 0.0.0.0:8443:8443 \ -p 0.0.0.0:50000:50000 \ --env JENKINS_OPTS="--httpPort=8080" \ --env JAVA_OPTS=-"Djavax.net.ssl.trustStore=/var/jenkins_home/keystore/cacerts" \ -v jenkins_config:/var/jenkins_home \ jenkins/jenkins:lts
Rather than just blindly running that script, which you can do without breaking anything in a laboratory environment, you might first want to read through to the end of this article to understand why --user root
is present, along with the JAVA_OPTS
environment variable.
Importantly, before creating a container with the script in Listing 1, I will ensure that changes to configuration data persist between stops and starts by creating and checking a volume called jenkins_config
:
$ docker volume create jenkins_config $ docker volume ls | grep jenkins local jenkins_config
To run the script, proceed with creating a container:
$ ./run_jenkins.sh
If you run $ docker ps
and no errors are present, you should see it running.
The Plugins Quandary
The more minor of my connectivity issues were that I couldn't update plugins to get the most secure versions. Jenkins uses an online repository to store and serve its incredible library of exceptionally useful plugins. It seems, however, that under some scenarios, even when a proxy isn't used to connect to the Internet, Jenkins struggles to connect over HTTPS.
After hunting online and trying a few different fixes without success, what worked for me was a remarkably simple URL edit (Figure 1) that let me continue updating and installing the plugins required for the project demo I was preparing. To get to that UI option, navigate to Manage Jenkins | Manage Plugins , select the Advanced tab, and scroll to the bottom of the page.
Simply alter https to http in the URL and then click the Submit button. You can now promptly navigate to the Check Now button, which is on the bottom right of that same page. Then scroll back to the top of the page and click the Updates tab to check that the fix worked. If for some reason that doesn't work, go into your browser settings and see if you are using a proxy to access the Internet. If you are, at the top of the same page as shown in Figure 1, you can enter your proxy information manually (e.g., web.proxy.org:8080 ), along with login details if they are used. If it works, update all your plugins as required.
If you are keen to use HTTPS for your plugin connectivity (which is obviously recommended for the benefit of security outside of a lab environment), you can potentially use the next solution, or (armed with the knowledge that JUC stands for Jenkins Update Center) you could create your own plugin repository locally, according to instructions online [2]. This step could also be useful if you want to limit which plugins developers have access to for security reasons.
Buy this article as PDF
(incl. VAT)