Automating Let's Encrypt SSL Certificate Renewal for Azure Application Gateway
Introduction to Let's Encrypt
Let's Encrypt is a free, automated, and open certificate authority (CA) that provides SSL/TLS certificates, enabling secure communication between websites and their users. It simplifies the process of obtaining and managing certificates, making HTTPS more accessible to everyone.
Key Features of Let's Encrypt
How Let's Encrypt Works
Setting Up Let's Encrypt for Azure Application Gateway
1. Create an Azure App Service (Web App)
2. Create an Azure Storage Account
3. Configure Azure Application Gateway
Automating SSL Certificate Renewal with Azure Automation
1. Create an Azure Automation Account
2. Create a PowerShell Runbook
->
#######################################################################
# Script that renews a Let's Encrypt certificate for an Azure Application Gateway
# Pre-requirements:
#????? - Have a storage account in which the folder path has been created:
#??????? '/.well-known/acme-challenge/', to put here the Let's Encrypt DNS check files
?
#????? - Add "Path-based" rule in the Application Gateway with this configuration:
#?????? ????- Path: '/.well-known/acme-challenge/*'
#?????????? - Check the configure redirection option
#?????????? - Choose redirection type: permanent
#?????????? - Choose redirection target: External site
#?????????? - Target URL: <Blob public path of the previously created storage account>
#??????????????? - Example: 'https://test.blob.core.windows.net/public'
#????? - For execution on Azure Automation: Import 'AzureRM.profile', 'AzureRM.Network'
#??????? and 'ACMESharp' modules in Azure
######################################################################
?
Param(
??? [string]$domain,
??? [string]$EmailAddress,
??? [string]$STResourceGroupName,
??? [string]$storageName,
??? [string]$AGResourceGroupName,
??? [string]$AGName,
??? [string]$AGOldCertName
)
if (-not (Get-Module -Name Az.Accounts -ListAvailable)) {
??? Install-Module -Name Az.Accounts -Force
}
if (-not (Get-Module -Name Az.Storage -ListAvailable)) {
??? Install-Module -Name Az.Storage -Force
}
if (-not (Get-Module -Name ACME-PS -ListAvailable)) {
??? Install-Module -Name ACME-PS -Force -Scope CurrentUser
}
if (-not (Get-Module -Name Az.Network -ListAvailable)) {
??? Install-Module -Name Az.Network -Force
}
?
Import-Module ACME-PS;
Import-Module Az.Accounts;
Import-Module Az.Storage;
Import-Module Az.Network
?
领英推荐
Disable-AzContextAutosave
Connect-AzAccount -Identity
$state = New-ACMEState -Path $env:TEMP
$serviceName = 'LetsEncrypt'
Get-ACMEServiceDirectory $state -ServiceName $serviceName -PassThru;
New-ACMENonce $state;
New-ACMEAccountKey $state -PassThru;
New-ACMEAccount $state -EmailAddresses $EmailAddress -AcceptTOS;
$state = Get-ACMEState -Path $env:TEMP;
New-ACMENonce $state -PassThru;
$identifier = New-ACMEIdentifier $domain;
$order = New-ACMEOrder -State $state -Identifiers $identifier;
if ($null -eq $order) { # Will fetch the order
??? $order = Find-ACMEOrder -State $state -Identifiers $identifier;
}
$authZ = Get-ACMEAuthorization -State $state -Order $order;
$challenge = Get-ACMEChallenge -State $state -Authorization $authZ -Type "http-01";
$fileName = $env:TMP + '\' + $challenge.Token;
Set-Content -Path $fileName -Value $challenge.Data.Content -NoNewline;
$blobName = ".well-known/acme-challenge/" + $challenge.Token
$storageAccount = Get-AzStorageAccount -ResourceGroupName $STResourceGroupName -Name $storageName
$ctx = $storageAccount.Context
Get-AzStorageContainerAcl -Name "public" -Context $ctx
Set-AzStorageBlobContent -File $fileName -Container "public" -Context $ctx -Blob $blobName
Get-AzStorageBlob -Container "public" -Context $ctx -Blob $blobName
$challenge | Complete-ACMEChallenge -State $state;
while($order.Status -notin ("ready","invalid")) {
??? Start-Sleep -Seconds 10;
??? $order | Update-ACMEOrder -State $state -PassThru;
}
if($order.Status -ieq ("invalid")) {
??? $order | Get-ACMEAuthorizationError -State $state;
??? throw "Order was invalid";
}
$certKey = New-ACMECertificateKey -Path "$env:TEMP\$domain.key.xml";
?
Complete-ACMEOrder -State $state -Order $order -CertificateKey $certKey;
while(-not $order.CertificateUrl) {
??? Start-Sleep -Seconds 15
??? $order | Update-ACMEOrder -State $state -PassThru
}
$password = ConvertTo-SecureString -String "**********" -Force -AsPlainText
Export-ACMECertificate $state -Order $order -CertificateKey $certKey -Path "$env:TEMP\$domain.pfx" -Password $password;
?
# Delete blob to check DNS
Remove-AzStorageBlob -Container "public" -Context $ctx -Blob $blobName
?
### RENEW APPLICATION GATEWAY CERTIFICATE ###
$appgw = Get-AzApplicationGateway -ResourceGroupName $AGResourceGroupName -Name $AGName
Set-AzApplicationGatewaySSLCertificate -Name $AGOldCertName -ApplicationGateway $appgw -CertificateFile "$env:TEMP\$domain.pfx" -Password $password
Set-AzApplicationGateway -ApplicationGateway $appgw
->
3. Test and Deploy the Runbook
4. Schedule Automated Renewals
Diagram Flow
Conclusion
Automating the renewal of Let's Encrypt SSL certificates in Azure using Azure Automation and PowerShell Runbooks significantly reduces manual effort and enhances security. By implementing this solution, organizations can ensure uninterrupted HTTPS availability, comply with security best practices, and simplify certificate management.