Skip to main content

Generate Azure TLS Certificate

Reusable Workflow
WorkflowVersionSource
Generate Azure TLS Certificatev1release-certificate-v1.yaml

Reusable workflow that checks whether a TLS certificate stored in Azure Key Vault is missing or close to expiration, and if so requests a new one from Let's Encrypt via the ACME DNS-01 challenge using Azure DNS. The check and renewal are handled by the underlying renew-tls-certificate composite action.

How It Works​

  1. Check: Downloads the current certificate from Key Vault (if present) and verifies that it does not expire within 30 days. If the certificate is missing, expired, or force_renewal is true, the renewal flow is triggered.
  2. Renew: Logs in to Azure, generates a fresh RSA-2048 CSR, runs the ACME client to complete the DNS-01 challenge against Azure DNS, converts the resulting certificate chain to PFX, and uploads it back to Key Vault.

Prerequisites​

Let's Encrypt account credentials are managed at the organization level. You need to add them as repository secrets before using this workflow:

  • LETS_ENCRYPT_PRIVATE_KEY_JSON — Let's Encrypt account private key in JWK JSON format (copy from organization secrets)
  • LETS_ENCRYPT_REGISTRATION_JSON — Let's Encrypt account registration info in JSON format (copy from organization secrets)

Inputs​

NameRequiredDefaultDescription
key_vault_nameYes—Name of the Azure Key Vault storing the certificate
csr_common_nameYes—Common Name (CN) for the Certificate Signing Request (e.g. myapp.example.com)
dns_zoneYes—Azure DNS Zone used for the ACME DNS-01 challenge (e.g. example.com)
dns_zone_resource_groupYes—Resource Group that contains the DNS Zone
force_renewalNofalseForce renewal even if the certificate is not close to expiration
environmentNoinfra-prodGitHub Environment prefix; the workflow runs in {environment}-cd

Usage​

Call the workflow from your repository using workflow_call. Schedule it to run periodically (e.g. weekly) to ensure certificates never expire.

name: Renew TLS Certificate

on:
workflow_dispatch:
inputs:
force_renewal:
description: "Force certificate renewal"
required: false
default: "false"
type: boolean
schedule:
- cron: "0 8 * * 1" # Every Monday at 08:00 UTC

permissions:
contents: read
id-token: write

jobs:
renew:
name: "myapp.example.com"
uses: pagopa/dx/.github/workflows/release-azure-certificate-v1.yaml@main
secrets: inherit
with:
key_vault_name: "my-keyvault"
csr_common_name: "myapp.example.com"
dns_zone: "example.com"
dns_zone_resource_group: "my-dns-rg"
force_renewal: ${{ inputs.force_renewal || false }}
environment: "automation-prod"

Force a Renewal Manually​

You can trigger the workflow manually from the GitHub Actions UI using workflow_dispatch and set force_renewal to true to bypass the expiry check. This is useful when troubleshooting or recovering from a failed renewal.

Failure Alerting​

Because this workflow runs on a schedule, failures may go unnoticed. The workflow supports optional Slack notifications: when a scheduled run fails, it automatically posts an alert to a Slack channel if the SLACK_WEBHOOK_URL secret is configured as a repository secret pointing to the desired channel.