azurerm_key_vault_secret
provider "azurerm" {
version = "~> 1.23.0"
}
variable "objectid" {
type = "string"
}
data "azurerm_client_config" "current" {}
resource "azurerm_resource_group" "this" {
name = "tf-secret-test"
location = "westeurope"
}
resource "azurerm_storage_account" "this" {
name = "tfsecrettest"
resource_group_name = "${azurerm_resource_group.this.name}"
location = "${azurerm_resource_group.this.location}"
account_tier = "Standard"
account_replication_type = "LRS"
account_kind = "StorageV2"
}
resource "azurerm_key_vault" "this" {
name = "tf-secret-test"
resource_group_name = "${azurerm_resource_group.this.name}"
location = "${azurerm_resource_group.this.location}"
tenant_id = "${data.azurerm_client_config.current.tenant_id}"
sku {
name = "standard"
}
}
resource "azurerm_key_vault_access_policy" "service" {
key_vault_id = "${azurerm_key_vault.this.id}"
tenant_id = "${data.azurerm_client_config.current.tenant_id}"
object_id = "${var.objectid}"
key_permissions = [
]
secret_permissions = [
"get",
"set",
"list",
"delete",
]
}
resource "azurerm_key_vault_access_policy" "gui" {
key_vault_id = "${azurerm_key_vault.this.id}"
tenant_id = "${azurerm_function_app.gui.identity.0.tenant_id}"
object_id = "${azurerm_function_app.gui.identity.0.principal_id}"
key_permissions = [
]
secret_permissions = [
"get",
]
}
resource "azurerm_key_vault_secret" "IotHubConnection" {
name = "IotHubConnection"
value = "secret"
key_vault_id = "${azurerm_key_vault.this.id}"
depends_on = ["azurerm_key_vault_access_policy.service"]
}
resource "azurerm_app_service_plan" "this" {
name = "tf-secret-test"
resource_group_name = "${azurerm_resource_group.this.name}"
location = "${azurerm_resource_group.this.location}"
kind = "functionapp"
sku {
tier = "Dynamic"
size = "Y1"
}
}
resource "azurerm_function_app" "gui" {
name = "tf-secret-test"
resource_group_name = "${azurerm_resource_group.this.name}"
location = "${azurerm_resource_group.this.location}"
app_service_plan_id = "${azurerm_app_service_plan.this.id}"
storage_connection_string = "${azurerm_storage_account.this.primary_connection_string}"
identity {
type = "SystemAssigned"
}
app_settings {
FUNCTIONS_WORKER_RUNTIME = "dotnet"
IotHubConnection = "@Microsoft.KeyVault(SecretUri=${azurerm_key_vault_secret.IotHubConnection.id})"
WEBSITE_RUN_FROM_PACKAGE = "1"
}
version = "~2"
}
Changing the secret eg. through adding a "2" in the secret does change the id of secret. So the id of the current secret version is written to the environment var of the function. This done in a single terraform apply
.
Changing the secret eg. through adding a "2" in the secret does not change the id of secret. So the environment var of the function is not written. Running terraform again will change the environment var.
terraform apply -var 'objectid=<objectid of user>
secret2
terraform apply -var 'objectid=<objectid of user>
terraform apply -var 'objectid=<objectid of user>
The uri of a key vault sercet changes for every version. (see
https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references#reference-syntax)
I just ran into this same issue attempting to do what @StefanSchoof described, but my azurerm_key_vault_secret id happens to be output from a separate module and I am referencing the output for use in a function_app app_settings block. But the behavior is the same:
The following alternate path creates an explicit terraform error:
Repeat Step 1 above
Repeat Step 2 above
Error: Provider produced inconsistent final plan
When expanding the plan for module.api.azurerm_function_app.api-dev to include
new values learned so far during apply, provider "azurerm" produced an invalid
new value for .app_settings["xxxxxxAuthKey"]: was
cty.StringVal("@Microsoft.KeyVault(SecretUri=https://xxxxxx-dev.vault.azure.net/secrets/xxxxxx-key/139fcc1e99e44dc888ab52ba8b4b7e39)"),
but now
cty.StringVal("@Microsoft.KeyVault(SecretUri=https://xxxxxx-dev.vault.azure.net/secrets/xxxxxx-key/7d479680095f48c58d3b49c1047ff847)").This is a bug in the provider, which should be reported in the provider's own
issue tracker.
The bug will repeat from there on out because the secret id will always be out of sync (and behind) secret value changes. The bug can be cleared by running terraform apply with out updating secret value from Step 3, effectively getting the out of sync id value back in current state.
I'm seeing the same thing, except I'm explicitly using the version
of the azurerm_key_vault_secret
. version
also doesn't appear to cause any cascading updates when a new version is created. It's only on a subsequent run of apply does Terraform release the version has changed and updates my app_settings.
I'm seeing the same thing, except I'm explicitly using the
version
of theazurerm_key_vault_secret
.version
also doesn't appear to cause any cascading updates when a new version is created. It's only on a subsequent run of apply does Terraform release the version has changed and updates my app_settings.
@jagregory I was running into the same thing, but it looks like if I explicitly taint that resource by running terraform taint module.keyvault.azurerm_key_vault_secret.secret
then the subsequent apply appears to work. It's a bit of a hammer because the secret gets deleted and created again, but it seems like this is a workaround.
If you're always interested in latest version of the Key Vault secret, you can use this workaround - basically omit the version from SecretUri
. e.g. https://kv-we-retrieve-kv-secret.vault.azure.net/secrets/MySecretValue/
@syedhassaanahmed depending on where you use the secret, this workaround will not help. For instance when using KeyVault-referenced AppSettings in AppService, you would manually need to restart the AppService after you updated a secret for it to be picked up. Otherwise the AppService will not fetch the "latest".
Any news on this item or other workarounds that don't require a restart to the App Service?
I'm also interested if there will be a fix for this. Only knowing about the version ID after a modification breaks our CI pipeline.
Our workaround was to run terraform with the target
option and update the secrets first and only after run it for all resources (without the target
option, as you normally do).
This might not be ideal when running it from your local machine, but it definitely helps when you run it part of your Azure Devops pipeline for instance.
Thanks, @cosminstirbu - that is a neat and easy solution which provided the workaround we needed!
Most helpful comment
I just ran into this same issue attempting to do what @StefanSchoof described, but my azurerm_key_vault_secret id happens to be output from a separate module and I am referencing the output for use in a function_app app_settings block. But the behavior is the same:
The following alternate path creates an explicit terraform error:
Repeat Step 1 above
Repeat Step 2 above
The bug will repeat from there on out because the secret id will always be out of sync (and behind) secret value changes. The bug can be cleared by running terraform apply with out updating secret value from Step 3, effectively getting the out of sync id value back in current state.