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

Carlos Saltos @csaltos

About: I code in Scala, Elm, Python and Ruby. Now trying to learn Haskell, Rust, Gleam and OCaml

Location:
Buenos Aires, Argentina
Joined:
Jun 30, 2020

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

Publish Date: Oct 6 '20
2 4

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:

Comments 4 total

  • Feargal
    Feargal Jan 4, 2021

    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?

  • Feargal
    Feargal Jan 4, 2021

    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
    • Feargal
      Feargal Jan 4, 2021

      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.

  • Felipe Mica
    Felipe MicaFeb 5, 2021

    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
Add comment