0

Azure services used:

  1. Keyvault
  2. App Configuration

I was trying to store the secrets from keyvault that were created, on to app configuration. I was getting the below error and not sure on how to proceed. Kindly help me with your guidance.

│ Error: Invalid count argument
│ 
│   on ../../modules/appconfiguration/main.tf line 75, in data "azurerm_key_vault_secret" "kv_secret":
│   75:   count        = length(data.azurerm_key_vault_secrets.kv_all_secrets.names)
│ 
│ The "count" value depends on resource attributes that cannot be determined
│ until apply, so Terraform cannot predict how many instances will be
│ created. To work around this, use the -target argument to first apply only
│ the resources that the count depends on.

All of the secret insertion to keyvault and extraction from keyvault is running on the same code. The app configuration needs to be referenced to the keyvault secrets.

Please find the code below for reference:

# Step 1: Fetching all the secrets from Keyvault

data "azurerm_key_vault_secrets" "kv_all_secrets" {
  key_vault_id = data.azurerm_key_vault.kv.id
}

# Step 2: Looping in each secrets based on it name

data "azurerm_key_vault_secret" "kv_secret" {
  count        = length(data.azurerm_key_vault_secrets.kv_all_secrets.names)
  name         = data.azurerm_key_vault_secrets.kv_all_secrets.names[count.index]
  key_vault_id = data.azurerm_key_vault.kv.id
}

# Step 3: Looping on each contents from previous data block to get the name and versionless Id of the secret stored

resource "azurerm_app_configuration_key" "app_config_key" {
  #for_each                = data.azurerm_key_vault_secret.kv_secret
  count                   = length(data.azurerm_key_vault_secret.kv_secret)
  configuration_store_id  = data.azurerm_app_configuration.app_config.id
  key                     = data.azurerm_key_vault_secret.kv_secret[count.index].name
  type                    = "vault"
  vault_key_reference     =  data.azurerm_key_vault_secret.kv_secret[count.index].versionless_id
}
  • 2
    The error is clear. You have to deploy your code in two stages, the first one using `-target` argument. Did you do that? – Marcin Mar 20 '23 at 07:55
  • unfortunately not. I did not find many resources or examples I could refer to in terraform using -target argument. Could you please help me with the resources available? – Gautham Sharma Mar 20 '23 at 09:30
  • 1
    Please review the following documentation on using target: https://developer.hashicorp.com/terraform/cli/commands/plan#resource-targeting – Noam Gur Mar 20 '23 at 10:12
  • did you try it with the for_each instead? `#for_each = data.azurerm_key_vault_secret.kv_secret` – silent Mar 20 '23 at 12:19
  • @silent Yes I did try it for_each as well. I get the same error there to use -target – Gautham Sharma Mar 20 '23 at 12:45

1 Answers1

0

It worked for me when I have run below code:

I have created all the secrets through terraform :

resource "azurerm_key_vault" "example" {
  name                        = "kavyaexmplkeyvault"
  location                    = data.azurerm_resource_group.example.location
  resource_group_name         = data.azurerm_resource_group.example.name
  enabled_for_disk_encryption = true
  tenant_id                   = data.azurerm_client_config.current.tenant_id
  soft_delete_retention_days  = 7
  purge_protection_enabled    = false
  sku_name = "standard"

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
   object_id = data.azurerm_client_config.current.object_id

    
    certificate_permissions = [
      "Create",
      "Delete",
      "DeleteIssuers",
      "Get",
      "GetIssuers",
      "Import",
      "List",
      "ListIssuers",
      "ManageContacts",
      "ManageIssuers",
      "Purge",
      "SetIssuers",
      "Update",
    ]

    key_permissions = [
      "Backup",
      "Create",
      "Decrypt",
      "Delete",
      "Encrypt",
      "Get",
      "Import",
      "List",
      "Purge",
      "Recover",
      "Restore",
      "Sign",
      "UnwrapKey",
      "Update",
      "Verify",
      "WrapKey",
    ]

    secret_permissions = [
      "Backup",
      "Delete",
      "Get",
      "List",
      "Purge",
      "Recover",
      "Restore",
      "Set",
    ]
    storage_permissions = [
      "Get","Set"
    ]
  }

  
} 

resource "azurerm_key_vault_secret" "connstr" {
  name         = "SBconnectionstring"
  value        =  "gsdnjgsgjh3.3jgjshgfdj"
  key_vault_id = azurerm_key_vault.example.id
}

resource "azurerm_key_vault_secret" "passwrd" {
  
  name         = "passwrd"
  value        =  "kjghjh@123"
  key_vault_id = azurerm_key_vault.example.id
}
   
resource "azurerm_key_vault_secret" "secret" {
  name         = "secret"
  value        =  "Mysecret"
  key_vault_id = azurerm_key_vault.example.id
}

enter image description here

Then fetched the secretes using the same commands :

Fetching all the secrets from Keyvault

data "azurerm_key_vault_secrets" "kv_all_secrets" {
  key_vault_id = azurerm_key_vault.example.id
}

Looping in each secrets based on it name

data "azurerm_key_vault_secret" "kv_secret" {
  count        = length(data.azurerm_key_vault_secrets.kv_all_secrets.names)
  name         = data.azurerm_key_vault_secrets.kv_all_secrets.names[count.index]
  key_vault_id = azurerm_key_vault.example.id
}

output "keyvaultcount" {
  value =length(data.azurerm_key_vault_secret.kv_secret)
  
}



resource "azurerm_app_configuration" "appconf" {
  name                = "appConfkav"
 resource_group_name = data.azurerm_resource_group.example.name
location                 = data.azurerm_resource_group.example.location
}



resource "azurerm_role_assignment" "appconf_dataowner" {
  scope                = azurerm_app_configuration.appconf.id
  role_definition_name = "App Configuration Data Owner"
  principal_id         = data.azurerm_client_config.current.object_id
}

Looping on each contents from previous data block to get the name and versionless Id of the secret stored.

Note: Here i used depends_on parameter in app config block to say that first role has to be assigned before fetching the secrets and storing.

resource "azurerm_app_configuration_key" "app_config_key" {
  count                   = length(data.azurerm_key_vault_secret.kv_secret)
  configuration_store_id  = azurerm_app_configuration.appconf.id
  key                     = data.azurerm_key_vault_secret.kv_secret[count.index].name
  type                    = "vault"
  vault_key_reference     =  data.azurerm_key_vault_secret.kv_secret[count.index].versionless_id
  depends_on = [
    azurerm_role_assignment.appconf_dataowner
  ]
}

enter image description here

enter image description here

It Added all the secrets from keyvault to App config :

enter image description here

I have terraform version v1.0.7
And

terraform {
  required_providers {
azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.40.0"
    }
}
kavyaS
  • 8,026
  • 1
  • 7
  • 19
  • This worked in my lab environment though. But the problem is in the actual dev environment where we have the keyvault with secrets made available and the later is being called via module structure. As per the suggestion from terraform, it states "use the -target argument to first apply only the resources that the count depends on." I have not find many resources that tells how the -target arg can be used. – Gautham Sharma Mar 21 '23 at 07:47
  • First target those resources whicha re dependent example: `terraform apply -target=data.azurerm_key_vault_secrets.kv_all_secrets` or for two resources example : `terraform apply -target=azurerm_resource_group.example -target=azurerm_virtual_network.example` .After correct dependent resources are applied with target, then run `terraform -apply` to apply all changes. – kavyaS Mar 22 '23 at 04:02