From c369d0982c540e6ef381cea49a2f8a12084ee830 Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 11:07:40 +0200 Subject: [PATCH 01/13] docs(azure-kv-docs) update docs --- modules/azure-kv/.terraform-docs.yml | 48 ++++++++ modules/azure-kv/README.md | 106 +----------------- modules/azure-kv/_examples/basic/README.md | 5 + modules/azure-kv/_examples/basic/main.tf | 44 ++++++++ .../_examples/comprehensive/README.md | 6 + .../comprehensive/module.reference.hcl | 58 ++++++++++ .../comprehensive/values.reference.yaml | 43 +++++++ modules/azure-kv/docs/footer.md | 24 ++++ modules/azure-kv/docs/header.md | 68 +++++++++++ modules/azure-kv/main.tf | 6 +- modules/azure-kv/outputs.tf | 3 +- modules/azure-kv/variables.tf | 34 ++++-- 12 files changed, 325 insertions(+), 120 deletions(-) create mode 100644 modules/azure-kv/.terraform-docs.yml create mode 100644 modules/azure-kv/_examples/basic/README.md create mode 100644 modules/azure-kv/_examples/basic/main.tf create mode 100644 modules/azure-kv/_examples/comprehensive/README.md create mode 100644 modules/azure-kv/_examples/comprehensive/module.reference.hcl create mode 100644 modules/azure-kv/_examples/comprehensive/values.reference.yaml create mode 100644 modules/azure-kv/docs/footer.md create mode 100644 modules/azure-kv/docs/header.md diff --git a/modules/azure-kv/.terraform-docs.yml b/modules/azure-kv/.terraform-docs.yml new file mode 100644 index 000000000..3a69365ff --- /dev/null +++ b/modules/azure-kv/.terraform-docs.yml @@ -0,0 +1,48 @@ +formatter: "markdown" + +version: "" + +header-from: docs/header.md +footer-from: docs/footer.md + +recursive: + enabled: false + path: modules + include-main: true + +sections: + hide: [] + show: [] + +content: "" + +output: + file: "README.md" + mode: inject + template: |- + + {{ .Content }} + + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: false + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index 2df9594a8..9738c7e55 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -1,104 +1,2 @@ -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.0 | -| [azurerm](#requirement\_azurerm) | ~> 4.21.0 | -| [azurerm](#requirement\_azurerm) | ~> 2.53.0 | - -## Providers - -| Name | Version | -|------|---------| -| [azurerm](#provider\_azurerm) | ~> 4.21.0 | -| [azuread](#provider\_azuread) | ~> 2.53.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [azurerm_key_vault.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | -| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | -| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | -| [azuread_user.this](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/user) | data source | -| [azuread_group.this](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/group) | data source | -| [azuread_application.this](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/application) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | Specifies whether the Key Vault is enabled for Azure Disk Encryption | `bool` | n/a | yes | -| [name](#input\_name) | The name of the Key Vault | `string` | n/a | yes | -| [purge\_protection\_enabled](#input\_purge\_protection\_enabled) | Specifies whether purge protection is enabled for the Key Vault | `bool` | n/a | yes | -| [resource\_group](#input\_resource\_group) | The name of the resource group in which the Key Vault is created | `string` | n/a | yes | -| [sku\_name](#input\_sku\_name) | The SKU name of the Key Vault (e.g., standard or premium) | `string` | n/a | yes | -| [soft\_delete\_retention\_days](#input\_soft\_delete\_retention\_days) | The number of days that soft-deleted items are retained in the Key Vault | `number` | n/a | yes | -| [enable_rbac_authorization](#input\_enable\_rbac\_authorization) | Set RBAC authorization for the Key Vault. Disable access policies authorization | `bool` | n/a | yes | -| [access_policies](#input\_access\_policies) | Block for access policies definition. Will fail if `enable_rbac_authorization: true` | `list(object)` | n/a | optional | -| [access_policies.name](#input\_access\_policies.name) | Name for the access policy. Display name in groups and SPN, user principal name in users and custom for `object_id` | `string` | n/a | optional | -| [access_policies.name.type](#input\_access\_policies.name.type) | Entity type \[ group \| service_principal \| user \]. If we provide the `object_id` type value must be `""` | `string` | n/a | optional | -| [access_policies.name.object_id](#input\_access\_policies.name.object_id) | Object ID of the entity. If we provide an entity type value must be `""` | `string` | n/a | optional | -| [access_policies.name.key_permissions](#input\_access\_policies.name.key_permissions) | [List of key permissions](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#key_permissions) | `list(string)` | n/a | optional | -| [access_policies.name.secret_permissions](#input\_access\_policies.name.secret_permissions) | [List of secret permissions](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#secret_permissions) | `list(string)` | n/a | optional | -| [access_policies.name.certificate_permissions](#input\_access\_policies.name.certificate_permissions) | [List of certificate permissions](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#certificate_permissions) | `list(string)` | n/a | optional | -| [access_policies.name.storage_permissions](#input\_access\_policies.name.storage_permissions) | [List of storage permissions](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault#storage_permissions) | `list(string)` | n/a | optional | -| [tags\_from\_rg](#input\_tags\_from\_rg) | Enable inherit tags from resource group | `bool` | `false` | no | -| [tags](#input\_tags) | Tags | `map(string)` | `{}` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [id](#output\_id) | n/a | - -## Example - -```yaml -# kv.yaml - values: - name: "keyvault_name" - tags_from_rg: true - tags: - extra_tags: "example" - enabled_for_disk_encryption: true - resource_group: "resource_group_name" - soft_delete_retention_days: 7 - purge_protection_enabled: true - sku_name: "standard" - enable_rbac_authorization: false # If RBAC is set to true access policies will fail if there are any defined. - access_policies: - - name: "Name for the Object ID" - type: "" # Leave empty value if you provide directly the object ID - object_id: "1a9590f4-27d3-4abf-9e30-5be7f46959bb" - key_permissions: ["Get", "List"] - secret_permissions: ["Get", "List"] - certificate_permissions: ["Get", "List"] - storage_permissions: ["Get", "List"] - - name: "Group display name" - type: "group" - object_id: "" # Leave empty value if you want to look up the group ID - key_permissions: ["Get", "List"] - secret_permissions: ["Get", "List"] - certificate_permissions: ["Get", "List"] - storage_permissions: ["Get", "List"] - - name: "Service Principal display name" - type: "service_principal" - object_id: "" # Leave empty value if you want to look up the service principal ID - key_permissions: ["Get", "List"] - secret_permissions: ["Get", "List"] - certificate_permissions: ["Get", "List"] - storage_permissions: ["Get", "List"] - - name: "User principal name" - type: "user" - object_id: "" # Leave empty value if you want to look up the user ID - key_permissions: ["Get", "List"] - secret_permissions: ["Get", "List"] - certificate_permissions: ["Get", "List"] - storage_permissions: ["Get", "List"] - -``` + + diff --git a/modules/azure-kv/_examples/basic/README.md b/modules/azure-kv/_examples/basic/README.md new file mode 100644 index 000000000..101f19936 --- /dev/null +++ b/modules/azure-kv/_examples/basic/README.md @@ -0,0 +1,5 @@ +# Basic example — `azure-kv` + +Creates one Key Vault with **Azure RBAC** enabled and **no access policies**. + +Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 letters and numbers). Configure the `azurerm` and `azuread` providers (subscription and authentication) before `terraform apply`. diff --git a/modules/azure-kv/_examples/basic/main.tf b/modules/azure-kv/_examples/basic/main.tf new file mode 100644 index 000000000..e337a9b47 --- /dev/null +++ b/modules/azure-kv/_examples/basic/main.tf @@ -0,0 +1,44 @@ +# Replace resource_group with an existing RG name and name with a globally unique vault name (3–24 alphanumeric). + +terraform { + required_version = ">= 1.7.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 4.21.0" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 2.53.0" + } + } +} + +provider "azurerm" { + features {} +} + +provider "azuread" {} + +module "key_vault" { + source = "../.." + + name = "kv-basicex0001" + resource_group = "example-rg" + enabled_for_disk_encryption = false + soft_delete_retention_days = 7 + purge_protection_enabled = false + sku_name = "standard" + enable_rbac_authorization = true + access_policies = [] + + tags_from_rg = false + tags = { + example = "basic" + } +} + +output "vault_uri" { + value = module.key_vault.vault_uri +} diff --git a/modules/azure-kv/_examples/comprehensive/README.md b/modules/azure-kv/_examples/comprehensive/README.md new file mode 100644 index 000000000..8b6be7081 --- /dev/null +++ b/modules/azure-kv/_examples/comprehensive/README.md @@ -0,0 +1,6 @@ +# Comprehensive reference — `azure-kv` + +- [`module.reference.hcl`](./module.reference.hcl) — Illustrative module block with **access policies** (direct `object_id` and Azure AD lookups by type/name). +- [`values.reference.yaml`](./values.reference.yaml) — Same inputs as YAML for `yamldecode` or external tooling. + +These samples are documentation-oriented: replace names, IDs, and resource group with values valid in your tenant before apply. Keep large samples here instead of embedding them in the terraform-docs `README.md` body. diff --git a/modules/azure-kv/_examples/comprehensive/module.reference.hcl b/modules/azure-kv/_examples/comprehensive/module.reference.hcl new file mode 100644 index 000000000..3f2880cbc --- /dev/null +++ b/modules/azure-kv/_examples/comprehensive/module.reference.hcl @@ -0,0 +1,58 @@ +# Same intent as values.reference.yaml, expressed as a module block. +# enable_rbac_authorization must be false when access_policies is non-empty. + +module "key_vault" { + source = "../.." + + name = "kv-myapp-ref01" + resource_group = "my-resource-group" + enabled_for_disk_encryption = true + soft_delete_retention_days = 7 + purge_protection_enabled = true + sku_name = "standard" + enable_rbac_authorization = false + + tags_from_rg = true + tags = { + extra = "from-module" + } + + access_policies = [ + { + name = "Name for the Object ID" + type = "" + object_id = "1a9590f4-27d3-4abf-9e30-5be7f46959bb" + key_permissions = ["Get", "List"] + secret_permissions = ["Get", "List"] + certificate_permissions = ["Get", "List"] + storage_permissions = ["Get", "List"] + }, + { + name = "Group display name" + type = "group" + object_id = "" + key_permissions = ["Get", "List"] + secret_permissions = ["Get", "List"] + certificate_permissions = ["Get", "List"] + storage_permissions = ["Get", "List"] + }, + { + name = "Service Principal display name" + type = "service_principal" + object_id = "" + key_permissions = ["Get", "List"] + secret_permissions = ["Get", "List"] + certificate_permissions = ["Get", "List"] + storage_permissions = ["Get", "List"] + }, + { + name = "user@contoso.com" + type = "user" + object_id = "" + key_permissions = ["Get", "List"] + secret_permissions = ["Get", "List"] + certificate_permissions = ["Get", "List"] + storage_permissions = ["Get", "List"] + }, + ] +} diff --git a/modules/azure-kv/_examples/comprehensive/values.reference.yaml b/modules/azure-kv/_examples/comprehensive/values.reference.yaml new file mode 100644 index 000000000..f5b6eb3da --- /dev/null +++ b/modules/azure-kv/_examples/comprehensive/values.reference.yaml @@ -0,0 +1,43 @@ +# Reference values for azure-kv (e.g. Helm / wrapper YAML). +# If enable_rbac_authorization is true, access_policies must be []. + +values: + name: "kv-myapp-ref01" + tags_from_rg: true + tags: + extra: "from-yaml" + enabled_for_disk_encryption: true + resource_group: "my-resource-group" + soft_delete_retention_days: 7 + purge_protection_enabled: true + sku_name: "standard" + enable_rbac_authorization: false + access_policies: + - name: "Name for the Object ID" + type: "" + object_id: "1a9590f4-27d3-4abf-9e30-5be7f46959bb" + key_permissions: ["Get", "List"] + secret_permissions: ["Get", "List"] + certificate_permissions: ["Get", "List"] + storage_permissions: ["Get", "List"] + - name: "Group display name" + type: "group" + object_id: "" + key_permissions: ["Get", "List"] + secret_permissions: ["Get", "List"] + certificate_permissions: ["Get", "List"] + storage_permissions: ["Get", "List"] + - name: "Service Principal display name" + type: "service_principal" + object_id: "" + key_permissions: ["Get", "List"] + secret_permissions: ["Get", "List"] + certificate_permissions: ["Get", "List"] + storage_permissions: ["Get", "List"] + - name: "user@contoso.com" + type: "user" + object_id: "" + key_permissions: ["Get", "List"] + secret_permissions: ["Get", "List"] + certificate_permissions: ["Get", "List"] + storage_permissions: ["Get", "List"] diff --git a/modules/azure-kv/docs/footer.md b/modules/azure-kv/docs/footer.md new file mode 100644 index 000000000..e12d47fdf --- /dev/null +++ b/modules/azure-kv/docs/footer.md @@ -0,0 +1,24 @@ +## Examples + +For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples): + +- [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/basic) — Key Vault with **RBAC** enabled and no access policies; set an existing resource group and a globally unique vault name (see folder README). +- [comprehensive](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/comprehensive) — Reference HCL and YAML for **access policies** (object ID and Azure AD lookups) and tag options (`values.reference.yaml`; see folder README). + +## Resources + +Terraform **azurerm** links below use **4.21.0** as a baseline aligned with the minimum `azurerm` version in `versions.tf` (`>= 4.21.0`). **azuread** links use **2.53.0**, aligned with `versions.tf` (`~> 2.53.0`). Pinned versions in your workspace appear in the **Providers** table after regenerating this README with `terraform-docs .`, as described in [README.md generation](https://github.com/prefapp/tfm/blob/main/CONTRIBUTING.md#5-readmemd-generation). + +- **Azure Key Vault**: [https://learn.microsoft.com/azure/key-vault/](https://learn.microsoft.com/azure/key-vault/) +- **azurerm_key_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault) +- **azurerm_client_config** (data source): [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/client_config](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/client_config) +- **azurerm_resource_group** (data source): [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/resource_group) +- **azuread_user** (data source): [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/user](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/user) +- **azuread_group** (data source): [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/group](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/group) +- **azuread_service_principal** (data source): [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/service_principal](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/service_principal) +- **Terraform AzureRM provider**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0) +- **Terraform AzureAD provider**: [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0) + +## Support + +For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues). diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md new file mode 100644 index 000000000..66d9339bd --- /dev/null +++ b/modules/azure-kv/docs/header.md @@ -0,0 +1,68 @@ +# Azure Key Vault Terraform module (`azure-kv`) + +## Overview + +This module creates an **Azure Key Vault** (`azurerm_key_vault`) in an **existing resource group**. It supports **Azure RBAC** on the vault or **classic access policies**, optional resolution of principals via **Azure AD** data sources (user, group, or service principal by display or UPN), tag merge from the resource group, and lifecycle **preconditions** so access policies are not mixed with RBAC when that combination is invalid. + +The module does **not** create the resource group, private endpoints, or key/secret/certificate resources; consumers add those separately if needed. + +## Key features + +- **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. +- **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. +- **Access policies**: Optional list with `type` (`user`, `group`, `service_principal`) and `name` for lookup, or `object_id` with empty `type` for a direct principal. +- **Outputs**: Resource `id`, `name`, `vault_uri`, `location`, `resource_group_name`, and `tenant_id` for wiring apps, DNS, or role assignments. + +## Prerequisites + +- Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. +- **Key Vault name** must be **globally unique**, 3–24 characters, alphanumeric. +- **Azure AD provider** is required by the module declaration; configure `provider "azuread"` in the root module even when using RBAC-only (no access policy lookups). +- For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). + +## Basic usage + +Point `source` at this module and set required inputs. Use **RBAC** (`enable_rbac_authorization = true`) with an empty `access_policies` list for the smallest surface, or **access policies** with `enable_rbac_authorization = false`. + +### Minimal example (RBAC on the vault) + +```hcl +module "key_vault" { + source = "git::https://github.com/prefapp/tfm.git//modules/azure-kv?ref=" + + name = "kv-myapp-dev01" + resource_group = "my-resource-group" + enabled_for_disk_encryption = false + soft_delete_retention_days = 7 + purge_protection_enabled = false + sku_name = "standard" + enable_rbac_authorization = true + access_policies = [] + + tags_from_rg = false + tags = { + environment = "dev" + } +} +``` + +Assign **Key Vault data plane** or **management** roles at scope vault or above when using RBAC; this module does not create role assignments. + +## File structure + +``` +. +├── CHANGELOG.md +├── main.tf +├── outputs.tf +├── variables.tf +├── versions.tf +├── docs +│ ├── footer.md +│ └── header.md +├── _examples +│ ├── basic +│ └── comprehensive +├── README.md +└── .terraform-docs.yml +``` diff --git a/modules/azure-kv/main.tf b/modules/azure-kv/main.tf index 2bb2aa317..b240707f6 100644 --- a/modules/azure-kv/main.tf +++ b/modules/azure-kv/main.tf @@ -1,8 +1,8 @@ # DATA SECTION -## https://registry.terraform.io/providers/hashicorp/azurerm/3.113.0/docs/data-sources/client_config +## https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/client_config data "azurerm_client_config" "current" {} -## https://registry.terraform.io/providers/hashicorp/azurerm/3.113.0/docs/data-sources/resource_group +## https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/resource_group data "azurerm_resource_group" "this" { name = var.resource_group } @@ -57,7 +57,7 @@ locals { # RESOURCES SECTION -## https://registry.terraform.io/providers/hashicorp/azurerm/3.113.0/docs/resources/key_vault +## https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault resource "azurerm_key_vault" "this" { name = var.name location = data.azurerm_resource_group.this.location diff --git a/modules/azure-kv/outputs.tf b/modules/azure-kv/outputs.tf index c06b777b0..3dc3367dc 100644 --- a/modules/azure-kv/outputs.tf +++ b/modules/azure-kv/outputs.tf @@ -1,3 +1,4 @@ output "id" { - value = azurerm_key_vault.this.id + description = "The Azure resource ID of the Key Vault." + value = azurerm_key_vault.this.id } diff --git a/modules/azure-kv/variables.tf b/modules/azure-kv/variables.tf index ae4bcbc8d..ef840bab6 100644 --- a/modules/azure-kv/variables.tf +++ b/modules/azure-kv/variables.tf @@ -1,39 +1,48 @@ variable "name" { - type = string + type = string + description = "Globally unique name of the Key Vault (3–24 alphanumeric characters)." } variable "enabled_for_disk_encryption" { - type = bool + type = bool + description = "Whether the vault can be used for Azure Disk Encryption." } variable "soft_delete_retention_days" { - type = number + type = number + description = "Number of days soft-deleted items are retained before permanent deletion." } variable "purge_protection_enabled" { - type = bool + type = bool + description = "Whether purge protection is enabled (prevents permanent purge of soft-deleted vaults and objects when true)." } variable "sku_name" { - type = string + type = string + description = "SKU for the vault (`standard` or `premium`)." } variable "resource_group" { - type = string + type = string + description = "Name of the existing resource group where the Key Vault will be created." } variable "enable_rbac_authorization" { - type = bool + type = bool + description = "When true, use Azure RBAC for data plane access; access policies must be empty (see precondition in main.tf)." } variable "tags_from_rg" { - type = bool - default = false + type = bool + description = "When true, merge tags from the resource group with `tags`." + default = false } variable "tags" { - type = map(string) - default = {} + type = map(string) + description = "Tags applied to the Key Vault (merged with resource group tags when `tags_from_rg` is true)." + default = {} } variable "access_policies" { @@ -46,5 +55,6 @@ variable "access_policies" { certificate_permissions = optional(list(string)) storage_permissions = optional(list(string)) })) - default = [] + description = "Legacy access policies when `enable_rbac_authorization` is false. Each entry needs a unique `name`. Provide `object_id` or set `type` to `user` / `group` / `service_principal` with `name` for lookup." + default = [] } From 8f7d501d3742221493abed6f0f215ccd191151b6 Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 11:19:54 +0200 Subject: [PATCH 02/13] docs(azure-kv-docs) update docs --- modules/azure-kv/_examples/basic/main.tf | 16 ++++++++-------- .../azure-kv/_examples/comprehensive/README.md | 2 +- modules/azure-kv/docs/header.md | 2 +- modules/azure-kv/variables.tf | 10 ++++++++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/modules/azure-kv/_examples/basic/main.tf b/modules/azure-kv/_examples/basic/main.tf index e337a9b47..5769d39d3 100644 --- a/modules/azure-kv/_examples/basic/main.tf +++ b/modules/azure-kv/_examples/basic/main.tf @@ -24,14 +24,14 @@ provider "azuread" {} module "key_vault" { source = "../.." - name = "kv-basicex0001" - resource_group = "example-rg" - enabled_for_disk_encryption = false - soft_delete_retention_days = 7 - purge_protection_enabled = false - sku_name = "standard" - enable_rbac_authorization = true - access_policies = [] + name = "kv-basicex0001" + resource_group = "example-rg" + enabled_for_disk_encryption = false + soft_delete_retention_days = 7 + purge_protection_enabled = false + sku_name = "standard" + enable_rbac_authorization = true + access_policies = [] tags_from_rg = false tags = { diff --git a/modules/azure-kv/_examples/comprehensive/README.md b/modules/azure-kv/_examples/comprehensive/README.md index 8b6be7081..e7c365d74 100644 --- a/modules/azure-kv/_examples/comprehensive/README.md +++ b/modules/azure-kv/_examples/comprehensive/README.md @@ -3,4 +3,4 @@ - [`module.reference.hcl`](./module.reference.hcl) — Illustrative module block with **access policies** (direct `object_id` and Azure AD lookups by type/name). - [`values.reference.yaml`](./values.reference.yaml) — Same inputs as YAML for `yamldecode` or external tooling. -These samples are documentation-oriented: replace names, IDs, and resource group with values valid in your tenant before apply. Keep large samples here instead of embedding them in the terraform-docs `README.md` body. +These samples are documentation-oriented: replace names, IDs, and resource group with values valid in your tenant before apply. Each `access_policies` entry needs a **distinct, non-empty `name`** (the module uses it as an internal map key). Keep large samples here instead of embedding them in the terraform-docs `README.md` body. diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md index 66d9339bd..971a6406a 100644 --- a/modules/azure-kv/docs/header.md +++ b/modules/azure-kv/docs/header.md @@ -10,7 +10,7 @@ The module does **not** create the resource group, private endpoints, or key/sec - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. -- **Access policies**: Optional list with `type` (`user`, `group`, `service_principal`) and `name` for lookup, or `object_id` with empty `type` for a direct principal. +- **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. - **Outputs**: Resource `id`, `name`, `vault_uri`, `location`, `resource_group_name`, and `tenant_id` for wiring apps, DNS, or role assignments. ## Prerequisites diff --git a/modules/azure-kv/variables.tf b/modules/azure-kv/variables.tf index ef840bab6..b665725b3 100644 --- a/modules/azure-kv/variables.tf +++ b/modules/azure-kv/variables.tf @@ -48,13 +48,19 @@ variable "tags" { variable "access_policies" { type = list(object({ type = optional(string) - name = optional(string) + name = string object_id = optional(string, "") key_permissions = optional(list(string)) secret_permissions = optional(list(string)) certificate_permissions = optional(list(string)) storage_permissions = optional(list(string)) })) - description = "Legacy access policies when `enable_rbac_authorization` is false. Each entry needs a unique `name`. Provide `object_id` or set `type` to `user` / `group` / `service_principal` with `name` for lookup." + description = <<-EOT + Legacy access policies when `enable_rbac_authorization` is false. + + Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time. + + Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. + EOT default = [] } From 35c46edc5289b704bc935bb9eb0bcb36fe8ef73d Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 11:21:32 +0200 Subject: [PATCH 03/13] docs(azure-kv-docs) update docs --- modules/azure-kv/README.md | 146 ++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 1 deletion(-) diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index 9738c7e55..b1ba1788d 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -1,2 +1,146 @@ - +# Azure Key Vault Terraform module (`azure-kv`) + +## Overview + +This module creates an **Azure Key Vault** (`azurerm_key_vault`) in an **existing resource group**. It supports **Azure RBAC** on the vault or **classic access policies**, optional resolution of principals via **Azure AD** data sources (user, group, or service principal by display or UPN), tag merge from the resource group, and lifecycle **preconditions** so access policies are not mixed with RBAC when that combination is invalid. + +The module does **not** create the resource group, private endpoints, or key/secret/certificate resources; consumers add those separately if needed. + +## Key features + +- **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. +- **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. +- **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. +- **Outputs**: Resource `id`, `name`, `vault_uri`, `location`, `resource_group_name`, and `tenant_id` for wiring apps, DNS, or role assignments. + +## Prerequisites + +- Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. +- **Key Vault name** must be **globally unique**, 3–24 characters, alphanumeric. +- **Azure AD provider** is required by the module declaration; configure `provider "azuread"` in the root module even when using RBAC-only (no access policy lookups). +- For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). + +## Basic usage + +Point `source` at this module and set required inputs. Use **RBAC** (`enable_rbac_authorization = true`) with an empty `access_policies` list for the smallest surface, or **access policies** with `enable_rbac_authorization = false`. + +### Minimal example (RBAC on the vault) + +```hcl +module "key_vault" { + source = "git::https://github.com/prefapp/tfm.git//modules/azure-kv?ref=" + + name = "kv-myapp-dev01" + resource_group = "my-resource-group" + enabled_for_disk_encryption = false + soft_delete_retention_days = 7 + purge_protection_enabled = false + sku_name = "standard" + enable_rbac_authorization = true + access_policies = [] + + tags_from_rg = false + tags = { + environment = "dev" + } +} +``` + +Assign **Key Vault data plane** or **management** roles at scope vault or above when using RBAC; this module does not create role assignments. + +## File structure + +``` +. +├── CHANGELOG.md +├── main.tf +├── outputs.tf +├── variables.tf +├── versions.tf +├── docs +│ ├── footer.md +│ └── header.md +├── _examples +│ ├── basic +│ └── comprehensive +├── README.md +└── .terraform-docs.yml +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.7.0 | +| [azuread](#requirement\_azuread) | ~> 2.53.0 | +| [azurerm](#requirement\_azurerm) | >= 4.21.0 | + +## Providers + +| Name | Version | +|------|---------| +| [azuread](#provider\_azuread) | 2.53.1 | +| [azurerm](#provider\_azurerm) | 4.67.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [azurerm_key_vault.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | +| [azuread_group.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/group) | data source | +| [azuread_service_principal.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/service_principal) | data source | +| [azuread_user.this](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/data-sources/user) | data source | +| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | +| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [access\_policies](#input\_access\_policies) | Legacy access policies when `enable_rbac_authorization` is false.

Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time.

Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. |
list(object({
type = optional(string)
name = string
object_id = optional(string, "")
key_permissions = optional(list(string))
secret_permissions = optional(list(string))
certificate_permissions = optional(list(string))
storage_permissions = optional(list(string))
}))
| `[]` | no | +| [enable\_rbac\_authorization](#input\_enable\_rbac\_authorization) | When true, use Azure RBAC for data plane access; access policies must be empty (see precondition in main.tf). | `bool` | n/a | yes | +| [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | Whether the vault can be used for Azure Disk Encryption. | `bool` | n/a | yes | +| [name](#input\_name) | Globally unique name of the Key Vault (3–24 alphanumeric characters). | `string` | n/a | yes | +| [purge\_protection\_enabled](#input\_purge\_protection\_enabled) | Whether purge protection is enabled (prevents permanent purge of soft-deleted vaults and objects when true). | `bool` | n/a | yes | +| [resource\_group](#input\_resource\_group) | Name of the existing resource group where the Key Vault will be created. | `string` | n/a | yes | +| [sku\_name](#input\_sku\_name) | SKU for the vault (`standard` or `premium`). | `string` | n/a | yes | +| [soft\_delete\_retention\_days](#input\_soft\_delete\_retention\_days) | Number of days soft-deleted items are retained before permanent deletion. | `number` | n/a | yes | +| [tags](#input\_tags) | Tags applied to the Key Vault (merged with resource group tags when `tags_from_rg` is true). | `map(string)` | `{}` | no | +| [tags\_from\_rg](#input\_tags\_from\_rg) | When true, merge tags from the resource group with `tags`. | `bool` | `false` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [id](#output\_id) | The Azure resource ID of the Key Vault. | + +## Examples + +For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples): + +- [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/basic) — Key Vault with **RBAC** enabled and no access policies; set an existing resource group and a globally unique vault name (see folder README). +- [comprehensive](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/comprehensive) — Reference HCL and YAML for **access policies** (object ID and Azure AD lookups) and tag options (`values.reference.yaml`; see folder README). + +## Resources + +Terraform **azurerm** links below use **4.21.0** as a baseline aligned with the minimum `azurerm` version in `versions.tf` (`>= 4.21.0`). **azuread** links use **2.53.0**, aligned with `versions.tf` (`~> 2.53.0`). Pinned versions in your workspace appear in the **Providers** table after regenerating this README with `terraform-docs .`, as described in [README.md generation](https://github.com/prefapp/tfm/blob/main/CONTRIBUTING.md#5-readmemd-generation). + +- **Azure Key Vault**: [https://learn.microsoft.com/azure/key-vault/](https://learn.microsoft.com/azure/key-vault/) +- **azurerm\_key\_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault) +- **azurerm\_client\_config** (data source): [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/client_config](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/client_config) +- **azurerm\_resource\_group** (data source): [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/data-sources/resource_group) +- **azuread\_user** (data source): [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/user](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/user) +- **azuread\_group** (data source): [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/group](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/group) +- **azuread\_service\_principal** (data source): [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/service_principal](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0/docs/data-sources/service_principal) +- **Terraform AzureRM provider**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0) +- **Terraform AzureAD provider**: [https://registry.terraform.io/providers/hashicorp/azuread/2.53.0](https://registry.terraform.io/providers/hashicorp/azuread/2.53.0) + +## Support + +For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues). + \ No newline at end of file From dc69b10750f48bf6e08fbf813253e9e638c77001 Mon Sep 17 00:00:00 2001 From: pablosanchezpaz <76182461+pablosanchezpaz@users.noreply.github.com> Date: Mon, 4 May 2026 11:27:31 +0200 Subject: [PATCH 04/13] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- modules/azure-kv/docs/header.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md index 971a6406a..b44a219ab 100644 --- a/modules/azure-kv/docs/header.md +++ b/modules/azure-kv/docs/header.md @@ -1,4 +1,4 @@ -# Azure Key Vault Terraform module (`azure-kv`) +# **Azure Key Vault Terraform Module** (`azure-kv`) ## Overview From 6bbfa014eb779e65a069dff5afbf3c0d740cd54e Mon Sep 17 00:00:00 2001 From: pablosanchezpaz <76182461+pablosanchezpaz@users.noreply.github.com> Date: Mon, 4 May 2026 11:27:52 +0200 Subject: [PATCH 05/13] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- modules/azure-kv/docs/header.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md index b44a219ab..8925e67b7 100644 --- a/modules/azure-kv/docs/header.md +++ b/modules/azure-kv/docs/header.md @@ -11,7 +11,7 @@ The module does **not** create the resource group, private endpoints, or key/sec - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. - **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. -- **Outputs**: Resource `id`, `name`, `vault_uri`, `location`, `resource_group_name`, and `tenant_id` for wiring apps, DNS, or role assignments. +- **Outputs**: Resource `id` for wiring downstream dependencies that need the Key Vault resource identifier. ## Prerequisites From 8b8f93c7bde0a9f5b1bbb24978799575f06ba89a Mon Sep 17 00:00:00 2001 From: pablosanchezpaz <76182461+pablosanchezpaz@users.noreply.github.com> Date: Mon, 4 May 2026 11:28:09 +0200 Subject: [PATCH 06/13] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- modules/azure-kv/docs/header.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md index 8925e67b7..ac2cd7e24 100644 --- a/modules/azure-kv/docs/header.md +++ b/modules/azure-kv/docs/header.md @@ -16,7 +16,7 @@ The module does **not** create the resource group, private endpoints, or key/sec ## Prerequisites - Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. -- **Key Vault name** must be **globally unique**, 3–24 characters, alphanumeric. +- **Key Vault name** must be **globally unique**, 3–24 characters, and use only letters, numbers, and hyphens. - **Azure AD provider** is required by the module declaration; configure `provider "azuread"` in the root module even when using RBAC-only (no access policy lookups). - For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). From 068dd8313ab1093f15bb2c968059d3db3c11c693 Mon Sep 17 00:00:00 2001 From: pablosanchezpaz <76182461+pablosanchezpaz@users.noreply.github.com> Date: Mon, 4 May 2026 11:28:26 +0200 Subject: [PATCH 07/13] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- modules/azure-kv/.terraform-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure-kv/.terraform-docs.yml b/modules/azure-kv/.terraform-docs.yml index 3a69365ff..051fe55c5 100644 --- a/modules/azure-kv/.terraform-docs.yml +++ b/modules/azure-kv/.terraform-docs.yml @@ -36,7 +36,7 @@ settings: anchor: true color: true default: true - description: false + description: true escape: true hide-empty: false html: true From 51271bde797a273b4fdea25eea63f2a8a0cae493 Mon Sep 17 00:00:00 2001 From: pablosanchezpaz <76182461+pablosanchezpaz@users.noreply.github.com> Date: Mon, 4 May 2026 11:28:57 +0200 Subject: [PATCH 08/13] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- modules/azure-kv/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/azure-kv/variables.tf b/modules/azure-kv/variables.tf index b665725b3..fdff3207a 100644 --- a/modules/azure-kv/variables.tf +++ b/modules/azure-kv/variables.tf @@ -1,6 +1,6 @@ variable "name" { type = string - description = "Globally unique name of the Key Vault (3–24 alphanumeric characters)." + description = "Globally unique name of the Key Vault (3–24 characters; letters, numbers, and hyphens)." } variable "enabled_for_disk_encryption" { From 4d4956dda656f950c55c9d62f599445e314e6ca7 Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 11:29:20 +0200 Subject: [PATCH 09/13] docs(azure-kv-docs) update docs --- modules/azure-kv/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index b1ba1788d..5b751be9d 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -1,5 +1,5 @@ -# Azure Key Vault Terraform module (`azure-kv`) +# **Azure Key Vault Terraform Module** (`azure-kv`) ## Overview @@ -12,12 +12,12 @@ The module does **not** create the resource group, private endpoints, or key/sec - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. - **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. -- **Outputs**: Resource `id`, `name`, `vault_uri`, `location`, `resource_group_name`, and `tenant_id` for wiring apps, DNS, or role assignments. +- **Outputs**: Resource `id` for wiring downstream dependencies that need the Key Vault resource identifier. ## Prerequisites - Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. -- **Key Vault name** must be **globally unique**, 3–24 characters, alphanumeric. +- **Key Vault name** must be **globally unique**, 3–24 characters, and use only letters, numbers, and hyphens. - **Azure AD provider** is required by the module declaration; configure `provider "azuread"` in the root module even when using RBAC-only (no access policy lookups). - For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). @@ -105,7 +105,7 @@ No modules. | [access\_policies](#input\_access\_policies) | Legacy access policies when `enable_rbac_authorization` is false.

Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time.

Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. |
list(object({
type = optional(string)
name = string
object_id = optional(string, "")
key_permissions = optional(list(string))
secret_permissions = optional(list(string))
certificate_permissions = optional(list(string))
storage_permissions = optional(list(string))
}))
| `[]` | no | | [enable\_rbac\_authorization](#input\_enable\_rbac\_authorization) | When true, use Azure RBAC for data plane access; access policies must be empty (see precondition in main.tf). | `bool` | n/a | yes | | [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | Whether the vault can be used for Azure Disk Encryption. | `bool` | n/a | yes | -| [name](#input\_name) | Globally unique name of the Key Vault (3–24 alphanumeric characters). | `string` | n/a | yes | +| [name](#input\_name) | Globally unique name of the Key Vault (3–24 characters; letters, numbers, and hyphens). | `string` | n/a | yes | | [purge\_protection\_enabled](#input\_purge\_protection\_enabled) | Whether purge protection is enabled (prevents permanent purge of soft-deleted vaults and objects when true). | `bool` | n/a | yes | | [resource\_group](#input\_resource\_group) | Name of the existing resource group where the Key Vault will be created. | `string` | n/a | yes | | [sku\_name](#input\_sku\_name) | SKU for the vault (`standard` or `premium`). | `string` | n/a | yes | From 3ea2132e1f04ed6f861f1f8609da838d2e2165fd Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 11:54:09 +0200 Subject: [PATCH 10/13] docs(azure-kv-docs) update docs --- modules/azure-kv/README.md | 53 ++++++++++++++++++---- modules/azure-kv/_examples/basic/README.md | 2 +- modules/azure-kv/_examples/basic/main.tf | 7 +-- modules/azure-kv/docs/header.md | 53 ++++++++++++++++++---- 4 files changed, 93 insertions(+), 22 deletions(-) diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index 5b751be9d..f90b946c7 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -1,31 +1,31 @@ -# **Azure Key Vault Terraform Module** (`azure-kv`) +# **Azure Key Vault Terraform Module** ## Overview -This module creates an **Azure Key Vault** (`azurerm_key_vault`) in an **existing resource group**. It supports **Azure RBAC** on the vault or **classic access policies**, optional resolution of principals via **Azure AD** data sources (user, group, or service principal by display or UPN), tag merge from the resource group, and lifecycle **preconditions** so access policies are not mixed with RBAC when that combination is invalid. +This module creates an **Azure Key Vault** (`azurerm_key_vault`) in an **existing resource group**. It supports **Azure RBAC** on the vault or **classic access policies**, optional resolution of principals via **Azure AD** data sources (user, group, or service principal by display name or UPN), tag merge from the resource group, and lifecycle **preconditions** so access policies are not mixed with RBAC when that combination is invalid. -The module does **not** create the resource group, private endpoints, or key/secret/certificate resources; consumers add those separately if needed. +The module does **not** create the resource group, private endpoints, or key/secret/certificate resources; consumers add those separately if needed. Use it when you want a small, opinionated wrapper around `azurerm_key_vault` with consistent tagging and access-policy wiring for teams that still use vault access policies or are migrating toward vault-level RBAC. -## Key features +## Key Features - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. - **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. -- **Outputs**: Resource `id` for wiring downstream dependencies that need the Key Vault resource identifier. +- **Outputs**: Exposes the Key Vault **`id`** for downstream resources, role assignments, or references that need the Azure resource identifier. ## Prerequisites - Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. - **Key Vault name** must be **globally unique**, 3–24 characters, and use only letters, numbers, and hyphens. -- **Azure AD provider** is required by the module declaration; configure `provider "azuread"` in the root module even when using RBAC-only (no access policy lookups). +- The module lists **`azuread`** in `required_providers`; your root module must declare **`azuread`** (and usually `provider "azuread" {}`) so Terraform can initialize the tree. **Azure AD data sources** in this module run only for access policies that use `type` `user`, `group`, or `service_principal`; entries that only set `object_id` (with empty `type`) do not perform those lookups. - For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). -## Basic usage +## Basic Usage Point `source` at this module and set required inputs. Use **RBAC** (`enable_rbac_authorization = true`) with an empty `access_policies` list for the smallest surface, or **access policies** with `enable_rbac_authorization = false`. -### Minimal example (RBAC on the vault) +### Example (RBAC on the vault) ```hcl module "key_vault" { @@ -47,7 +47,42 @@ module "key_vault" { } ``` -Assign **Key Vault data plane** or **management** roles at scope vault or above when using RBAC; this module does not create role assignments. +Assign **Key Vault data plane** or **management** roles at vault scope or above when using RBAC; this module does not create role assignments. + +### Example (access policies, RBAC disabled) + +```hcl +module "key_vault_access_policies" { + source = "git::https://github.com/prefapp/tfm.git//modules/azure-kv?ref=" + + name = "kv-myapp-legacy01" + resource_group = "my-resource-group" + enabled_for_disk_encryption = false + soft_delete_retention_days = 7 + purge_protection_enabled = false + sku_name = "standard" + enable_rbac_authorization = false + + tags_from_rg = false + tags = { + environment = "dev" + } + + access_policies = [ + { + name = "workload-spn" + type = "" + object_id = "11111111-1111-1111-1111-111111111111" + key_permissions = ["Get", "List"] + secret_permissions = ["Get", "List"] + certificate_permissions = ["Get", "List"] + storage_permissions = ["Get", "List"] + }, + ] +} +``` + +Replace `object_id` with a real principal in your tenant. To resolve principals by **UPN / display name** instead, set `type` to `user`, `group`, or `service_principal` and set `name` accordingly; that path uses the Azure AD provider data sources. ## File structure diff --git a/modules/azure-kv/_examples/basic/README.md b/modules/azure-kv/_examples/basic/README.md index 101f19936..32c814f58 100644 --- a/modules/azure-kv/_examples/basic/README.md +++ b/modules/azure-kv/_examples/basic/README.md @@ -2,4 +2,4 @@ Creates one Key Vault with **Azure RBAC** enabled and **no access policies**. -Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 letters and numbers). Configure the `azurerm` and `azuread` providers (subscription and authentication) before `terraform apply`. +Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 characters: letters, numbers, and hyphens). Configure the **`azurerm`** provider for your subscription. This module also declares **`azuread`** in `required_providers`; include `provider "azuread" {}` in the example root so `terraform init` succeeds (no Azure AD lookups run for this RBAC-only configuration). diff --git a/modules/azure-kv/_examples/basic/main.tf b/modules/azure-kv/_examples/basic/main.tf index 5769d39d3..d66b62d07 100644 --- a/modules/azure-kv/_examples/basic/main.tf +++ b/modules/azure-kv/_examples/basic/main.tf @@ -1,4 +1,4 @@ -# Replace resource_group with an existing RG name and name with a globally unique vault name (3–24 alphanumeric). +# Replace resource_group with an existing RG name and name with a globally unique vault name (3–24 characters: letters, numbers, hyphens). terraform { required_version = ">= 1.7.0" @@ -39,6 +39,7 @@ module "key_vault" { } } -output "vault_uri" { - value = module.key_vault.vault_uri +output "key_vault_id" { + description = "Azure resource ID of the Key Vault (only output exposed by this module)." + value = module.key_vault.id } diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md index ac2cd7e24..8355cd55b 100644 --- a/modules/azure-kv/docs/header.md +++ b/modules/azure-kv/docs/header.md @@ -1,30 +1,30 @@ -# **Azure Key Vault Terraform Module** (`azure-kv`) +# **Azure Key Vault Terraform Module** ## Overview -This module creates an **Azure Key Vault** (`azurerm_key_vault`) in an **existing resource group**. It supports **Azure RBAC** on the vault or **classic access policies**, optional resolution of principals via **Azure AD** data sources (user, group, or service principal by display or UPN), tag merge from the resource group, and lifecycle **preconditions** so access policies are not mixed with RBAC when that combination is invalid. +This module creates an **Azure Key Vault** (`azurerm_key_vault`) in an **existing resource group**. It supports **Azure RBAC** on the vault or **classic access policies**, optional resolution of principals via **Azure AD** data sources (user, group, or service principal by display name or UPN), tag merge from the resource group, and lifecycle **preconditions** so access policies are not mixed with RBAC when that combination is invalid. -The module does **not** create the resource group, private endpoints, or key/secret/certificate resources; consumers add those separately if needed. +The module does **not** create the resource group, private endpoints, or key/secret/certificate resources; consumers add those separately if needed. Use it when you want a small, opinionated wrapper around `azurerm_key_vault` with consistent tagging and access-policy wiring for teams that still use vault access policies or are migrating toward vault-level RBAC. -## Key features +## Key Features - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. - **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. -- **Outputs**: Resource `id` for wiring downstream dependencies that need the Key Vault resource identifier. +- **Outputs**: Exposes the Key Vault **`id`** for downstream resources, role assignments, or references that need the Azure resource identifier. ## Prerequisites - Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. - **Key Vault name** must be **globally unique**, 3–24 characters, and use only letters, numbers, and hyphens. -- **Azure AD provider** is required by the module declaration; configure `provider "azuread"` in the root module even when using RBAC-only (no access policy lookups). +- The module lists **`azuread`** in `required_providers`; your root module must declare **`azuread`** (and usually `provider "azuread" {}`) so Terraform can initialize the tree. **Azure AD data sources** in this module run only for access policies that use `type` `user`, `group`, or `service_principal`; entries that only set `object_id` (with empty `type`) do not perform those lookups. - For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). -## Basic usage +## Basic Usage Point `source` at this module and set required inputs. Use **RBAC** (`enable_rbac_authorization = true`) with an empty `access_policies` list for the smallest surface, or **access policies** with `enable_rbac_authorization = false`. -### Minimal example (RBAC on the vault) +### Example (RBAC on the vault) ```hcl module "key_vault" { @@ -46,7 +46,42 @@ module "key_vault" { } ``` -Assign **Key Vault data plane** or **management** roles at scope vault or above when using RBAC; this module does not create role assignments. +Assign **Key Vault data plane** or **management** roles at vault scope or above when using RBAC; this module does not create role assignments. + +### Example (access policies, RBAC disabled) + +```hcl +module "key_vault_access_policies" { + source = "git::https://github.com/prefapp/tfm.git//modules/azure-kv?ref=" + + name = "kv-myapp-legacy01" + resource_group = "my-resource-group" + enabled_for_disk_encryption = false + soft_delete_retention_days = 7 + purge_protection_enabled = false + sku_name = "standard" + enable_rbac_authorization = false + + tags_from_rg = false + tags = { + environment = "dev" + } + + access_policies = [ + { + name = "workload-spn" + type = "" + object_id = "11111111-1111-1111-1111-111111111111" + key_permissions = ["Get", "List"] + secret_permissions = ["Get", "List"] + certificate_permissions = ["Get", "List"] + storage_permissions = ["Get", "List"] + }, + ] +} +``` + +Replace `object_id` with a real principal in your tenant. To resolve principals by **UPN / display name** instead, set `type` to `user`, `group`, or `service_principal` and set `name` accordingly; that path uses the Azure AD provider data sources. ## File structure From c4721e30a7fa0833f0a6786f67ec90d24df6c79b Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 12:01:51 +0200 Subject: [PATCH 11/13] docs(azure-kv-docs) update docs --- modules/azure-kv/README.md | 2 +- modules/azure-kv/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index f90b946c7..fb75781ae 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -137,7 +137,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [access\_policies](#input\_access\_policies) | Legacy access policies when `enable_rbac_authorization` is false.

Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time.

Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. |
list(object({
type = optional(string)
name = string
object_id = optional(string, "")
key_permissions = optional(list(string))
secret_permissions = optional(list(string))
certificate_permissions = optional(list(string))
storage_permissions = optional(list(string))
}))
| `[]` | no | +| [access\_policies](#input\_access\_policies) | Legacy access policies when `enable_rbac_authorization` is false.

Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time.

Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. |
list(object({
type = optional(string)
name = optional(string)
object_id = optional(string, "")
key_permissions = optional(list(string))
secret_permissions = optional(list(string))
certificate_permissions = optional(list(string))
storage_permissions = optional(list(string))
}))
| `[]` | no | | [enable\_rbac\_authorization](#input\_enable\_rbac\_authorization) | When true, use Azure RBAC for data plane access; access policies must be empty (see precondition in main.tf). | `bool` | n/a | yes | | [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | Whether the vault can be used for Azure Disk Encryption. | `bool` | n/a | yes | | [name](#input\_name) | Globally unique name of the Key Vault (3–24 characters; letters, numbers, and hyphens). | `string` | n/a | yes | diff --git a/modules/azure-kv/variables.tf b/modules/azure-kv/variables.tf index fdff3207a..5d65b255c 100644 --- a/modules/azure-kv/variables.tf +++ b/modules/azure-kv/variables.tf @@ -48,7 +48,7 @@ variable "tags" { variable "access_policies" { type = list(object({ type = optional(string) - name = string + name = optional(string) object_id = optional(string, "") key_permissions = optional(list(string)) secret_permissions = optional(list(string)) From ab0c0e03707f955b0440597cc0ba5efe788a0f2a Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 12:05:15 +0200 Subject: [PATCH 12/13] docs(azure-kv-docs) update docs --- modules/azure-kv/README.md | 6 +++--- modules/azure-kv/_examples/basic/README.md | 2 +- modules/azure-kv/_examples/comprehensive/README.md | 2 +- modules/azure-kv/docs/header.md | 4 ++-- modules/azure-kv/variables.tf | 4 +++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index fb75781ae..cfd474e96 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -11,14 +11,14 @@ The module does **not** create the resource group, private endpoints, or key/sec - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. -- **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. +- **Access policies**: Optional list; object fields remain optional in the type for compatibility. For real policies, use a **non-empty, unique `name`** per row (`main.tf` uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. - **Outputs**: Exposes the Key Vault **`id`** for downstream resources, role assignments, or references that need the Azure resource identifier. ## Prerequisites - Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. - **Key Vault name** must be **globally unique**, 3–24 characters, and use only letters, numbers, and hyphens. -- The module lists **`azuread`** in `required_providers`; your root module must declare **`azuread`** (and usually `provider "azuread" {}`) so Terraform can initialize the tree. **Azure AD data sources** in this module run only for access policies that use `type` `user`, `group`, or `service_principal`; entries that only set `object_id` (with empty `type`) do not perform those lookups. +- The module depends on **hashicorp/azuread** and **hashicorp/azurerm** (`versions.tf`); Terraform installs the required provider versions. Configure **`provider "azuread"`** with working credentials **only when** access policies use `type` `user`, `group`, or `service_principal` so the lookup data sources can run. For RBAC-only setups or policies that only set `object_id` (empty `type`), those data sources are not instantiated and you do not need Azure AD authentication for this module alone. - For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). ## Basic Usage @@ -137,7 +137,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [access\_policies](#input\_access\_policies) | Legacy access policies when `enable_rbac_authorization` is false.

Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time.

Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. |
list(object({
type = optional(string)
name = optional(string)
object_id = optional(string, "")
key_permissions = optional(list(string))
secret_permissions = optional(list(string))
certificate_permissions = optional(list(string))
storage_permissions = optional(list(string))
}))
| `[]` | no | +| [access\_policies](#input\_access\_policies) | Legacy access policies when `enable_rbac_authorization` is false.

Attributes stay **optional** in the object type for backward compatibility with existing callers. When you pass entries, each one should still set a **non-empty, unique `name`**: `main.tf` uses `name` as the `for_each` key and to index Azure AD data sources, so missing or duplicate names typically surface as errors at plan time.

Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup.

If `type` is empty and `object_id` is empty, the module cannot resolve an object ID and that row is skipped for the vault access policy block (no explicit error). |
list(object({
type = optional(string)
name = optional(string)
object_id = optional(string, "")
key_permissions = optional(list(string))
secret_permissions = optional(list(string))
certificate_permissions = optional(list(string))
storage_permissions = optional(list(string))
}))
| `[]` | no | | [enable\_rbac\_authorization](#input\_enable\_rbac\_authorization) | When true, use Azure RBAC for data plane access; access policies must be empty (see precondition in main.tf). | `bool` | n/a | yes | | [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | Whether the vault can be used for Azure Disk Encryption. | `bool` | n/a | yes | | [name](#input\_name) | Globally unique name of the Key Vault (3–24 characters; letters, numbers, and hyphens). | `string` | n/a | yes | diff --git a/modules/azure-kv/_examples/basic/README.md b/modules/azure-kv/_examples/basic/README.md index 32c814f58..fa283ece3 100644 --- a/modules/azure-kv/_examples/basic/README.md +++ b/modules/azure-kv/_examples/basic/README.md @@ -2,4 +2,4 @@ Creates one Key Vault with **Azure RBAC** enabled and **no access policies**. -Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 characters: letters, numbers, and hyphens). Configure the **`azurerm`** provider for your subscription. This module also declares **`azuread`** in `required_providers`; include `provider "azuread" {}` in the example root so `terraform init` succeeds (no Azure AD lookups run for this RBAC-only configuration). +Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 characters: letters, numbers, and hyphens). Configure the **`azurerm`** provider for your subscription. The module declares **`azuread`** in `required_providers`; Terraform resolves provider packages automatically—this RBAC-only stack does not evaluate Azure AD data sources. If you add access policies with `type` set to `user`, `group`, or `service_principal`, configure the **Azure AD** provider so those lookups can authenticate. diff --git a/modules/azure-kv/_examples/comprehensive/README.md b/modules/azure-kv/_examples/comprehensive/README.md index e7c365d74..3da8db3f7 100644 --- a/modules/azure-kv/_examples/comprehensive/README.md +++ b/modules/azure-kv/_examples/comprehensive/README.md @@ -3,4 +3,4 @@ - [`module.reference.hcl`](./module.reference.hcl) — Illustrative module block with **access policies** (direct `object_id` and Azure AD lookups by type/name). - [`values.reference.yaml`](./values.reference.yaml) — Same inputs as YAML for `yamldecode` or external tooling. -These samples are documentation-oriented: replace names, IDs, and resource group with values valid in your tenant before apply. Each `access_policies` entry needs a **distinct, non-empty `name`** (the module uses it as an internal map key). Keep large samples here instead of embedding them in the terraform-docs `README.md` body. +These samples are documentation-oriented: replace names, IDs, and resource group with values valid in your tenant before apply. The variable type keeps `name` optional for compatibility, but each sample row uses a **distinct, non-empty `name`** because `main.tf` keys lookups by `name`. Keep large samples here instead of embedding them in the terraform-docs `README.md` body. diff --git a/modules/azure-kv/docs/header.md b/modules/azure-kv/docs/header.md index 8355cd55b..51fafe104 100644 --- a/modules/azure-kv/docs/header.md +++ b/modules/azure-kv/docs/header.md @@ -10,14 +10,14 @@ The module does **not** create the resource group, private endpoints, or key/sec - **Key Vault**: SKU, soft delete retention, purge protection, disk encryption integration, tenant binding. - **Authorization model**: `enable_rbac_authorization` toggles between RBAC and access policies; when RBAC is enabled, `access_policies` must be empty. -- **Access policies**: Optional list; each entry must set a **non-empty, unique `name`** (the module uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. +- **Access policies**: Optional list; object fields remain optional in the type for compatibility. For real policies, use a **non-empty, unique `name`** per row (`main.tf` uses it as a `for_each` key and for Azure AD lookups). Use `type` (`user`, `group`, `service_principal`) plus `name`, or `object_id` with empty `type` for a direct principal. - **Outputs**: Exposes the Key Vault **`id`** for downstream resources, role assignments, or references that need the Azure resource identifier. ## Prerequisites - Existing **resource group** (`resource_group`); the module reads it for location and optional tag inheritance. - **Key Vault name** must be **globally unique**, 3–24 characters, and use only letters, numbers, and hyphens. -- The module lists **`azuread`** in `required_providers`; your root module must declare **`azuread`** (and usually `provider "azuread" {}`) so Terraform can initialize the tree. **Azure AD data sources** in this module run only for access policies that use `type` `user`, `group`, or `service_principal`; entries that only set `object_id` (with empty `type`) do not perform those lookups. +- The module depends on **hashicorp/azuread** and **hashicorp/azurerm** (`versions.tf`); Terraform installs the required provider versions. Configure **`provider "azuread"`** with working credentials **only when** access policies use `type` `user`, `group`, or `service_principal` so the lookup data sources can run. For RBAC-only setups or policies that only set `object_id` (empty `type`), those data sources are not instantiated and you do not need Azure AD authentication for this module alone. - For **access policies** with principal lookup, principals must exist and be resolvable (correct UPN, group display name, or service principal display name). ## Basic Usage diff --git a/modules/azure-kv/variables.tf b/modules/azure-kv/variables.tf index 5d65b255c..7c2825d2b 100644 --- a/modules/azure-kv/variables.tf +++ b/modules/azure-kv/variables.tf @@ -58,9 +58,11 @@ variable "access_policies" { description = <<-EOT Legacy access policies when `enable_rbac_authorization` is false. - Each object must include a **non-empty, unique `name`**: the module uses `name` as the map key in `for_each` and to index Azure AD data sources, so duplicate or empty values will fail at plan time. + Attributes stay **optional** in the object type for backward compatibility with existing callers. When you pass entries, each one should still set a **non-empty, unique `name`**: `main.tf` uses `name` as the `for_each` key and to index Azure AD data sources, so missing or duplicate names typically surface as errors at plan time. Provide `object_id` (with `type` unset/empty) or set `type` to `user`, `group`, or `service_principal` and use `name` as UPN, group display name, or service principal display name for lookup. + + If `type` is empty and `object_id` is empty, the module cannot resolve an object ID and that row is skipped for the vault access policy block (no explicit error). EOT default = [] } From 30199a2581acd206bed3cc0e0ee68c1380b93839 Mon Sep 17 00:00:00 2001 From: "pablo.sanchez" Date: Mon, 4 May 2026 13:19:22 +0200 Subject: [PATCH 13/13] docs(azure-kv-docs) update docs --- modules/azure-kv/.terraform-docs.yml | 2 +- modules/azure-kv/README.md | 8 ++++---- modules/azure-kv/_examples/basic/README.md | 2 +- modules/azure-kv/_examples/basic/main.tf | 6 ------ modules/azure-kv/docs/footer.md | 4 ++-- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/modules/azure-kv/.terraform-docs.yml b/modules/azure-kv/.terraform-docs.yml index 051fe55c5..199016010 100644 --- a/modules/azure-kv/.terraform-docs.yml +++ b/modules/azure-kv/.terraform-docs.yml @@ -41,7 +41,7 @@ settings: hide-empty: false html: true indent: 2 - lockfile: true + lockfile: false read-comments: true required: true sensitive: true diff --git a/modules/azure-kv/README.md b/modules/azure-kv/README.md index cfd474e96..3ddb53955 100644 --- a/modules/azure-kv/README.md +++ b/modules/azure-kv/README.md @@ -115,8 +115,8 @@ Replace `object_id` with a real principal in your tenant. To resolve principals | Name | Version | |------|---------| -| [azuread](#provider\_azuread) | 2.53.1 | -| [azurerm](#provider\_azurerm) | 4.67.0 | +| [azuread](#provider\_azuread) | ~> 2.53.0 | +| [azurerm](#provider\_azurerm) | >= 4.21.0 | ## Modules @@ -161,9 +161,9 @@ For detailed examples, refer to the [module examples](https://github.com/prefapp - [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/basic) — Key Vault with **RBAC** enabled and no access policies; set an existing resource group and a globally unique vault name (see folder README). - [comprehensive](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/comprehensive) — Reference HCL and YAML for **access policies** (object ID and Azure AD lookups) and tag options (`values.reference.yaml`; see folder README). -## Resources +## Remote resources -Terraform **azurerm** links below use **4.21.0** as a baseline aligned with the minimum `azurerm` version in `versions.tf` (`>= 4.21.0`). **azuread** links use **2.53.0**, aligned with `versions.tf` (`~> 2.53.0`). Pinned versions in your workspace appear in the **Providers** table after regenerating this README with `terraform-docs .`, as described in [README.md generation](https://github.com/prefapp/tfm/blob/main/CONTRIBUTING.md#5-readmemd-generation). +Terraform **azurerm** links below use **4.21.0** as a baseline aligned with the minimum `azurerm` version in `versions.tf` (`>= 4.21.0`). **azuread** links use **2.53.0**, aligned with `versions.tf` (`~> 2.53.0`). Provider version constraints for your workspace appear in the **Providers** table above after regenerating this README with `terraform-docs .`, as described in [README.md generation](https://github.com/prefapp/tfm/blob/main/CONTRIBUTING.md#5-readmemd-generation). - **Azure Key Vault**: [https://learn.microsoft.com/azure/key-vault/](https://learn.microsoft.com/azure/key-vault/) - **azurerm\_key\_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault) diff --git a/modules/azure-kv/_examples/basic/README.md b/modules/azure-kv/_examples/basic/README.md index fa283ece3..03a91625b 100644 --- a/modules/azure-kv/_examples/basic/README.md +++ b/modules/azure-kv/_examples/basic/README.md @@ -2,4 +2,4 @@ Creates one Key Vault with **Azure RBAC** enabled and **no access policies**. -Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 characters: letters, numbers, and hyphens). Configure the **`azurerm`** provider for your subscription. The module declares **`azuread`** in `required_providers`; Terraform resolves provider packages automatically—this RBAC-only stack does not evaluate Azure AD data sources. If you add access policies with `type` set to `user`, `group`, or `service_principal`, configure the **Azure AD** provider so those lookups can authenticate. +Set `resource_group` to an existing resource group and `name` to a **globally unique** vault name (3–24 characters: letters, numbers, and hyphens). This root only configures **`azurerm`** for your subscription; the child module still lists **`azuread`** in its `required_providers` (Terraform installs it), but this RBAC-only path does not evaluate Azure AD data sources. If you extend the stack with access policies using `type` `user`, `group`, or `service_principal`, add **`provider "azuread"`** (and credentials) so those lookups can run. diff --git a/modules/azure-kv/_examples/basic/main.tf b/modules/azure-kv/_examples/basic/main.tf index d66b62d07..2c00ea780 100644 --- a/modules/azure-kv/_examples/basic/main.tf +++ b/modules/azure-kv/_examples/basic/main.tf @@ -8,10 +8,6 @@ terraform { source = "hashicorp/azurerm" version = ">= 4.21.0" } - azuread = { - source = "hashicorp/azuread" - version = "~> 2.53.0" - } } } @@ -19,8 +15,6 @@ provider "azurerm" { features {} } -provider "azuread" {} - module "key_vault" { source = "../.." diff --git a/modules/azure-kv/docs/footer.md b/modules/azure-kv/docs/footer.md index e12d47fdf..615f200b6 100644 --- a/modules/azure-kv/docs/footer.md +++ b/modules/azure-kv/docs/footer.md @@ -5,9 +5,9 @@ For detailed examples, refer to the [module examples](https://github.com/prefapp - [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/basic) — Key Vault with **RBAC** enabled and no access policies; set an existing resource group and a globally unique vault name (see folder README). - [comprehensive](https://github.com/prefapp/tfm/tree/main/modules/azure-kv/_examples/comprehensive) — Reference HCL and YAML for **access policies** (object ID and Azure AD lookups) and tag options (`values.reference.yaml`; see folder README). -## Resources +## Remote resources -Terraform **azurerm** links below use **4.21.0** as a baseline aligned with the minimum `azurerm` version in `versions.tf` (`>= 4.21.0`). **azuread** links use **2.53.0**, aligned with `versions.tf` (`~> 2.53.0`). Pinned versions in your workspace appear in the **Providers** table after regenerating this README with `terraform-docs .`, as described in [README.md generation](https://github.com/prefapp/tfm/blob/main/CONTRIBUTING.md#5-readmemd-generation). +Terraform **azurerm** links below use **4.21.0** as a baseline aligned with the minimum `azurerm` version in `versions.tf` (`>= 4.21.0`). **azuread** links use **2.53.0**, aligned with `versions.tf` (`~> 2.53.0`). Provider version constraints for your workspace appear in the **Providers** table above after regenerating this README with `terraform-docs .`, as described in [README.md generation](https://github.com/prefapp/tfm/blob/main/CONTRIBUTING.md#5-readmemd-generation). - **Azure Key Vault**: [https://learn.microsoft.com/azure/key-vault/](https://learn.microsoft.com/azure/key-vault/) - **azurerm_key_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.21.0/docs/resources/key_vault)