Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions modules/azure-kv/.terraform-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
formatter: "markdown" # this is required

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: |-
<!-- BEGIN_TF_DOCS -->
{{ .Content }}
<!-- END_TF_DOCS -->

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
179 changes: 111 additions & 68 deletions modules/azure-kv/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,97 @@
<!-- BEGIN_TF_DOCS -->
# Azure Key Vault Terraform Module

## Overview

This Terraform module allows you to create and manage an Azure Key Vault with support for:
- Custom access policies and/or RBAC authorization.
- Integration with Resource Group and tag inheritance.
- Soft delete protection and retention configuration.
- Detailed permissions for keys, secrets, certificates, and storage.

## Main features
- Create Key Vault with advanced security options.
- Support for access policies and RBAC.
- Integration with Azure AD groups, users, and service principals.
- Realistic configuration example.

## Complete usage 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 true, access policies will fail if any are defined.
access_policies:
- name: "Name for the Object ID"
type: "" # Leave empty if you provide the object ID directly
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 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 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 to look up the user ID
key_permissions: ["Get", "List"]
secret_permissions: ["Get", "List"]
```

## Notes
- If `enable_rbac_authorization` is true, you must not define access policies.
- You can inherit tags from the resource group with `tags_from_rg`.
- Configure retention and soft delete protection according to your security needs.

## File structure

```
.
├── main.tf
├── variables.tf
├── outputs.tf
├── README.md
├── CHANGELOG.md
└── docs/
├── header.md
└── footer.md
```

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.7.0 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | ~> 4.21.0 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | ~> 2.53.0 |
| <a name="requirement_azuread"></a> [azuread](#requirement\_azuread) | ~> 2.53.0 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >= 4.21.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | ~> 4.21.0 |
| <a name="provider_azurerm"></a> [azuread](#provider\_azuread) | ~> 2.53.0 |
| <a name="provider_azuread"></a> [azuread](#provider\_azuread) | ~> 2.53.0 |
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >= 4.21.0 |

## Modules

Expand All @@ -22,83 +102,46 @@ No modules.
| 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 |
| [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 |
|------|-------------|------|---------|:--------:|
| <a name="input_enabled_for_disk_encryption"></a> [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | Specifies whether the Key Vault is enabled for Azure Disk Encryption | `bool` | n/a | yes |
| <a name="input_name"></a> [name](#input\_name) | The name of the Key Vault | `string` | n/a | yes |
| <a name="input_purge_protection_enabled"></a> [purge\_protection\_enabled](#input\_purge\_protection\_enabled) | Specifies whether purge protection is enabled for the Key Vault | `bool` | n/a | yes |
| <a name="input_resource_group"></a> [resource\_group](#input\_resource\_group) | The name of the resource group in which the Key Vault is created | `string` | n/a | yes |
| <a name="input_sku_name"></a> [sku\_name](#input\_sku\_name) | The SKU name of the Key Vault (e.g., standard or premium) | `string` | n/a | yes |
| <a name="input_soft_delete_retention_days"></a> [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 |
| <a name="input_enable_rbac_authorization"></a> [enable_rbac_authorization](#input\_enable\_rbac\_authorization) | Set RBAC authorization for the Key Vault. Disable access policies authorization | `bool` | n/a | yes |
| <a name="input_accesss_policies"></a> [access_policies](#input\_access\_policies) | Block for access policies definition. Will fail if `enable_rbac_authorization: true` | `list(object)` | n/a | optional |
| <a name="input_accesss_policies.name"></a> [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 |
| <a name="input_accesss_policies.name.type"></a> [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 |
| <a name="input_accesss_policies.name.object_id"></a> [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 |
| <a name="input_accesss_policies.name.key_permissions"></a> [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 |
| <a name="input_accesss_policies.name.secret_permissions"></a> [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 |
| <a name="input_accesss_policies.name.certificate_permissions"></a> [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 |
| <a name="input_accesss_policies.name.storage_permissions"></a> [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 |
| <a name="input_tags_from_rg"></a> [tags\_from\_rg](#input\_tags\_from\_rg) | Enable inherit tags from resource group | `bool` | `false` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags | `map(string)` | `{}` | no |
| <a name="input_access_policies"></a> [access\_policies](#input\_access\_policies) | n/a | <pre>list(object({<br/> type = optional(string)<br/> name = optional(string)<br/> object_id = optional(string, "")<br/> key_permissions = optional(list(string))<br/> secret_permissions = optional(list(string))<br/> certificate_permissions = optional(list(string))<br/> storage_permissions = optional(list(string))<br/> }))</pre> | `[]` | no |
| <a name="input_enable_rbac_authorization"></a> [enable\_rbac\_authorization](#input\_enable\_rbac\_authorization) | n/a | `bool` | n/a | yes |
| <a name="input_enabled_for_disk_encryption"></a> [enabled\_for\_disk\_encryption](#input\_enabled\_for\_disk\_encryption) | n/a | `bool` | n/a | yes |
| <a name="input_name"></a> [name](#input\_name) | n/a | `string` | n/a | yes |
| <a name="input_purge_protection_enabled"></a> [purge\_protection\_enabled](#input\_purge\_protection\_enabled) | n/a | `bool` | n/a | yes |
| <a name="input_resource_group"></a> [resource\_group](#input\_resource\_group) | n/a | `string` | n/a | yes |
| <a name="input_sku_name"></a> [sku\_name](#input\_sku\_name) | n/a | `string` | n/a | yes |
| <a name="input_soft_delete_retention_days"></a> [soft\_delete\_retention\_days](#input\_soft\_delete\_retention\_days) | n/a | `number` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | n/a | `map(string)` | `{}` | no |
| <a name="input_tags_from_rg"></a> [tags\_from\_rg](#input\_tags\_from\_rg) | n/a | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_id"></a> [id](#output\_id) | n/a |

## Example
## Examples

```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"]
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 basic access policies and optional RBAC.

