The World's Leader in Hosting

Rackspace Journal

Subscribe to Rackspace Journal: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Rackspace Journal: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Rackspace Journal Authors: Greg Schulz, OnPage Blog, Dynatrace Blog, Mehdi Daoudi, AppDynamics Blog

Related Topics: Rackspace Journal

Blog Feed Post

Lightboard Lessons: Automating SSL on BIG-IP with Let's Encrypt!

In this episode of Lightboard Lessons, I describe the Let's Encrypt automated certificate generation process and how to customize a hook script to automate the challenges and and certificate deployment.

What is Let's Encrypt?

Let’s Encrypt is a certificate authority available in beta since Dec 2015, but launched publicly in April 2016. To steal the opening paragraph from their "Getting Started" page:

Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate can be. Let’s Encrypt automates away the pain and lets site operators turn on and manage HTTPS with simple commands. Using Let’s Encrypt is free, so there is no need to arrange payment.

Free? Say what? Yep...free. And automated, which is right up our alley here at DevCentral!

How Does Let's Encrypt Work?

I’ll defer to their how it works page for details, but basically the steps are:

  1. Define a list of domains you want to secure
  2. Your client reaches out to the Let’s Encrypt servers to initiate a challenge for those domains.
  3. The servers will issue an http or dns challenge based on your request
  4. You need to place a file on your web server or a txt record in the dns zone file with that challenge information.
  5. The servers will validate your challenge information and notify you
  6. You will clean up your challenge files or txt records
  7. The servers will issue the certificate and certificate chain to you
  8. You now have the key, cert, and chain, and can deploy to your web servers or in our case, to the BIG-IP

 An overview of that process for the dns challenge is shown in the image below.

Let's Encrypt Overview

Components

As discussed in the video, there are a few components to this solution. Let’s Encrypt has a staging server you can use until you have everything working properly, which I’d recommend so you don’t get rate limited on production requesting the same domains repeatedly. This is set in the config.sh file.

  • letsencrypt.sh - this is the Let’s Encrypt client application, which is unaltered from lukas2511’s github repository. This is the central nervous system of the operation
  • config files - these are helper files for the shell script
    • config.sh - this is the config file for the letsencrypt.sh script. Staging server, local directories, key sizes, challenge type, etc are defined here.
    • creds.json - I used this file to store my BIG-IP credentials and DNS provider API keys so when I do demoes I am not sharing this information with the world.
    • domains.txt - this is where you put the domains you want to sign with Let’s Encrypt. If you want your root domain and a www alias, you’d put these on the same line.
  • le_hook.py - this is the python hook script I wrote for letsencrypt.sh to hand off to manage the dns challenges and the certificate deployment.

Running the script, I added (hook) to the logging output so you can see who has control, the shell script or the hook script at any particular time.

[email protected]:/var/tmp/le$ ./letsencrypt.sh -c -f /var/tmp/le/config/config.sh
./letsencrypt.sh: line 1: h: command not found
# INFO: Using main config file /var/tmp/le/config/config.sh
# INFO: Using additional config file /var/tmp/le/config/config.sh
Processing rahmen-empire.net with alternative names: www.rahmen-empire.net
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting challenge for rahmen-empire.net...
 + Requesting challenge for www.rahmen-empire.net...
 + (hook) executing: deploy_challenge
 + (hook) TXT record created: _acme-challenge.rahmen-empire.net => tv10Ta53-7yKiy8jLTQCBtx7-ixoLD15JQYK1TH3Ick
 + (hook) Result: {u'message': u'Command Successful', u'code': 100}
 + (hook) Settling down for 10s...
 + (hook) All challenge records found!
 + Responding to challenge for rahmen-empire.net...
 + (hook) executing: clean_challenge
 + (hook) TXT record deleted: 254547326
 + (hook) Result: {u'message': u'Command Successful', u'code': 100}
 + Challenge is valid!
 + (hook) executing: deploy_challenge
 + (hook) TXT record created: _acme-challenge.www.rahmen-empire.net => LFuj9hnWQiSpZc2-jyS0E8l9p_bt7nvUtK39EUu3Xlw
 + (hook) Result: {u'message': u'Command Successful', u'code': 100}
 + (hook) Settling down for 10s...
 + (hook) All challenge records found!
 + Responding to challenge for www.rahmen-empire.net...
 + (hook) executing: clean_challenge
 + (hook) TXT record deleted: 254547327
 + (hook) Result: {u'message': u'Command Successful', u'code': 100}
 + Challenge is valid!
 + Requesting certificate...
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + (hook) executing: deploy_cert
 + (hook) New Certificate/Key created.
INFO:__main__: + (hook) New Certificate/Key created.
 + Done!

And if we take a look at the directory where files are dumped, we can see the key, the cert, and the chain are ready for us! Note that each time certs are generated the symlinks will update so the old files will still be available.

Cert Directory Lights

If you run it again, you’ll see that it will not even reach out to the Let’s Encrypt servers because not enough time has expired.

[email protected]:/var/tmp/le$ ./letsencrypt.sh -c -f /var/tmp/le/config/config.sh
./letsencrypt.sh: line 1: h: command not found
# INFO: Using main config file /var/tmp/le/config/config.sh
# INFO: Using additional config file /var/tmp/le/config/config.sh
Processing rahmen-empire.net with alternative names: www.rahmen-empire.net
 + Checking domain name(s) of existing cert... unchanged.
 + Checking expire date of existing cert...
 + Valid till Nov  7 13:29:00 2016 GMT (Longer than 30 days). Skipping renew!
 + (hook) executing: unchanged_cert
 + (hook) No changes necessary.

Now we can look at the BIG-IP and see the key/cert/chain in place. Note that the Fake LE Intermediate is due to the staging server I used, it would not show that if I used production.

Let's Encrypt Certs on BIG-IP

And finally, the clientssl profile created and ready for use.

Let's Encrypt Certs - clientssl profile

You can take this the next step forward and apply the profile to the virtual server, but I’ll leave that to you!

Resources

This project is hosted here in our github repositories. I will be clean up the hook script once my pull requests hit production release for f5-common-python.

The links below are the resources I used to reference or build upon for my solution. 

Read the original blog entry...

More Stories By Jason Rahm

Experienced predominantly in the networking realm over the last dozen or so years, Jason is expanding his horizons towards systems management and even trying his hand at python.

Jason assists in the maintenance duties for http://devcentral.f5.com, contributes frequently in the forums, and writes weekly on some cool geekery in the F5 product lines. When not working, Jason enjoys spending time with his beautiful wife Michelle and his four children. He is active and volunteers network administration duties at his church and if there are any remaining minutes in the week, he enjoys Wii & XBOX, tennis, racquetball, softball, etc. He does not enjoy running, but does (scratch that, thinks about doing) it anyway to recover his youthful appearance.