HCLでポリシーが書けるようになった!!ということで、概要をまとめてみました。 本記事は概要説明とサンプルコードがメインとなっています。
HCP Terraformを使った実際の操作や画面についてはこちら
※本記事は 2026年8月時点の情報です。Terraform Policy は現在ベータ(beta)機能であり、本番環境での利用は非推奨とされています。最新情報は必ず公式ドキュメントを確認してください。
※本機能はHCP Terraform有償版の利用が前提となっています。Pay-as-Goもありますのでこれを機にぜひHCP Terraformをご検討ください!
もくじ
- Terraform Policy とは?
― Policy as Code の新しい選択肢 - Terraform Policy のメリット
― Sentinel / OPA との違い - 全体ワークフロー
- 評価タイミング(3ステージ)と強制レベル(Enforcement Level)
- 基本の書き方
- 一歩進んだ書き方
filter/locals/input/ 組み込み関数 - Terraform Policyならではの書き方
リソース間参照・データソース参照 - ポリシーのテスト
tfpolicy validate/tfpolicy test/.policytest.hcl - まとめ
- tfpolicy コード例
各アジェンダの要旨
1. Terraform Policy とは何か
Terraform Policy は、HCL(HashiCorp Configuration Language)で記述する Policy as Code フレームワークです。tf policyとも呼称します。
Terraform のプロバイダと直接統合されており、プロバイダが定義するあらゆるリソース・属性をポリシーから参照できます。この方式で書いたポリシーは実行時に HCP Terraform が評価し、組織全体のガバナンスをTerraformのRunワークフローの中に組み込めます。
そもそもPolicy as Codeとは、「ポリシーをコードとして書く」ことでバージョン管理・テスト・自動デプロイといったソフトウェア開発のベストプラクティスをそのままガバナンスに適用できる、という発想ですが今回、第三の書き方としてHCLでの記述が可能になりました。
2. Terraform Policy のメリット
- HCLで記述できる:やはりこれが第一のメリット。.tfや.hclファイルを作成するときと同じ言語なので、別言語(Sentinel DSL/Rego[OPA])を覚える必要がない。
-
terraform init段階での評価ができる:プロバイダ/モジュールをダウンロードする前にポリシー評価でき、非準拠なものは取得自体をブロックできる。使用できるプロバイダーの制限などで活用できる。
Sentinel/OPA は init/plan 完了後に動くため、tfpolicy独自の判定タイミングである。 - apply後(post-apply)評価:ARNやID、ポート番号など applyしないと確定しない値 に対してもポリシーを書ける。(※ただしその結果に応じてapply自体を中止することはできない)
-
リソース間参照・データソース参照のヘルパー関数:
core::getresources()/core::getdatasource()で関連リソースやデータソースを問い合わせられる。Sentinel/OPA では手動でplan JSONなどから走査する必要があった。
| 観点 | Sentinel | OPA | Terraform Policy |
|---|---|---|---|
| ポリシー言語 | Sentinel DSL(独自) | Rego(独自) | HCL(Terraformと同一) |
| 強制レベル | advisory / soft / hard mandatory | pass/fail のみ | advisory / mandatory_overridable / mandatory |
| init時のブロック | 不可(DL後に評価) | 不可(DL後に評価) | 可(DL前に評価) |
| apply後の評価 | 不可 | 不可 | 可(post-apply) |
| リソース間参照 | 手動でループ・突合 | plan JSONを手動パース | 関数で問い合わせ |
| データソース参照 | ネイティブでは不可 | ネイティブでは不可 | 関数で問い合わせ |
↑こちらにもsentinel vs OPA vs tfpolicyの情報がまとまっています。
3. 全体ワークフロー
導入時の流れは次の5ステップです。
- リソース・プロバイダ・モジュールなどに対するポリシーを作成する。
- ローカルの
tfpolicyCLI でテストし、意図どおりに動くか確認する。 - ポリシーをVCS(Gitリポジトリ)にコミットし、HCP Terraform に接続する。
- HCP Terraform 上でポリシーを ポリシーセット にまとめ、プロジェクト/ワークスペース/タグを対象に指定する。
- ワークスペースのRunを実行するとポリシー評価がトリガーされ、結果がHCP Terraformに表示される。
4. 評価タイミング(3ステージ)と強制レベル
Terraform Policy は Run の中の 3つのタイミング で評価されます。
-
Setup(init時):プロバイダ/モジュールの
sourceやversionを、ダウンロード前に評価。違反するとダウンロード自体を止める。 - Plan time:参照する属性がplan時点で確定していれば、インフラ変更前にplanに対して評価。設定ミスを事前に検知するのに最適。
-
Apply time:
(known after apply)な値(ARN・IDなど)は、apply後に評価。applyを止めることはできないが、違反を即座にエラーとして通知し、担当者が手動で是正する。
強制レベル(enforcement_level) はポリシーごとに指定でき、以下の3種類です。
-
advisory:違反しても続行、警告のみ表示。 -
mandatory:違反すると停止。 -
mandatory_overridable:違反すると停止するが、権限のあるユーザーはオーバーライドして続行できる。(=SentinelのSoft mandatory)
5. 基本の書き方
ポリシーは .policy.hcl という拡張子のファイルに書きます。
・リソース
リソースを対象にするなら resource_policy ブロックを使い、enforce ブロックの condition(真になるべき条件)と error_message で検証を定義します。
属性は attrs. プレフィックスで参照します(後述のコード例参照)。
・モジュール、プロバイダー
provider_policy はプロバイダーのソースやバージョンを、module_policy はモジュールのソースやバージョンを検証します。
これらは meta.source / meta.version といったメタ属性を参照でき、init段階でダウンロードをブロックできます。
6. 一歩進んだ書き方(filter / locals / input / 関数)
-
filter:ポリシーを適用するリソースを属性で絞り込む(例:env=testingのものだけ)。 -
locals:ポリシー内のローカル値。ルート直下・ブロック内どちらにも書ける。 -
input:ポリシーをパラメータ化する入力変数。デフォルト値やテストでの上書きが可能。 - 組み込み関数:
core::length()、core::keys()、core::contains()、core::semverconstraint()、core::startswith()など、Terraformの多くの標準関数に加えポリシー専用関数が使える。 -
operations:["create","update","delete"]のうち、どの操作で評価するかを制御。prior_attrs(変更前の状態)を参照する場合はupdate/deleteを指定する。
7. Terraform Policyならではの書き方 ーリソース間参照・データソース参照ー
Terraform Policy が独自に組み込める条件です。
SentinelやOPAはPlan JSONファイルに記載されている値ベースでの突合でしたが、tf policyであれば実行中のTerraformエンジンに値を取りに行けるので、以下のような値の問い合わせができます。
-
core::getresources(type, filter):指定タイプの関連リソースを問い合わせる。「S3バケットには必ずprivateなACLリソースが紐づいていること」といったリソース間の関係を簡潔に検証できる。 -
core::getdatasource(type, filter):評価時にデータソース結果を直接参照する。「承認済みAMI/KMSキーの一覧をデータソースから引き、それ以外は禁止」といった動的な要件を書ける。
8. ポリシーのテスト
ポリシーは .policytest.hcl ファイルでテストします。
policytest ブロックで対象ポリシーを指定し、resource/provider/module ブロックでモックのリソースを定義、expect_failure = true で「失敗するはず」のケースを表現します。データソースは data ブロックで、入力変数は inputs ブロックでモックします。tfpolicy test で実行します。
tfpolicy CLI を利用するためには、別途準備が必要です。
・terraform CLIとは別に、tfpolicy CLIの個別インストールが必要
・tf policyを利用するには、Terraform CLIのバージョンがv1.16以上である必要がある
※2026年8月現在、v1.16以上はBeta版のみの提供であるため、terraform CLIを使って本番環境を操作する端末へのインストールはしないようにしてください。
9. まとめ
tfpolicyは以下のような方々におすすめです。
・既に Terraform / HCL に慣れているチーム
・Sentinel/OPAの学習コストやポリシーのメンテナンスに課題を感じているチーム
・init段階でのブロックやapply後の検証といったTerraform実行モデルとも連携したガバナンスを求めるチーム
現状はPublic Betaですが、まずはローカルCLIでの検証や非本番でぜひトライアルしてみてください!
10. tfpolicyコード例
ディレクトリ構成の例
. ├── policies/ │ ├── ebs_encryption.policy.hcl │ ├── aws_provider.policy.hcl │ └── module_validation.policy.hcl └── tests/ ├── ebs_encryption.policytest.hcl └── ...
例1. シンプルなストレージポリシー(EBS暗号化の強制)
# policies/ebs_encryption.policy.hcl
resource_policy "aws_ebs_volume" "encryption_required" {
enforcement_level = "mandatory"
enforce {
condition = attrs.encrypted == true
error_message = "すべてのEBSボリュームは暗号化が必須です。"
}
}
例2. ワイルドカードで全リソースにタグ付けを強制
# policies/require_tags.policy.hcl
resource_policy "aws_*" "require_tags" {
enforcement_level = "mandatory_overridable"
enforce {
core::try(core::length(attrs.tags), 0) > 0
error_message = "すべてのAWSリソースに最低1つのタグを付与してください。"
}
}
そのほか、プロバイダバージョンの強制や使用モジュールの制御など、いろんなアイディアがあると思います!
HCP Terraformでtfpolicyを実際にさわってみた記事はこちら
参考リンク
- Terraform Policy 概要: https://developer.hashicorp.com/terraform/policy
- ポリシーの書き方: https://developer.hashicorp.com/terraform/policy/write/policies
- ポリシー例: https://developer.hashicorp.com/terraform/policy/write/examples
- resource_policy リファレンス: https://developer.hashicorp.com/terraform/policy/reference/policy/resource-policy
- ポリシーフレームワーク比較: https://developer.hashicorp.com/terraform/policy/compare
- インストール: https://developer.hashicorp.com/terraform/policy/install
※ Terraform Policy はベータ機能です。本記事のコードは公式ドキュメント(v0.1.x)の仕様に基づいていますが、GA(正式版)までに構文が変わる可能性があります。