Terraformのポリシー審査はTerraform Cloud/EnterpriseのSentinelだけが解ではありません。OPA(Rego)による事前審査は、マルチツール/マルチクラウドで一貫したガバナンスを実現できます。
このガイドでは、terraform show -jsonの計画JSONを入力にしたOPA/Rego検証を軸に、比較検討、実装パターン、例外管理、試験で問われやすいポイントまでを扱います。
Terraformの計画結果はterraform show -jsonで機械可読なJSONとして取得できます。OPA(Rego)はこのJSONを入力に許可/拒否を判定できるため、CIでのゲーティングに適しています。Terraform Cloud/Enterpriseを使わないケースや、クラウド横断で単一のポリシー言語に統一したい場合の選択肢になります。
実務では、CIでplanを生成し、そのJSONをconftest(OPAsをラップするCLI)で検証、失敗時はマージやデプロイを止めます。apply前に恒常的にチェックできるため、事後監査ではなく事前予防の形でガバナンスを効かせられます。
ポリシー審査は1つの正解に収束しません。チーム規模、利用プラットフォーム、既存のCI/CD、運用コストで選択が変わります。以下は代表的な選択肢と向き不向きの整理です。
Terraform Cloud/EnterpriseのSentinelは最短で強力ですが、プラットフォーム依存度が高まります。OPA/Rego+Conftestはベンダーロックを避けつつ、幅広いユースケースに適応可能です。HCL静的解析(tfsecやTrivy)は早期検出に優れますが、実際の差分(計画)を理解しません。
| アプローチ | 適用層/対象 | 介入ポイント | 強み |
|---|---|---|---|
| OPA/Rego + Conftest | Terraform plan(JSON) | CIのplan直後 | ベンダーロック低/表現力高/他ツールにも転用可 |
| Terraform Cloud/Enterprise Sentinel | Run間での計画適用 | Plan/Applyの直前直後 | プラットフォームと密連携/運用が簡易 |
| HCL静的解析(tfsec/Trivyなど) | HCL/静的コード | PR作成〜plan前 | 検出が早い/導入が容易 |
| 手動レビュー(レビュー規約) | PR/設計ドキュメント | 任意 | 柔軟/コンテキスト判断が可能 |
最小限の型合わせとして、resource_changes配列と各要素のchange.afterを参照します。チェック対象は原則create/update/replace(= ["create","delete"])です。deleteやno-opは除外します。
タグ必須、命名規則、リージョン制限、サイズ上限といったガードレールは、単一のdeny集合を返すパターンで実装するとテスト容易性が高まります。
Rego例: タグ(owner)必須ポリシー(plan JSONを入力)
package tfplan.tags
deny[msg] {
some i
rc := input.resource_changes[i]
should_check(rc.change.actions)
after := rc.change.after
after != null
required := "owner"
not has_required_tag(after, required)
msg := sprintf("%s.%s is missing tag %q", [rc.type, rc.name, required])
}
should_check(actions) {
actions == ["create"]
} or {
actions == ["update"]
} or {
actions == ["create", "delete"] # replace
}
has_required_tag(after, key) {
tags := get_tags(after)
tags[key]
}
get_tags(obj) = tags {
tags := obj.tags
} else = tags {
tags := obj.tags_all
} else = tags {
tags := {}
}
ポリシーの主目的が『これから作る/変えるものの安全性確認』であればplan JSONが第一選択です。差分を直接評価でき、偽陽性を抑えられます。一方、コンプライアンス監査や資産台帳との突合など『現状の棚卸し』が主眼ならstate JSONが有用です。
Rego側では、入力の揺らぎ(プロバイダ差の属性名)に耐えるため、補助関数で属性取得を抽象化します。タグや名前など共通概念はラッパー関数に寄せ、ルール本文はビジネス意図の記述に集中します。
基本形は3ステップです。1) terraform init/plan、2) terraform show -jsonでJSON化、3) conftest testでRegoを適用。conftestの終了コードは0(合格)/非0(拒否)なので、そのままジョブのゲートに使えます。
マルチモジュール構成では、各ディレクトリでplan→conftestを並列実行し、失敗があれば全体を止める設計が現実的です。キャッシュを適切に使い、plan生成のコストを抑えます。
現場では例外ゼロは非現実的です。Rego内に例外許容の仕組み(注釈ファイルやメタデータ)を設け、期限・範囲・根拠を明確に管理します。例外は必ず期限付き、理由付き、対象限定にします。
ポリシー変更は破壊的になり得ます。新ルールは警告モード→強制モードの段階適用を行い、CIで2週間程度のサンドボックス期間を確保すると安全です。
Pro
問題 1
組織はTerraform計画の内容に対してタグ必須や命名規則を自動検証したい。Terraform Cloud/Enterpriseは使っていない。最小の運用コストで事前ゲートを実装するアプローチはどれか。
正解: A
事前の自動ゲートには計画差分の評価が必要です。planをJSON化してOPA/Regoで検証すれば、差分に基づく厳密な判断が可能で、CIの終了コードでゲーティングできます。terraform validateは構文/一部ローカル検証に限られ、手動レビューや事後監査は自動ゲートの要件を満たしません。
plan JSONとstate JSON、どちらをポリシー入力に使うべきですか?
事前ゲートにはplan JSONが第一選択です。差分(これから起きる変更)を評価できます。state JSONは棚卸しや事後監査、資産可視化に向きます。両方使う二段構えも有効です。
Regoでプロバイダ差の属性名が違い困ります。どう設計すべきですか?
属性取得をヘルパー関数に抽象化し、ルール本文から切り離します。例としてtags/tags_allの両方に対応するget_tagsを用意し、以降のロジックはget_tagsの返り値に依存させます。
小さく始めるには何から実装すべきですか?
まずは1つの高効果ルール(例: 主要リソースへのownerタグ必須)をRegoで作り、CIにplan→show -json→conftestの最短パスを組み込みます。合格/不合格の可観測性(明確なdenyメッセージ、アーティファクト化)を先に整えると拡張が容易です。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...