Automating Let’s Encrypt Certificate Renewal using DNS Challenge Type

AWS/Route53

Create the following scripts in a single directory:

  1. aws.sh — Script will create the TXT validation record
  2. aws.json — JSON required by aws-cli
  3. aws-clean.sh — Script will remove the TXT record after validation.
  4. aws-clean.json — JSON required by aws-cli
  5. Dockerfile — (Optional) build container to run certbot
  6. entrypoint.sh — (Option) entrypoint file for the container

aws.sh

#!/bin/bash
#aws.sh

export AWS_ACCESS_KEY_ID=|aws_id|
export AWS_SECRET_ACCESS_KEY=|aws_secret|

DNS_REC_NAME="_acme-challenge"
DNS_REC_DATA="$CERTBOT_VALIDATION"

# Replace string with validation and TXT name
sed -i "s/CHANGEME/$DNS_REC_DATA/g" /aws.json
sed -i "s/NAME/$DNS_REC_NAME.$CERTBOT_DOMAIN/g" /aws.json

# Create TXT record
aws route53 change-resource-record-sets --hosted-zone-id |domain_zone_id| \
--change-batch file://aws.json

# Sleep to make sure DNS propagates before lets encrypt validates.
sleep 30
export AWS_ACCESS_KEY_ID=|aws_id|
export AWS_SECRET_ACCESS_KEY=|aws_secret|

DNS_REC_NAME="_acme-challenge."
DNS_REC_DATA="$CERTBOT_VALIDATION"
# Create TXT record
aws route53 change-resource-record-sets --hosted-zone-id |domain_zone_id| \
--change-batch file://aws.json

aws.json

{
"Comment": "aws.json",
"Changes": [ {
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "NAME",
"Type": "TXT",
"TTL": 600,
"ResourceRecords": [{"Value": "\"CHANGEME\""}]
}}
]
}

aws-clean.sh

#!/bin/bash
#aws-clean.sh

export AWS_ACCESS_KEY_ID=|aws_id|
export AWS_SECRET_ACCESS_KEY=|aws_secret|

############################################################

DNS_REC_NAME="_acme-challenge"
DNS_REC_DATA="$CERTBOT_VALIDATION"

# Replace string with TXT name
sed -i "s/CHANGEME/$DNS_REC_DATA/g" /aws-clean.json
sed -i "s/NAME/$DNS_REC_NAME.$CERTBOT_DOMAIN/g" /aws-clean.json

aws route53 change-resource-record-sets --hosted-zone-id |domain_zone_id| \
--change-batch file://aws-clean.json

aws-clean.json

{
"Comment": "aws-clean.json",
"Changes": [ {
"Action": "DELETE",
"ResourceRecordSet": {
"Name": "NAME",
"Type": "TXT",
"TTL": 600,
"ResourceRecords": [{"Value": "\"CHANGEME\""}]
}}
]
}

Dockerfile

FROM ubuntu:bionic-20191029

RUN apt update

#Enter your timezone
RUN ln -snf /usr/share/zoneinfo/America/New_York /etc/localtime && echo America/New_York > /etc/timezone
RUN apt -y install certbot curl awscli

COPY aws.sh /aws.sh
COPY aws.json /aws.json
COPY aws-clean.sh /aws-clean.sh
COPY aws-clean.json /aws-clean.json

COPY entrypoint.sh /usr/bin/
ENTRYPOINT entrypoint.sh

entrypoint.sh

#!/bin/bash

certbot -d example.com --agree-tos --register-unsafely-without-email --manual \
--preferred-challenges dns --manual-auth-hook /aws.sh \
--manual-cleanup-hook /aws-clean.sh --manual-public-ip-logging-ok \
--force-renewal certonly
# Add logic to handle the certs/keys when they are issued.
$ chmod +x *.sh
$ docker build -t certbot-manager .
$ docker run certbot-manager

GoDaddy

The Godaddy scripts will update the TXT records via Godaddy’s API. When creating keys, make sure to choose the production environment.

  1. gdaddy.sh — Script will create the TXT validation record
  2. gdaddy-clean.sh — Script will change the TXT record value to “clean”.
  3. Dockerfile — (Optional) build container to run certbot
  4. entrypoint.sh — (Option) entrypoint file for the container

gdaddy.sh

#!/bin/bash

