Using Dehydrated to generate LetsEncrypt certs for your internal services

After the long process of building out my PoC vault cluster for storing LUKS keys (Series starting here: Part Zero), i needed a way to generate LetsEncrypt certs for these private services. Dehydrated to the rescue. Using Dehydrated i can create certs using the LetsEncrypt DNS challenge. Dehydrated will create the DNS record required for the challenge on Route53 on-the-fly then remove it once i have the cert.

There are a couple of things we need to have setup and installed before we can actually generate the certs:

  • Have jq installed – yum install jq
  • Have cli53 installed
  • Have a copy of Dehydrated
  • Have a copy of the Route53 hook.

It is possible to set this up with other DNS providers, but as i use Route53, ill only be going through that process. I imagine other DNS providers will be the same, just using a different hook.

Installing cli53

This is a simple step, grab the latest version from the CLI53 Github. When i wrote this, the latest version was 0.8.16.

Once you have the binary you just need to move it to the correct location, set the permissions and setup the credentials file:

sudo mv cli53-linux-amd64 /usr/local/bin/cli53
sudo chmod +x /usr/local/bin/cli53
vim ~/.aws/credentials

You need to have an AWS access key and secret key already to do this. Setup the credentials file so it looks like this:

[default]
aws_access_key_id = QWERTYUIOPASDFGHJKL
aws_secret_access_key = AbUnChOfRaNdOmChArAcTeRs

You can then test it with:

 [jon@jons-laptop ~]$ cli53 list
ID             Name            Record count Comment
arandomid      domain1.com     13           domain1
arandomid      domain2.com.    32           domain2
arandomid      domain3.com.    10           domain3
arandomid      domain4.com.    20           domain4
arandomid      domain5.com.    6            domain5

Obviously that table will show correct domain details. That is all for the CLI53 section.

Grabbing Dehydrated

Next up we need to grab the latest version of Dehydrated from their Github page. Just download the zip then unzip. You can move the directory to where-ever you want, i tend to just have a directory called “Apps” in my home.

Now we need to create the config file. In the Dehydrated directory, create a new file named just config. You also need to create a couple of directories in the same place, these are: certs,chains,accounts.

Now open the config file in whatever text editor you like and paste in the following (changing it to suite your directory location:

CHALLENGETYPE="dns-01"
HOOK=/home/jon/Apps/dehydrated-master/hook.sh
HOOK_CHAIN="no"
LOCKFILE=/tmp/lock
CHAINCACHE=/home/jon/Apps/dehydrated-master/chains
CERTDIR=/home/jon/Apps/dehydrated-master/certs
ACCOUNTDIR=/home/jon/Apps/dehydrated-master/accounts
DOMAINS_TXT=/home/jon/Apps/dehydrated-master/domains.txt

That should be all we need to do for now for Dehydrated.

Grabbing the Route53 Hook

This is a quick section, all we need to do is grab hook.sh from HERE. Save it in the Dehydrated directory and make it executable with:

chmod +x hook.sh

Setting up the domains.txt file

We can use the domains.txt file to specify what domains we want a cert for and how we want them setup. Here is an example of the formating:

example.org # without any alternative names
example.com www.example.com # with an alternative name of www.example.com
example.net www.example.net wiki.example.net # example.net with the alternative names: www.example.net and wiki.example.net

So when i did this for my Vault cluster, i used the bottom option as the cert was for all related hostnames.

Time to run it!

Now is the time we generate our certs!

First we need to register with ACME using ./dehydrated --register --accept-terms:

[jon@jons-laptop dehydrated-master]$ ./dehydrated --register --accept-terms
# INFO: Using main config file /home/jon/Apps/dehydrated-master/config
+ Generating account key...
+ Registering account key with ACME server...
+ Fetching account ID...
+ Done!

Then we can create our certs with ./dehydrated -c -f /home/jon/Apps/dehydrated-master/config:

[jon@jons-laptop dehydrated-master]$ ./dehydrated -c -f /home/jon/Apps/dehydrated-master/config 
# INFO: Using main config file /home/jon/Apps/dehydrated-master/config
Processing vault.domain.name with alternative names: consul1.domain.name consul2.domain.name consul3.domain.name vault1.domain.name vault2.domain.name
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting new certificate order from CA...
 + Received 6 authorizations URLs from the CA
 + Handling authorization for consul1.domain.name
 + Handling authorization for consul2.domain.name
 + Handling authorization for consul3.domain.name
 + Handling authorization for vault.domain.name
 + Handling authorization for vault1.domain.name
 + Handling authorization for vault2.domain.name
 + 6 pending challenge(s)
 + Deploying challenge tokens...
Creating challenge record for consul1.domain.name in zone domain.name
Created record: '_acme-challenge.consul1.domain.name. 60 IN TXT "nZTn68fg4fE0LMXeOFU0gWmylrg8Ty7RlaJo6Wd-Qy4"'
Waiting for sync...........................
Completed
Creating challenge record for consul2.domain.name in zone domain.name
Created record: '_acme-challenge.consul2.domain.name. 60 IN TXT "CUeTsCRqmXKPqLjp4iMuHXOx_sx1tR9b29Nsz9j04KQ"'
Waiting for sync.............................
Completed
Creating challenge record for consul3.domain.name in zone domain.name
Created record: '_acme-challenge.consul3.domain.name. 60 IN TXT "8kmqcGz_BoguGKOuuqileWTF4xnghy2-MPgyMTx43rY"'
Waiting for sync............................
Completed
Creating challenge record for vault.domain.name in zone domain.name
Created record: '_acme-challenge.vault.domain.name. 60 IN TXT "1tufbVV2W_gkXmWz3N0SxD6XR09jo-FF9Gedyd4KwFU"'
Waiting for sync............................
Completed
Creating challenge record for vault1.domain.name in zone domain.name
Created record: '_acme-challenge.vault1.domain.name. 60 IN TXT "TPKBeAHuXFOOr2SSFSDbu4ewqGgpwsAshmlMgwKBkvI"'
Waiting for sync...........................
Completed
Creating challenge record for vault2.domain.name in zone domain.name
Created record: '_acme-challenge.vault2.domain.name. 60 IN TXT "n7Nvv0V0U6vl-ztt6WQpJbiaSYLTFM_G-ITUJCzea_Y"'
Waiting for sync..............................
Completed
 + Responding to challenge for consul1.domain.name authorization...
 + Challenge is valid!
 + Responding to challenge for consul2.domain.name authorization...
 + Challenge is valid!
 + Responding to challenge for consul3.domain.name authorization...
 + Challenge is valid!
 + Responding to challenge for vault.domain.name authorization...
 + Challenge is valid!
 + Responding to challenge for vault1.domain.name authorization...
 + Challenge is valid!
 + Responding to challenge for vault2.domain.name authorization...
 + Challenge is valid!
 + Cleaning challenge tokens...
Deleting challenge record for consul1.domain.name from zone domain.name
1 record sets deleted
Deleting challenge record for consul2.domain.name from zone domain.name
1 record sets deleted
Deleting challenge record for consul3.domain.name from zone domain.name
1 record sets deleted
Deleting challenge record for vault.domain.name from zone domain.name
1 record sets deleted
Deleting challenge record for vault1.domain.name from zone domain.name
1 record sets deleted
Deleting challenge record for vault2.domain.name from zone domain.name
1 record sets deleted
 + Requesting certificate...
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + Done!

Just a quick note, i replace my actual domain with just domain.name.

That is it. If you check in the certs directory, you will find you LetsEncrypt cert ready to put where ever you need.

Leave a Reply

Your email address will not be published. Required fields are marked *