0
votes

I'm trying to add a private self-signed certificate to an Azure App Service (as in the screenshot at the bottom) via the REST API (in PowerShell). I call the API as follows:

$certBody = @{
  name = "InfoServiceTAKeyVaultDev"
  location = "West Europe"
  properties = @{
    keyVaultId = "/subscriptions/<subscriptionId>/resourceGroups/BzInfoServiceTADEV/providers/Microsoft.KeyVault/vaults/BzKVInfoServiceTADev"
    keyVaultSecretName = "InfoServiceTAKeyVaultCert"
  }
}
Invoke-RestMethod `
  -Method Put `
  -Uri ("https://management.azure.com/subscriptions/<subscriptionId>" +
        "/resourceGroups/BzInformatieServiceResourceGroupDEV" +
        "/providers/Microsoft.Web/certificates" +
        "/InfoServiceTAKeyVaultDev" +
        "?api-version=2016-03-01") `
  -Headers @{ Authorization = ("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU...")
              "Content-Type" = "application/json" } `
  -Body ($certBody | ConvertTo-Json -Compress -Depth 3)

The result is an error message: The service does not have access to '/subscriptions/<subscriptionId>/resourcegroups/bzinfoservicetadev/providers/microsoft.keyvault/vaults/bzkvinfoservicetadev' Key Vault. Please make sure that you have granted necessary permissions to the service to perform the request operation.

In this context, who is 'the service' that does not have access to this Key Vault? I already found some posts claiming I should add service principal abfa0a7c-a6b6-4736-8310-5855508787cd to my Key Vault access policies but that does not have any effect.

Screenshot of the desired end result:

Desired end result

UPDATE: I had already enabled the advanced access policy Enable access to Azure Resource Manager for template deployment. This also does not do the trick.

4
Ensure that the service principal has all the permissions. The only thing that worked for me though is adding the service principal 24681998-555f-4570-a559-2fced2d7e841 which shows up as Microsoft.Azure.WebSites. You can add this through the portal, by adding an access policy for Microsoft.Azure.WebSites or through arm with the GUID.Tim Scriv

4 Answers

2
votes

The comment by @tim-scriv proved to be very helpful. I had to add the following principal to the Key Vault access policies: Microsoft Azure App Service (object id: 3ed082e0-d6c4-4071-ac9e-61363535a0a3). Permission to get secrets is enough.

0
votes

You will need to add the Enable access to Azure Resource Manager for template deployment advanced access policy.

You are not directly adding the cert to the webapp, you are telling the webapp where the cert exists. The web app relies on Resource Manager to actually go and collect the certificate and install it into the webapp.

Key vault does have extensive audit logging that can be enabled to understand what is attempting to access secrets that makes these issues a little easier to debug.

0
votes

I had the above issue and fixed it by following this article https://github.com/Azure/azure-quickstart-templates/tree/master/201-web-app-certificate-from-key-vault;

By default, 'Microsoft.Azure.WebSites' Resource Provider (RP) doesn't have access to the Key Vault specified in the template hence you need to authorize it by executing the following PowerShell commands before deploying the template:

Login-AzureRmAccount Set-AzureRmContext -SubscriptionId AZURE_SUBSCRIPTION_ID Set-AzureRmKeyVaultAccessPolicy -VaultName KEY_VAULT_NAME -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get

ServicePrincipalName parameter represents Microsoft.Azure.WebSites RP in user tenant and will remain same for all Azure subscriptions. This is a onetime operation. Once you have a configured a Key Vault properly, you can use it for deploying as many certificates as you want without executing these PowerShell commands again.

0
votes

Adding the Microsoft Azure App Service principal to have GET access to the KeyVault also fixed the same issue for me.

In my case I was trying to execute an ARM Template through Terraform using the azurerm_template_deployment command to add an SSL Cert to an Azure Web App Service and then bind the cert to the URL.