Automating Certificate Management with keyvault-acme

Saving you time with automated certificate management.

Introduction

As organizations continue to move their applications and infrastructure to the cloud, the management of SSL certificates becomes increasingly important. SSL certificates ensure secure communication between clients and servers by encrypting data and validating the authenticity of the server.

In Azure, A Key Vault is a popular service for securely storing and managing secrets, including SSL certificates. However, obtaining and renewing these certificates can be a tedious and time-consuming task. This is where keyvault-acmebot comes in.

keyvault-acmebot is an open-source tool that integrates Azure services (Function, Key Vault, Managed Identity) with Let’s Encrypt to automatically obtain and renew SSL certificates. It simplifies the process of managing certificates for your Azure-based applications by automating the entire lifecycle—from obtaining the certificate to securely storing it in Key Vault.

In this post, we’ll take a closer look at how to use keyvault-acmebot to automate SSL certificate management.

What is keyvault-acmebot?

keyvault-acmebot is a bot that uses the ACME protocol (Automatic Certificate Management Environment) to interact with Let’s Encrypt, a free Certificate Authority (CA) that issues SSL certificates. The tool automates the entire process of requesting, validating, and renewing SSL certificates and securely stores them in Azure Key Vault.

The main features of keyvault-acmebot include:

  • Automated SSL certificate provisioning:
    The bot automatically requests certificates from Let’s Encrypt based on the domain names you configure.

  • Automatic renewal:
    Once the certificates are obtained, the bot automatically renews them when they are close to expiration.

  • Secure storage:
    SSL certificates are securely stored in Azure Key Vault, allowing you to manage them just like any other secret.

  • Support for DNS-01 challenge:
    The bot supports the DNS challenge type for domain validation, which is particularly useful for scenarios where HTTP challenges cannot be used.

Deployment time

Back in 2023, I quote some bicep to deploy this acme solution, and during the festive break while having some spare time on my hands, I’ve cleaned up the code base and moved it over from “CARML (Common Azure Resource Modules Library)” to “Azure Verified Modules”. You can check out the code base here: https://github.com/builtwithcaffeine/bwc-keyvault-acme-bicep.

Please note, this solution uses Access Policies for Access/Authentication

During the deployment, An Enterprise Application and Service Principal will be created and the following resources deployed:

image

The Function App will have a System Assigned Managed Identity created, which will be configured with the following RBAC roles at the subscription level:

DNS Zone Contributor

  • Provides permissions to manage DNS zones, enabling the Function App to create and manage DNS records required for its operation.
  • This role will be scoped to ensure access to only the DNS zones necessary for the Function App’s functionality.

Private DNS Zone Contributor

  • Grants the Function App the ability to manage Private DNS Zones, facilitating dynamic DNS updates essential for integration with other Azure services.
  • The scope of this role will be restricted to relevant Private DNS Zones to adhere to the principle of least privilege.

By assigning these roles at the subscription level, the Function App will inherit permissions across all DNS zones in the subscription, streamlining access management.

Prerequisites

Before you begin, ensure that you have both Azure CLI and Azure Bicep installed. To install, run the following in an administrative context:

1
2
3
4
$appList = ('Git.Git', 'Microsoft.AzureCLI', 'Microsoft.Bicep')
foreach ($app in $appList) {
    winget install --scope Machine --exact --id $app
}

Clone the Repository

Clone the repository to your local machine:

1
2
git clone https://github.com/builtwithcaffeine/bwc-keyvault-acme-bicep.git
Set-Location -Path 'bwc-keyvault-acme-bicep'

Configure Parameters

Open deployNow.ps1 and customize the parameters in the $kvacmeparams hash table to suit your environment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Key Vault ACME Parameters
$kvacmeparams = @{
    spName                    = "sp-kvacme-letsencrypt-$environmentType"
    funcName                  = "func-kvacme-$environmentType-$locationShortCode"
    entraIdGroup              = "sec-kvacme-funcapp-portal-$environmentType"

    virtualNetworkCidr        = "192.168.0.0/24"
    virtualNetworkSubnet      = "192.168.0.0/24"

    acmeMailAddress           = "alerts@builtwithcaffeine.cloud"
    acmeEndPoint              = "https://acme-v02.api.letsencrypt.org/"

    resourceGroupName         = "rg-kvacme-$environmentType-$locationShortCode"
    virtualNetworkName        = "vnet-kvacme-$environmentType-$locationShortCode"
    managedIdentityName       = "id-kvacme-$environmentType-$locationShortCode"
    keyVaultName              = "kv-kvacme-$environmentType-$locationShortCode"
    storageAccountName        = "stgkvacme$locationShortCode"
    logAnalyticsWorkspaceName = "log-kvacme-$environmentType-$locationShortCode"
    appInsightsName           = "appi-kvacme-$environmentType-$locationShortCode"
    appServicePlanName        = "asp-kvacme-$environmentType-$locationShortCode"
    functionAppName           = "func-kvacme-$environmentType-$locationShortCode"
}

Execute the Bicep Deployment

Run the deployment script to create and configure the necessary resources. Replace with your Azure subscription ID, and specify the environment type (e.g., [dev], [acc], or [prod]):

1
2
3
4
5
.\deployNow.ps1 `
-subscriptionId <subscription-id> `
-environmentType [dev|acc|prod] `
-location westeurope `
-deploy

Operating Instructions

Once the deployment is completed, (Takes around 5 minutes, after 6 hours of build time :D). Head to the function app and open the Default domain url:

Enterprise App Authentication

When you first open the function app, You’ll need to authenticate the Enterprise App.

Creating SSL Certificate

Here is the portal for the Key Vault ACME, If you want to create a record click Add From the DNS Zone, You can pick from Azure Public DNS or Azure Private DNS Zone.

Advanced Options

Click Add,

Finally, Checking the Azure Key Vault we can see the certificate

Wrap Up

Automating certificate management is a game-changer for organizations operating in the cloud. By leveraging keyvault-acmebot, you can simplify SSL certificate handling, reducing manual intervention while ensuring your applications remain secure and compliant.

This solution demonstrates the power of combining Azure Key Vault with automation tools like Let’s Encrypt and Bicep for Infrastructure as Code. From deploying resources with Azure Verified Modules to managing certificates with minimal effort, this workflow is a robust and scalable way to handle SSL certificates in Azure environments.

The repository bwc-keyvault-acme-bicep serves as a practical implementation, offering everything you need to get started. Whether you’re setting up certificates for public or private DNS zones, this approach saves time and provides enterprise-grade security.

If you have questions or enhancements you’d like to see, feel free to contribute or open an issue in the repository. Let automation take the hassle out of certificate management!

Share with your network!

Built with Hugo - Theme Stack designed by Jimmy