Azure App Service Team Blog

How the App Service team functions

Creating a local PFX copy of App Service Certificate

Introduction

Last year, we introduced ‘App Service Certificate’, a certificate lifecycle management offering. Azure portal provides a user-friendly experience for creating App Service Certificates and using them with App Service Apps. You can read more about this service here. While the portal provides first class experience for deploying App Service Certificate through Key Vault to App Service Apps, we have been receiving customer requests where they would like to use these certificates outside of App Service platform, say with Azure Virtual Machines. In this blogpost, I am going to describe how to create a local PFX copy of App Service Certificate so that you can use it anywhere you want.

Prerequisites

Before making a local copy, make sure that:
1. The App Service Certificate is in ‘Issued’ state
2. It’s assigned to a Key Vault (Step 1 in the link shared above).

Creating a local copy

You can use the following PowerShell script to create a local PFX copy. Provide appropriate values from the highlighted parameters and save the script as copyasc.ps1.
Example:

$appServiceCertificateName = "ascdemo"
$resourceGroupName = "ascdemorg"
$azureLoginEmailId = "user@microsoft.com"
$subscriptionId = "fb2c25dc-6bab-45c4-8cc9-cece7c42a95a"

Type the following commands in PowerShell console to execute the script:

Powershell –ExecutionPolicy Bypass
.\copyasc.ps1

copyasc.ps1:

$appServiceCertificateName = ""
$resourceGroupName = ""
$azureLoginEmailId = ""
$subscriptionId = ""

Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId $subscriptionId

$ascResource = Get-AzureRmResource -ResourceName $appServiceCertificateName -ResourceGroupName $resourceGroupName -ResourceType "Microsoft.CertificateRegistration/certificateOrders" -ApiVersion "2015-08-01"
$keyVaultId = ""
$keyVaultSecretName = ""

$certificateProperties=Get-Member -InputObject $ascResource.Properties.certificates[0] -MemberType NoteProperty
$certificateName = $certificateProperties[0].Name
$keyVaultId = $ascResource.Properties.certificates[0].$certificateName.KeyVaultId
$keyVaultSecretName = $ascResource.Properties.certificates[0].$certificateName.KeyVaultSecretName

$keyVaultIdParts = $keyVaultId.Split("/")
$keyVaultName = $keyVaultIdParts[$keyVaultIdParts.Length - 1]
$keyVaultResourceGroupName = $keyVaultIdParts[$keyVaultIdParts.Length - 5]
Set-AzureRmKeyVaultAccessPolicy -ResourceGroupName $keyVaultResourceGroupName -VaultName $keyVaultName -UserPrincipalName $azureLoginEmailId -PermissionsToSecrets get
$secret = Get-AzureKeyVaultSecret -VaultName $keyVaultName -Name $keyVaultSecretName
$pfxCertObject=New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @([Convert]::FromBase64String($secret.SecretValueText),"", [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfxPassword = -join ((65..90) + (97..122) + (48..57) | Get-Random -Count 50 | % {[char]$_})
$currentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath
[Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath
[io.file]::WriteAllBytes(".\appservicecertificate.pfx", $pfxCertObject.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $pfxPassword))
Write-Host "Created an App Service Certificate copy at: $currentDirectory\appservicecertificate.pfx"
Write-Warning "For security reasons, do not store the PFX password. Use it directly from the console as required."
Write-Host "PFX password: $pfxPassword"

Once the script is executed, you would see a new file in the current directory called ‘appservicecertificate.pfx’. This is a password protected PFX, the PowerShell console would display the corresponding password. For security reasons, do not store this password in a text file. You can use the password directly from the console as required. Also, don’t forget to delete the local PFX file once you no longer need it.

Things to note

If you create a copy of App Service Certificate this way, it won’t have any impact on existing App Service SSL bindings that were creating using the portal experience. It also won’t affect any such SSL bindings you may create in the future. You can still Rekey and Renew an App Service Certificate with one click even after making a copy but you would be responsible for creating a new local copy with the new certificate and updating all services that are using the old certificate.

Tips

This section compares this method of certificate deployment with the built-in Azure portal experience for Web Apps. It also contains recommendations you should follow when you use the PFX copy elsewhere.

Title

Azure portal Deployment

Deploying local PFX copy

Recommendations

Auto/Manual Renew

When an App Service Certificate is renewed, all the corresponding App Service SSL bindings are updated automatically

When a certificate is renewed, you would need to manually update all the services that are using a local copy.

Turn off Auto renew as you won’t know when exactly an App Service Certificate gets renewed with Auto renew and this would end up breaking your SSL endpoints. Manually renew such App Service Certificates before they expire

Rekey

Just like renewal, the corresponding SSL bindings are updated automatically

Just like renewal, you would need to manually update all such services.

 

Deployment

When deploying certificate this way, you don’t need any file locally and there won’t be any secrets to clean up

When deploying certificate this way, you would have the PFX certificate on local disk.

Always delete the local copy once you no longer need it as you can create a PFX copy as many times as you want. Also, never store the password shown in PowerShell console locally. This way, even if somehow an adversary gets hold of your local disk, he still won’t be able to use the PFX certificate as it’s protected by a strong password

Getting in touch

If you have an App Service Certificate that you would like to use outside of App Service ecosystem, then give this a try and let us know how it goes. If you run into any issues, please let us know on the App Service forum.