Introduction
If you are reading this, chances are you already know what Let’s Encrypt is about. In this case you can simply skip ahead.
Otherwise, in their homepage there is a pretty good description:
A nonprofit Certificate Authority providing TLS certificates to 300 million websites.
300 million websites. Wow! Wouldn’t it be nice to use these certificates on your Cisco Routers? Good news! You can.
The PKI and the business of buying a certificate
Nowadays Public Key Infrastructure (in short PKI) is a fundamental presence behind (all?) our interactions with the digital world, and Certificates are specifically one of its primary building blocks.
In your average digital life, you may come across certificates in many places, the most common is the “lock” symbol besides the site name in your browser address bar. This symbol indicates the connection to that website is encrypted using some type of TLS, and, you guessed it, TLS needs a certificate to kick-off the secure connection. If the browser doesn’t recognize the entity that released the certificate, it will warn you or possibly not even load the content of the site. A verified certificate is what makes possible to have a much more secure Internet.
Before Let’s Encrypt, to obtain a browser trusted certificate, you would rely on traditional Certificate Authorities (CAs). These are companies that verify your legitimate use of a certain domain, and then issue a set of “certificate” files which you load into the web server. They generally provide this type of service for a fee.
For some types of certificates (notably the so called EV certificates, where EV stands for Extended Validation) there is considerable work to be done, so it is more than fair to pay for it. Let’s Encrypt doesn’t offer this type of certificates, but for our simple needs (lab or proof of concept) the Domain Validation (DV) is enough.
Let’s Encrypt Innovation
Let’s Encrypt is a Certificate Authority (CA) that provides SSL certificates at no cost.
They can do this also because they leverage automation in every step of the process.
Thanks to a clever (and secure) system a CA can now generate certificates automatically. This system relies on two key concepts:
- delegate the trust validation to the Internet infrastructure itself (ex: if I can establish a secure connection to your server through the public Internet by looking up the address http://example.com, then I can reasonably trust you to have legitimate control upon that example.com domain),
- short–lived certificates that require (relatively) frequent renewals, so you must keep demonstrating legitimate ownership of the domain.
Both the validation and the renewal processes are completely automatic. Which leads us to the core section of this article: how can we make this happen on Cisco IOS XE without user intervention.
Use LE Certificates on Cisco IOS XE
There are valid scenarios where you might want to load LE certificates on a Cisco IOS XE router, basically in all cases where you don’t want (or need) the type of service provided by a traditional CA. The perfect example is a lab, or POC setup, where cost must be minimized 😃
Generating/renewing the certificate on a separate computer, and then accessing the router to manually load the renewed files isn’t convenient and takes time. For this reason I’ve decided to assemble a small DYI solution that somewhat helps with that, by running all the certificate management tasks inside the Guestshell container inside the router.
You can access the script by cloning the ciscoautocert GitHub repo in your guestshell, it’s all explained in the repo README. If you want to understand the logic behind what the script actually does, keep reading.
Disclaimer
This all started as a simple proof of concept, which I use in my lab.
The code is probably not very elegant nor production–ready, as it was assembled quickly to have something that would help me present the idea and see it working. I’m not a professional developer, so, if you spot mistakes or know a way to improve the whole process, please do open an issue on GitHub, all suggestions are welcome!
Implementation
👉 tl;dr
1️⃣ I run certbot inside the Guestshell container, then
2️⃣ package the resulting LE certificate in a
pkcs #12 bundle and copy it to bootflash, where
3️⃣ a
EEM script will find it to perform the actual IOS XE configuration.
4️⃣ cron
will run periodically certbot to see when it’s time to renew. When needed, the process will repeat steps 1, 2 and 3.
The components that we need to make this work are:
- Cisco IOS XE Guestshell container (with Python and the cron job scheduler);
- Certbot by the EFF;
- Cisco IOS Embedded Event Manager ( EEM).
Given the power and flexibility of certbot, there are many ways to perform a renewal, and this procedure is transparent to whichever authentication method works in your environment.
In my particular case, due to how my lab environment is configured, it was very convenient for me to use DNS validation. Therefore I’ve opted to use acme-dns which I found perfect for my specific setup. Take into account acme-dns can provide a gradient of security. In my case, I am happy with using public servers, but I do restrict the IP from which the request can be made to the IP of the guestshell. Once again, you can easily modify this to fit your needs.
You might have more strict requirements in your environment, so configure certbot the way that works best for you.
A final note about the IOS XE version: this was used successfully on 17.9.x and 17.10 running on a Catalyst 8000v. I’m fairly confident it could work fine on older versions.
The IOS Embedded Event Manager (EEM) Script
Before we enter the guestshell, we can already deploy the first piece of the puzzle: the EEM script that runs in IOS. This EEM applet will update the crypto trustpoint configuration when it finds a new pkcs12 bundle in a predetermined place of the bootflash.
It’s safe to run this once per day, typically at the time you would create less impact while the certificate is updated (takes less than a second anyway).
I’m no EEM expert, and I know there is a huge community of experts that could do a much better job. But this is a quick solution that worked for me. As always: if you know how to improve this work, please share your solution through github and I’ll make sure it gets merged.
The script is inside the repository, it’s called
ios-applet.eem
. To use it simply copy the content, modify the event cron trigger to the time you like, and paste it in the IOS configuration (don’t forget to write save).
Prepare the Guestshell
Describing how to get the IOS XE Guestshell up and running is outside the scope of this article. There are plenty of excellent resources on the Internet, like the official guide or independent sites like Matt’s Networking Nonsense, where you can find a lot of interesting stuff, including this great video 👇
I have tested with multiple IP configurations for the Guestshell (mostly with and without PAT), they all worked. Make sure your IP configuration is consistent with the type of certbot validation you will be using. In my case, DNS validation offers a great deal of flexibility.
Once you are able to open the shell, the first thing that we need to do is create the /root folder, and install both git and a recent version of Python 3.
In the IOS-XE packaged Guestshell container, Python might be somewhat old, and albeit I reckon Cisco will update the container image in a somewhat near future, it is best to run Certbot on something newer, in my case I went for Python 3.9.
The steps needed to install Python, setup a virtual environment and install certbot are documented in the repository README file.
For convenience, the acme-dns plugin is distributed inside the repository, so you don’t need to download it separately.
Perform the initial Let’s Encrypt enrollment
Once all pre-requisites in the guestshell are satisfied, we proceed to the initial setup. There is a simple script that will guide you through that, it’s called first_run.sh
.
Setup cron
If the certificate generation was successful, we are almost there, the infrastructure is all in place, the only thing we need to complete the process is setup the cron
entries that will take care of periodically renewing the certificate. The initial setup script will create a simple executable file in the home of the guestshell account, called renewcron.sh
which you can call via a cron entry. Make sure it is ran as root. This is an example:
33 3 * * * sudo /home/guestshell/renewcron.sh
Note: Certbot is carefully designed, and for non-interactive renewals it adds a random delay (between 1 second and 8 minutes I believe). Since most of the times there is nothing to renew, you can safely run this job once a day (if you want to add more randomness, you could pick a time that is not the top of the hour or the half hour, it will play nicely with load distribution on LE servers).
Anyway, at this point, if all goes well, certbot will run every day. When you are past the first 60 days of validity of your certificate, it will renew it….and you will continue to benefit from your trusted certificate for 60 more days ✨
Wrap-up
I hope you found this interesting, send me your comments or suggestions, thanks for reading this post… …and Let’s Encrypt!