Securing your Azure Web App with Let's Encrypt.
Ope Adeyomoye
Posted on April 20, 2020
This post assumes that you have deployed your web app in a Docker container on Microsoft Azure's fully-managed App Service platform. It also assumes that, for some reason, you want to manually obtain an SSL certificate for your app, and manually renew it before it expires.
Before we get to certificates...
When you deploy your app on Azure's App Service platform, you automatically get a URL that can be used to view your app. It'll usually be in the form: https://your-app-name.azurewebsites.net. If you like the free domain and don't exactly see a need to use a custom domain, then you probably don't need most of the rest of this post. I'd suggest you turn on "HTTPS only" tho.
Chances are, however, you do want to serve your app using a custom domain. If you've not added a custom domain to your App Service app, please see Azure's docs on this and follow the steps there.
It could be much easier
Azure lets you create a free certificate and add it your App Service app at the click of a couple buttons. It's issued by DigiCert, managed by App Service, and renewed automatically.
If you'd like to use this instead of rolling your own, see Azure's docs on it and don't forget to turn on HTTPS Only.
Getting a certificate
Let's Encrypt recommends using the Certbot ACME client for certificate issuance. Certbot can automate certificate issuance and installation, but this post demonstrates using Certbot in manual mode.
First, let's install Certbot. On Debian 10+ systems:
$ sudo apt-get update
$ sudo apt-get install certbot
For other Debian versions, linux distros or different operating systems, please see Certbot's installation docs.
Issuing a certificate
Now, let's get an SSL certificate issued for yourdomain.com
. On the command line:
$ sudo certbot certonly -d yourdomain.com --manual --preferred-challenges dns
That command:
- via the
certonly
sub-command, tells Certbot to simply obtain a new certificate, and not install it on your local machine; - tells Certbot to use a DNS challenge. As opposed to an HTTPS challenge where you'd have to upload a certain file to a specific directory on your server, a DNS challenge requires you to add a DNS TXT record on your domain.
After a few simple questions, Certbot will ask you to create a DNS TXT record, usually under the name _acme-challenge.yourdomain.com
, with a value it provides. Usually, you'll do this via your DNS provider. Please see your DNS provider's docs on how to create DNS records for your domain.
If it all went well, you should see a message like this:
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/yourdomain.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/yourdomain.com/privkey.pem
Your cert will expire on <some-date>. 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
Add your shiny new certificate to App Service
To secure a custom domain for your web app, Azure requires a private certificate in the PKCS #12 file format. Certbot does not generate this file by default, but you can create it using some of the files it does generate.
Create a private certificate
For this, you'll need:
- your server certificate file;
- the private key for your certificate;
- the intermediate certificate from Let's Encrypt CA.
All those files can be found at /etc/letsencrypt/live/yourdomain.com/
, and you can simply run the following commands to create your private certificate:
# create a staging area
$ mkdir /tmp/sandbox -p
$ cd /tmp/sandbox
# copy the needed files over
$ SOURCE=/etc/letsencrypt/live/yourdomain.com
$ sudo cp $SOURCE/{cert.pem,privkey.pem,chain.pem} .
# make the files your own
# assuming your username is ope...
$ sudo chown ope *.pem
# finally, create the private certificate,
# saving it to "certificate.pfx"
$ openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem
That last command asks you to enter an export password. Please make note of that password since you'll need it when uploading your private certificate on Azure.
Upload the private certificate
From your Azure portal, navigate to your App Service web app and click on the "Custom domains" menu item. In the page that comes up, find the row that contains the custom domain you added and click "Add binding" under the "SSL Binding" column.
In the sidebar that comes up, click "Upload PFX Certificate"
Within the form that's displayed next, select the certificate.pfx
file you created, and enter the password you chose.
Click "Upload" to proceed. The next screen should look like this:
Click "Add Binding" once you've selected the relevant options.
That's it! Once the deployment is complete on Azure, you can now navigate to your web app, via your custom domain, using HTTPS.
Clean up
You can't subsequently download your private certificate from Azure App Service, so you might want to store the local copy somewhere other than the system temp directory:
$ cp /tmp/sandbox/certificate.pfx /path/to/dir/
Once your private certificate is safe, you may clear out the sandbox:
$ rm /tmp/sandbox/ -R
Consider turning on "HTTPS Only"
Azure App Service has a little handy feature, called HTTPS Only, that helps redirect all of your app's HTTP traffic to HTTPS.
That makes sure that any client communication with your app is encrypted, and visitors aren't scared away with "Connection not secure" messages from their browsers.
To turn this on, head on to your App Service within the Azure portal, and click on the TLS/SSL settings menu item. You'll find the option there under "Protocol Settings".
Posted on April 20, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.