Jason, our CTO, discusses the automatic deployment of Let's Encrypt SSL/TLS Certificates on Azure App Gateway.
Automation is critical for our cloud infrastructure at Nexosis. In our Amazon Web Service environments, free SSL/TLS certificates are provided through Certificate Manager and can be easily automated through CloudFormation templates - no issues here.
The situation is somewhat different in Azure where App Service Certificates can cost 69.99 or $299.99 (wildcard) per year per domain. We use different domain names for Dev, UAT and Production environments. Having to manually setup SSL on each doesn’t excite me very much. However, this solution is sufficient and the cost nominal, but will only work with a very limited set of Azure Resources. Additionally, generating the certs and getting them signed still requires manual process so any SSL/TLS solution involves some variation of "pay money" and perform a manual process - that's a no go.
One example involves applying an SSL/TLS Certificate on an Azure Application Gateway. Automation of this Resource Type is supported via ARM Template by including a PFX formatted certificate or by running some Azure PowerShell scripts to apply the signed SSL/TLS certificate. The automation of generating, signing and deploying the Certificate is up to us.
Let's Encrypt provides free SSL / TLS Certificates as well as automation so the process should be pretty straight-forward.
- Azure App Gateway SSL/TLS Certificate
- Let's Encrypt provides free SSL/TLS certificates and automation - using ACMESharp for PowerShell automation
- Azure Managed DNS Zone for scriptable automation to prove domain ownership to Let's Encrypt
Here's what the automation module looks like - make sure Azure Modules are installed & up to date - this requires launching an elevated Powershell ISE - Install the ACMESharp Powershell Module and log into Azure.
PS c:\Code> Install-Module AzureRM -AllowClobber PS C:\Code> Install-Module ACMESharp PS C:\Code> Login-AzureRmAccount PS C:\Code> Deploy-LeSslCertToAzure ` -appGatewayRgName 'web-resoucegroup-rg' ` -appGatewayName 'mydomaintocertweb-agw' ` -domainToCert 'www.mydomaintocert.com' ` -certPassword 'mySweetPassword123!@' ` -azureDnsZone 'mydomaintocert.com' ` -dnsAlias 'wwwDomainCert' ` -azureDnsZoneResourceGroup 'web-resoucegroup-rg' ` -registrationEmail 'email@example.com'
The process the script needs to automate
Setup ACME Vault, Validation Domain OwnerShip, and submit, sign and save SSL/TLS Certificate.
- Create a new ACME Vault if it doesn't exist - this keeps track of Registration with Let's Encrypt, and stores certificates in their various states as they are generated, submitted and signed.
- Register and accept the Terms of Service if needed.
- Check on the status of this Certificate. If the ACME Vault can't find cert by alias name using the parameter dnsAlias, create a new Identifier for Domain name and retrieve the Challenge value.
- Create or update the DNS Zone azureDnsZone with a TXT record that Let's Encrypt can check to verify we own the domain.
- Request a challenge to Let's Encrypt to validate the DNS TXT Record.
- Domain challenge returns VALID, Generate the Certificate and submit it for Signing by Let's Encrypt.
- Update the local ACME Vault - this will fetch Root and Intermediate CA's for certificates so the full Certificate Chain can be exported properly.
- Retrieve the Signed Certificate in PKCS#12 format with complete cert chain and save it to a PFX file specified by the signedSslCertificate property and protect it with the supplied certPassword property.
Configure SSL/TLS Ports, Listeners, SSL/TLS Cert and Routing Rule to the Application Gateway.
- Get a reference to the App Gateway named appGatewayName contained in the Resource Group appGatewayRgName.
- On the App Gateway, add a new front end port on TCP 443 for SSL/TLS.
- Submit the SSL/TLS Certificate w/ Password to the App Gateway.
- Create a new HTTPS Listener that's associated with the Front End Port and associate it to the SSL/TLS Certificate.
- Add a Routing Rule that maps the listener to the back end IP pool.
- Commit the changes to Azure.
This approach works pretty well, however there are points that feel a little bit hacky - here are some plans to improve that I'm considering in the future:
- Automation for Cert Renewal - this would ideally run as a Playbook in Azure - it's unclear if the ACMESharp will work.
- Adding native support to ACMESharp for App Gateways and other cloud services.
- Decouple the PFX creation and the deployment to an App Gateway - this would allow greater flexibility for the script to add PFX to other resource types.