The following terraform configuration is supposed to:
- Obtain the id of the relevant Key Vault
- Obtain the id of the certificate secret
- Setup custom hostname binding
- Setup app service certificate
data "azurerm_key_vault" "hosting_secondary_kv" {
name = local.ctx.HostingSecondaryKVName
resource_group_name = local.ctx.HostingSecondaryRGName
}
data "azurerm_key_vault_secret" "cert" {
name = var.env == "prod" ? local.ctx.ProdCertificateName : local.ctx.NonProdCertificateName
key_vault_id = data.azurerm_key_vault.hosting_secondary_kv.id
}
resource "azurerm_app_service_custom_hostname_binding" "webapp_fqdn" {
for_each = local.apsvc_map
hostname = each.value.fqdn
app_service_name = azurerm_app_service.webapp[each.key].name
resource_group_name = var.regional_web_rg[each.value.location].name
ssl_state = "SniEnabled"
thumbprint = azurerm_app_service_certificate.cert[each.value.location].thumbprint
depends_on = [
azurerm_traffic_manager_endpoint.ep
]
}
resource "azurerm_app_service_certificate" "cert" {
for_each = local.locations
name = var.env == "prod" ? local.ctx.ProdCertificateName : local.ctx.NonProdCertificateName
resource_group_name = var.regional_web_rg[each.value].name
location = each.value
key_vault_secret_id = data.azurerm_key_vault_secret.cert.id
}
I have configured all the permissions as explained in https://www.terraform.io/docs/providers/azurerm/r/app_service_certificate.html
Running the code yields the following error:
Error: Error creating/updating App Service Certificate "wildcard-np-xyzhcm-com" (Resource Group "MyAppServiceResourceGroup"): web.CertificatesClient#CreateOrUpdate: Failure responding to request: StatusCode=403 -- Original Error: autorest/azure: Service returned an error. Status=403 Code="LinkedAuthorizationFailed" Message="The client '5...8' with object id '5...8' has permission to perform action 'Microsoft.Web/certificates/write' on scope '/subscriptions/0...7/resourceGroups/MyAppServiceResourceGroup/providers/Microsoft.Web/certificates/wildcard-np-xyzhcm-com'; however, it does not have permission to perform action 'write' on the linked scope(s) '/subscriptions/0...7/resourceGroups/MyKeyVaultResourceGroup/providers/Microsoft.KeyVault/vaults/MyKeyVault' or the linked scope(s) are invalid."
All the resources are in the same subscription.
I do not understand. Does Azure want me to grant the Service Principal performing the deployment (5...8
) the 'write' permission on the key vault containing the certificate? What am I missing?
EDIT 1
I used terraform to create the access policy to the Key Vault. Here is the relevant code:
A custom role definition allowing the "Microsoft.KeyVault/vaults/read" action:
resource "azurerm_role_definition" "key_vault_reader" {
name = "Key Vault Reader"
scope = data.azurerm_subscription.current.id
permissions {
actions = ["Microsoft.KeyVault/vaults/read"]
not_actions = []
}
assignable_scopes = [
data.azurerm_subscription.current.id
]
}
Letting the Microsoft WebApp Service Principal access the certificate:
data "azurerm_key_vault" "hosting_secondary_kv" {
name = local.ctx.HostingSecondaryKVName
resource_group_name = local.ctx.HostingSecondaryRGName
}
data "azuread_service_principal" "MicrosoftWebApp" {
application_id = "abfa0a7c-a6b6-4736-8310-5855508787cd"
}
resource "azurerm_key_vault_access_policy" "webapp_sp_access_to_hosting_secondary_kv" {
key_vault_id = data.azurerm_key_vault.hosting_secondary_kv.id
object_id = data.azuread_service_principal.MicrosoftWebApp.object_id
tenant_id = data.azurerm_subscription.current.tenant_id
secret_permissions = ["get"]
certificate_permissions = ["get"]
}
Next grant the Service Principal used by the deployment the custom Key Vault Reader role in the resource group of the respective Key Vault:
data "azurerm_key_vault" "hosting_secondary_kv" {
name = local.ctx.HostingSecondaryKVName
resource_group_name = local.ctx.HostingSecondaryRGName
}
data "azurerm_role_definition" "key_vault_reader" {
name = "Key Vault Reader"
scope = data.azurerm_subscription.current.id
}
resource "azurerm_role_assignment" "sp_as_hosting_secondary_kv_reader" {
scope = "${data.azurerm_subscription.current.id}/resourceGroups/${local.ctx.HostingSecondaryRGName}"
role_definition_id = data.azurerm_role_definition.key_vault_reader.id
principal_id = azuread_service_principal.sp.id
}
Finally setup the access policy for the aforementioned Service Principal:
resource "azurerm_key_vault_access_policy" "sp_access_to_hosting_secondary_kv" {
key_vault_id = data.azurerm_key_vault.hosting_secondary_kv.id
object_id = azuread_service_principal.sp.object_id
tenant_id = data.azurerm_subscription.current.tenant_id
secret_permissions = ["get"]
certificate_permissions = ["get"]
}
And the snapshots from the portal: