Helay
Helay

Reputation: 139

Prevent KeyVault from updating secrets using Terraform

I'm building a terraform template to create Azure resources including Keyvault Secrets. The customer Subscription policy doesn't allow anyone to update/delete/view keyvault secrets.

If I run terraform apply for the first time, it will work perfectly. However, running the same template again will give you the following error: Error:

Error updating Key Vault "####" (Resource Group "####"): keyvault.VaultsClient#Update: Failure responding to request: StatusCode=403 --
Original Error: autorest/azure: Service returned an error. Status=403 Code="RequestDisallowedByPolicy" Message="Resource '###' was disallowed by policy. Policy identifiers: '[{\"policyAssignment\":{\"name\":\"###nis-deny-keyvault-acl\", ...

on ..\..\modules\azure\keyvault\main.tf line 15, in resource "azurerm_key_vault" "keyvault": 
15: resource "azurerm_key_vault" "keyvault" { 

Here is the Keyvault module:

variable "keyvault_id" { 
  type        = string
} 
variable "secrets" { 
  type        = map(string) 
} 


locals { 
  secret_names = keys(var.secrets) 
} 

resource "azurerm_key_vault_secret" "secret" { 
  count        = length(var.secrets) 
  name         = local.secret_names[count.index] 
  value        = var.secrets[local.secret_names[count.index]] 
  key_vault_id = var.keyvault_id 
} 

data "azurerm_key_vault_secret" "secrets" { 
  count        = length(var.secrets) 
  depends_on   = [azurerm_key_vault_secret.secret] 
  name         = local.secret_names[count.index] 
  key_vault_id = var.keyvault_id 
} 

output "keyvault_secret_attributes" { 
  value = [for i in range(length(azurerm_key_vault_secret.secret.*.id)) : data.azurerm_key_vault_secret.secrets[i]] 
} 

And here is the module from my template:

locals { 
  secrets_map = { 
    appinsights-key     = module.app_insights.app_insights_instrumentation_key 
    storage-account-key  = module.storage_account.primary_access_key 
  }
  output_secret_map = { 
    for secret in module.keyvault_secrets.keyvault_secret_attributes : 
    secret.name => secret.id 
  } 
} 

module "keyvault" { 
  source              = "../../modules/azure/keyvault" 
  keyvault_name       = local.kv_name 
  resource_group_name = azurerm_resource_group.app_rg.name 
} 


module "keyvault_secrets" { 
  source      = "../../modules/azure/keyvault-secret" 
  keyvault_id = module.keyvault.keyvault_id 
  secrets     = local.secrets_map 
} 

module "app_service_keyvault_access_policy" { 
  source                  = "../../modules/azure/keyvault-policy" 
  vault_id                = module.keyvault.keyvault_id 
  tenant_id               = module.app_service.app_service_identity_tenant_id 
  object_ids              = module.app_service.app_service_identity_object_ids 
  key_permissions         = ["get", "list"] 
  secret_permissions      = ["get", "list"] 
  certificate_permissions = ["get", "list"] 
} 

Upvotes: 2

Views: 2502

Answers (2)

TechnoCowboy
TechnoCowboy

Reputation: 344

I know this is a late answer, but for future visitors:

The pipeline running the Terraform Plan and Apply will need to have proper access to the key vault.

So, if you are running your CI/CD from Azure Pipelines, you would typically have a service connection that your pipeline uses for authentication. The service connection you use for Terraform is most likely based on a service principal that has contributor rights (at least at resource group level) for it to provisioning anything at all.

If that is the case, then you must add a policy giving that same service principal (Use the Service Principals Enterprise Object Id) to have at least list, get and set permissions for secrets.

Upvotes: 1

bursson
bursson

Reputation: 556

Using Terraform for provisioning and managing a keyvault with that kind of limitations sounds like a bad idea. Terraforms main idea is to monitor the state of your resources - if it is not allowed to read the resource it becomes pretty useless. Your problem is not even that Terraform is trying to update something, it fails because it wants to check the current state of your resource and fails.

If your goal is just to create secrets in a keyvault, I would just us the az keyvault commands like this:

az login
az keyvault secret set --name mySecret --vault-name myKeyvault --value mySecretValue

An optimal solution would of course be that your service principal that you use for executing Terrafom commands has the sufficient rights to perform the actions it was created for.

Upvotes: 1

Related Questions