Azure Let's Encrypt Certificate Automation
This repository contains an automated solution for creating, renewing, and managing Let's Encrypt SSL/TLS certificates using GitHub Actions and Azure services. The certificates are stored in Azure Key Vault for easy consumption by your Azure applications.
- 🔄 Automated renewals - Runs on the 1st and 15th of every month
- 🔒 Secure storage - Certificates stored in Azure Key Vault
- 🔍 DNS validation - Uses Azure DNS for domain ownership validation
- 🔄 Version management - Automatically disables old certificate versions
You need the following Azure resources set up:
-
Azure DNS Zone - For domain validation
- Must contain the domain you're generating certificates for
- Example:
example.com
DNS Zone forapp.example.com
certificates
-
Azure Key Vault - For certificate storage
- Must have sufficient access policies for the service principal
Secret | Description |
---|---|
AZURE_CLIENT_ID |
Azure service principal client ID |
AZURE_CLIENT_SECRET |
Azure service principal secret |
AZURE_TENANT_ID |
Azure tenant ID |
AZURE_SUBSCRIPTION_ID |
Azure subscription ID |
LETS_ENCRYPT_EMAIL |
Email for Let's Encrypt registration |
KEY_VAULT_RESOURCE_NAME |
Name of your Azure Key Vault |
Variable | Description |
---|---|
DOMAIN_NAME |
Domain for certificate (e.g., app.example.com ) |
AZURE_DNS_ZONE_NAME |
Azure DNS Zone name (e.g., example.com ) |
The service principal used by GitHub Actions requires:
- Certificates: Get, List, Import, Update
- Secrets: Get, List, Set
- DNS Zone Contributor - To create TXT records for domain validation
The workflow uses the following permissions:
id-token: write
- For Azure logincontents: read
- For repository access
-
Workflow Trigger
- Runs on a schedule (1st and 15th of each month)
- Can be triggered manually with optional staging parameter
-
Certificate Check
- Checks if certificate exists in Key Vault
- Calculates days until expiry
- Skips renewal if more than 30 days left
-
Certificate Generation
- Uses Posh-ACME to interact with Let's Encrypt
- Uses Azure DNS for domain validation
- Generates a Full Chain PFX certificate
-
Key Vault Storage
- Imports certificate to Key Vault with generated name:
cert-{domain-name}
- Example:
cert-{app-example-com}
- Imports certificate to Key Vault with generated name:
-
Version Management
- Identifies the newly imported certificate
- Disables all older versions of the certificate
The GitHub Actions workflow (generate-cert.yml
) handles:
- Scheduling certificate renewals
- Azure authentication
- Running the PowerShell script
The PowerShell script (create-lets-encrypt-cert.ps1
) handles:
- Checking for existing certificates
- Interacting with Let's Encrypt
- Managing certificate versions in Key Vault
Certificates are automatically renewed when they're within 30 days of expiry. No action required.
- Go to the "Actions" tab in your GitHub repository
- Select "Generate-Lets-Encrypt-Certificate" workflow
- Click "Run workflow"
- Optionally select "Use Lets Encrypt staging environment" for testing
- Click "Run workflow"
Currently, this solution relies on checking Azure Key Vault for certificate information. A more robust approach would be to implement dedicated state management using Azure Storage:
- 🔄 Persistent Order Tracking - Store ACME order IDs and challenge responses
- 🏗️ Certificate History - Track renewal cycles and past validation issues
⚠️ Rate Limit Prevention - Monitor and respect Let's Encrypt rate limits- 🔁 Cross-Run Consistency - Share state between workflow executions
-
Create an Azure Storage Account table to store:
- Domain registration status
- Challenge verification details
- Order IDs and account keys
- Renewal history
-
Update the certificate script to:
- Read previous state before operations
- Store outcomes after operations
- Handle edge cases more gracefully
-
Benefits:
- Improved reliability when DNS validation is delayed
- Better handling of partial failures
- Historical data for troubleshooting
This enhancement would make the solution more enterprise-ready and resilient against intermittent failures.
-
DNS Validation Failures
- Ensure the service principal has DNS Zone Contributor permissions
- Check that the DNS Zone matches the domain's parent zone
-
Key Vault Access Issues
- Verify the service principal has proper Key Vault access policies
- Check for "Access denied" errors in the workflow logs
-
Rate Limit Errors
- Use the staging environment for testing to avoid hitting Let's Encrypt production rate limits
- Ensure you're not requesting too many certificates for the same domain
The script outputs detailed information about:
- Certificate expiry dates
- Certificate versions and thumbprints
- Disabled certificate versions
This project is licensed under the MIT License - see the LICENSE file for details.