This site is an archive and is no longer updated.
    Back to Guides
    CloudAzure

    Azure Key Vault Certificates

    Centralized certificate management for Azure infrastructure. Azure Key Vault stores certificates alongside their private keys and adds lifecycle management—import, generate, renew, and deploy certificates to App Service, Application Gateway, AKS, and API Management from a single vault.

    15-20 min readFebruary 2026Intermediate
    LinkedInX
    Azure Key Vault Certificates - Centralized certificate management connecting to App Service, Application Gateway, API Management, and AKS

    Quick Reference

    • Import formats: PEM (with private key) or PFX/PKCS#12
    • Partnered CAs: DigiCert, GlobalSign (auto-renewal supported)
    • Access control: RBAC or Access Policies (RBAC recommended)
    • Auto-renewal: Only with integrated CAs (DigiCert, GlobalSign)
    • Certificate size limit: Subject name ≤ 200 characters
    • Polling interval: Application Gateway checks Key Vault every 4 hours

    Golden Path: App Gateway + Key Vault + Public CA

    Already have a PFX from your CA? Here's the fastest path to TLS termination on Application Gateway.

    bash
    # 1. Create vault (skip if you already have one)
    az keyvault create --name kv-myapp-certs --resource-group rg-certs \
      --enable-rbac-authorization true --enable-purge-protection true
    
    # 2. Grant your App Gateway's managed identity access
    az role assignment create --assignee <appgw-identity-principal-id> \
      --role "Key Vault Certificate User" \
      --scope $(az keyvault show --name kv-myapp-certs --query id -o tsv)
    
    # 3. Import your PFX
    az keyvault certificate import --vault-name kv-myapp-certs \
      --name myapp-tls --file ./myapp.pfx --password "YourPfxPassword"
    
    # 4. Reference in App Gateway listener (use SECRET URI, versionless)
    # https://kv-myapp-certs.vault.azure.net/secrets/myapp-tls

    Renewal: Import the new cert with the same name — Key Vault creates a new version. App Gateway polls every 4 hours and picks it up automatically (no restart needed).

    Watch out: If any downstream service pins to the certificate thumbprint (e.g., in App Service custom domain bindings or API Management), it will not auto-update. You must update thumbprint references manually after renewal.

    What Is Azure Key Vault

    Azure Key Vault is Microsoft's cloud service for securely storing and managing secrets, keys, and certificates. When you store a certificate in Key Vault, it creates a composite object: the X.509 certificate, the private key, and a lifecycle policy—all managed together.

    Certificate Object = Three Objects

    • Certificate — X.509 metadata + lifecycle policy (expiry notifications, auto-renewal settings)
    • Key — The asymmetric key pair (RSA or EC) used for cryptographic operations
    • Secret — The full PFX or PEM bundle including the private key (this is what you export)

    Name collision warning: Key Vault creates a key and secret with the same name as the certificate. If you try to create a certificate named "myapp" but a secret named "myapp" already exists, the operation will fail. Delete or rename the conflicting object first.

    Key Facts

    • • Key Vaults are regional resources — a vault lives in a single region, but can store certificates for any domain
    • • FIPS 140-2 Level 2 validated (Standard tier) or Level 3 (Premium tier with HSM-backed keys)
    • • Soft-delete is mandatory (since February 2025) with a configurable retention period of 7–90 days

    Key Vault Defaults vs Recommended

    SettingDefaultRecommended
    Key algorithmRSA 2048RSA 3072+ for new deployments
    Validity period12 months12 months or less (shorter = better)
    Subject namingCN onlySANs preferred; CN is deprecated for domain matching
    Content typePKCS#12 (PFX)PKCS#12 for Azure services; PEM for Linux/containers
    Key reuse on renewalfalsefalse (generate fresh key pair each renewal)

    EKU guidance: For TLS server authentication, ensure digitalSignature and keyEncipherment key usages plus the Server Authentication (1.3.6.1.5.5.7.3.1) EKU are present. Key Vault does not validate EKUs for you — misconfigured EKUs will only surface when the certificate is deployed to a service.

    Azure Key Vault vs AWS ACM

    FeatureAzure Key VaultAWS ACM
    Certificate storageYes (with private key)Yes (managed, no export by default)
    Private key exportYes (if policy allows)Exportable public certs and certain Private CA-issued certs
    Auto-renewalDigiCert/GlobalSign onlyAll ACM-issued certs
    Self-signed supportYes (generate in vault)No
    CSR generationYes (in-vault)No
    PricingPer operation ($0.03/10K ops)Free for ACM-issued
    Integrated CAsDigiCert, GlobalSignAmazon CA

    Coming from AWS ACM? See our AWS Certificate Manager (ACM) Guide to understand how Key Vault differs in exportability, CA integration, and lifecycle management.

    Creating a Key Vault

    Azure CLI

    bash
    # Create a resource group
    az group create \
      --name rg-certificates \
      --location eastus
    
    # Create a Key Vault with RBAC, soft-delete, and purge protection
    az keyvault create \
      --name kv-myapp-certs \
      --resource-group rg-certificates \
      --location eastus \
      --enable-rbac-authorization true \
      --enable-soft-delete true \
      --enable-purge-protection true \
      --soft-delete-retention-days 90

    PowerShell

    powershell
    # Create a resource group
    New-AzResourceGroup -Name "rg-certificates" -Location "eastus"
    
    # Create a Key Vault with RBAC and purge protection
    New-AzKeyVault `
      -VaultName "kv-myapp-certs" `
      -ResourceGroupName "rg-certificates" `
      -Location "eastus" `
      -EnableRbacAuthorization `
      -EnablePurgeProtection `
      -SoftDeleteRetentionInDays 90

    RBAC Roles for Certificates

    RolePermissionsUse Case
    Key Vault AdministratorFull control over vault and all objectsVault owners, PKI admins
    Key Vault Certificates OfficerCreate, import, update, delete certificatesCertificate management automation
    Key Vault Certificate UserRead certificate metadata and secretsApp Service, Application Gateway
    Key Vault ReaderRead vault metadata only (no secrets)Auditors, monitoring

    FixMyCert recommendation: Soft-delete is now mandatory for all new vaults. Always enable purge protection in production — it prevents permanent deletion of certificates during the retention period, protecting against accidental or malicious deletion.

    Importing Certificates

    Key Vault supports two import formats: PFX/PKCS#12 (binary, password-protected) and PEM (Base64-encoded, must include the private key).

    Import PFX (Azure CLI)

    bash
    # Import a PFX certificate with password
    az keyvault certificate import \
      --vault-name kv-myapp-certs \
      --name myapp-tls \
      --file ./myapp.pfx \
      --password "YourPfxPassword"

    Import PEM (Azure CLI)

    bash
    # Import a PEM certificate (must include private key)
    # Combine cert + key into single PEM file first:
    # cat cert.pem key.pem > combined.pem
    az keyvault certificate import \
      --vault-name kv-myapp-certs \
      --name myapp-tls \
      --file ./combined.pem

    Import PFX (PowerShell)

    powershell
    $password = ConvertTo-SecureString -String "YourPfxPassword" -AsPlainText -Force
    Import-AzKeyVaultCertificate `
      -VaultName "kv-myapp-certs" `
      -Name "myapp-tls" `
      -FilePath "./myapp.pfx" `
      -Password $password

    Common Import Errors

    ErrorCauseFix
    Private key is not specifiedPEM file missing private keyConcatenate cert + key into one PEM file
    Unable to parse X5c chainMalformed PEM or extra whitespaceValidate PEM format; remove trailing spaces
    Certificate name already existsName collision with existing secret/keyDelete or rename conflicting object
    Specified content type not validWrong file format or extensionUse .pfx for PKCS#12, .pem for PEM
    Subject name limited to 200 charactersCN/Subject exceeds 200 char limitShorten subject; use SANs instead
    Insufficient permissionsMissing Certificates Officer roleAssign Key Vault Certificates Officer RBAC role
    PEM parsing error (line separators)Windows CRLF line endings in PEMConvert to Unix LF: dos2unix combined.pem

    Format Conversion

    bash
    # PEM to PFX (for Key Vault import)
    openssl pkcs12 -export \
      -out certificate.pfx \
      -inkey private.key \
      -in certificate.crt \
      -certfile chain.crt \
      -password pass:YourPassword
    bash
    # PFX to PEM (extract from PFX)
    openssl pkcs12 -in certificate.pfx \
      -out combined.pem \
      -nodes \
      -password pass:YourPassword

    Need help with formats? See our Certificate Formats Guide and OpenSSL Commands Reference.

    Generating Certificates

    Method A: Self-Signed Certificate

    bash
    # Create a self-signed certificate with JSON policy
    az keyvault certificate create \
      --vault-name kv-myapp-certs \
      --name myapp-internal \
      --policy '{
        "issuerParameters": { "name": "Self" },
        "keyProperties": {
          "keyType": "RSA",
          "keySize": 2048,
          "exportable": true,
          "reuseKey": false
        },
        "secretProperties": { "contentType": "application/x-pkcs12" },
        "x509CertificateProperties": {
          "subject": "CN=myapp.internal.example.com",
          "validityInMonths": 12,
          "subjectAlternativeNames": {
            "dnsNames": ["myapp.internal.example.com", "myapp.dev.example.com"]
          }
        }
      }'

    FixMyCert warning: Do not use Key Vault self-signed certificates beyond lab and non-production environments. They create an isolated trust silo — nothing trusts them by default, and distributing a custom root CA to browsers and devices creates operational overhead that defeats the purpose. For production, always use a CA-signed certificate (public CA for external services, enterprise CA for internal).

    Method B: CSR-Based (Any CA)

    Use this workflow to get a certificate from any CA while keeping the private key in Key Vault.

    4-Step Workflow

    1. 1. Create certificate with "Unknown" issuer (generates CSR + key pair)
    2. 2. Download the CSR from Key Vault
    3. 3. Submit CSR to your CA and get the signed certificate
    4. 4. Merge the signed certificate back into Key Vault
    bash
    # Step 1: Create certificate request (generates CSR in vault)
    az keyvault certificate create \
      --vault-name kv-myapp-certs \
      --name myapp-public \
      --policy '{
        "issuerParameters": { "name": "Unknown" },
        "keyProperties": { "keyType": "RSA", "keySize": 2048, "exportable": true },
        "x509CertificateProperties": {
          "subject": "CN=myapp.example.com",
          "validityInMonths": 12,
          "subjectAlternativeNames": {
            "dnsNames": ["myapp.example.com", "www.myapp.example.com"]
          }
        }
      }'
    
    # Step 2: Download the CSR
    az keyvault certificate pending show \
      --vault-name kv-myapp-certs \
      --name myapp-public \
      --query csr -o tsv > myapp.csr
    
    # Step 3: Submit CSR to your CA (external step)
    # Your CA returns a signed certificate (e.g., signed-cert.crt)
    
    # Step 4: Merge the signed certificate
    az keyvault certificate pending merge \
      --vault-name kv-myapp-certs \
      --name myapp-public \
      --file signed-cert.crt

    Validate your CSR before submitting: Use our CSR Checker tool to verify the CSR contents match your requirements. For format conversion help, see the Certificate Formats and OpenSSL essentials guides.

    Method C: Integrated CA (DigiCert/GlobalSign)

    bash
    # Configure the CA issuer (one-time setup)
    az keyvault certificate issuer create \
      --vault-name kv-myapp-certs \
      --issuer-name DigiCertIssuer \
      --provider-name DigiCert \
      --account-id "YOUR_DIGICERT_ACCOUNT_ID" \
      --password "YOUR_DIGICERT_API_KEY"
    
    # Create a certificate using the integrated CA
    az keyvault certificate create \
      --vault-name kv-myapp-certs \
      --name myapp-production \
      --policy '{
        "issuerParameters": { "name": "DigiCertIssuer" },
        "keyProperties": { "keyType": "RSA", "keySize": 2048, "exportable": true },  // set false if policy disallows export
        "x509CertificateProperties": {
          "subject": "CN=myapp.example.com",
          "validityInMonths": 12,
          "subjectAlternativeNames": {
            "dnsNames": ["myapp.example.com", "www.myapp.example.com"]
          }
        },
        "lifetimeActions": [
          { "action": { "actionType": "AutoRenew" }, "trigger": { "daysBeforeExpiry": 30 } }
        ]
      }'

    Note: Only DigiCert and GlobalSign are integrated CAs in Key Vault. For all other CAs (Let's Encrypt, Sectigo, etc.), use the CSR-based workflow (Method B) or import certificates manually.

    Renewal & Auto-Rotation

    Auto-Renewal with Integrated CAs

    Certificates issued through DigiCert or GlobalSign can auto-renew. Configure the lifetimeAction in the certificate policy:

    bash
    # Update certificate policy with auto-renewal
    az keyvault certificate set-attributes \
      --vault-name kv-myapp-certs \
      --name myapp-production \
      --policy '{
        "lifetimeActions": [
          {
            "action": { "actionType": "AutoRenew" },
            "trigger": { "daysBeforeExpiry": 30 }
          }
        ]
      }'

    Email Notifications (Non-Integrated CAs)

    For certificates from non-integrated CAs, configure email notifications to alert you before expiry:

    bash
    # Set up email notification before expiry
    az keyvault certificate set-attributes \
      --vault-name kv-myapp-certs \
      --name myapp-tls \
      --policy '{
        "lifetimeActions": [
          {
            "action": { "actionType": "EmailContacts" },
            "trigger": { "daysBeforeExpiry": 30 }
          }
        ]
      }'
    
    # Add certificate contacts for notifications
    az keyvault certificate contact add \
      --vault-name kv-myapp-certs \
      --email "[email protected]" \
      --name "PKI Team" \
      --phone "555-0100"

    Event Grid Integration

    Use Azure Event Grid to trigger automation (Azure Functions, Logic Apps) on certificate events:

    bash
    # Create an Event Grid subscription for certificate events
    az eventgrid event-subscription create \
      --name cert-expiry-alert \
      --source-resource-id $(az keyvault show --name kv-myapp-certs --query id -o tsv) \
      --endpoint https://myapp.azurewebsites.net/api/cert-webhook \
      --included-event-types \
        Microsoft.KeyVault.CertificateNearExpiry \
        Microsoft.KeyVault.CertificateExpired \
        Microsoft.KeyVault.CertificateNewVersionCreated

    FixMyCert recommendation: Don't rely on email alone. Combine email contacts with Event Grid subscriptions for a robust monitoring strategy. Use Event Grid to trigger automated renewal pipelines for non-integrated CAs.

    47-day certificates are coming. The CA/Browser Forum is moving toward 47-day certificate lifetimes. Build automation now — manual renewal at this frequency is unsustainable. See our 47-Day Certificate Timeline Guide.

    Automation Patterns for DevOps

    Pattern 1: ACME → Key Vault

    Run certbot or acme.sh in a scheduled runner (Azure DevOps pipeline, GitHub Action, or cron job). After obtaining the certificate, convert to PFX and import into Key Vault. App Gateway and App Service consume the updated cert via managed identity — no manual steps.

    bash
    # Example: certbot renewal → Key Vault import pipeline
    certbot renew --deploy-hook '
      openssl pkcs12 -export -out /tmp/cert.pfx \
        -inkey /etc/letsencrypt/live/myapp/privkey.pem \
        -in /etc/letsencrypt/live/myapp/fullchain.pem \
        -passout pass:AutoGenPassword
      az keyvault certificate import \
        --vault-name kv-myapp-certs --name myapp-tls \
        --file /tmp/cert.pfx --password AutoGenPassword
      rm /tmp/cert.pfx
    '

    Pattern 2: Corporate CA → Key Vault

    For enterprise CAs (ADCS, Venafi, EJBCA): enroll via SCEP/EST or offline CSR, export the signed certificate as PFX, then script az keyvault certificate import into your CI/CD pipeline. For ADCS environments, autoenrollment can populate Key Vault via a bridge script that monitors the Windows certificate store and pushes new certs to the vault.

    Pattern 3: Event-Driven Renewal

    Subscribe to CertificateNearExpiry events via Event Grid. Route events to an Azure Function or Logic App that either (a) triggers your ACME renewal pipeline, (b) calls your CA's API to reissue, or (c) creates a ServiceNow/Jira ticket for manual renewal. This turns Key Vault into the single source of truth for certificate lifecycle state.

    Using with Azure Services

    Application Gateway

    Application Gateway can reference Key Vault certificates using a managed identity. Use versionless URIs so the gateway picks up renewed certificates automatically.

    bash
    # Create a user-assigned managed identity
    az identity create \
      --name appgw-identity \
      --resource-group rg-certificates
    
    # Get the identity's principal ID
    IDENTITY_ID=$(az identity show \
      --name appgw-identity \
      --resource-group rg-certificates \
      --query principalId -o tsv)
    
    # Assign Key Vault Certificate User role
    az role assignment create \
      --assignee $IDENTITY_ID \
      --role "Key Vault Certificate User" \
      --scope $(az keyvault show --name kv-myapp-certs --query id -o tsv)
    
    # Reference certificate in App Gateway (versionless URI)
    # Use the SECRET URI, not the certificate URI:
    # https://kv-myapp-certs.vault.azure.net/secrets/myapp-tls

    CRITICAL GOTCHA

    Application Gateway uses the /secrets/ URI, NOT the /certificates/ URI

    ✓ Correct: https://kv-myapp-certs.vault.azure.net/secrets/myapp-tls

    ✗ Wrong: https://kv-myapp-certs.vault.azure.net/certificates/myapp-tls

    The /secrets/ URI returns the full PFX including the private key. The /certificates/ URI only returns the public certificate without the private key—useless for TLS termination.

    Common App Gateway + Key Vault Errors

    ErrorCauseFix
    UserAssignedIdentityDoesNotHaveGetPermissionManaged identity missing RBAC roleAssign Key Vault Certificate User role
    SecretNotFoundUsing /certificates/ URI instead of /secrets/Change to /secrets/ URI
    KeyVaultAccessDeniedFirewall blocking App GatewayAllow trusted Microsoft services or add App Gateway subnet
    CertificateNotYetValidCertificate notBefore is in the futureCheck certificate validity dates
    Old cert still served after renewalApp Gateway polling delay (up to 4 hours)Wait for next poll or restart App Gateway

    App Service

    bash
    # Import Key Vault certificate to App Service
    az webapp config ssl import \
      --resource-group rg-myapp \
      --name myapp-webapp \
      --key-vault kv-myapp-certs \
      --key-vault-certificate-name myapp-tls

    App Service provider registration: App Service uses the Microsoft.Azure.App Service resource provider to access Key Vault. The service principal app ID varies by cloud (Public: abfa0a7c-a6b6-4736-8310-5855508787cd). Ensure this principal has Key Vault Certificate User or equivalent access.

    AKS (Azure Kubernetes Service)

    bash
    # Enable the Secrets Store CSI Driver addon on AKS
    az aks enable-addons \
      --resource-group rg-myapp \
      --name myapp-aks \
      --addons azure-keyvault-secrets-provider

    Then create a SecretProviderClass to mount certificates as files in your pods:

    yaml
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: kv-tls-cert
    spec:
      provider: azure
      parameters:
        clientID: "<workload-identity-client-id>"   # Workload identity (recommended)
        keyvaultName: "kv-myapp-certs"
        tenantId: "<your-tenant-id>"
        objects: |
          array:
            - |
              objectName: myapp-tls
              objectType: secret
      secretObjects:                                 # Sync to a k8s Secret for TLS ingress
        - secretName: myapp-tls-secret
          type: kubernetes.io/tls
          data:
            - objectName: myapp-tls
              key: tls.key
            - objectName: myapp-tls
              key: tls.crt
    yaml
    # Mount in your pod spec (volumes + volumeMounts)
    spec:
      serviceAccountName: myapp-sa    # SA annotated with workload identity
      containers:
        - name: myapp
          volumeMounts:
            - name: tls-cert
              mountPath: "/mnt/certs"
              readOnly: true
      volumes:
        - name: tls-cert
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: kv-tls-cert

    For full Kubernetes certificate automation: See our cert-manager for Kubernetes Guide for ACME-based certificate management with Let's Encrypt on AKS.

    API Management

    Azure API Management can reference Key Vault certificates for custom domains and client certificate validation. Use a system-assigned managed identity, grant it Key Vault Certificate User, then reference the secret URI in the custom domain blade — APIM pulls the PFX from Key Vault the same way Application Gateway does.

    bash
    # Enable system-assigned managed identity on APIM (via Azure Resource Manager)
    az resource update --ids $(az apim show --name myapp-apim \
      --resource-group rg-myapp --query id -o tsv) \
      --set identity.type=SystemAssigned
    
    # Get APIM's principal ID
    APIM_PRINCIPAL=$(az apim show --name myapp-apim --resource-group rg-myapp \
      --query identity.principalId -o tsv)
    
    # Grant Key Vault access
    az role assignment create --assignee $APIM_PRINCIPAL \
      --role "Key Vault Certificate User" \
      --scope $(az keyvault show --name kv-myapp-certs --query id -o tsv)
    
    # In the portal: APIM → Custom domains → Add → select Key Vault certificate
    # Reference: https://kv-myapp-certs.vault.azure.net/secrets/myapp-tls

    Retrieving & Exporting

    Download Public Certificate Only

    bash
    # Download the public certificate (no private key)
    az keyvault certificate download \
      --vault-name kv-myapp-certs \
      --name myapp-tls \
      --file myapp-public.pem \
      --encoding PEM

    Get Certificate with Private Key (via Secret)

    bash
    # Get the full certificate + private key via the secret object
    az keyvault secret download \
      --vault-name kv-myapp-certs \
      --name myapp-tls \
      --file myapp-full.pfx \
      --encoding base64

    PowerShell: Full Export with Private Key

    powershell
    # Export certificate with private key (PowerShell)
    $secret = Get-AzKeyVaultSecret -VaultName "kv-myapp-certs" -Name "myapp-tls"
    $secretBytes = [Convert]::FromBase64String($secret.SecretValueText)
    [IO.File]::WriteAllBytes("myapp-export.pfx", $secretBytes)
    
    # Convert to PEM if needed
    openssl pkcs12 -in myapp-export.pfx -out myapp-export.pem -nodes

    Key insight: To get the private key, you must read the secret object, not the certificate object. The certificate object only returns the public X.509 certificate. The secret object contains the full PFX/PEM bundle with the private key.

    Troubleshooting

    Decision Tree: Certificate Import Failing?

    text
    Certificate import failing?
    ├─ "Private key is not specified"
    │  └─ PEM file is missing the private key block
    │     → Concatenate: cat cert.pem key.pem > combined.pem
    ├─ "Unable to parse X5c chain"
    │  └─ Malformed PEM (extra whitespace, Windows line endings)
    │     → Run: dos2unix combined.pem && openssl x509 -in cert.pem -noout
    ├─ "Certificate name already exists"
    │  └─ A secret or key with the same name exists
    │     → Delete conflicting object or use a different name
    ├─ "Specified content type not valid"
    │  └─ File format doesn't match extension
    │     → Verify: file certificate.pfx (should show PKCS#12)
    └─ Certificate expired
       └─ Key Vault rejects expired certificates
          → Obtain a renewed certificate first

    CLI Quick Checks

    bash
    # Verify PFX is valid
    openssl pkcs12 -info -in certificate.pfx -noout
    
    # Check PEM has private key
    grep -c "PRIVATE KEY" combined.pem  # Should return 1
    
    # List soft-deleted certs (name collision check)
    az keyvault certificate list-deleted --vault-name kv-myapp-certs -o table
    
    # Verify your RBAC role
    az role assignment list --assignee $(az ad signed-in-user show --query id -o tsv) \
      --scope $(az keyvault show --name kv-myapp-certs --query id -o tsv) -o table

    Decision Tree: Certificate Stuck "In Progress"?

    text
    Certificate stuck "In Progress"?
    ├─ Using integrated CA (DigiCert/GlobalSign)?
    │  └─ Check issuer credentials and account status
    │     → az keyvault certificate issuer show --vault-name <vault> --issuer-name <issuer>
    ├─ Using CSR workflow (Unknown issuer)?
    │  └─ Waiting for you to merge the signed certificate
    │     → Download CSR, submit to CA, then merge signed cert
    └─ DNS validation pending?
       └─ CA is waiting for domain validation
          → Check your DNS records and CA dashboard

    Decision Tree: App Gateway Not Picking Up New Cert?

    text
    Application Gateway not picking up new cert?
    ├─ Using versioned URI?
    │  └─ Versioned URIs point to a specific version forever
    │     → Switch to versionless URI (remove version segment)
    ├─ Using /certificates/ URI instead of /secrets/?
    │  └─ App Gateway needs /secrets/ for the private key
    │     → Change to: https://<vault>.vault.azure.net/secrets/<name>
    ├─ Managed identity permissions changed?
    │  └─ Identity lost Key Vault access
    │     → Re-assign Key Vault Certificate User role
    ├─ Key Vault firewall blocking?
    │  └─ Firewall rules exclude App Gateway
    │     → Allow trusted Microsoft services or add App Gateway subnet
    └─ Polling delay (up to 4 hours)?
       └─ App Gateway checks Key Vault every 4 hours
          → Wait for next poll cycle or restart the App Gateway

    CLI Quick Checks

    bash
    # Check the secret content type (should be application/x-pkcs12)
    az keyvault secret show --vault-name kv-myapp-certs --name myapp-tls \
      --query contentType -o tsv
    
    # Compare Key Vault cert version vs what App Gateway is using
    az keyvault certificate show --vault-name kv-myapp-certs --name myapp-tls \
      --query sid -o tsv  # Shows the linked secret URI with version
    
    # Verify managed identity has access
    az role assignment list --assignee <appgw-identity-principal-id> \
      --scope $(az keyvault show --name kv-myapp-certs --query id -o tsv) -o table
    
    # Check if Key Vault firewall allows App Gateway
    az keyvault network-rule list --name kv-myapp-certs -o table

    Verify Certificate with OpenSSL

    bash
    # Verify the exported certificate
    openssl x509 -in myapp-public.pem -text -noout
    
    # Check certificate chain
    openssl verify -CAfile chain.pem myapp-public.pem
    
    # Test TLS connection to your endpoint
    openssl s_client -connect myapp.example.com:443 -servername myapp.example.com

    Best Practices

    1

    1.Use RBAC over Access Policies

    RBAC provides granular, Azure-native permission management. Access Policies are legacy and harder to audit. New vaults should always use RBAC authorization.

    2

    2.Enable purge protection

    Purge protection prevents permanent deletion of certificates during the soft-delete retention period. This protects against accidental deletion and insider threats.

    3

    3.Use versionless URIs

    Always reference certificates without a version in the URI (e.g., /secrets/myapp-tls instead of /secrets/myapp-tls/abc123). This ensures services automatically pick up renewed certificates.

    4

    4.Separate vaults by environment

    Use distinct vaults for dev, staging, and production. This limits blast radius, simplifies RBAC, and prevents accidental cross-environment certificate usage.

    5

    5.Monitor with Event Grid

    Subscribe to CertificateNearExpiry and CertificateExpired events via Event Grid. Trigger automated renewal pipelines or PagerDuty/Slack alerts.

    6

    6.Audit with Azure Monitor

    Enable diagnostic settings on Key Vault and send logs to Log Analytics. Monitor for unauthorized access attempts, failed operations, and certificate lifecycle events.

    7

    7.Plan for 47-day certificates

    The CA/Browser Forum is shortening certificate lifetimes. Ensure your renewal automation can handle certificates that expire every 47 days without manual intervention.

    8

    8.Tag certificates

    Use Azure tags (environment, team, application, expiry-owner) on certificates for cost tracking, ownership clarity, and automated inventory reporting.

    Frequently Asked Questions

    Back to All GuidesLast updated: February 2026