Closed jared-koiter closed 2 weeks ago
Hi rcskosir,
From my use of this resource I haven't needed to specify the versionless secret ID like you might for an Application Gateway.
When I used the .id resource attribute and viewed the certificate in the app services Certificate pane it did not seem to be pinned to a version ID. I haven't been through a renewal of these certificates yet however.
From the App Service Certificate management pane there seems to be a sync option which furthers my suspicion that .id is fine here.
Cheers
I might have missed the intended path for automatic certificate rotation in that case.
In my own scenario I had updated a certificate in the Key Vault to a new version, but the certificate reference in the App Service certificates pane was not updating to the new version (unless I hit 'Sync' manually). When I looked at the contents of the azurerm_key_vault_certificate secret_id
it was displaying a versioned path like https://example-key-vault.vault.azure.net/secrets/example-keyvault-cert/1234567890abcdef1234567890abcdef
. I was under the impression that this meant it was locked to a specific version, but running something like terraform apply
to try and force an update (like I assumed the 'Sync' button would do) showed no changes.
I found another issue connected to the https://github.com/hashicorp/terraform-provider-azurerm/pull/21989 PR which appears to have added suppression for changes to the secret ID, which explains why I didn't see any changes to be made by Terraform.
I also found the following in the documentation for managing Key Vault certificate imports in App Services:
If you update your certificate in Key Vault with a new certificate, App Service automatically syncs your certificate within 24 hours.
I suspect that I was merely impatient in expecting the App Services to automatically sync their certificates once the Key Vault source was updated to a new version, and that the Terraform provider doesn't need to be responsible for forcing the update to take place. It might still be worth adding support for using a versionless ID in the key_vault_secret_id
field, especially if Azure itself is not storing a versioned reference.
I had the same misconception @jared-koiter mentions about how the auto rotation works.
The provider requires a version, but after cert is added to the app service, the daily sync will will automatically bring in a newer version of the cert.
Terraform might still reference an older version, but Terraform ignores the version on this resource, so it doesn't detect a change.
So the certificate rotation works on its own.
It would still be good to have the provider allow a versionless secret ID, so you didn't have to refer to potentially stale versions just to get the resource created.
Terraform might still reference an older version, but Terraform ignores the version on this resource, so it doesn't detect a change.
This is incorrect, as I regularly see plans that cause a forced replacement due to the secret id changing.
This is ridiculous.
If you're following recommendations, you will likely have a key vault in a different subscription than the app service, as per Landing Zone Design recommendations.
If this is the case, the fact that I can't pass a versionless ID means that:
I don't care if Azure figures out the link on the backend: I'm being asked to hard code a versioned ID that will expire at some point. The azurerm_app_service_certificate
resource should allow me to pass a single id string without a version.
https://{KV}.vault.azure.net/{secrets,certificate}/{cert_name}
is a complete and valid reference, recognized by other resources that require a KV reference to a certificate (see the azurerm_application_gateway
resource)
resource "azurerm_application_gateway" "application_gateway" {
[...]
ssl_certificate {
name = "${name}-cert"
key_vault_secret_id = var.certificate
}
}
Especially in the case where I need to have an app gateway and an app service referencing the same KV stored certificate, I shouldn't have multiple interfaces in to the same value. I'm passing the standard KV ID for the secretless value, azurerm_app_service_certificate
should accept that format, regardless of the backend behavior around versions and auto sync.
Here is a fix with help from post: phillipsj
data "azurerm_key_vault" "cert_kv"{
name = "my-ky"
resource_group_name = "my-rg"
provider = azurerm.my-other-subscription
}
data "azurerm_key_vault_certificate" "domain_cert" {
name = replace(var.dns_hostname, ".", "-")
key_vault_id = data.azurerm_key_vault.cert_kv.id
}
# This does not work because cross-subscription
# resource "azurerm_app_service_certificate" "domain_cert" {
# name = replace(var.dns_hostname, ".", "-")
# resource_group_name = var.rg.name
# location = var.location
# key_vault_secret_id = data.azurerm_key_vault_certificate.domain_cert.secret_id
# }
# Grant Microsoft managed app secret and cert reader on the keyvault before (not done here otherwise would affect other deployments)
# https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-certificate?tabs=apex#authorize-app-service-to-read-from-the-vault
resource "azapi_resource" "app_service_certificate" {
type = "Microsoft.Web/certificates@2022-03-01"
name = replace(var.dns_hostname, ".", "-")
parent_id = var.rg.id
location = var.location
body = jsonencode({
properties = {
keyVaultId = data.azurerm_key_vault.cert_kv.id
keyVaultSecretName = data.azurerm_key_vault_certificate.domain_cert.name
serverFarmId = azurerm_service_plan.plan.id
}
kind = "string"
})
response_export_values = ["properties.thumbprint"]
}
resource "azurerm_app_service_custom_hostname_binding" "main" {
hostname = var.dns_hostname
app_service_name = azurerm_linux_web_app.app.name
resource_group_name = var.rg.name
ssl_state = "SniEnabled"
thumbprint = jsondecode(azapi_resource.app_service_certificate.output).properties.thumbprint
}
Is there an existing issue for this?
Community Note
Terraform Version
1.5.3
AzureRM Provider Version
3.66.0
Affected Resource(s)/Data Source(s)
azurerm_app_service_certificate
Terraform Configuration Files
Debug Output/Panic Output
Expected Behaviour
azurerm_app_service_certificate
resource should be created referencing the versionless (latest) ID of the Key Vault certificate, allowing for automatic certificate rotation.Actual Behaviour
Resource cannot be created. Only works if referencing the
secret_id
attribute of the Key Vault certificate which contains the version. Resource field validation seems to be using theNestedItemId
function which requires the parsed string to include a version ID, though there are other functions in that file that allow for versionless/optional version validation.Steps to Reproduce
terraform apply
Important Factoids
No response
References
Similar request to #14085 which added versionless ID support to
azurerm_storage_encryption_scope
.