Obtain Free Let’s Encrypt Certificates and Store Them in Azure Key Vault: A Step by Step Guide

Reading Time: 12 minutes


When providing training, I demonstrate how to obtain free automated Let’s Encrypt certificates and store them in Azure Key Vault using an ACME Bot. I’ve been asked a few times to put together a step-by-step guide, so here it is.

IMPORTANT: I am implementing this solution in a demo environment with a domain name I have registered, which is not used in production. Please be careful when implementing any new solution in production. Ensure you thoroughly research and understand what you’re deploying first.

In this post I will go through a step by step guide on how to deploy a low cost solution in Azure to obtain free TLS certs from Let’s Encrypt and store them in Azure Key Vault. Furthermore, we can automatically renew these certificates and request for additional TLS certificates as needed.

Free Managed Certificates provided by the Azure platform
Depending on which services you use in Azure, there are free certificates available for use, for example, with Azure App Services and Azure Front Door. These certs are free, managed by the Azure platform and automatically renewed. However, free managed certs are limited to some services in Azure, so can not be used for all solutions.

What is Let’s Encrypt?
Let’s Encrypt is a Certificate Authority that provides free TLS certificates, making it easy for websites to enable HTTPS encryption and create a more secure Internet for everyone. Let’s Encrypt is a project of the nonprofit Internet Security Research Group.

What is ACME?
ACME stands for Automatic Certificate Management Environment. It’s a protocol that helps automate the process of obtaining and renewing SSL/TLS certificates. This means you don’t have to manually request or update certificates; ACME does it for you, making it easier to keep your website secure. There are several ACME providers, including Let’s Encrypt, which is the provider I will be using. Other providers include Buypass Go SSL, ZeroSSL, Google Trust Services, SSL.com and more.

Let’s Encrypt is one of the well known providers, offering free certificates and supports the ACME protocol for automation. To request free TLS certs, I will deploy a client to interact with the provider Let’s Encrypt. I’ll cover further details on the client later in this post.

If you wish to follow along with this demo, I will be deploying/using the below services. If you don’t have access to an Azure subscription, not to worry, I will provide a step by step guide including screenshots whilst I go through the deployment.

  • Azure Subscription: this solution will cost a small amount so an Azure Subscription is required for billing.
  • Domain name: I’ll be using a domain I have previously registered, cloudcrazy.co.uk
  • Client: Key Vault ACME bot. I’ll be using an Azure Function to run the Key Vault ACME bot client. The ACME bot will connect to the ACME provider (Let’s Encrypt) to allow me to request FREE TLS certs. I won’t be building the ACME bot client from scratch, it already exists on GitHub at the following link, GitHub Acmebot.

  • Azure App Service Plan: an Azure App Service Plan will be deployed for the Client (Azure Function App) to run in consumption mode, so it will only cost a small amount when I trigger the function app requesting for new certs, or when the app checks for certificate expiry/renewals.

  • Storage account: A storage account will be required for the client (Azure Function App) but won’t take up to much storage.

  • Azure Key Vault: the ACME bot will also connect to Key Vault as that’s where I will be storing my TLS certs.

  • Azure DNS: The DNS zone name I will be using and requesting certificates for is cloudcrazy.co.uk. You will need your own domain name. I’ll be creating an Azure DNS zone and configuring name server records for cloudcrazy.co.uk to redirect to Azure DNS. Other domain providers are also supported, such as Amazon Route 53, Cloudflare, GoDaddy, Google Cloud DNS and more. I’ll be deploying Azure DNS. With some additional effort you can also use your own custom DNS solution.

Let’s get started

  1. Visit the ACME Bot GitHub page at the following link, GitHub ACMEbot

  2. Feel free to browse the page to understand the ACME Bot further. The page shows the following at the time of writing this post.
Image

Image

Image



3. Scrolling down to the bottom of the page, I see the option to deploy this solution into my Azure environment using an ARM (Azure Resource Manager) template. I’ll be deploying into Azure (Public). Click the Deploy to Azure button. The repository also includes the option to deploy via Terraform modules and Azure Bicep if that’s what you’re already using as part of your preferred IaC (Infrastructure as code) solution.

Image


