Terraform CloudのSentinelポリシー入門

1. 概要

  • Sentinelとは何か(Policy as Code)
  • Terraformに対してSentinelポリシーが評価されるタイミング
  • Sentinelの基本構文とよく使うポリシー例
  • PolicySetの設定方法

Sentinelは、HashiCorpが開発したPolicy as Codeフレームワークです。Terraform CloudのPlus以上のプランで使えます。「EBSは必ず暗号化する」「タグのEnvironmentが必須」などのルールをコードで定義し、Runサイクルで自動チェックできます。


2. Sentinelが評価されるタイミング

terraform plan
  ↓
Plan結果
  ↓
Sentinelポリシー評価  ← ここ
  ↓(pass)
terraform apply

planが終わり、applyが始まる前にSentinelが実行されます。ポリシーに違反するとapplyがブロックされます。


3. Sentinelポリシーの基本構文

# sentinel/enforce-encryption.sentinel
# EBSボリュームがすべて暗号化されていることを確認する

import "tfplan/v2" as tfplan

# plan中のすべてのaws_instanceリソースを取得
all_instances = filter tfplan.resource_changes as _, rc {
  rc.type is "aws_instance" and
  rc.mode is "managed" and
  (rc.change.actions contains "create" or rc.change.actions contains "update")
}

# 各インスタンスのroot_block_deviceが暗号化されているか確認
deny_unencrypted = rule {
  all all_instances as _, rc {
    rc.change.after.root_block_device[0].encrypted is true
  }
}

# メインルール
main = rule {
  deny_unencrypted
}

4. よく使うSentinelポリシー例

タグの必須チェック

# sentinel/require-tags.sentinel
import "tfplan/v2" as tfplan

required_tags = ["Name", "Environment", "ManagedBy"]

# managed resourceすべてにrequired_tagsが含まれることを確認
all_resources = filter tfplan.resource_changes as _, rc {
  rc.mode is "managed" and
  (rc.change.actions contains "create" or rc.change.actions contains "update")
}

deny_missing_tags = rule {
  all all_resources as _, rc {
    all required_tags as tag {
      rc.change.after.tags[tag] is defined and
      rc.change.after.tags[tag] is not null and
      rc.change.after.tags[tag] is not ""
    }
  }
}

main = rule { deny_missing_tags }

許可するインスタンスタイプを制限する

# sentinel/allowed-instance-types.sentinel
import "tfplan/v2" as tfplan

allowed_types = [
  "t3.micro",
  "t3.small",
  "t3.medium",
  "t3.large",
]

all_instances = filter tfplan.resource_changes as _, rc {
  rc.type is "aws_instance" and
  rc.mode is "managed"
}

deny_large_instances = rule {
  all all_instances as _, rc {
    rc.change.after.instance_type in allowed_types
  }
}

main = rule { deny_large_instances }

5. Terraform CloudでのSentinel設定

Sentinel設定はTerraform Cloud UIで行います。

Settings → Policy Sets → Create a new policy set
  ├─ VCS連携: sentinelポリシーファイルをリポジトリで管理
  ├─ 適用範囲: 全Workspace or 特定Workspaceのみ
  └─ Enforcement Level: hard-mandatory / soft-mandatory / advisory

Enforcement Level:

レベル動作
hard-mandatory違反するとapplyが必ずブロック
soft-mandatory違反時にオーナーが手動オーバーライド可能
advisory違反しても警告のみ(applyはブロックしない)

6. Terraform側のコード(Sentinelが評価する対象)

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  cloud {
    organization = "my-org"
    workspaces {
      name = "production"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

# このリソースはSentinelポリシーの評価対象
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"  # ← allowed-instance-typesで確認

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true  # ← enforce-encryptionで確認
  }

  tags = {
    Name        = "${var.environment}-web"  # ← require-tagsで確認
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

7. 関連記事


8. まとめ

  • SentinelはPolicy as Codeで、planの後・applyの前にガバナンスルールを自動チェックする
  • Terraform Cloud Plus以上のプランで利用可能
  • EBS暗号化必須・タグ必須・インスタンスタイプ制限などのポリシーをコードで定義する
  • Enforcement LevelでハードブロックかアドバイザリかをWorkspaceごとに制御できる
  • OSSで同等のことをしたい場合はOPA/Conftestが選択肢

対象バージョン: Terraform Cloud / Sentinel (2024) 公式ドキュメント: https://developer.hashicorp.com/terraform/cloud-docs/policy-enforcement/sentinel