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:
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.
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.
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
That is it. If you check in the
certs directory, you will find you LetsEncrypt cert ready to put where ever you need.