「Terraform Cloudを使って、Policy as Codeでガバナンスを効かせたい」
Terraform Cloudの魅力的な機能の一つにSentinelやOPAを使って作成したポリシーを簡単に適用できることがあると思います。
今回は、Sentinelを使ったポリシー作成とワークスペースへのポリシー適用の流れについて書きます。
Terraform CloudのPolicy as Code
Terraform CloudではTeam & Governance以上のプランでSentinelやOPAを使ったポリシーを、組織やワークスペースに適用できる機能があります。
この機能を使うことで、Terraform Cloud上でインフラを作成する際にポリシーに違反している場合はデプロイできないといったことが可能です。
ポリシーの例)
- EC2インスタンスのインスタンスサイズがt2.micro~mediumのみ作成を許可
- Nameタグがついていないインスタンスは作成不可
- 作成するリソースのコストが100USD/月未満の場合は許可
Install the Sentinel CLI | Terraform | HashiCorp Developer
上記のようなポリシーをTerraform Cloud上でPolicy Setとして登録して使用します。
Policy Setの概要は以下です。
図中はPolicy Setを1つのWork Spaceに関連づけているますが複数のワークスペースや組織自体に関連づけることも可能です。
Terraform Cloud Policy Set適用の流れ
Terraform CloudでPolicy Setを適用する流れを、説明していきます。 Terraform Cloudのチュートリアルを参考にしています。
ローカルにSentinel CLIをインストール
ローカルにSentinel CLIをインストールします。
Sentinel CLIを実行するためにTerraform Planのデータが必要なため、次のステップでデータを取得します。
Install the Sentinel CLI | Terraform | HashiCorp Developer
既存のワークスペースからMock Dataを取得
データの取得は簡単です。既存のワークスペースからRuns
>Download Sentinel mocks
を選択するだけです。
Generate Policy Mock Data | Terraform | HashiCorp Developer
mock*.sentinelというファイルがいくつかダウンロードできると思います。 plan・run・configといった形で、それぞれにポリシールールを定義できます。(今回は次のステップでplanを使用しています)
ダウンロードしたファイルの情報は、sentinel.hcl
にも書かれています。
sentinel.hcl
mock "tfconfig" {
module {
source = "mock-tfconfig.sentinel"
}
}
mock "tfconfig/v1" {
module {
source = "mock-tfconfig.sentinel"
}
}
mock "tfconfig/v2" {
module {
source = "mock-tfconfig-v2.sentinel"
}
}
mock "tfplan" {
module {
source = "mock-tfplan.sentinel"
}
}
mock "tfplan/v1" {
module {
source = "mock-tfplan.sentinel"
}
}
mock "tfplan/v2" {
module {
source = "mock-tfplan-v2.sentinel"
}
}
mock "tfstate" {
module {
source = "mock-tfstate.sentinel"
}
}
mock "tfstate/v1" {
module {
source = "mock-tfstate.sentinel"
}
}
mock "tfstate/v2" {
module {
source = "mock-tfstate-v2.sentinel"
}
}
mock "tfrun" {
module {
source = "mock-tfrun.sentinel"
}
}
Generate Policy Mock Data | Terraform | HashiCorp Developer
ローカルでPolicyを作成・テストする
ポリシー作成に必要なファイルをサンプルリポジトリを例に説明します。
sentinel.hcl
Sentinelの設定を定義しています。
先程ダウンロードしたファイルの中にあった、sentinel.hcl
です。
必要な部分だけ残して他を削除します。
sentinel.hcl
mock "tfplan/v2" {
module {
source = "mock-tfplan-v2.sentinel"
}
}
restrict-aws-instances-type-and-tag.sentinel
ポリシーを定義するファイルです。 今回は、Nameタグ・EC2インスタンスタイプのポリシーを定義しています。
# Imports mock data
import "tfplan/v2" as tfplan
# Get all AWS instances from all modules
ec2_instances = filter tfplan.resource_changes as _, rc {
rc.type is "aws_instance" and
(rc.change.actions contains "create" or rc.change.actions is ["update"])
}
# Mandatory Instance Tags
mandatory_tags = [
"Name",
]
# Allowed Types
allowed_types = [
"t2.micro",
"t2.small",
"t2.medium",
]
# Rule to enforce "Name" tag on all instances
mandatory_instance_tags = rule {
all ec2_instances as _, instance {
all mandatory_tags as mt {
instance.change.after.tags contains mt
}
}
}
# Rule to restrict instance types
instance_type_allowed = rule {
all ec2_instances as _, instance {
instance.change.after.instance_type in allowed_types
}
}
# Main rule that requires other rules to be true
main = rule {
(instance_type_allowed and mandatory_instance_tags) else true
}
mock-tfplan-v2.sentinel
作成したポリシーのテストに使用します。(長いため、抜粋しています。)
mock-tfplan-v2.sentinel
resource_changes = {
"aws_instance.ubuntu": {
"address": "aws_instance.ubuntu",
"change": {
## ...
"after": {
## ..
"tags": {
"Name": "Provisioned by Terraform",
},
## ..
}
## ...
},
## ...
},
}
Policyのテスト
ポリシーのテストは以下のコマンドで実行できます。
$ sentinel apply restrict-aws-instances-type-and-tag.sentinel
Pass - restrict-aws-instances-type-and-tag.sentinel
Write a Sentinel Policy for a Terraform Deployment | Terraform | HashiCorp Developer
Terraform CloudでPolicy Setを作成する
Policyのテストが完了したら、実際にTerraform Cloud上で使用してみます。
sentinel.hcl
にenforcement_level
の設定を追加します。
この設定でポリシーに対する寛容度を設定することができます。
sentinel.hcl
policy "restrict-aws-instances-type-and-tag" {
enforcement_level = "hard-mandatory"
}
mock "tfplan/v2" {
module {
source = "mock-tfplan-v2.sentinel"
}
}
例) - ポリシー違反していても、ログに残してTerraformの実行を許可 - ポリシー違反していたら、Terraform実行を拒否
詳しくは以下をご確認ください。
Upload Your Sentinel Policy Set to Terraform Cloud | Terraform | HashiCorp Developer
上記の変更が完了してGithubにも反映したらTerraform Cloudのコンソールから、Policy Setsを選択します。 ワークスペースを作る時と同様に、Githubリポジトリと接続することができます。
Policyの適用範囲を設定して、Policy Sets作成します。
Policy Setをワークスペースに適用して、実行されることを確認する
最後にPolicyが適用されているかをワークスペースで確認します。
ルール外のインスタンスサイズで作成しようとすると、以下のようにポリシーでエラーが出ます。
インスタンスサイズ変更後は、Apply可能な状態になりました。
Control Costs with Policies | Terraform | HashiCorp Developer
おわりに
Terraform CloudでSentinelを使ったPolicy適用でした。
Terraformリポジトリが複数ある場合、Policyを一括して適用するのは少し手間がかかるかもしれません。
Terraform Cloudを使用すれば、簡単に組織やワークスペースに対してPolicyを適用できて運用を楽にできそうです。
以上、AWS事業本部の佐藤(@chari7311)でした。