azure-verified-modules について
Terraform モジュールを Azure Verified Modules の認定要件に適合させるためのガイドです。モジュール構成、プロバイダー制約、テスト、ドキュメント、変更管理を扱います。
主な機能
- 01AVM モジュールのバージョン固定参照
- 02Azure プロバイダーのバージョン規則
- 03Terraform の命名とブロック順序
- 04変数と出力の要件
- 05テストとドキュメントの基準
活用シーン
- 01Terraform モジュールの AVM 要件確認
- 02Azure モジュール変更の指針
- 03プロバイダー、テスト、文書設定の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hashicorp/ agent-skills --skill azure-verified-modulesインストール後、Claude Code で/azure-verified-modulesを入力して読み込まれたか確認します。
詳細
Azure Verified Modules(AVM)の要件
このガイドでは、Azure Verified Modules の認定に必須の要件について説明します。これらの要件により、Azure Terraform モジュール全体で一貫性、品質、保守性が確保されます。
参考資料:
目次
- モジュール間の相互参照
- Azure プロバイダーの要件
- コードスタイルの標準
- 変数の要件
- 出力の要件
- ローカル値の標準
- Terraform 構成の要件
- テストの要件
- ドキュメントの要件
- 破壊的変更と機能管理
- コントリビューションの標準
- コンプライアンスチェックリスト
モジュール間の相互参照
重要度: MUST | 要件: TFFR1
リソースモジュールまたはパターンモジュールを作成する際、モジュールの所有者は他のモジュールを相互参照してもかまいません。ただし、次の条件があります。
- モジュールは、バージョンを固定した HashiCorp Terraform レジストリの参照を使用して参照 しなければなりません
- 例:
source = "Azure/xxx/azurerm"とversion = "1.2.3"
- 例:
- モジュールは Git 参照(例:
git::https://xxx.yyy/xxx.gitまたはgithub.com/xxx/yyy)を使用 してはなりません - モジュールに AVM 以外のモジュールへの参照を含めて はなりません
Azure プロバイダーの要件
重要度: MUST | 要件: TFFR3
作成者は、次の Azure プロバイダーのみを使用 しなければなりません。
| プロバイダー | 最小バージョン | 最大バージョン |
|---|---|---|
| azapi | >= 2.0 | < 3.0 |
| azurerm | >= 4.0 | < 5.0 |
要件:
- 作成者は、Azurerm、Azapi、または両方のプロバイダーを選択してもかまいません
- プロバイダーのバージョンを適用するために、
required_providersブロックを使用 しなければなりません - 悲観的バージョン制約演算子(
~>)を使用 することが望ましいです
例:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
azapi = {
source = "Azure/azapi"
version = "~> 2.0"
}
}
}
コードスタイルの標準
小文字の snake_casing
重要度: MUST | 要件: TFNFR4
次の項目には小文字の snake_casing を使用 しなければなりません。
- ローカル値
- 変数
- 出力
- リソース(シンボリック名)
- モジュール(シンボリック名)
例:snake_casing_example
リソースとデータソースの順序
重要度: SHOULD | 要件: TFNFR6
- 依存先のリソースを先に記述 することが望ましいです
- 依存関係のあるリソースは、互いに近い位置に定義 することが望ましいです
Count と for_each の使用
重要度: MUST | 要件: TFNFR7
- 条件付きリソース作成には
countを使用します - リソースの
for_eachコレクションにはmap(xxx)またはset(xxx)を使用 しなければなりません - マップのキーまたはセットの要素は、静的なリテラルで なければなりません
例:
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"]
}
リソースおよびデータブロック内の順序
重要度: SHOULD | 要件: TFNFR8
リソース/データブロック内の順序:
-
メタ引数(先頭):
providercountfor_each
-
引数/ブロック(中間、アルファベット順):
- 必須引数
- オプション引数
- 必須のネストされたブロック
- オプションのネストされたブロック
-
メタ引数(末尾):
depends_onlifecycle(サブ順序:create_before_destroy、ignore_changes、prevent_destroy)
各セクションは空行で区切ります。
モジュールブロックの順序
重要度: SHOULD | 要件: TFNFR9
モジュールブロック内の順序:
-
先頭のメタ引数:
sourceversioncountfor_each
-
引数(アルファベット順):
- 必須引数
- オプション引数
-
末尾のメタ引数:
depends_onproviders
ライフサイクルの ignore_changes 構文
重要度: MUST | 要件: TFNFR10
ignore_changes 属性を二重引用符で囲んではなりません。
良い例:
lifecycle {
ignore_changes = [tags]
}
悪い例:
lifecycle {
ignore_changes = ["tags"]
}
条件付き作成における Null の比較
重要度: SHOULD | 要件: TFNFR11
条件付きのリソース作成が必要なパラメーターは、プランの段階で「適用後に既知」となる問題を避けるため、object 型でラップしてください。
推奨例:
variable "security_group" {
type = object({
id = string
})
default = null
}
オプションのネストされたオブジェクトに対する動的ブロック
重要度: MUST | 要件: TFNFR12
条件付きのネストされたブロックには、必ず次のパターンを使用してください。
dynamic "identity" {
for_each = <condition> ? [<some_item>] : []
content {
# block content
}
}
coalesce/try によるデフォルト値
重要度: SHOULD | 要件: TFNFR13
良い例:
coalesce(var.new_network_security_group_name, "${var.subnet_name}-nsg")
悪い例:
var.new_network_security_group_name == null ? "${var.subnet_name}-nsg" : var.new_network_security_group_name
モジュール内のプロバイダー宣言
重要度: MUST | 要件: TFNFR27
- モジュール内で
providerを宣言してはなりません(configuration_aliasesを除く) - モジュール内の
providerブロックでは、必ずaliasのみを使用してください - プロバイダー設定は、モジュールの利用者から渡すことが望ましいです
変数の要件
許可されない変数
重要度: MUST | 要件: TFNFR14
モジュールの所有者は、モジュール全体の動作を制御するために、enabled や module_depends_on のような変数を追加してはなりません。特定のリソース用のブール型機能切り替えは許容されます。
変数定義の順序
重要度: SHOULD | 要件: TFNFR15
変数は次の順序にすることが望ましいです。
- すべての必須フィールド(アルファベット順)
- すべてのオプションフィールド(アルファベット順)
変数の命名規則
重要度: SHOULD | 要件: TFNFR16
- HashiCorp の命名規則に従ってください
- 機能切り替えには、
xxx_disabledではなくxxx_enabledのような肯定形を使用することが望ましいです
説明付きの変数
重要度: SHOULD | 要件: TFNFR17
descriptionには、パラメーターの目的と想定されるデータ型を正確に記述することが望ましいです- 対象読者は開発者ではなく、モジュールの利用者です
object型には HEREDOC 形式を使用してください
型付きの変数
重要度: MUST | 要件: TFNFR18
- すべての変数に
typeを定義しなければなりません typeは可能な限り具体的にすることが望ましいです- 十分な理由がある場合に限り、
anyを使用できます - 真偽値には
string/numberではなくboolを使用してください map(any)ではなく、具体的なobjectを使用してください
機密データを含む変数
重要度: SHOULD | 要件: TFNFR19
変数の型が object で機密フィールドを含む場合、変数全体を sensitive = true にするか、機密フィールドを個別の変数に分けることが望ましいです。
コレクションの Null 以外のデフォルト値
重要度: SHOULD | 要件: TFNFR20
ループで使用するコレクション値(セット、マップ、リスト)では、nullable を false に設定することが望ましいです。スカラー値の場合、null に意味上の役割があることがあります。
デフォルトでの Null 許容を避ける
重要度: MUST | 要件: TFNFR21
Null 値を必要とする特別な意味上の理由がない限り、nullable = true は避けなければなりません。
sensitive = false を避ける
重要度: MUST | 要件: TFNFR22
sensitive = false は(これがデフォルトであるため)避けなければなりません。
機密変数のデフォルト値の条件
重要度: MUST | 要件: TFNFR23
機密性のある入力(デフォルトのパスワードなど)にデフォルト値を設定してはなりません。
非推奨の変数の扱い
重要度: MUST | 要件: TFNFR24
- 非推奨の変数は
deprecated_variables.tfに移動してください - 説明の冒頭に
DEPRECATEDを付けてください - 置き換え先の名前を明記してください
- メジャーバージョンのリリース時に整理してください
出力の要件
追加の Terraform 出力
重大度: SHOULD | 要件: TFFR2
作成者は、機密データが含まれる可能性があり、API やプロバイダーのバージョンによってスキーマが変更される可能性があるため、リソースオブジェクト全体を出力しないでください。
ベストプラクティス:
- リソースの 計算済み 属性を個別の出力として出力します(腐敗防止層パターン)。
- すでに入力値となっている値は出力しないでください(
nameを除く)。 - 機密属性には
sensitive = trueを使用します。 for_eachでデプロイされたリソースの場合、計算済み属性をマップ構造で出力します。
例:
# Single resource computed attribute
output "foo" {
description = "MyResource foo attribute"
value = azurerm_resource_myresource.foo
}
# for_each resources
output "childresource_foos" {
description = "MyResource children's foo attributes"
value = {
for key, value in azurerm_resource_mychildresource : key => value.foo
}
}
# Sensitive output
output "bar" {
description = "MyResource bar attribute"
value = azurerm_resource_myresource.bar
sensitive = true
}
機密データの出力
重大度: MUST | 要件: TFNFR29
機密データを含む出力は、sensitive = true を指定しなければなりません。
非推奨の出力の処理
重大度: MUST | 要件: TFNFR30
- 非推奨の出力を
deprecated_outputs.tfに移動します。 - 新しい出力は
outputs.tfに定義します。 - メジャーバージョンのリリース時に整理します。
ローカル値の規則
locals.tf の構成
重大度: MAY | 要件: TFNFR31
locals.tfにはlocalsブロックのみを含めることを推奨します。- 高度なシナリオでは、リソースの隣に
localsブロックを宣言してもかまいません。
ローカル値のアルファベット順での配置
重大度: MUST | 要件: TFNFR32
locals ブロック内の式はアルファベット順に並べなければなりません。
ローカル値の型の明確化
重大度: SHOULD | 要件: TFNFR33
正確な型を使用します(例:年齢には string ではなく number を使用します)。
Terraform 構成要件
Terraform バージョン要件
重大度: MUST | 要件: TFNFR25
terraform.tf の要件:
terraformブロックは 1 つだけ含めなければなりません。- 1 行目で
required_versionを定義しなければなりません。 - 最小バージョン制約を含めなければなりません。
- 最大メジャーバージョン制約を含めなければなりません。
~> #.#または>= #.#.#, < #.#.#形式を使用することを推奨します。
例:
terraform {
required_version = "~> 1.6"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
required_providers 内のプロバイダー
重大度: MUST | 要件: TFNFR26
terraformブロックにはrequired_providersブロックを含めなければなりません。- 各プロバイダーには
sourceとversionを指定しなければなりません。 - プロバイダーはアルファベット順に並べることを推奨します。
- 直接必要なプロバイダーのみを含めます。
sourceはnamespace/name形式でなければなりません。versionには最小および最大メジャーバージョン制約を含めなければなりません。~> #.#または>= #.#.#, < #.#.#形式を使用することを推奨します。
テスト要件
テストツール
重大度: MUST | 要件: TFNFR5
AVM に必要なテストツール:
- Terraform(
terraform validate/fmt/test) - terrafmt
- Checkov
- tflint(azurerm ルールセットを使用)
- Go(カスタムテストで任意)
テストプロバイダーの構成
重大度: SHOULD | 要件: TFNFR36
堅牢なテストを行うため、テストプロバイダーの構成では prevent_deletion_if_contains_resources を明示的に false に設定することを推奨します。
ドキュメント要件
モジュールドキュメントの生成
重大度: MUST | 要件: TFNFR2
- ドキュメントは Terraform Docs を使用して自動生成しなければなりません。
- モジュールのルートに
.terraform-docs.ymlファイルを配置しなければなりません。
破壊的変更と機能管理
機能トグルの使用
重大度: MUST | 要件: TFNFR34
マイナー/パッチバージョンで追加する新しいリソースには、デフォルトで作成されないようにするためのトグル変数を用意しなければなりません。
variable "create_route_table" {
type = bool
default = false
nullable = false
}
resource "azurerm_route_table" "this" {
count = var.create_route_table ? 1 : 0
# ...
}
破壊的変更の可能性を確認する
重大度: MUST | 要件: TFNFR35
慎重な対応が必要な破壊的変更:
リソースブロック:
- 条件付き作成なしで新しいリソースを追加する
- デフォルト以外の値を持つ引数を追加する
dynamicを使わずにネストされたブロックを追加するmovedブロックなしでリソース名を変更するcountをfor_eachに、またはその逆に変更する
変数/出力ブロック:
- 変数を削除または名前変更する
- 変数の
typeを変更する - 変数の
default値を変更する nullableを false に変更するsensitiveを false から true に変更するdefaultなしで変数を追加する- 出力を削除する
- 出力の
valueを変更する - 出力の
sensitive値を変更する
貢献基準
GitHub リポジトリのブランチ保護
重大度: MUST | 要件: TFNFR3
モジュールの所有者は、デフォルトブランチ(通常は main)にブランチ保護ポリシーを必ず設定してください。
- マージ前にプルリクエストを必須にする
- 直近のレビュー可能なプッシュに対する承認を必須にする
- 新しいコミットがプッシュされたときに、古いプルリクエストの承認を無効にする
- リニアな履歴を必須にする
- 強制プッシュを禁止する
- 削除を許可しない
- CODEOWNERS のレビューを必須にする
- 設定のバイパスを許可しない
- 管理者にも適用する
準拠チェックリスト
Azure Verified Modules の開発またはレビューでは、次のチェックリストを使用してください。
モジュール構造
- モジュール間の参照では、バージョンを固定したレジストリソースを使用する
- Azure プロバイダー(azurerm/azapi)のバージョンが AVM の要件を満たしている
- モジュールのルートに
.terraform-docs.ymlがある - CODEOWNERS ファイルがある
コードスタイル
- すべての名前で lower snake_casing を使用する
- リソースは依存関係が先になるように並べる
-
for_eachでは、静的キーを持つmap()またはset()を使用する - リソース/データ/モジュールのブロックは、適切な内部順序に従う
-
ignore_changesを引用符で囲まない - 条件付きのネストされたオブジェクトには動的ブロックを使用する
- デフォルト値には
coalesce()またはtry()を使用する
変数
-
enabledまたはmodule_depends_on変数がない - 変数は必須(アルファベット順)、次に任意(アルファベット順)の順に並べる
- すべての変数に明確な型を指定する(
anyは避ける) - すべての変数に説明がある
- コレクションには
nullable = falseを指定する -
sensitive = falseの宣言がない - 機密性の高い入力にデフォルト値を設定しない
- 非推奨の変数を
deprecated_variables.tfに移動する
出力
- 出力ではアンチコラプションレイヤーパターン(個別の属性)を使用する
- 機密性の高い出力には
sensitive = trueを指定する - 非推奨の出力を
deprecated_outputs.tfに移動する
Terraform の構成
-
terraform.tfにバージョン制約(~>形式)がある - すべてのプロバイダーを含む
required_providersブロックがある - モジュール内に
provider宣言がない(エイリアスを除く) - ローカル値をアルファベット順に並べる
テストと品質
- 必須のテストツールが設定されている
- 新しいリソースに機能切り替えがある
- 破壊的変更をレビューし、文書化している
概要統計
- 機能要件: 3
- 非機能要件: 34
- 要件の合計: 37
重大度別
- MUST: 21 件の要件
- SHOULD: 14 件の要件
- MAY: 2 件の要件
基準:Azure Verified Modules - Terraform Requirements