GODADDY_API_KEY="|godaddy_api_key|"
GODADDY_API_SECRET="|godaddy_api_secret|"
GODADDY_URL="https://api.godaddy.com/"
############################################################

# Replace all of a Domain's type of DNS Records

DNS_REC_TYPE=TXT
DNS_REC_NAME="_acme-challenge"
DNS_REC_DATA="$CERTBOT_VALIDATION"
DNS_REC_TTL="600"

IFS='.' read -ra ADDR <<< $CERTBOT_DOMAIN
if [[ ${#ADDR[@]} > 2 ]]; then
DNS_REC_NAME=`echo $CERTBOT_DOMAIN | cut --delimiter="." -f 1`;
DNS_REC_NAME=`echo _acme-challenge.$DNS_REC_NAME`;
fi

curl -X PUT \
"${GODADDY_URL}/v1/domains/${CERTBOT_DOMAIN}/records/${DNS_REC_TYPE}/${DNS_REC_NAME}" \
-H "accept: application/json" -H "Content-Type: application/json" \
-H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}" \
-d "[{ \"data\": \"${DNS_REC_DATA}\", \"name\": \"${DNS_REC_NAME}\", \"ttl\": ${DNS_REC_TTL} }]"

# Sleep to make sure DNS propagates before lets encrypt validates.
sleep 30
GODADDY_API_KEY="|godaddy_api_key|"
GODADDY_API_SECRET="|godaddy_api_secret|"
GODADDY_URL="https://api.godaddy.com/"
curl -X PUT \
"${GODADDY_URL}/v1/domains/${CERTBOT_DOMAIN}/records/${DNS_REC_TYPE}/${DNS_REC_NAME}" \
-H "accept: application/json" -H "Content-Type: application/json" \
-H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}" \
-d "[{ \"data\": \"${DNS_REC_DATA}\", \"name\": \"${DNS_REC_NAME}\", \"ttl\": ${DNS_REC_TTL} }]"

gdaddy-clean.sh

#!/bin/bash
GODADDY_API_KEY="|godaddy_api_key|"
GODADDY_API_SECRET="|godaddy_api_secret|"
GODADDY_URL="https://api.godaddy.com/"
############################################################

# Replace all of a Domain's type of DNS Records

DNS_REC_TYPE=TXT
DNS_REC_NAME="_acme-challenge"
DNS_REC_TTL="600"

IFS='.' read -ra ADDR <<< $CERTBOT_DOMAIN
if [[ ${#ADDR[@]} > 2 ]]; then
DNS_REC_NAME=`echo $CERTBOT_DOMAIN | cut --delimiter="." -f 1`;
DNS_REC_NAME=`echo _acme-challenge.$DNS_REC_NAME`;
fi

curl -X PUT \
"${GODADDY_URL}/v1/domains/${CERTBOT_DOMAIN}/records/${DNS_REC_TYPE}/${DNS_REC_NAME}" \
-H "accept: application/json" -H "Content-Type: application/json" \
-H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}" \
-d "[{ \"data\": \"clean\", \"name\": \"${DNS_REC_NAME}\", \"ttl\": ${DNS_REC_TTL} }]"

Dockerfile

FROM ubuntu:bionic-20191029

RUN apt update

#Enter your timezone
RUN ln -snf /usr/share/zoneinfo/America/New_York /etc/localtime && echo America/New_York > /etc/timezone
RUN apt -y install certbot curl

COPY gdaddy.sh /gdaddy.sh
COPY gdaddy-clean.sh /gdaddy-clean.sh

COPY entrypoint.sh /usr/bin/
ENTRYPOINT entrypoint.sh

entrypoint.sh

#!/bin/bash

certbot -d example.com --agree-tos --register-unsafely-without-email --manual \
--preferred-challenges dns --manual-auth-hook /gdaddy.sh \
--manual-cleanup-hook /gdaddy-clean.sh --manual-public-ip-logging-ok \
--force-renewal certonly
# Add logic to handle the certs/keys when they are issued.
$ chmod +x *.sh
$ docker build -t certbot-manager .
$ docker run certbot-manager

Conclusion

Hopefully this will steer you in the right direction automating your Let’s Encrypt renewal process. Good luck!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Chariot Solutions

Chariot Solutions

Chariot Solutions is a top IT consulting firm specializing in software and mobile development, and development in the cloud. Visit us at chariotsolutions.com.