HCLでポリシーが書けるようになった!!ということで、概要をまとめてみました。 本記事は実際の操作や画面などの紹介がメインとなっています。
Terraform Policyの概要についてはこちら
※本記事は 2026年8月時点の情報です。Terraform Policy は現在ベータ(beta)機能であり、本番環境での利用は非推奨とされています。最新情報は必ず公式ドキュメントを確認してください。
※本機能はHCP Terraform有償版の利用が前提となっています。Pay-as-Goもありますのでこれを機にぜひHCP Terraformをご検討ください!
この記事で紹介していること
HCLポリシーを作って実際にHCP Terraform上でRunを実行しtfpolicyに評価させてみました。
全体の流れ
- 事前準備(Beta特有の準備事項とtfpolicy CLIインストール)
- ポリシーを書く(
.policy.hcl) - ローカルでテスト(
tfpolicy validate/tfpolicy test) - VCSリポジトリに配置してpush
- HCP Terraformでポリシーセットを作成
- Runを実行して評価結果を見る
- わざと違反させてみる
- apply後の値を検証する(post-apply)
事前準備
★ベータ版特有の準備事項
現在Terraform Policy は Terraform v1.16以上が必須ですが、2026年8月時点でv1.16以上は正式版(GA)が存在せず、プレリリース版のみです。
そのためベータ版特有の事前準備が存在します。
手順1. Orgで「Show Terraform pre-releases」を有効化する
Workspaceの設定にあるバージョン選択からプレリリース版を一覧に出すため、まず以下の設定をします。
- HCP Terraform の Organization Settings → General を開く
- Show Terraform pre-releases にチェックを入れて保存
これをオンにしないと、次のステップでv1.16系がプルダウンに出てきません。
手順2. 対象WorkspaceのTerraformバージョンを 1.16.x(alphaYYYYMMDD) に変更する
- 対象ワークスペース(例:
tfpolicy-test)→ Settings → General を開く -
Terraform Version のプルダウンから、alphaビルド(例:
1.16.0-alpha20260715)を選択して保存
補足:1.16以降はぱっと見だとプルダウンのリスト内に出てこないので、検索窓で1.16...と入力して選択肢を表示させます。またalpha版を選ぶことに注意してください。
手順3. 対象Workspaceに個別タグ(例:Non-Pro)を付与する
ポリシーセットは「全体/プロジェクト/ワークスペース/タグ」のスコープで適用先を絞れます。
検証対象だけにポリシーを効かせたいので、対象ワークスペースにタグを付けておき、後でポリシーセットをそのタグに付与する方式が管理しやすいです。
- ワークスペース → Settings → Tags(またはOverviewのTags)
-
Non-ProやBetaなど、識別しやすいタグを作成して付与
★GA後も必須となるであろう準備事項
ローカルに 最新版のTerraform CLIとtfpolicy CLI を用意する
ローカルでポリシーを書いてテストするために、tfpolicy CLI をインストールします(Terraform CLIとは別物で個別インストールが必要)。
tfpolicy test などを実行するtfpolicy CLIには Terraform v1.16以上 が必要なので、最新のTerraform CLIにアップグレードする必要があります。
ただし前述した通りv1.16以上は現在GAではないため、本番環境の操作に使用しない端末にインストールすることを推奨します。
# tfpolicy CLI(linux_amd64の例)
cd /tmp
curl -LO https://releases.hashicorp.com/tfpolicy/0.1.0/tfpolicy_0.1.0_linux_amd64.zip
unzip -o tfpolicy_0.1.0_linux_amd64.zip
sudo mv tfpolicy /usr/local/bin/
tfpolicy version # => 0.1.0
STEP1. ポリシーを書く(.policy.hcl)
今回使ったポリシーは以下です。ファイルは .policy.hcl 拡張子で policies/ 配下に置きます。
① EBS暗号化
# policies/ebs_encryption.policy.hcl
resource_policy "aws_ebs_volume" "encryption_required" {
enforcement_level = "mandatory_overridable"
enforce {
condition = attrs.encrypted == true
error_message = "すべてのEBSボリュームは暗号化が必須です。"
}
}
② 全AWSリソースにタグ必須
# policies/require_tags.policy.hcl
resource_policy "aws_*" "require_tags" {
enforcement_level = "mandatory_overridable"
enforce {
# tags が null でも落ちないようにする(後述)
condition = core::try(core::length(attrs.tags), 0) > 0
error_message = "すべてのAWSリソースに最低1つのタグを付与してください。"
}
}
STEP2. ローカルでテストする(tfpolicy validate / test)
HCP TerraformでPolicy setを作る前に、手元で構文チェックとテストをします。
テストは .policytest.hcl に書きます。
# tests/ebs_encryption.policytest.hcl
policytest {
targets = ["../policies/ebs_encryption.policy.hcl"]
}
resource "aws_ebs_volume" "pass" {
attrs = { availability_zone = "ap-northeast-3a", size = 1, encrypted = true }
}
resource "aws_ebs_volume" "fail_not_encrypted" {
expect_failure = true
attrs = { availability_zone = "ap-northeast-3a", size = 1, encrypted = false }
}
cd /path/to/repo
tfpolicy validate --policies=policies/
tfpolicy test --policies=policies/ --tests=tests/
まずはポリシーの構文チェックでvalidateを実行します。
次にtestを実行します。testの場合、--policies / --tests フラグはほぼ必須です(基本的にはルートフォルダもしくはtestやpoliciesフォルダの親フォルダなどで実行するため。付けないと "No policies found" になります)。
全ケースが pass になればOKです。
STEP3. VCSリポジトリに配置してpushする
ポリシーとテスト、そして検証対象のTerraform構成を、同じGitリポジトリにまとめます。
ディレクトリ構成例は以下です。
.
├── policies/
│ ├── ebs_encryption.policy.hcl
│ ├── require_tags.policy.hcl
│ └── post_apply_ebs.policy.hcl
├── tests/
├── ebs_encryption.policytest.hcl
└── require_tags.policytest.hcl
STEP4. HCP Terraformでポリシーセットを作成する
ここからはHCP Terraformを操作し、ポリシーセットを作成してVCSのリポジトリとリンクさせます。
参考:VCS setup for Terraform policy
-
HCP Terraform にサインインし、Organization を開く
-
Settings → Policy Sets を開く
-
Create a new policy set をクリック
-
Policy framework に Terraform policy を選択
-
設定を入力:
-
Name:ポリシーセット名(例:
tfpolicy-01) - Scope of policies:手順3で付けたタグ(例:beta) に紐づけて適用先を絞る
-
Name:ポリシーセット名(例:
7.対象のVCSリポジトリを接続
STEP5. Runを実行して評価結果を見る
対象ワークスペースでRunを実行します。
planの前後やApply後に 「Terraform policy evaluations」 ステージが現れれば、新フレームワークがちゃんと有効になっている証拠です。
ポリシーが準拠していると、Terraform policy evaluations passed と表示され、All タブに評価済みポリシーの一覧が出ます。
STEP6. わざと違反させてみる
タグなしのEBSボリュームを1個追加して、ポリシーに違反させます。
# main.tf に追記
resource "aws_ebs_volume" "test-vol2" {
availability_zone = data.aws_availability_zones.available.names[0]
size = 1
encrypted = true
# tags を書かない → 違反(mandatory_overridable)
}
再Runすると、Terraform policy evaluations が failed になります。
STEP7. apply後の値を検証する(post-apply)
途中でApply後の値を検証するポリシーを追加してみました。
apply後の値(ARN/ID)を検証(post-apply)
# policies/post_apply_ebs.policy.hcl
resource_policy "aws_ebs_volume" "validate_post_apply" {
enforcement_level = "mandatory"
# id は apply後に採番される(vol-xxxx)
enforce {
condition = core::startswith(attrs.id, "vol-")
error_message = "EBSボリュームIDが不正です: ${attrs.id}"
}
# arn も apply後に確定。承認済みリージョンか検証
enforce {
condition = core::startswith(attrs.arn, "arn:aws:ec2:ap-northeast-3:")
error_message = "EBSボリュームが承認済みリージョンにありません: ${attrs.arn}"
}
}
attrs. でリソース属性を参照します。plan時点では未確定(known after apply)な属性を参照すると、そのポリシーは自動的に apply後に評価されます。
ひとつ注意点としては、apply後評価はapplyを止められるわけではありません(既に作成済みのため)。
違反があっても止まるのではなく、apply後にエラーとして通知されるため、修正は別作業になります。
各クラウドサービスのポリシーと同じタイミングの検知にはなりますが、管理者のTerraform UI利用頻度が高かったり、Apply直後のちょっとしたテストに利用したりなど、活用できる場面はありそうです。
おまけ:ミニトラブル
「Failed」ではなく「Errored」になる
最初にtagなしのリソースを作成してrequire_tags を違反させたとき、Failed ではなく Errored になり、mandatory_overridable なのにオーバーライドできず強制停止してしまいました。
ログを見ると:
Error: Invalid function argument
condition = attrs.tags != null && core::length(core::keys(attrs.tags)) > 0
- aws_ebs_volume.violation
Error: Invalid value for "inputMap" parameter: argument must not be null.
attrs.tags is null
原因は、tagsを丸ごと書かないと attrs.tags が null になり、core::keys(null) の評価時に例外が発生することでした。
さらに、&& が短絡評価されず、前半の条件結果に関わらず後半の式も評価されたため、エラーが発生してしまいました。
対処としては nullでも安全な条件にしておくことが必要です。
# NG(nullでErroredになる)
condition = attrs.tags != null && core::length(core::keys(attrs.tags)) > 0
# OK(nullでも落ちず、正常にFailedになる)
condition = core::try(core::length(attrs.tags), 0) > 0
core::try(core::length(attrs.tags), 0) は、attrs.tags がnullで length が失敗したら 0 を返すので、0 > 0 が false となり 正常な違反判定(Failed) になります。
修正後は、想定通り Failed(Mandatory_overridable)になり、Overrideボタンが出るようになりました。
今回のように、最低1つ以上値を入れさせるような制御をしたいものの、null値が起こり得る場合にはこの書き方が有効だと思われます。
でもGAまでに直っていてほしいので開発チームにFeedbackしようと思います。
まとめ
conditionの記述については少し慣れが必要かもしれませんが、全体的にHCLはやはり可読性が高いなと思いました。
ベータ機能ゆえの制約や事前準備はありますが、HCLを書いたことがある方にはぜひ使い倒してほしいと思います。
まずは検証用ワークスペースで試してみてください!
参考リンク
- Terraform Policy 概要: https://developer.hashicorp.com/terraform/policy
- VCS setup for Terraform policy: https://developer.hashicorp.com/terraform/cloud-docs/workspaces/policy-enforcement/manage-policy-sets/terraform-policy-vcs
- HCP Terraform policy enforcement overview: https://developer.hashicorp.com/terraform/cloud-docs/workspaces/policy-enforcement
- 関数リファレンス: https://developer.hashicorp.com/terraform/policy/reference/functions
- インストール: https://developer.hashicorp.com/terraform/policy/install












