#!/bin/bash # # [1] "If you're using a CA other than AWS Certificate Manager and if you want to # use the same certificate both for CloudFront and for other AWS services, # you must upload the certificate twice: once for CloudFront and once for the # other services." (http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/SecureConnections.html#CNAMEsAndHTTPS) # # If using your cert on cloudfront, make sure your cloudfront distribution has # a behavior for .well-known/acme-challenge/* that lets requests through to # the origin. You will probably need to forward the 'host' header in this behavior. # # References: # http://marketing.intracto.com/renew-https-certificate-on-amazon-cloudfront # https://vincent.composieux.fr/article/install-configure-and-automatically-renew-let-s-encrypt-ssl-certificate # https://github.com/alex/letsencrypt-aws CONFIG_FILE='/usr/local/etc/le-exampledomain-webroot.ini' LE_PATH='/opt/letsencrypt' LOAD_BALANCER_NAME='exampleloadbalancer' export AWS_DEFAULT_PROFILE='ExampleProfile' export AWS_DEFAULT_REGION='us-west-2' EXP_LIMIT=30 UPDATE_CLOUDFRONT=true # deletes the old certs DELETE_OLD=false if [ ! -f $CONFIG_FILE ]; then echo "[ERROR] config file does not exist: $CONFIG_FILE" exit 1; fi DOMAIN=`grep "^\s*domains" $CONFIG_FILE | sed "s/^\s*domains\s*=\s*//" | sed 's/(\s*)\|,.*$//'` CERT_FILE="/etc/letsencrypt/live/$DOMAIN/fullchain.pem" if [ ! -f $CERT_FILE ]; then echo "[ERROR] certificate file not found for domain $DOMAIN." fi DATE_NOW=$(date -d "now" +%s) EXP_DATE=$(date -d "`openssl x509 -in $CERT_FILE -text -noout | grep "Not After" | cut -c 25-`" +%s) EXP_DAYS=$(echo \( $EXP_DATE - $DATE_NOW \) / 86400 |bc) echo "Checking expiration date for $DOMAIN..." if [ "$EXP_DAYS" -gt "$EXP_LIMIT" ] && [ "$1" != "--force" ] ; then echo "The certificate is up to date, no need for renewal ($EXP_DAYS days left)." exit 0; else echo "The certificate for $DOMAIN is about to expire soon. Starting webroot renewal script..." $LE_PATH/letsencrypt-auto certonly --agree-tos --renew-by-default --config $CONFIG_FILE CERT_NAME="auto_cert_`date +%m-%d-%y_%H-%M-%S`" echo "Uploading $CERT_NAME to IAM" # path needs to be this to work for cloudfront (will work with elb too) CERT_RES=$(aws iam upload-server-certificate \ --server-certificate-name $CERT_NAME \ --certificate-body file:///etc/letsencrypt/live/$DOMAIN/cert.pem \ --private-key file:///etc/letsencrypt/live/$DOMAIN/privkey.pem \ --certificate-chain file:///etc/letsencrypt/live/$DOMAIN/chain.pem \ --path /cloudfront/production/ \ --output json ) echo $CERT_RES NEW_CERT_ARN=$(echo $CERT_RES | python -c 'import json,sys;obj=json.load(sys.stdin);print(obj["ServerCertificateMetadata"]["Arn"])') echo $NEW_CERT_ARN echo "Updating ELB IAM cert..." sleep 20 aws elb set-load-balancer-listener-ssl-certificate \ --load-balancer-name $LOAD_BALANCER_NAME \ --load-balancer-port 443 \ --ssl-certificate-id $NEW_CERT_ARN if [ UPDATE_CLOUDFRONT = true ] ; then echo "Updating cloudfront distribution..." aws configure set preview.cloudfront true DISTRIBUTION=$(aws cloudfront list-distributions --query \ "DistributionList.Items[0].{DistributionId: Id}" --output text) OLD_CERT_ARN=$(aws cloudfront list-distributions --query "DistributionList.Items[0].ViewerCertificate.Certificate" --output text) aws cloudfront get-distribution-config --id $DISTRIBUTION --query 'DistributionConfig' --output json > /tmp/dist_config.json sed -i "s/$OLD_CERT_ARN/$NEW_CERT_ARN/" /tmp/dist_config.json aws cloudfront update-distribution \ --id $DISTRIBUTION \ --distribution-config file:///tmp/dist_config.json echo "Done updating cloudfront" fi echo "Renewal process finished for domain $DOMAIN" # TODO: test! if [ DELETE_OLD = true ] ; then echo "Deleting ALL old certs in 10 minutes..." sleep 600 aws iam list-server-certificates --query \ "ServerCertificateMetadataList[?ServerCertificateName != '$CERT_NAME'].ServerCertificateName" \ --output text | xargs -n 1 aws iam \ delete-server-certificate \ --server-certificate-name echo "Deleted old certificates" fi exit 0; fi