loading...

OpenVPN: Let’s Encrypt DNS verification on AWS Route53 and OpenVPN Access Server SSL certificate auto update

setevoy profile image Arseny Zinchenko Originally published at rtfm.co.ua on ・5 min read

In addition to the OpenVPN: SSL and hostname configuration post about OpenVPN Access Server, set up and configuration.

So, three months passed and it’s time to renew Let’s Encrypt SSL certificate (see. Prometheus: Alertmanager и blackbox-exporter — проверка срока действия SSL и нотификация в Slack, Rus).

I could use a well-know for me scheme with the webroot but OpenVPN AS accepts connections itself and there is no NGINX, and install it just for the webroot and Let’s Encrypt renewals – not too good idea.

Better let’s use DNS verification now.

AWS IAM and certbot-user

We have our domains served by AWS Route53 so use certbot-dns-route53 here.

Get your zone ID:

Create IAM-policy, in the ChangeResourceRecordSets set zone’s ID:

{
    "Version": "2012-10-17",
    "Id": "certbot-dns-route53 sample policy",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ListHostedZones",
                "route53:GetChange"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "route53:ChangeResourceRecordSets"
            ],
            "Resource" : [
                "arn:aws:route53:::hostedzone/Z30***LB6"
            ]
        }
    ]
}

(later I thought that it could be a good idea to add zone name to the policy or user names to make them more descriptive, as zone/user has access to the only one zone here)

Create a new user with the Programmatic access:

In the Permissions chose Attach existing policies directly and attach policy created above:

For testing – install aws-cli:

root@openvpnas2:~# apt -y install awscli

Under the openvpnas user configure AWS CLI default-profile:

openvpnas@openvpnas2:~$ aws configure
AWS Access Key ID [None]: AKI***JEL
AWS Secret Access Key [None]: Lry***ide
Default region name [None]:
Default output format [None]: json

Check config:

root@openvpnas2:~# cat /home/openvpnas/.aws/config
[default]
output = json

OK – profile exists and it will be used later by the certbot.

To test access – try to get zones list:

openvpnas@openvpnas2:~$ aws route53 list-hosted-zones --output text
HOSTEDZONES     33C2D264-***-***-***-3052BEA607A9    /hostedzone/Z30***LB6      example.com. 103
...

All good here.

certbot DNS verification

Install certbot:

openvpnas@openvpnas2:~$ sudo apt -y install certbot

And the Route53 plugin:

openvpnas@openvpnas2:~$ sudo apt -y install python3-certbot-dns-route53

Authorize and obtain the certificate:

root@openvpnas2:~# certbot certonly --dns-route53 -d vpn.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Found credentials in shared credentials file: ~/.aws/credentials
Plugins selected: Authenticator dns-route53, Installer None
Attempting to parse the version 0.31.0 renewal configuration file found at /etc/letsencrypt/renewal/vpn.example.com.conf with version 0.23.0 of Certbot. This might not work.
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
dns-01 challenge for vpn.example.com
Waiting 10 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:

- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/vpn.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/vpn.example.com/privkey.pem
...

Check the zone in the Route53 – certbot must create a TXT-record here which will be used for authorization, and certbot will update it with a new value on each renewal

Check renewals config for this domain:

root@openvpnas2:~# cat /etc/letsencrypt/renewal/vpn.example.com.conf
renew_before_expiry = 30 days
...
Options used in the renewal process
[renewalparams]
authenticator = dns-route53
account = 6bc***4f6
installer = None

Then will be enough just to execute certbot renew.

OpenVPN Access Server SSL update

To update SSL in the OpenVPN AS need to:

  1. upload the domain's certificate: sacli --key "cs.cert" --value_file "/etc/letsencrypt/live/vpn.example.com/cert.pem" ConfigPut
  2. upload Let’s Encrypt's certificate: sacli --key "cs.ca_bundle" --value_file "/etc/letsencrypt/live/vpn.example.com/chain.pem" ConfigPut
  3. upload our private key: sacli --key "cs.priv_key" --value_file "/etc/letsencrypt/live/vpn.example.com/privkey.pem" ConfigPut
  4. and rstart OpenVPN server

Collect all of them in one bash-script which will be called later by cron.

Go to the OpenVPN scripts catalog:

root@openvpnas2:~# cd  /usr/local/openvpn_as/scripts/

Create a ssl_renew.sh script:

#!/usr/bin/env bash

SCRIPTS="/usr/local/openvpn_as/scripts/"

$SCRIPTS/sacli --key "cs.cert" --value_file "/etc/letsencrypt/live/vpn.example.com/cert.pem" ConfigPut
$SCRIPTS/sacli --key "cs.ca_bundle" --value_file "/etc/letsencrypt/live/vpn.example.com/chain.pem" ConfigPut
$SCRIPTS/sacli --key "cs.priv_key" --value_file "/etc/letsencrypt/live/vpn.example.com/privkey.pem" ConfigPut

$SCRIPTS/sacli start

Just in case – backup exisitng keys:

root@openvpnas2:/usr/local/openvpn_as/scripts# cp /usr/local/openvpn_as/etc/web-ssl/server.crt /usr/local/openvpn_as/etc/web-ssl/server.crt.OLD

root@openvpnas2:/usr/local/openvpn_as/scripts# cp /usr/local/openvpn_as/etc/web-ssl/server.key /usr/local/openvpn_as/etc/web-ssl/server.key.OLD

Run your new script:

root@openvpnas2:/usr/local/openvpn_as/scripts# ./ssl_renew.sh
[True, {}]
[True, {}]
[True, {}]
RunStart warm None
{
  "active_profile": "ProfileName",
  "errors": {},
  "service_status": {
    ...
    "web": "restarted"
  }
}

WILL_RESTART ['web', 'client']

Check in a browser:

Then add a hook for certbot to run this script after renew.

Edit the /etc/letsencrypt/renewal/vpn.example.com.conf file:

...
[renewalparams]
authenticator = dns-route53
account = 6bc***4f6
installer = None
renew_hook = /usr/local/sbin/openvpnas_renewcerts.sh

And the last thing – add a crontask with certbot renew, execute crontab -e:

0 0 * * * /usr/bin/certbot renew &> /var/log/letsencrypt/letsencrypt.log

Done.

Similar posts

Posted on by:

setevoy profile

Arseny Zinchenko

@setevoy

DevOps, cloud and infrastructure engineer. Love Linux, OpenSource, and AWS.

Discussion

pic
Editor guide
 

LetsEncrypt have revoked around 3 million certs last night due to a bug that they found. Are you impacted by this, Check out ?

DevTo
[+] dev.to/dineshrathee12/letsencrypt-...

GitHub
[+] github.com/dineshrathee12/Let-s-En...

LetsEncryptCommunity
[+] community.letsencrypt.org/t/letsen...