DEV Community

loading...

Update an AWS CloudFront custom SSL/TLS certificate using AWS CLI

Carlos Saltos
I code in Scala, Elm, Javascript, Svelte, Python and Ruby. Now trying to learn Haskell and Rust.
・2 min read

What ?

A simple guide of the steps to follow for updating an SSL/TLS certificate PROGRAMMATICALLY using AWS CLI.

Why ?

Because the official documentation about it is a whole mess when is something rather easy and I'd like to share with others and possibly save some time.

How ?

Once you generate your custom certificate using, for example, Let's Encrypt, you may run these AWS CLI commands to update it using bash:


# Use any name but prefer to use one based on a timestamp since they cannot be repeated on every update
AWS_MY_CERT_NAME=my-cert-$(date +%Y%m%d)

# Set the CloudFront distribution we want to update (found at AWS console)
MY_CLOUDFRONT_ID=EV40L17AXPTKC

# Upload the custom certificate to IAM (using ACM does not work)
aws iam upload-server-certificate --server-certificate-name $AWS_MY_CERT_NAME --certificate-body file://my-cert.pem --private-key file://my-cert-privkey.pem --certificate-chain file://my-cert-chain.pem --path /cloudfront/

# Get certificate ID for the update
AWS_MY_CERT_ID=$(aws iam get-server-certificate --server-certificate-name $AWS_MY_CERT_NAME --query "ServerCertificate.ServerCertificateMetadata.ServerCertificateId" --output text)

# Here the trick: load the current configuration to patch it on the fly (AWS has no other option currently)
aws cloudfront get-distribution-config --id $MY_CLOUDFRONT_ID --query DistributionConfig > config.json

sed -i.bak "s/.*\"IAMCertificateId\".*/\"IAMCertificateId\": \"$AWS_MY_CERT_ID\",/g" config.json
sed -i.bak "s/.*\"Certificate\".*/\"Certificate\": \"$AWS_MY_CERT_ID\",/g" config.json

aws cloudfront update-distribution --id $MY_CLOUDFRONT_ID --distribution-config file://config.json
Enter fullscreen mode Exit fullscreen mode

NOTE: using the /cloudfront/ path is important for making the certificate available for CloudFront usage.

When ?

You can add these commands to a bash script file to run it using cron configuration every month (or sooner depending on the frequency of your updates)

Who ?

These commands are based on these blogs and references:

Discussion (4)

Collapse
felipelalli profile image
Felipe Mica • Edited

Hi! I am getting this error:

"The If-Match version is missing or not valid for the resource"

EDIT: I found out!

It is missing these steps:

CERT_ETAG=$(aws cloudfront get-distribution-config --id $MY_CLOUDFRONT_ID --query ETag)
# remove quotes:
CERT_ETAG="${CERT_ETAG%\"}"
CERT_ETAG="${CERT_ETAG#\"}"
aws cloudfront update-distribution --if-match $CERT_ETAG --id $MY_CLOUDFRONT_ID --distribution-config file://config.json
Enter fullscreen mode Exit fullscreen mode
Collapse
feargalwag profile image
Feargal

I got it working by using jq instead of sed, thanks for the great guide! Here's an example on how to use jq to manipulate the json for anyone else stuck on the tricky regex of sed

tmp=${mktemp}
jq '.ViewerCertificate.SSLSupportMethod = "sni-only"'  config.json > "$tmp" && mv "$tmp" config.json
Enter fullscreen mode Exit fullscreen mode
Collapse
feargalwag profile image
Feargal

One issue is that it's tricky to get environment variables in jq so I just hardcoded everything I need to update in the cloudfront distro.

Collapse
feargalwag profile image
Feargal

I keep getting this error first of all.

sed -i.bak "s/.\"ViewerCertificate\"./\"ACMCertificateArn\": \"$AWS_MY_CERT_ID\",/g" config.json
sed: 1: "s/.*"ViewerCertificate" ...": bad flag in substitute command: 'f'

sed -i.bak '' "s/.\"ViewerCertificate\"./\"ACMCertificateArn\": \"$AWS_MY_CERT_ID\",/g" config.json
sed: s/."ViewerCertificate"./"ACMCertificateArn": "arn:aws:acm:us-east-1:316897671968:certificate/9f337eae-09ef-4f4b-8d50-3c7e05bedc75",/g: No such file or directory
➜ owner-webapp git:(SF-727-qa) ✗

Can I use this method to update acm certificate credentials if the certificate is already created?