Skip to content

Instantly share code, notes, and snippets.

@voronenko-p

voronenko-p/blog.md Secret

Created May 29, 2019
Embed
What would you like to do?

Wildcard certificates from letsencrypt on aws cloud

Letsencrypt is nowadays very popular certificates authority.

It is standard defacto for most of situations when you need green sealed certificate on your environment. New version of the API (v2) provides very nice way to issue wildcard certificates using DNS validation.

Althouth it is not recommended to put read/write dns credentials on a such environment, there might be exception that forces you to do so on a temporary basis.

Workaround below provides way to limit write scope of the credentials, when your domain is served by AWS Route53.

Let's assume we want to create wildcard certificate for our staging environment

*.staging.yourdomain.com

Step A - zone preparation for acme checks

Create another public hosted zone for the domain _acme-challenge.staging.yourdomain.com I know, you are probably thinking "but that's not a domain!", but in the relevant sense, it actually is still a domain, just four level one.

Route 53 will assign 4 new nameservers to this new hosted zone. Make a note of those servers.

You will get something like

https://gist.github.com/6ffd4af1cc8a826c5a8f23cde50e8755

Step B - delegating acme actions to dedicated acme hosted zone

Return to your original hosted zone, and create a record for _acme-challenge.staging.yourdomain.com of type NS. As a value you will use to create this record use those 4 nameservers that Route 53 assigned to the new hosted zone, one per line.

Important! Do not change any of the existing NS records in either of the zones.

What we have implemented by this step is called a delegation - i.e. you are delegating authority for staging.yourdomain.com subdomain to a different hosted zone, which you will notice was automatically assigned a completely different set of 4 Route 53 servers from those that handle your parent domain.

You can now create a new record in the root of the new hosted zone, and when you do a DNS query for _acme-challenge.ldap.example.com, the answer returned will be the answer from the new hosted zone.

Now, you can give your script permission only to modify records in the new zone, and it will be unable to modify anything in the parent zone, because you gave it no permissions, there. So we approaching to the next step

STEP C - creating policy with limited access

Now we can prepare AWS policy with fine grained permissions

https://gist.github.com/b619ddd891df3d81bda2040e3c67dc53

and link this policy to appropriate IAM user, and get his access credentials.

Corresponding terraform script might be as following (always check to most recent documentation https://certbot-dns-route53.readthedocs.io/en/stable/ )

https://gist.github.com/89332b544e571819c25c100aaeb40a68

STEP D - setting up aws credentials (for certbot example)

Setup AWS credentials We now need to put the AWS credentials on the server so the plugin can use them. I run all my certbot commands out of the default user’s home folder, your setup might be different.

In the home folder create an .aws folder and inside that create a text file with the name credentials with the following contents.

https://gist.github.com/835a14ce5c797872be9db9f58eea6238

Replace the placeholders with the access key and secret access key that you just saved from AWS and fill them in.

Once created, check it was configured properly

https://gist.github.com/3f44726f78424dd8f55a4304eae391e4

Next step would be, naturally, generating cthe certificate

Example - generating certificate with certbot

Install tool of your choice, for example, classic certbot (examples below are given for ubuntu family)

https://gist.github.com/87aa1d1848474830108660face0a0c6c

or using their up-to-date script

https://gist.github.com/003ec1186e8e2956931ab7e335f0f03f

https://gist.github.com/3a481a9ec35733f5fa6b119b0389f800

If you see output like below, you are done:

https://gist.github.com/b2e4b796a3518b654a2bede6bc053611

Now let's ensure, that our domain will be prolonged

https://gist.github.com/79db5aa08132d0efaf21a68d298c9c72

If you want to setup cron, and you have specified custom log, config, work dirs - make sure to specify full path in crontab.

https://gist.github.com/bcfc5e5846e6165de4bd5365bf7d4ccf

Your certificates will be located under config dir

https://gist.github.com/6185eccea8ab58347ba72ca7cfe86ee2

Example - generating certificate with acme.sh

But my own preference is pure shell acme.sh

Acme.sh https://github.com/Neilpang/acme.sh - it is another extra cool tool written purely in shell. It supports number of dns providers in form of shell(!) plugins https://github.com/Neilpang/acme.sh/tree/master/dnsapi

Each plugin has comprehensive documentation on configuring https://github.com/Neilpang/acme.sh/wiki/dnsapi

For Route53, you will need to export your credentials

https://gist.github.com/2b8472a3d2280996234f70968e473b4e

With acme.sh

https://gist.github.com/6acfbdcc18f5228b90f3561a2da8850b

Renewing is also straightforward - just create cron similar to

https://gist.github.com/e1dbc90c6013662ce138893e3a8731b3

Finally

Use certificates in your webserver

Code

Terraform snippets might be found at https://github.com/Voronenko/route53-letsencrypt-policy/ ; Ansible role assisting you with install on target server can be found here: https://github.com/softasap/sa-acme-sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment