Skip to content
Development
Skill

/azure-verified-modules

Azure Verified Modules (AVM) requirements and best practices for developing certified Azure Terraform modules. Use when creating or reviewing Azure modules that need AVM certification.

From plugin
agent-skills
91020 skills

Claude Code

$ npx -y skills add hashicorp/agent-skills --skill azure-verified-modules --agent claude-code

SKILL.md

azure-verified-modules.SKILL.md
name: azure-verified-modules
description: Azure Verified Modules (AVM) requirements and best practices for developing certified Azure Terraform modules. Use when creating or reviewing Azure modules that need AVM certification.
metadata:
  lifecycle-status: active

Azure Verified Modules (AVM) Requirements

This guide covers the mandatory requirements for Azure Verified Modules certification. These requirements ensure consistency, quality, and maintainability across Azure Terraform modules.

**References:**

  • [Azure Verified Modules](https://azure.github.io/Azure-Verified-Modules/)
  • [AVM Module Specifications](https://azure.github.io/Azure-Verified-Modules/specs/module-specs/)

Table of Contents

  • [Module Cross-Referencing](#module-cross-referencing)
  • [Azure Provider Requirements](#azure-provider-requirements)
  • [Code Style Standards](#code-style-standards)
  • [Variable Requirements](#variable-requirements)
  • [Output Requirements](#output-requirements)
  • [Local Values Standards](#local-values-standards)
  • [Terraform Configuration Requirements](#terraform-configuration-requirements)
  • [Testing Requirements](#testing-requirements)
  • [Documentation Requirements](#documentation-requirements)
  • [Breaking Changes & Feature Management](#breaking-changes--feature-management)
  • [Contribution Standards](#contribution-standards)
  • [Compliance Checklist](#compliance-checklist)

---

Module Cross-Referencing

**Severity:** MUST | **Requirement:** TFFR1

When building Resource or Pattern modules, module owners **MAY** cross-reference other modules. However:

  • Modules **MUST** be referenced using HashiCorp Terraform registry reference to a pinned version
  • Example: `source = "Azure/xxx/azurerm"` with `version = "1.2.3"`
  • Modules **MUST NOT** use git references (e.g., `git::https://xxx.yyy/xxx.git` or `github.com/xxx/yyy`)
  • Modules **MUST NOT** contain references to non-AVM modules

---

Azure Provider Requirements

**Severity:** MUST | **Requirement:** TFFR3

Authors **MUST** only use the following Azure providers:

| Provider | Min Version | Max Version | |----------|-------------|-------------| | azapi | >= 2.0 | < 3.0 | | azurerm | >= 4.0 | < 5.0 |

**Requirements:**

  • Authors **MAY** select either Azurerm, Azapi, or both providers
  • **MUST** use `required_providers` block to enforce provider versions
  • **SHOULD** use pessimistic version constraint operator (`~>`)

**Example:**

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
    azapi = {
      source  = "Azure/azapi"
      version = "~> 2.0"
    }
  }
}

---

Code Style Standards

Lower snake_casing

**Severity:** MUST | **Requirement:** TFNFR4

**MUST** use lower snake_casing for:

  • Locals
  • Variables
  • Outputs
  • Resources (symbolic names)
  • Modules (symbolic names)

Example: `snake_casing_example`

Resource & Data Source Ordering

**Severity:** SHOULD | **Requirement:** TFNFR6

  • Resources that are depended on **SHOULD** come first
  • Resources with dependencies **SHOULD** be defined close to each other

Count & for_each Usage

**Severity:** MUST | **Requirement:** TFNFR7

  • Use `count` for conditional resource creation
  • **MUST** use `map(xxx)` or `set(xxx)` as resource's `for_each` collection
  • The map's key or set's element **MUST** be static literals

**Example:**

resource "azurerm_subnet" "pair" {
  for_each             = var.subnet_map  # map(string)
  name                 = "${each.value}-pair"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/24"]
}

Resource & Data Block Internal Ordering

**Severity:** SHOULD | **Requirement:** TFNFR8

**Order within resource/data blocks:**

1. **Meta-arguments (top)**:

  • `provider`
  • `count`
  • `for_each`

2. **Arguments/blocks (middle, alphabetical)**:

  • Required arguments
  • Optional arguments
  • Required nested blocks
  • Optional nested blocks

3. **Meta-arguments (bottom)**:

  • `depends_on`
  • `lifecycle` (with sub-order: `create_before_destroy`, `ignore_changes`, `prevent_destroy`)

Separate sections with blank lines.

Module Block Ordering

**Severity:** SHOULD | **Requirement:** TFNFR9

**Order within module blocks:**

1. **Top meta-arguments**:

  • `source`
  • `version`
  • `count`
  • `for_each`

2. **Arguments (alphabetical)**:

  • Required arguments
  • Optional arguments

3. **Bottom meta-arguments**:

  • `depends_on`
  • `providers`

Lifecycle ignore_changes Syntax

**Severity:** MUST | **Requirement:** TFNFR10

The `ignore_changes` attribute **MUST NOT** be enclosed in double quotes.

**Good:**

lifecycle {
  ignore_changes = [tags]
}

**Bad:**

lifecycle {
  ignore_changes = ["tags"]
}

Null Comparison for Conditional Creation

**Severity:** SHOULD | **Requirement:** TFNFR11

For parameters requiring conditional resource creation, wrap with `object` type to avoid "known after apply" issues during plan stage.

**Recommended:**

variable "security_group" {
  type = object({
    id = string
  })
  default = null
}

Dynamic Blocks for Optional Nested Objects

**Severity:** MUST | **Requirement:** TFNFR12

Nested blocks under conditions **MUST** use this pattern:

dynamic "identity" {
  for_each = <condition> ? [<some_item>] : []

  content {
    # block content
  }
}

Default Values with coalesce/try

**Severity:** SHOULD | **Requirement:** TFNFR13

**Good:**

coalesce(var.new_network_security_group_name, "${var.subnet_name}-nsg")

**Bad:**

var.new_network_security_group_name == null ? "${var.subnet_name}-nsg" : var.new_network_security_group_name

Provider Declarations in Modules

**Severity:** MUST | **Requirement:** TFNFR27

  • `provider` **MUST NOT** be declared in modules (except for `configuration_a
Read more
@hashicorp
Ships withagent-skills

HashiCorp Agent Skills for Terraform and Packer. See SKILLS.md for the complete catalog and lifecycle status of each Skill. Legal note: Your use of a third-party MCP client or LLM is subject solely to that provider's terms.

Stars on GitHub

Momentum

stars in total
910
Star history of hashicorp/agent-skills on GitHub, a chart by star-history.com

Other skills on agent-skills.

aws-ami-builder

aws-ami-builder

Build Amazon Machine Images (AMIs) with Packer using the amazon-ebs builder. Use when creating custom AMIs for EC2 instances.

push-to-registry

push-to-registry

Push Packer build metadata to HCP Packer registry for tracking and managing image lifecycle. Use when integrating Packer builds…

windows-builder

windows-builder

Build Windows images with Packer using WinRM communicator and PowerShell provisioners. Use when creating Windows AMIs, Azure…

provider-actions

provider-actions

Implement Terraform Provider actions using the Plugin Framework. Use when developing imperative operations that execute at…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about azure-verified-modules.

Which coding agents can use azure-verified-modules?
azure-verified-modules installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.