From f94b4356dfbbdc7c7f9066d198e7f3e613d793a2 Mon Sep 17 00:00:00 2001 From: NaKamize Date: Sun, 19 Jul 2026 11:46:17 +0200 Subject: [PATCH 1/2] role assignment fix --- terraform/keyvault.tf | 7 ------- terraform/main.tf | 14 ++------------ terraform/provider.tf | 3 --- terraform/variables.tf | 4 ++-- 4 files changed, 4 insertions(+), 24 deletions(-) diff --git a/terraform/keyvault.tf b/terraform/keyvault.tf index ed42f27e..a21f2b87 100644 --- a/terraform/keyvault.tf +++ b/terraform/keyvault.tf @@ -8,20 +8,15 @@ resource "azurerm_key_vault" "main" { sku_name = "standard" rbac_authorization_enabled = true soft_delete_retention_days = 7 - # Off for now so the vault can be freely deleted/recreated during setup; flip to true - # once this is settled and you want protection against accidental/malicious deletion. purge_protection_enabled = false } -# Lets Terraform (running as the current signed-in user/service principal) create and -# manage secret values in the vault. resource "azurerm_role_assignment" "terraform_secrets_officer" { scope = azurerm_key_vault.main.id role_definition_name = "Key Vault Secrets Officer" principal_id = data.azurerm_client_config.current.object_id } -# Lets the Container App's managed identity read secret values at runtime. resource "azurerm_role_assignment" "container_app_secrets_user" { scope = azurerm_key_vault.main.id role_definition_name = "Key Vault Secrets User" @@ -42,8 +37,6 @@ resource "azurerm_key_vault_secret" "mysql_database_url" { depends_on = [azurerm_role_assignment.terraform_secrets_officer] } -# Sourced directly from the ACR resource's own computed attribute — no separate -# variable needed, Azure does expose this one back via the API. resource "azurerm_key_vault_secret" "acr_admin_password" { name = "acr-admin-password" value = azurerm_container_registry.registries-ujmikamiacr0.admin_password diff --git a/terraform/main.tf b/terraform/main.tf index 17b02a86..73b53de7 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -166,8 +166,6 @@ resource "azurerm_log_analytics_workspace" "workspaces-workspace_ujmikamiapp2_hm resource_group_name = azurerm_resource_group.resource_groups-ujmikamiapp20.name lifecycle { - # Not captured by the import (state has it null); the provider always wants to - # write an explicit value on first apply regardless of what we set here. ignore_changes = [local_authentication_enabled] } } @@ -182,17 +180,13 @@ resource "azurerm_storage_container" "containers-media0" { container_access_type = "blob" name = "media" storage_account_id = "/subscriptions/ffaa5a63-e63d-498f-9747-c1deed636ef4/resourceGroups/ujmikamiapp2/providers/Microsoft.Storage/storageAccounts/ujmikamiblob" - depends_on = [ - # One of azurerm_storage_account.storage_accounts-ujmikamiblob0,azurerm_storage_account_queue_properties.queue_services-default0 (can't auto-resolve as their ids are identical) - ] + depends_on = [] } resource "azurerm_storage_container" "containers-static0" { container_access_type = "blob" name = "static" storage_account_id = "/subscriptions/ffaa5a63-e63d-498f-9747-c1deed636ef4/resourceGroups/ujmikamiapp2/providers/Microsoft.Storage/storageAccounts/ujmikamiblob" - depends_on = [ - # One of azurerm_storage_account.storage_accounts-ujmikamiblob0,azurerm_storage_account_queue_properties.queue_services-default0 (can't auto-resolve as their ids are identical) - ] + depends_on = [] } resource "azurerm_storage_account_queue_properties" "queue_services-default0" { storage_account_id = azurerm_storage_account.storage_accounts-ujmikamiblob0.id @@ -214,10 +208,6 @@ resource "azurerm_static_web_app" "static_sites-ujmikamiapp0" { name = "ujmikamiapp" repository_branch = "main" repository_url = "https://github.com/NaKamize/ujmikamiapp" - # Azure never exposes the deployment token back via the API (write-only at creation), - # so aztfexport can't recover it. This placeholder only exists to satisfy the provider's - # "all three or none" validation; ignore_changes below means Terraform never tries to - # actually change the live GitHub Actions linkage using it. repository_token = "unmanaged-see-lifecycle-block" resource_group_name = azurerm_resource_group.resource_groups-ujmikamiapp20.name diff --git a/terraform/provider.tf b/terraform/provider.tf index b6853da9..12e30e27 100644 --- a/terraform/provider.tf +++ b/terraform/provider.tf @@ -4,8 +4,5 @@ provider "azurerm" { subscription_id = "ffaa5a63-e63d-498f-9747-c1deed636ef4" environment = "public" use_msi = false - # use_cli defaults to true (local az login) and use_oidc defaults to false; - # CI overrides the latter via the ARM_USE_OIDC=true env var, so neither is - # hardcoded here. resource_provider_registrations = "none" } diff --git a/terraform/variables.tf b/terraform/variables.tf index f7ac0d8d..a9e2fc38 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -1,11 +1,11 @@ variable "mysql_admin_password" { - description = "Existing admin password for the ujmikami-db MySQL Flexible Server (Azure never exposes this back via the API, so it must be supplied — set via TF_VAR_mysql_admin_password)." + description = "Existing admin password for the ujmikami-db MySQL Flexible Server." type = string sensitive = true } variable "django_secret_key" { - description = "Django SECRET_KEY for production (set via TF_VAR_django_secret_key)." + description = "Django SECRET_KEY for production (TF_VAR_django_secret_key)." type = string sensitive = true } From c54057e1478350a34cc7275e3e70d821ff4a5b3c Mon Sep 17 00:00:00 2001 From: NaKamize Date: Sun, 19 Jul 2026 11:53:53 +0200 Subject: [PATCH 2/2] role fixes --- terraform/keyvault.tf | 3 ++- terraform/main.tf | 4 ++++ terraform/variables.tf | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/terraform/keyvault.tf b/terraform/keyvault.tf index a21f2b87..0ec5f79e 100644 --- a/terraform/keyvault.tf +++ b/terraform/keyvault.tf @@ -12,9 +12,10 @@ resource "azurerm_key_vault" "main" { } resource "azurerm_role_assignment" "terraform_secrets_officer" { + for_each = toset(var.terraform_operator_principal_ids) scope = azurerm_key_vault.main.id role_definition_name = "Key Vault Secrets Officer" - principal_id = data.azurerm_client_config.current.object_id + principal_id = each.value } resource "azurerm_role_assignment" "container_app_secrets_user" { diff --git a/terraform/main.tf b/terraform/main.tf index 73b53de7..9301bfac 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -117,6 +117,10 @@ resource "azurerm_container_app" "container_apps-ujmikamiapp_env0" { name = "http-scaler" } } + + lifecycle { + ignore_changes = [template[0].container[0].image] + } } resource "azurerm_container_app_environment" "managed_environments-ujmikamiapp_env_env0" { location = "westus2" diff --git a/terraform/variables.tf b/terraform/variables.tf index a9e2fc38..5c9fd57c 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -9,3 +9,12 @@ variable "django_secret_key" { type = string sensitive = true } + +variable "terraform_operator_principal_ids" { + description = "Azure AD object IDs (human users and/or service principals) granted Key Vault Secrets Officer so they can manage secrets via Terraform. Fixed list, independent of whichever identity happens to be running a given plan/apply." + type = list(string) + default = [ + "5731fd27-fb2a-4dd3-b4b5-e709cb8980b0", + "4c0cd6ef-89ab-49f9-9184-1eed4afbb869", + ] +}