From 39ba611506d00ff278420b74b4e45e1356160d3f Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Tue, 21 Jan 2025 17:23:26 +0200 Subject: [PATCH 1/4] Add keyvault module --- src/modules/_security/keyvault/_locals.tf | 42 ++------------ src/modules/_security/keyvault/_outputs.tf | 12 ++++ src/modules/_security/keyvault/_variables.tf | 3 + .../_security/keyvault/access_policies.tf | 31 +++-------- src/modules/_security/keyvault/keyvault.tf | 9 +-- .../keyvault_access_policy/_locals.tf | 55 +++++++++++++++++++ .../keyvault_access_policy/_outputs.tf | 0 .../keyvault_access_policy/_variables.tf | 26 +++++++++ .../keyvault_access_policy/access_policies.tf | 35 ++++++++++++ .../access_policy/_variables.tf | 6 ++ .../access_policy/access_policy.tf | 9 +++ .../keyvault_private_endpoint/_locals.tf | 28 ++++++++++ .../keyvault_private_endpoint/_outputs.tf | 3 + .../keyvault_private_endpoint/_variables.tf | 23 ++++++++ .../private_endpoint.tf | 21 +++++++ .../keyvault/keyvault_secret/_outputs.tf | 19 +++++++ .../keyvault/keyvault_secret/_variables.tf | 19 +++++++ .../keyvault/keyvault_secret/main.tf | 9 +++ .../_security/keyvault/private_endpoint.tf | 12 ++++ src/modules/_security/keyvault/secrets.tf | 12 ++++ 20 files changed, 310 insertions(+), 64 deletions(-) create mode 100644 src/modules/_security/keyvault/keyvault_access_policy/_locals.tf create mode 100644 src/modules/_security/keyvault/keyvault_access_policy/_outputs.tf create mode 100644 src/modules/_security/keyvault/keyvault_access_policy/_variables.tf create mode 100644 src/modules/_security/keyvault/keyvault_access_policy/access_policies.tf create mode 100644 src/modules/_security/keyvault/keyvault_access_policy/access_policy/_variables.tf create mode 100644 src/modules/_security/keyvault/keyvault_access_policy/access_policy/access_policy.tf create mode 100644 src/modules/_security/keyvault/keyvault_private_endpoint/_locals.tf create mode 100644 src/modules/_security/keyvault/keyvault_private_endpoint/_outputs.tf create mode 100644 src/modules/_security/keyvault/keyvault_private_endpoint/_variables.tf create mode 100644 src/modules/_security/keyvault/keyvault_private_endpoint/private_endpoint.tf create mode 100644 src/modules/_security/keyvault/keyvault_secret/_outputs.tf create mode 100644 src/modules/_security/keyvault/keyvault_secret/_variables.tf create mode 100644 src/modules/_security/keyvault/keyvault_secret/main.tf create mode 100644 src/modules/_security/keyvault/private_endpoint.tf create mode 100644 src/modules/_security/keyvault/secrets.tf diff --git a/src/modules/_security/keyvault/_locals.tf b/src/modules/_security/keyvault/_locals.tf index 3d5dc992..6b55ec36 100644 --- a/src/modules/_security/keyvault/_locals.tf +++ b/src/modules/_security/keyvault/_locals.tf @@ -9,47 +9,13 @@ locals { var.resources.virtual_networks[split("/", config.subnet_ref)[0]].subnets[split("/", config.subnet_ref)[1]].id ) ] - + subnet_id = try( + var.resources.virtual_networks[split("/", var.settings.private_endpoint.subnet_ref)[0]].subnets[split("/", var.settings.private_endpoint.subnet_ref)[1]].id, + null + ) tags = merge( var.global_settings.tags, var.global_settings.inherit_resource_group_tags ? local.resource_group.tags : {}, try(var.settings.tags, {}) ) } - - -locals { - all_secret_permissions = [ - "Backup", - "Delete", - "Get", - "List", - "Purge", - "Recover", - "Restore", - "Set", - ] - - all_key_permissions = [ - "Backup", - "Create", - "Decrypt", - "Delete", - "Encrypt", - "Get", - "Import", - "List", - "Purge", - "Recover", - "Restore", - "Sign", - "UnwrapKey", - "Update", - "Verify", - "WrapKey", - "Release", - "Rotate", - "GetRotationPolicy", - "SetRotationPolicy", - ] -} diff --git a/src/modules/_security/keyvault/_outputs.tf b/src/modules/_security/keyvault/_outputs.tf index fda15d89..a6b440d4 100644 --- a/src/modules/_security/keyvault/_outputs.tf +++ b/src/modules/_security/keyvault/_outputs.tf @@ -5,3 +5,15 @@ output "id" { output "vault_uri" { value = azurerm_key_vault.main.vault_uri } + +output "resource_group_name" { + value = azurerm_key_vault.main.resource_group_name +} + +output "location" { + value = azurerm_key_vault.main.location +} + +output "name" { + value = azurerm_key_vault.main.name +} diff --git a/src/modules/_security/keyvault/_variables.tf b/src/modules/_security/keyvault/_variables.tf index 6edf68ec..f98a0145 100644 --- a/src/modules/_security/keyvault/_variables.tf +++ b/src/modules/_security/keyvault/_variables.tf @@ -6,11 +6,14 @@ variable "settings" { description = "All the configuration for this resource" } + + variable "resources" { type = object({ resource_groups = map(any) virtual_networks = map(any) managed_identities = map(any) + private_dns_zones = map(any) }) description = "All required resources" } diff --git a/src/modules/_security/keyvault/access_policies.tf b/src/modules/_security/keyvault/access_policies.tf index a12b6381..217a9300 100644 --- a/src/modules/_security/keyvault/access_policies.tf +++ b/src/modules/_security/keyvault/access_policies.tf @@ -1,24 +1,11 @@ -resource "azurerm_key_vault_access_policy" "logged_in_user" { - key_vault_id = azurerm_key_vault.main.id - tenant_id = var.global_settings.tenant_id - object_id = var.global_settings.object_id +module "initial_policy" { + source = "./keyvault_access_policy" + for_each = try(var.settings.access_policies, {}) - secret_permissions = local.all_secret_permissions - key_permissions = local.all_key_permissions -} - -resource "azurerm_key_vault_access_policy" "managed_identity" { - for_each = { - for access_policy_ref, config in var.settings.access_policies : - access_policy_ref => config - if can(config.managed_identity_ref) - } - key_vault_id = azurerm_key_vault.main.id - tenant_id = var.global_settings.tenant_id - object_id = var.resources.managed_identities[each.value.managed_identity_ref].principal_id - - # this is a bit of a hack to allow `secret_permissions` to be a string when "All" and otherwise a list - # the tfvars allows it, but the module needs us to convert it to list explicitly to get around the type errors - secret_permissions = try(each.value.secret_permissions, null) == "All" ? local.all_secret_permissions : try(tolist(each.value.secret_permissions), []) - key_permissions = try(each.value.key_permissions, null) == "All" ? local.all_key_permissions : try(tolist(each.value.key_permissions), []) + settings = var.settings + keyvault_id = azurerm_key_vault.main.id + access_policies = each.value + policy_name = each.key + global_settings = var.global_settings + resources = var.resources } diff --git a/src/modules/_security/keyvault/keyvault.tf b/src/modules/_security/keyvault/keyvault.tf index 57f21dfa..4532a1eb 100644 --- a/src/modules/_security/keyvault/keyvault.tf +++ b/src/modules/_security/keyvault/keyvault.tf @@ -7,10 +7,11 @@ resource "azurerm_key_vault" "main" { tenant_id = var.global_settings.tenant_id sku_name = try(var.settings.sku_name, "standard") - enabled_for_disk_encryption = try(var.settings.enabled_for_disk_encryption, null) - soft_delete_retention_days = try(var.settings.soft_delete_retention_days, null) - purge_protection_enabled = try(var.settings.purge_protection_enabled, null) - enable_rbac_authorization = try(var.settings.enable_rbac_authorization, false) + enabled_for_disk_encryption = try(var.settings.enabled_for_disk_encryption, null) + soft_delete_retention_days = try(var.settings.soft_delete_retention_days, null) + purge_protection_enabled = try(var.settings.purge_protection_enabled, null) + enable_rbac_authorization = try(var.settings.enable_rbac_authorization, false) + public_network_access_enabled = try(var.settings.public_network_access_enabled, false) network_acls { default_action = try(var.settings.network_rules.default_action, "Deny") diff --git a/src/modules/_security/keyvault/keyvault_access_policy/_locals.tf b/src/modules/_security/keyvault/keyvault_access_policy/_locals.tf new file mode 100644 index 00000000..82771146 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_access_policy/_locals.tf @@ -0,0 +1,55 @@ +locals { + all_secret_permissions = [ + "Backup", + "Delete", + "Get", + "List", + "Purge", + "Recover", + "Restore", + "Set", + ] + + all_key_permissions = [ + "Backup", + "Create", + "Decrypt", + "Delete", + "Encrypt", + "Get", + "Import", + "List", + "Purge", + "Recover", + "Restore", + "Sign", + "UnwrapKey", + "Update", + "Verify", + "WrapKey", + "Release", + "Rotate", + "GetRotationPolicy", + "SetRotationPolicy", + ] +} + +locals { + effective_key_permissions = ( + var.access_policies.key_permissions == "All" ? + local.all_key_permissions : + tolist(try(var.access_policies.key_permissions, [])) + ) + + effective_secret_permissions = ( + var.access_policies.secret_permissions == "All" ? + local.all_secret_permissions : + tolist(try(var.access_policies.secret_permissions, [])) + ) +} + + +locals { + debug_settings = var.settings + has_logged_in_key = contains(keys(var.settings), "managed_identity") +} diff --git a/src/modules/_security/keyvault/keyvault_access_policy/_outputs.tf b/src/modules/_security/keyvault/keyvault_access_policy/_outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/src/modules/_security/keyvault/keyvault_access_policy/_variables.tf b/src/modules/_security/keyvault/keyvault_access_policy/_variables.tf new file mode 100644 index 00000000..bd4ad120 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_access_policy/_variables.tf @@ -0,0 +1,26 @@ +variable "settings" { + description = "All the configuration for this resource" +} + +variable "keyvault_id" { + description = "keyvault id" +} + +variable "access_policies" { + validation { + condition = length(var.access_policies) <= 16 + error_message = "A maximun of 16 access policies can be set." + } +} +variable "global_settings" { + description = "Global settings for tinycaf" +} + +variable "policy_name" { + description = "The key of the access policy." + type = string +} + +variable "resources" { + description = "All the configuration for this resource" +} diff --git a/src/modules/_security/keyvault/keyvault_access_policy/access_policies.tf b/src/modules/_security/keyvault/keyvault_access_policy/access_policies.tf new file mode 100644 index 00000000..e2aa0df1 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_access_policy/access_policies.tf @@ -0,0 +1,35 @@ +module "logged_in_user" { + source = "./access_policy" + count = var.policy_name == "logged_in_user" ? 1 : 0 + keyvault_id = var.keyvault_id + tenant_id = var.global_settings.tenant_id + access_policies = try(var.access_policies, null) + object_id = var.global_settings.object_id + key_permissions = local.all_key_permissions + secret_permissions = local.all_secret_permissions +} + + +module "managed_identities" { + source = "./access_policy" + for_each = var.policy_name == "managed_identity" && length(try(var.access_policies.managed_identity_refs, [])) > 0 ? { for idx, ref in try(var.access_policies.managed_identity_refs, []) : idx => ref } : {} + + keyvault_id = var.keyvault_id + access_policies = var.access_policies + tenant_id = var.global_settings.tenant_id + object_id = var.resources.managed_identities[each.value].principal_id + key_permissions = local.effective_key_permissions + secret_permissions = local.effective_secret_permissions +} + +module "object_ids" { + source = "./access_policy" + for_each = var.policy_name == "object_ids" && length(try(var.access_policies.object_ids, [])) > 0 ? { for idx, obj_id in try(var.access_policies.object_ids, []) : idx => obj_id } : {} + + keyvault_id = var.keyvault_id + access_policies = var.access_policies + tenant_id = var.global_settings.tenant_id + object_id = each.value + key_permissions = local.effective_key_permissions + secret_permissions = local.effective_secret_permissions +} diff --git a/src/modules/_security/keyvault/keyvault_access_policy/access_policy/_variables.tf b/src/modules/_security/keyvault/keyvault_access_policy/access_policy/_variables.tf new file mode 100644 index 00000000..4a859544 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_access_policy/access_policy/_variables.tf @@ -0,0 +1,6 @@ +variable "keyvault_id" {} +variable "tenant_id" {} +variable "object_id" {} +variable "key_permissions" {} +variable "secret_permissions" {} +variable "access_policies" {} diff --git a/src/modules/_security/keyvault/keyvault_access_policy/access_policy/access_policy.tf b/src/modules/_security/keyvault/keyvault_access_policy/access_policy/access_policy.tf new file mode 100644 index 00000000..5fffd5a9 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_access_policy/access_policy/access_policy.tf @@ -0,0 +1,9 @@ +resource "azurerm_key_vault_access_policy" "main" { # Using the policy key in the resource name + key_vault_id = var.keyvault_id + + tenant_id = var.tenant_id + object_id = var.object_id + + key_permissions = var.key_permissions + secret_permissions = var.secret_permissions +} diff --git a/src/modules/_security/keyvault/keyvault_private_endpoint/_locals.tf b/src/modules/_security/keyvault/keyvault_private_endpoint/_locals.tf new file mode 100644 index 00000000..fbfafc96 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_private_endpoint/_locals.tf @@ -0,0 +1,28 @@ +locals { + subnet_ids = [ + for network_rule_ref, config in try(var.settings.network_rules.subnets, {}) : ( + var.resources.virtual_networks[split("/", config.subnet_ref)[0]].subnets[split("/", config.subnet_ref)[1]].id + ) + ] + subnet_id = try( + var.resources.virtual_networks[split("/", var.settings.private_endpoint.subnet_ref)[0]].subnets[split("/", var.settings.private_endpoint.subnet_ref)[1]].id, + null + ) + tags = merge( + var.global_settings.tags, + var.global_settings.inherit_resource_group_tags ? local.resource_group.tags : {}, + try(var.settings.tags, {}) + ) + + resource_group = var.resources.resource_groups[var.settings.resource_group_ref] + + resource_group_name = local.resource_group.name + location = local.resource_group.location +} + +locals { + dns_zone_ids = try([ + for zone in var.settings.private_endpoint.dns_zones_ref : + var.resources.private_dns_zones[zone].id + ], []) +} diff --git a/src/modules/_security/keyvault/keyvault_private_endpoint/_outputs.tf b/src/modules/_security/keyvault/keyvault_private_endpoint/_outputs.tf new file mode 100644 index 00000000..28c86573 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_private_endpoint/_outputs.tf @@ -0,0 +1,3 @@ +output "id" { + value = azurerm_private_endpoint.main.id +} diff --git a/src/modules/_security/keyvault/keyvault_private_endpoint/_variables.tf b/src/modules/_security/keyvault/keyvault_private_endpoint/_variables.tf new file mode 100644 index 00000000..9429c388 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_private_endpoint/_variables.tf @@ -0,0 +1,23 @@ +variable "global_settings" { + description = "Global settings for tinycaf" +} + +variable "settings" { + description = "All the configuration for this resource" +} + +variable "keyvault_id" { + description = "id of the keyvault" +} + +variable "resources" { + description = "All the configuration for this resource" +} + +variable "subnet_ref" { + description = "All the configuration for this resource" +} + +variable "dns_zones_ref" { + description = "All the configuration for this resource" +} diff --git a/src/modules/_security/keyvault/keyvault_private_endpoint/private_endpoint.tf b/src/modules/_security/keyvault/keyvault_private_endpoint/private_endpoint.tf new file mode 100644 index 00000000..02b6a0d1 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_private_endpoint/private_endpoint.tf @@ -0,0 +1,21 @@ +resource "azurerm_private_endpoint" "main" { + name = "pe-${var.settings.name}" + resource_group_name = local.resource_group_name + location = local.location + subnet_id = local.subnet_id + + tags = local.tags + + private_service_connection { + name = "psc-${var.settings.name}" + private_connection_resource_id = var.keyvault_id + + is_manual_connection = try(var.settings.private_endpoint.private_service_connection.is_manual_connection, false) + private_connection_resource_alias = try(var.settings.private_endpoint.private_service_connection.private_connection_resource_alias, null) + subresource_names = try(var.settings.private_endpoint.private_service_connection.subresource_names, null) + } + private_dns_zone_group { + name = try(var.settings.private_endpoint.dns_group_name, "default") + private_dns_zone_ids = local.dns_zone_ids + } +} diff --git a/src/modules/_security/keyvault/keyvault_secret/_outputs.tf b/src/modules/_security/keyvault/keyvault_secret/_outputs.tf new file mode 100644 index 00000000..cceddc11 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_secret/_outputs.tf @@ -0,0 +1,19 @@ +output "id" { + value = azurerm_key_vault_secret.main.id +} + +output "resource_id" { + value = azurerm_key_vault_secret.main.resource_id +} + +output "resource_versionless_id" { + value = azurerm_key_vault_secret.main.resource_versionless_id +} + +output "version" { + value = azurerm_key_vault_secret.main.version +} + +output "versionless_id" { + value = azurerm_key_vault_secret.main.versionless_id +} diff --git a/src/modules/_security/keyvault/keyvault_secret/_variables.tf b/src/modules/_security/keyvault/keyvault_secret/_variables.tf new file mode 100644 index 00000000..e494a0fd --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_secret/_variables.tf @@ -0,0 +1,19 @@ +variable "global_settings" { + description = "Global settings for tinycaf" +} + +variable "settings" { + description = "All the configuration for this resource" +} + +variable "keyvault_id" { + description = "id of the keyvault" +} + +variable "resources" { + description = "All the configuration for this resource" +} + +variable "secrets" { + description = "All the configuration for this resource" +} diff --git a/src/modules/_security/keyvault/keyvault_secret/main.tf b/src/modules/_security/keyvault/keyvault_secret/main.tf new file mode 100644 index 00000000..0bc57039 --- /dev/null +++ b/src/modules/_security/keyvault/keyvault_secret/main.tf @@ -0,0 +1,9 @@ +resource "azurerm_key_vault_secret" "main" { + name = var.secrets.name + value = var.secrets.value + key_vault_id = var.keyvault_id + + lifecycle { + ignore_changes = ["value"] + } +} diff --git a/src/modules/_security/keyvault/private_endpoint.tf b/src/modules/_security/keyvault/private_endpoint.tf new file mode 100644 index 00000000..aa090852 --- /dev/null +++ b/src/modules/_security/keyvault/private_endpoint.tf @@ -0,0 +1,12 @@ +module "keyvault_endpoint" { + source = "./keyvault_private_endpoint" + + count = try(var.settings.private_endpoint != null, false) ? 1 : 0 + + settings = var.settings + keyvault_id = azurerm_key_vault.main.id + subnet_ref = var.settings.private_endpoint.subnet_ref + dns_zones_ref = var.settings.private_endpoint.dns_zones_ref + global_settings = var.global_settings + resources = var.resources +} diff --git a/src/modules/_security/keyvault/secrets.tf b/src/modules/_security/keyvault/secrets.tf new file mode 100644 index 00000000..893c82ed --- /dev/null +++ b/src/modules/_security/keyvault/secrets.tf @@ -0,0 +1,12 @@ +module "secrets" { + source = "./keyvault_secret" + + # Use for_each to iterate over the secrets map + for_each = try(var.settings.secrets, {}) + + settings = var.settings + keyvault_id = azurerm_key_vault.main.id + secrets = each.value + global_settings = var.global_settings + resources = var.resources +} From 6ec66b758d1443dfb26847dbd443eb735681ef56 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Tue, 21 Jan 2025 17:24:56 +0200 Subject: [PATCH 2/4] Add example for keyvault module --- examples/keyvaults.tfvars | 41 +++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/examples/keyvaults.tfvars b/examples/keyvaults.tfvars index ec801abd..1626f549 100644 --- a/examples/keyvaults.tfvars +++ b/examples/keyvaults.tfvars @@ -1,19 +1,40 @@ keyvaults = { - kv_test = { - name = "kv-test-dv-ne-01" - resource_group_ref = "rg_test" + kv-acfin-01 = { + name = "kv-acfin-ne-01" + resource_group_ref = "acfin2" + public_network_access_enabled = true network_rules = { - default_action = "Deny" - allowed_ips = ["10.10.10.10", "20.20.20.20"] + default_action = "Allow" + allowed_ips = ["95.43.223.55"] subnets = { - allow_app1 = { - subnet_ref = "vnet_test/snet_app1" - } - allow_private_endpoints = { - subnet_ref = "vnet_test/snet_private_endpoints" + subnet1 = { + subnet_ref = "vnet_acfin_prod_01/sn-resources" } } } + access_policies = { + managed_identity = { + managed_identity_refs = ["id_acfin_01"] + secret_permissions = "All" + key_permissions = ["Get", "List"] + } + logged_in_user = { + secret_permissions = "All" + key_permissions = "All" + } + object_ids = { + object_ids = ["7c265d5c-6e52-4a53-b3a9-90c663567c64"] + secret_permissions = "All" + key_permissions = "All" + } + } + secrets = { + secret-skey = { + name = "SharedKey" + value = "default" + ignore_changes = true + } + } } } From 7f3efa6504d52090f392250145cd5eaa0a897837 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Tue, 21 Jan 2025 17:33:34 +0200 Subject: [PATCH 3/4] Add example for KeyVault --- examples/keyvaults.tfvars | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/keyvaults.tfvars b/examples/keyvaults.tfvars index 1626f549..56da6862 100644 --- a/examples/keyvaults.tfvars +++ b/examples/keyvaults.tfvars @@ -1,20 +1,20 @@ keyvaults = { - kv-acfin-01 = { - name = "kv-acfin-ne-01" - resource_group_ref = "acfin2" + kv-test = { + name = "kv-test-dev-01" + resource_group_ref = "rg-test" public_network_access_enabled = true network_rules = { default_action = "Allow" - allowed_ips = ["95.43.223.55"] + allowed_ips = ["10.10.10.10"] subnets = { subnet1 = { - subnet_ref = "vnet_acfin_prod_01/sn-resources" + subnet_ref = "vnet_test/snet_private_endpoints" } } } access_policies = { managed_identity = { - managed_identity_refs = ["id_acfin_01"] + managed_identity_refs = ["id_test"] secret_permissions = "All" key_permissions = ["Get", "List"] } @@ -23,14 +23,14 @@ keyvaults = { key_permissions = "All" } object_ids = { - object_ids = ["7c265d5c-6e52-4a53-b3a9-90c663567c64"] + object_ids = ["xxxxxxxxxxx-xxxxxxxxxxxxxxx"] secret_permissions = "All" key_permissions = "All" } } secrets = { secret-skey = { - name = "SharedKey" + name = "SecretKey" value = "default" ignore_changes = true } @@ -65,3 +65,10 @@ resource_groups = { location = "northeurope" } } + +managed_identities = { + id_test = { + name = "id-test-dv-ne-01" + rg_ref = "rg_test" + } +} From aa33cc6f95bcda713c3b31c0e8ade04840e9a769 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Tue, 21 Jan 2025 17:44:20 +0200 Subject: [PATCH 4/4] Add private dns zone in resources --- src/keyvault.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/keyvault.tf b/src/keyvault.tf index 7a0d8da6..df5055e7 100644 --- a/src/keyvault.tf +++ b/src/keyvault.tf @@ -8,5 +8,6 @@ module "keyvaults" { virtual_networks = module.virtual_networks resource_groups = module.resource_groups managed_identities = module.managed_identities + private_dns_zones = module.private_dns_zones } }