4. You’ll be prompted to login to the Azure portal

Image


5. After I log in, the provided ARM template is automatically launched from the ACME GitHub repository into my Azure environment with some default settings enabled. I will need to complete the remaining fields before I deploy.

Image


6. After completing the additional fields, this is what my deployment will look like. Please feel free to change as per your requirements.

Resource group name: rg-KeyVaultBot
Region: UK South
Mail Address: Email address for ACME account
ACME Endpoint: I am using provider Let’s Encrypt
Create With Key Vault: true (A new Key Vault will be created. If you have an existing Key Vault, click false and enter your key vault url in the Key Vault Base Url field.

Note
The new Azure Key Vault deployment configures RBAC for permissions and not access policies.

Image



7. When ready, click Review + Create, and then create after reading the terms.

Image

Image


8. The deployment should take about 5 minutes

Image


8. Click the button Go to resource group after the deployment has completed to check what has been deployed as part of this deployment.

Image

9. Click on the Function App from inside the resource group

Image


10. Explore the function app for now. Don’t make any changes.

11. If you click on Identity from the left pane, you’ll find that the deployment configured a system managed Identity for the function app. This gives the function app an identity which has been granted permissions to access the Azure Key Vault.

Image


12. Let’s open the client app via the function app. Copy the url of your function app from the overview page, and open it in a web browser.

Image


13. I get an error, not a very useful error but this is due to an authentication failure. I need to enable authentication for the app to allow me to login and access the client. We don’t want everyone on the Internet accessing this url anonymously and issuing certs on my behalf. In the next step, I will configure Entra ID authentication.

Image


14. I’ll be using authentication via Entra ID which will allow me to use my Entra ID account. There are also other authentication methods available. Click Authentication (Under Settings) from the left pane in your function app. It is also possible to configure authentication directly from Entra ID. I’ll be using the authentication option inside the function app for this demo.

Image


15. Click the button Add identity provider

Image

16. Click Microsoft from the list of Identity providers

Image

17. This wizard will create me an Entra ID app registration which will allow me to login to the function app using my Entra ID credentials. I am going to accept the default options here.

Image

Image

18. Click Add and wait for the deployment to complete

Image


19. Let’s try the client (function app) url again

Success, Entra ID is prompting for credentials

Image


20. Login with your Entra ID credentials

21. Permissions are needed for the application to access some information. Expand to check what permissions the app is needing.

Note: Carefully review what permissions are being granted before accepting for any app.

Image
Image


21. I click Accept button to grant the needed permissions

Image


22. I successfully log in to the client (function app), but there is a further error related to DNS.

Orchestrator function ‘GetCertificates_Orchestrator’ failed: The activity function ‘GetAllCertificates’ failed: “DNS Provider is not configured. Please check the documentation and configure it.”. See the function execution logs for additional details.

Image


The function app does not have access to my domain cloudcrazy.co.uk, therefore, it can not connect. I will need to resolve this before I can request for new TLS certificates from Let’s Encrypt.

23. Back in the Azure function app, under Settings, click Environment variables.

Image


24. Click the Add button

Image



25. Type the below:

Name: Acmebot:AzureDns:SubscriptionId
Value: Enter your subscription ID

Image



26. Click Apply, and the click Apply again to save changes.

27. Click Confirm. Your app may restart.

Image
Image



Azure DNS
I’ll be creating a new Azure DNS zone in my demo environment.

28. In the Azure Portal, search for and click DNS Zones

Image


29. Click create, select a resource group and input your domain.

Click Review and Create.

Image


30. Next, I need to grant permissions for the Azure Function App (the client) to connect to my DNS zone. This will allow the app to request and perform verification when requesting TLS certs from Let’s Encrypt.

Image


31. Click Add and then Add role assignment

Image


32. Select DNS Zone Contributor and click Next

Image


33. Select Managed identity and click + Select members

Image


34. Select the function app from the list and click Select. This allows the function app access to my Azure DNS zone.

Image


35. Click the button Review + Assign

36. Finally, I’ll be configuring the name servers for my domain cloudcrazy.co.uk so they point to my Azure DNS zone. Access the Azure DNS zone again and access the overview page.

I add the DNS name servers provided on the overview page to my new domain cloudcrazy.co.uk

Note: please don’t reconfigure name servers for a domain in production without prior planning. This could lead to downtime of your critical services. The domain I am using is currently not used for any production services.

Image



37. I login to my domain registrar portal and add the 4 provided name servers from the Azure portal. This process delegates access, allowing me to control my public DNS for cloudcrazy.co.uk from within the Azure portal.

IMPORTANT: I am implementing this solution in a demo environment with a domain name I have registered, which is not used in production. Please be careful when implementing any new solution in production. Ensure you thoroughly research and understand what you’re deploying first.

I add the name servers to my domain by accessing the domain registrar portal.

Image


38. That should be it. I’ll access my Azure Function app url again. No more DNS error.

39. Click Add

Image


40. Click the DNS Zone drop down list. Great, the function app is able to view the domain from Azure DNS. Remember, I allowed permissions for the app to access my Azure DNS zone in step 30 above.

Image

41. Now, it’s time to request for a cert from Let’s Encrypt. This is where we test if the client (Azure Function App) can connect to Let’s Encrypt and issue me a certificate which should automatically be stored in Azure Key Vault.

I request for a certificate for demo.cloudcrazy.co.uk

Image

42. Click the Add button which appears next to the DNS Names field, and then click Add towards the bottom. See image below.

Image

Advanced options allows you to modify the key size and add a custom certificate name if needed. I’ll be leaving the defaults.

Image


43. Done. If successful the certificate details should appear as shown in the image below.

Image


What happened in the background
The function app connected to Let’s Encrypt requesting for a TLS cert for demo.cloudcrazy.co.uk. Let’s Encrypt responds with instructions on what needs to be done in Azure DNS to verify that I own the domain. The Azure Function App adds a temporary dns record provided by Let’s Encrypt into my Azure DNS zone to complete the verification process. The Function App then returns to Let’s Encrypt to confirm the record has been added. Let’s Encrypt completes the verification check to confirm I own the domain cloudcrazy.co.uk, and issues the free TLS cert. The temporary record is then automatically deleted by the Azure Function App. This process took about 1 minute to complete and was completed automatically after I clicked the Add button in step 42.

Image

The image above displays Unmanaged certificates and Another CA certificates.

Unmanaged Certificates: If you had certificates in your Azure Key Vault which were not created by the ACME bot, those certificates would appear under unmanaged certificates.

Another CA certificates: certificates issued by another CA (Certificate Authority) would appear here.

44. Click the details button and explore the options available.

Image
Image


As seen in the image above, I can manage the certificate from the client dashboard, including manually renewing or revoking the certificate. Also, because the function app has an API, I could automate the process without having to access the dashboard directly.

Where is the certificate stored?

45. Finally, let’s check if the certificate is visible in Azure Key Vault.

  • I’ll access my Azure Key Vault, which was created as part of the deployment earlier.
  • Inside Key Vault, click certificates from the left pane
Image


46. You may receive the error below:

Error: The operation is not allowed by RBAC. If role assignments were recently changed, please wait several minutes for role assignments to become effective. 

Image


This permissions error indicates that my user accounts does not have the permissions to access certificates in Azure Key Vault. Let’s grant permissions by accessing Access control (IAM).

Image


For the purpose of this demo, I am granting my account the role, Key Vault Administrator.
Note: there are other lower privileged Key Vault roles available.

Image


47. Now that I have assigned my account permissions, let’s try that again.

The certificate is now visible to me in Azure Key Vault

Image


48. Click the certificate and you’ll see one version. Go back to your Azure function app and click the button to renew the certificate, you’ll find another version of the certificate will automatically appear in your Azure Key Vault. Any apps connecting to your certs will automatically start to use the new version of the certificate upon renewal.

Image
Image

And the Azure Key Vault now shows the new version of the certificate.

Image


49. Go ahead and request for a new certificate from within the Azure Function App dashboard. This time, I’ll input portal.cloudcrazy.co.uk and I’ll try a wild card of *.cloudcrazy.co.uk

Image


Image
Image
Image


Two additional certificates are now visible in Azure Key Vault as shown in the image below.

Image


I hope you found this demo useful.