Skip to content

Instantly share code, notes, and snippets.

@srkiNZ84
Last active August 17, 2021 15:21
Show Gist options
  • Save srkiNZ84/9c2cc9a363ca759e09733cc4d739109b to your computer and use it in GitHub Desktop.
Save srkiNZ84/9c2cc9a363ca759e09733cc4d739109b to your computer and use it in GitHub Desktop.
Bash script to automate the renewal of LetsEncrypt certificates using DNS authentication with Route53 and then updating the load balancers
#!/usr/bin/bash
# pre-requisites:
# apt install python3-pip awscli
# pip3 install certbot certbot-dns-route53 awscli
# mkdir .certbot/{config,work,logs}
# IAM policy attached to EC2 instance with:
# - route53:ListHostedZones
# - route53:GetChange
# - route53:ChangeResourceRecordSets
# - acm:ListCertificates
# - acm:ImportCertificate
# - acm:AddTagsToCertificate
# - elasticloadbalancing:SetLoadBalancerListenerSSLCertificate
# USAGE ./update_certificates.sh -d DOMAINTOGETCERTFOR -l LOADBALANCERTOUPDATE
# e.g. ./update_certificates.sh -d *.example.com -l production-public-lb
while getopts d:l: option
do
case "${option}"
in
d) DOMAIN=${OPTARG};;
l) LOADBALANCER=${OPTARG};;
esac
done
if [ -z "$DOMAIN" ] || [ -z "$LOADBALANCER" ];
then
echo "Error: Domain or LoadBalancer variable not set. Exiting"
echo "USAGE ./update_certificates.sh -d DOMAINTOGETCERTFOR -l LOADBALANCERTOUPDATE"
echo " e.g. ./update_certificates.sh -d *.example.com -l production-public-lb"
exit 1
fi
echo "$(date) Getting certificate for domain - $DOMAIN, and updating load balancer - $LOADBALANCER"
SHORTDOMAIN=$DOMAIN
if [[ "$DOMAIN" == *"*"* ]]
then
echo "Wildcard domain supplied - $DOMAIN"
SHORTDOMAIN=$(echo $DOMAIN | cut -d'.' -f2-)
echo "Without wildcard is $SHORTDOMAIN"
fi
# Get the certificates
.local/bin/certbot certonly \
--config-dir .certbot/config \
--work-dir .certbot/work \
--logs-dir .certbot/logs \
-n --agree-tos \
--email ops@example.com \
--dns-route53 -d $DOMAIN \
MD5SUM_CERT=$(md5sum .certbot/config/live/$SHORTDOMAIN/cert.pem | cut -d' ' -f1)
MD5SUM_KEY=$(md5sum .certbot/config/live/$SHORTDOMAIN/privkey.pem | cut -d' ' -f1)
TIMENOW=$(date +%s)
echo "Checking if certificate is already in AWS Certificate Manager..."
for acmCertificate in $(/home/ubuntu/.local/bin/aws acm list-certificates | jq -r .CertificateSummaryList[].CertificateArn)
do
echo "Checking certificate with ARN: $acmCertificate"
ACM_CERT_MD5SUM=$(/home/ubuntu/.local/bin/aws acm list-tags-for-certificate --certificate-arn $acmCertificate | jq -r '.Tags[] | select(.Key | contains("Md5SumCert")) | .Value')
if [[ "$MD5SUM_CERT" == "$ACM_CERT_MD5SUM" ]]
then
echo "$(date) Found certificate with matching hash! No need to import."
CERTIFICATE_ARN=$acmCertificate
break
fi
done
if [ -z "$CERTIFICATE_ARN" ]
then
echo "No matches found. Importing certificate to AWS Certificate Manager..."
CERTIFICATE_ARN=$(/home/ubuntu/.local/bin/aws acm import-certificate \
--certificate file://.certbot/config/live/$SHORTDOMAIN/cert.pem \
--private-key file://.certbot/config/live/$SHORTDOMAIN/privkey.pem \
--certificate-chain file://.certbot/config/live/$SHORTDOMAIN/chain.pem \
--tags Key=Name,Value=tj_co_wld_$TIMENOW Key=Md5SumCert,Value=$MD5SUM_CERT Key=Md5SumKey,Value=$MD5SUM_KEY \
| jq -r .CertificateArn)
fi
ELB_NAME=$LOADBALANCER
echo "$(date) Updating SSL certificate of $ELB_NAME load balancter to be $CERTIFICATE_ARN"
# Switch LoadBalancers to use the new certificate
/home/ubuntu/.local/bin/aws elb set-load-balancer-listener-ssl-certificate \
--load-balancer-name $ELB_NAME \
--load-balancer-port 443 \
--ssl-certificate-id $CERTIFICATE_ARN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment