Free of charge encryption? Sure, it's possible, thanks to Let's Encrypt. This nonprofit organization backed by many influential tech companies signs your certificates in the most user-friendly, automated way they can. Kudos to you Let's Encrypt, you're making the web safer! But in this post, I will take a look at a very specific case: how we can generate digital certificates in Oracle Linux with a DNS challenge. Let's start jump to it.

Certbot

With high regards for what Let's Encrypt is doing, let's take a look at certbot. I don't have any better way to describe what certbot is, so here it is directly from the documentation:

Certbot is a free, open source software tool for automatically using Let’s Encrypt certificates on manually-administrated websites to enable HTTPS.

Certbot is an interface with Let's Encrypt service, a CLI tool that can be used to generate and renew your certificates. It's a very simple and efficient instrument, well documented and with a plethora of plugins developed, or under development. Looking to generate Let's Encrypt certificates? Certbot is going to be your best friend.

First thing first, you will need to install certbot. I'm using Oracle Linux 7.9 and the install cannot be easier.

 sudo yum install certbot -y
 

No reason to drill into advanced functionalities like plugins, but it's interesting for what will come next to check the pre-installed options coming with certbot. Quick hint, we are going to use neither of them.

[opc@vm-certbot ~]$ certbot plugins

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* standalone
Description: Spin up a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot._internal.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Most of the tutorials on the internet are covering the HTTP challenge (checking if the webserver properly responds to the request), which means that you need to have a web server with port 80 open. Certbot is so cool that you receive customized install steps based on your web server and OS. Are you using the popular Nginx or Apache server? Let certbot do the job.

This approach is simple and works great for a single web server, the certificate being somehow "bound" to the server on which the client is running. But what if you would like to install the certificate on a load balancer, and distribute the traffic among multiple backend servers? What if you don't have a running http server, and such, you cannot pass the HTTP challenge? DNS to the rescue.

acme-dns

Certbot allows plugging a hook that registers acme-dns accounts and prompts the user to manually add the CNAME records to their main DNS zone on initial run. Sounds complicated? It's not. Let's see how it goes by downloading the python script first.

[opc@vm-certbot ~]$ sudo curl -o /etc/letsencrypt/acme-dns-auth.py https://raw.githubusercontent.com/joohoi/acme-dns-certbot-joohoi/master/acme-dns-auth.py
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  5570  100  5570    0     0  42256      0 --:--:-- --:--:-- --:--:-- 42196

[opc@vm-certbot ~]$ sudo chmod 0700 /etc/letsencrypt/acme-dns-auth.py

Check the first line of the file: depending on your system setup, you might need to change the path of your python install after shebang (#!).

[opc@vm-certbot ~]$ which python3
/usr/bin/python3

You're all set. When invoking certbot, you need to manually pass some arguments, like `--manual` that enable you to pass the dns hook. The script can use multiple challenges, but we're making it clear we're looking to use dns by `--preferred-challenges`. You want to make a pause and have the time to update your DNS config, and you do it thanks by `--debug-challenges`. Finally, provide the name or names of the domains you would like to sign the certificate for.

[opc@vm-certbot ~]$ sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.certbot.cloudness.net

A series of Y/N will be provided, based on your preference. It's self-explanatory so we skip it. What we need to pay close attention is the output of our script: Please add the following CNAME record to your main DNS zone:
_acme-challenge.certbot.cloudness.net CNAME 96096441-4076-4b47-ae40-02d8ba123f19.auth.acme-dns.io.
This is the moment when the script takes a pause, so you have the time to update your DNS entries. Don't press Enter until your zone changes have been propagated.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): alex@cloudness.net
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Account registered.
Requesting a certificate for *.certbot.cloudness.net
Performing the following challenges:
dns-01 challenge for certbot.cloudness.net
Running manual-auth-hook command: /etc/letsencrypt/acme-dns-auth.py
Output from manual-auth-hook command acme-dns-auth.py:
Please add the following CNAME record to your main DNS zone:
_acme-challenge.certbot.cloudness.net CNAME 96096441-4076-4b47-ae40-02d8ba123f19.auth.acme-dns.io.

Waiting for verification...

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Challenges loaded. Press continue to submit to CA. Pass "-v" for more info about
challenges.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Depending on how you're administering your DNS, these steps will be different, as there is nothing to do with our environment. For example, if your registrar is GoDaddy, the entry is going to look something like this.

Are the changes in place? Then you are ready to publish them. It might take some time to propagate them, so before getting back to our console make sure the entry is reachable. You can use a web-based tool like mxtoolbox, or dig it on your own :).

