I have multiple App Service with custom domains that I've uploaded a certificate for. Now I want to change from Bring Your Own Certificate to using Azure Managed Certificate so I don't have to update them once a year. How can I create new certificates in bulk?
Using Azure CLI and powershell we can first create a new certificate that is managed by Azure and then bind that certificate to the custom hostname.
param([string[]]$resourceIds)
foreach ($resourceId in $resourceIds)
{
# Get info about the web app
$resourceIdParts = $resourceId.Split("/")
$slot = $resourceIdParts[-2].Equals("slots")
if ($slot) {
$slotName = $resourceIdParts[-1]
$output = az webapp show --slot $slotName --ids $resourceId
} else {
$slotName = $null
$output = az webapp show --ids $resourceId
}
$webApp = ConvertFrom-Json -Input ($output -join ' ')
$hostname = $webApp.enabledHostNames | Where-Object { $_ -like '*.mydomain.com' } # <-- Here you'll have to change to something that will match the hostname you'll want to bind the certificate to
$subscription = ($webApp.id -split '/')[2]
$rg = ($webApp.id -split '/')[4]
$webAppName = $webApp.name.Replace("/" + ($slotName ?? ""), "")
# Specifying a cert name is optional but this format will match certs created previously in the Azure Portal
$certificateName = "$hostname-$($webAppName)"
# Create the new certificate
if ($slot) {
$output = az webapp config ssl create `
--name $webAppName `
--slot $slotName `
--hostname $hostname `
--certificate-name $certificateName `
--resource-group $rg `
--subscription $subscription
} else {
$output = az webapp config ssl create `
--name $webAppName `
--hostname $hostname `
--certificate-name $certificateName `
--resource-group $rg `
--subscription $subscription
}
$cert = ConvertFrom-Json -Input ($output -join ' ')
$thumbprint = $cert.properties.thumbprint ?? $cert.thumbprint # If the cert already exists, the thumbprint will be in the thumbprint property
# Bind the new cert
if ($slot) {
az webapp config ssl bind `
--slot $slotName `
--certificate-thumbprint $thumbprint `
--ssl-type SNI `
--ids $resourceId
} else {
az webapp config ssl bind `
--certificate-thumbprint $thumbprint `
--ssl-type SNI `
--ids $resourceId
}
}
Save it and invoke with one or more resource ids:
> .\Use-ManagedCertificate.ps1 -resourceIds /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/sites/<app-name>,/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/sites/<another-app-name>
If you haven't changed the default name or at least have predictable names this will get you started in figuring out where you are using your own certs using Azure Resource Graph Explorer:
resources
| where type has 'microsoft.web/sites'
| project id, name, properties.hostNameSslStates
| mv-expand properties_hostNameSslStates
| where properties_hostNameSslStates.name endswith '.mydomain.com' // Don't forget to update hostname
| where properties_hostNameSslStates.certificateResourceId
!endswith strcat_delim('-', properties_hostNameSslStates.name, replace("/(s|S)tagging", "", name)) // This will exclude all certs that has the naming format of the ones that have been created in the Azure Portal
| project id,
name,
resourceGroup = tostring(split(id, '/')[4]),
thumbprint = properties_hostNameSslStates.thumbprint,
domain = properties_hostNameSslStates.name
| order by name