1. 導入:なぜIaCにPolicy as Codeが必要なのか
クラウドインフラがコード化(IaC)された現代において、手動でのセキュリティチェックはもはや限界です。特にTerraform等の構成ミスにより、「S3バケットが意図せず公開される」「必要なタグが付与されていない」といったインシデントは後を絶ちません。Policy as Code(PaC)を導入することで、これら「守るべきルール」を自動化し、CIパイプラインの段階で構成ミスを検知・ブロックすることが可能になります。本記事では、OPAとRegoを用いた実務的な実装方法を解説します。
2. 基礎知識:OPAとRegoとは
Open Policy Agent (OPA) は、あらゆるスタックでポリシーを適用するためのオープンソースの汎用エンジンです。そして、そのポリシーを記述するための言語が Rego です。Regoは宣言型の言語であり、JSONやTerraformの計画ファイル(plan)を入力として受け取り、ポリシーに合致しているかを判定します。イメージとしては、「インフラ構成ファイルに対するユニットテスト」を書く感覚に近いです。
3. 実装・解決策:Terraformのプランを検証する
OPAでTerraformを検証する一般的なフローは以下の通りです。
1. Terraformの構成を `terraform plan -out=tfplan.binary` でバイナリ化する。
2. `terraform show -json tfplan.binary` でJSON形式に変換する。
3. OPAエンジンにJSONとRegoポリシーを渡し、検証を実行する。
このプロセスをGitHub ActionsやGitLab CIに組み込むことで、ルール違反があればデプロイを強制停止させることができます。
4. サンプルプログラム:S3バケットのパブリックアクセスを禁止する
以下は、S3バケットがパブリックアクセスを許可していないか(`acl`が`public-read`等になっていないか)を判定するRegoコードの例です。
package terraform.security
入力データ(tfplanのJSON)からリソースを取得
import input as tfplan
デフォルトでは「許可」とする(必要に応じてポリシーによる)
default allow = false
S3バケットのリソースを抽出
s3_buckets = [res |
res := tfplan.resource_changes[_]
res.type == “aws_s3_bucket”
]
ポリシー違反の定義:aclがpublic-readやpublic-read-writeになっている場合
deny[msg] {
bucket := s3_buckets[_]
# 設定値の変更がある場合にチェック
acl := bucket.change.after.acl
bad_acls := {“public-read”, “public-read-write”}
bad_acls[acl]
msg := sprintf(“警告: バケット %s はパブリックアクセスが許可されています。”, [bucket.address])
}
違反がなければallowをtrueにする
allow {
count(deny) == 0
}
5. 応用・注意点:現場で陥りやすい罠
注意点1:TerraformのバージョンとJSON構造
`terraform show -json` の出力形式は、Terraformのバージョンによって微妙に異なる場合があります。CIで利用する際は、TerraformとOPAのバージョンを固定しておくことが重要です。
注意点2:ルールを厳しくしすぎない
最初から全てのルールを適用しようとすると、CIが落ち続けて開発体験が低下します。まずは「S3の暗号化」や「公開制限」といった、クリティカルな項目から導入し、徐々にルールを拡大する「段階的導入」を強く推奨します。
注意点3:テストコードを併用する
Rego自体もプログラムであるため、ロジックのバグが発生します。Regoにはテスト機能(`opa test`)が備わっているため、ポリシーを書く際は必ずユニットテストを併記し、ポリシー自体が正しく判定できることを確認してください。

コメント