## Resources and support

- [Official Azure Key Vault documentation](https://learn.microsoft.com/en-us/azure/key-vault/)
- [Terraform reference for azurerm\_key\_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault)
- [Community support](https://github.com/prefapp/terraform-modules/discussions)

## Support

For issues, questions, or contributions related to this module, please visit the repository’s issue tracker: [https://github.com/prefapp/tfm/issues](https://github.com/prefapp/tfm/issues)
<!-- END_TF_DOCS -->
30 changes: 30 additions & 0 deletions modules/azure-kv/_examples/basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Basic example: Azure Key Vault with a simple access policy

module "azure_kv" {
source = "../../"

name = "example-kv"
resource_group = "example-rg"
sku_name = "standard"
enabled_for_disk_encryption = true
soft_delete_retention_days = 7
purge_protection_enabled = true
enable_rbac_authorization = false

access_policies = [
{
type = "User"
name = "example-user"
object_id = "00000000-0000-0000-0000-000000000000"
key_permissions = ["Get", "List"]
secret_permissions = ["Get", "List", "Set"]
certificate_permissions = []
storage_permissions = []
}
]

tags = {
environment = "dev"
application = "example"
}
}
27 changes: 27 additions & 0 deletions modules/azure-kv/_examples/basic/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Basic example values for azure-kv module

name: example-kv
resource_group: example-rg
sku_name: standard
enabled_for_disk_encryption: true
soft_delete_retention_days: 7
purge_protection_enabled: true
enable_rbac_authorization: false

access_policies:
- type: User
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example uses type: User (capitalized), while the docs elsewhere in this PR use lowercase values like group, service_principal, and user. Standardize the casing/value format across examples and docs to avoid confusing users and to ensure the example matches the documented accepted values.

Suggested change
- type: User
- type: user

Copilot uses AI. Check for mistakes.
name: example-user
object_id: 00000000-0000-0000-0000-000000000000
key_permissions:
- Get
- List
secret_permissions:
- Get
- List
- Set
certificate_permissions: []
storage_permissions: []

tags:
environment: dev
application: example
15 changes: 15 additions & 0 deletions modules/azure-kv/docs/footer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## 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 basic access policies and optional RBAC.

## Resources and support

- [Official Azure Key Vault documentation](https://learn.microsoft.com/en-us/azure/key-vault/)
- [Terraform reference for azurerm_key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault)
- [Community support](https://github.com/prefapp/terraform-modules/discussions)
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link points to prefapp/terraform-modules/discussions, while the rest of the documentation (examples/issues) points to prefapp/tfm. If the module is hosted under prefapp/tfm, align the community support link to the same repository to avoid sending users to the wrong place.

Suggested change
- [Community support](https://github.com/prefapp/terraform-modules/discussions)
- [Community support](https://github.com/prefapp/tfm/discussions)

Copilot uses AI. Check for mistakes.

## Support

For issues, questions, or contributions related to this module, please visit the repository’s issue tracker: [https://github.com/prefapp/tfm/issues](https://github.com/prefapp/tfm/issues)
Loading