https://mxtoolbox.com/SuperTool

Everything looks great. It's time to hit Enter and let certbot do it's magic.

Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/certbot.cloudness.net/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/certbot.cloudness.net/privkey.pem
   Your certificate will expire on 2021-07-18. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Congrats. The certificates signed by Let's Encrypt are now stored in you local environment. As you can notice, there are two files: the fullchain certificate and the private key. Let's take a look at them.

[opc@vm-certbot ~]$ sudo cat /etc/letsencrypt/live/certbot.cloudness.net/fullchain.pem
-----BEGIN CERTIFICATE-----
MIIFMzCCBBugAwIBAgISBDDDiesIPrvFasS8tThamgALMA0GCSqGSIb3DQEBCwUA
FyouY2VydGJvdC5jbG91ZG5lc3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAlFenRa4SVQbw0gLC9pQh/4GHyxMycqjq5yvMPYniwDuGAm8ZN3+2
UvcPDV8hWxleaU9le5++m4XRLIMVeQMI3CCWhPaHD8SwnJtPKzGrwsSRvSDnoid3
pBiqqByuH2I82Aw1jXNkRAkmjGncav16K+oSI7SRPMLGwVDHcbQOyA7V3Ypx7f6d
mPnyCod7xgkvatRTxJ4wU+zOheBfMAja2RTuMJq5pYHTkVOgzz3v7YMwvZF1viXT
7huU2Z6EfQYXup3ykZHYU6GnnNNIKoAIZB0FGhi4/fw/fIS59A3yf+uAMm8snc+M
mUvRu/8hpVcVC6DQSscmbg4KFYzdlUfCTQIDAQABo4ICUTCCAk0wDgYDVR0PAQH/
BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8E
AjAAMB0GA1UdDgQWBBTsuh0q6/hrbtBv9QmWu3PxPR3qbjAfBgNVHSMEGDAWgBQU
LrMXt1hWy65QCUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUHMAGG
FWh0dHA6Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3IzLmku
bGVuY3Iub3JnLzAiBgNVHREEGzAZghcqLmNlcnRib3QuY2xvdWRuZXNzLm5ldDBM
BgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIB
FhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCCAQMGCisGAQQB1nkCBAIEgfQE
gfEA7wB1AH0+8viP/4hVaCTCwMqeUol5K8UOeAl/LmqXaJl+IvDXAAABeOn78hEA
AAQDAEYwRAIgKEqgx2Rpsk/Cjoy0WKChRUXc050bKqO9uWReO5yhAdwCIDGREd5M
WK0ypv9p4KJW/zAWO4NxS2h/MkKhRuVQqdx3AHYAb1N2rDHwMRnYmQCkURX/dxUc
EdkCwQApBo2yCJo32RMAAAF46fvyJAAABAMARzBFAiEAk2bE3F6bvenfT3N/qb1k
kIBBQo9rYkVjXJZ3QkVWJkcCIFLzi33tfQ+TP1N7oaiIpMi3ug5MC6RADW7Fkh73
gZleMA0GCSqGSIb3DQEBCwUAA4IBAQC0/5GROdA0eFxFakclvBJ2bDNhh4YkjDCj
46LbKOPjRUiBwRYkgJUr+6VNEB1d7Dst73RCdl/pdEQxBuLAFwrFM97bHKOMVkP9
Lw8bzMk4CIP7mUNm5r+Z53/B7jx15gDd/dfWDaxrmvvqwxbV207X9RT0BBU7GKbc
dUwqcnS02ymrTyqom1o/n9oEQnaTT3Wk6xN582SCPliAxqDfZcd8IELjuNYgaqJG
hcdz78EdmxEmHh4gBBDrKTdI3bt6ENY7zMCuZwxr2WslDqCPbj2pt/WVT4vkpKXM
i/WjqonX2CxcrI5z/2w+WoZ2QuMt+aXoW5JpEFzPAFsUER0LbXqU
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/
MjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxCzAJBgNVBAMT
AlIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwIVKMz2oJTTDxLs
jVWSw/iC8ZmmekKIp10mqrUrucVMsa+Oa/l1yKPXD0eUFFU1V4yeqKI5GfWCPEKp
Tm71O8Mu243AsFzzWTjn7c9p8FoLG77AlCQlh/o3cbMT5xys4Zvv2+Q7RVJFlqnB
U840yFLuta7tj95gcOKlVKu2bQ6XpUA0ayvTvGbrZjR8+muLj1cpmfgwF126cm/7
gcWt0oZYPRfH5wm78Sv3htzB2nFd1EbjzK0lwYi8YGd1ZrPxGPeiXOZT/zqItkel
/xMY6pgJdz+dU/nPAeX1pnAXFK9jpP+Zs5Od3FOnBv5IhR2haa4ldbsTzFID9e1R
oYvbFQIDAQABo4IBaDCCAWQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
BAMCAYYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5p
ZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTE
p7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEE
AYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2Vu
Y3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0
LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYf
r52LFMLGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B
AQsFAAOCAQEA2UzgyfWEiDcx27sT4rP8i2tiEmxYt0l+PAK3qB8oYevO4C5z70kH
ejWEHx2taPDY/laBL21/WKZuNTYQHHPD5b1tXgHXbnL7KqC401dk5VvCadTQsvd8
S8MXjohyc9z9/G2948kLjmE6Flh9dDYrVYA9x2O+hEPGOaEOa1eePynBgPayvUfL
qjBstzLhWVQLGAkXXmNs+5ZnPBxzDJOLxhF2JIbeQAcH5H0tZrUlo5ZYyOqA7s9p
O5b85o3AM/OJ+CktFBQtfvBhcJVd9wvlwPsk+uyOy2HI7mNxKKgsBTt375teA2Tw
UdHkhVNcsAKX1H7GNNLOEADksd86wuoXvg==
-----END CERTIFICATE-----

You have the certificates, but you still need to configure your web server, load balancer, managed services or whatever it would be to use it. We will take a look in a later post how easy it is to install these certificates on OCI load balancer or WAF. Before we wrap it up, there is one more thing I would like to cover.

Our certificate is valid for a period of three months, as we can see by inspecting it. This means you will need to generate a new one once this expires. But certbot is renewing it automatically, you might say. Indeed, with a simple command, the new certificate will be re-issued.

[opc@vm-certbot ~]$ sudo certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/certbot.cloudness.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificates are not due for renewal yet:
  /etc/letsencrypt/live/certbot.cloudness.net/fullchain.pem expires on 2021-07-18 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

There is a valid certificate, so no need to renew it. Just for the sake of the exercise, you can run a dry run and see what will happen in three months.

[opc@vm-certbot ~]$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/certbot.cloudness.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator manual, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Simulating renewal of an existing certificate for *.certbot.cloudness.net
Performing the following challenges:
dns-01 challenge for certbot.cloudness.net
Running manual-auth-hook command: /etc/letsencrypt/acme-dns-auth.py
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/certbot.cloudness.net/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/certbot.cloudness.net/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -