letsencrypt-aws

letsencrypt-aws is a program that can be run in the background whichautomatically provisions and updates certificates on your AWS infrastructureusing the AWS APIs and Let's Encrypt.

How it works

letsencrypt-aws takes a list of ELBs, and which hosts you want them to beable to serve. It runs in a loop and every day does the following:

It gets the certificate for that ELB. If the certificate is going to expiresoon (in less than 45 days), it generates a new private key and CSR and sends arequest to Let's Encrypt. It takes the DNS challenge and creates a record inRoute53 for that challenge. This completes the Let's Encrypt challenge and wereceive a certificate. It uploads the new certificate and private key to IAMand updates your ELB to use the certificate.

In theory all you need to do is make sure this is running somewhere, and yourELBs' certificates will be kept minty fresh.

How to run it

Before you can use letsencrypt-aws you need to have created an account withthe ACME server (you only need to do this the first time). You can registerusing (if you already have an account you can skip this step):

You'll need to put the private key somewhere that letsencrypt-aws can accessit (either on the local filesystem or in S3).

You will also need to have your AWS credentials configured. You can use any ofthe mechanisms documented byboto3, oruse IAM instance profiles (which are supported, but not mentioned by theboto3 documentation). See below for which AWS permissions are required.

letsencrypt-aws takes it's configuration via the LETSENCRYPT_AWS_CONFIGenvironment variable directly or via a file pointed to by the environmentvariable LETSENCRYPT_AWS_CONFIG_FILE. This should be a JSON object with thefollowing schema:

The acme_account_key can either be located on the local filesystem or in S3.To specify a local file you provide "file:///path/to/key.pem" (on Windows use"file://C:/path/to/key.pem"), for S3 provide"s3://bucket-name/object-name". The key should be a PEM formatted RSA privatekey.

Then you can simply run it: python letsencrypt-aws.py update-certificates.

If you add the --persistent flag it will run forever, rather than just once,sleeping for 24 hours between each check for certificate expiration. This isuseful for production environments.

If your certificate is not expiring soon, but you need to issue a new oneanyways, the --force-issue flag can be provided.

Operational Security

Keeping the source of your certificates secure is, for obvious reasons,important. letsencrypt-aws relies heavily on the AWS APIs to do itsbusiness, so we recommend running this code from EC2, so that you can use theMetadata service for managing credentials. You can give your EC2 instance anIAM instance profile with permissions to manage the relevant services (seebelow for complete details).

You need to make sure that the ACME account private key is kept secure. Thebest choice is probably in an S3 bucket with encryption enabled and accesslimited with IAM.

Finally, wherever you're running letsencrypt-aws needs to be trusted.letsencrypt-aws generates private keys in memory and uploads them to IAMimmediately, they are never stored on disk.

IAM Policy

The minimum set of permissions needed for letsencrypt-aws to work is:

route53:ChangeResourceRecordSets

route53:GetChange

route53:ListHostedZones

elasticloadbalancing:DescribeLoadBalancers

elasticloadbalancing:SetLoadBalancerListenerSSLCertificate

iam:ListServerCertificates

iam:UploadServerCertificate

iam:GetServerCertificate

If your acme_account_key is provided as an s3:// URI you will also need:

s3:GetObject

It's likely possible to restrict these permissions by ARN, though this has notbeen fully explored.