この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
「terraform apply を実行するユーザーやロールにも最小限の権限を付与するようにしたい。」
Terraformで色々管理しているから、Terraform実行ユーザーの権限は強めにしているけど少し不安。最小限の権限を割り当てる方法はないかな?
そんな時には、Pikeを使ってみるのもいいかもしれません。
Pikeとは
一言で言うと、TerraformのコードからTerraform実行に必要な最小限のIAMポリシーを生成してくれるツールです。
JamesWoolfenden/pike: Pike is a tool for determining the permissions or policy required for IAC code
Terraform実行用IAMユーザー・IAMロールの権限
例えば、TerraformでAWSインフラを管理しているとします。
terraform apply
を実行するために、AWSリソースを操作する権限を持ったIAMユーザーやIAMロールが必要になります。
このIAMユーザーやIAMロールに渡す権限ですが、理想は最小限の権限であるべきです。 しかし、Terraformで管理するリソースが増えてくると最小限の運用の手間は大きいです。
そのため、セキュリティ的には良くないと分かっていても、Terraform実行用のIAMユーザーやIAMロールにはAdministratorAccess
などの強い権限のIAMポリシーを付与して運用することが多いかと思います。
Pikeを使うと
Pikeを使えば、Terraformのコードからterraform apply
に必要な最小限のIAMポリシーを作成するといったことができます。
以下は実行例です。 Pikeはterraformをサポートしていて、AWSプロパイダー以外にもGoogle CloudやAzureのプロパイダーもサポートしています。(2022/12/12時点)
$pike scan -o terraform -d ../modules/aws/terraform-aws-activemq
resource "aws_iam_policy" "terraformXVlBzgba" {
name = "terraformXVlBzgba"
path = "/"
description = "Add Description"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateNetworkInterface",
"ec2:CreateNetworkInterfacePermission",
"ec2:CreateSecurityGroup",
"ec2:CreateTags",
"ec2:DeleteNetworkInterface",
"ec2:DeleteNetworkInterfacePermission",
"ec2:DeleteSecurityGroup",
"ec2:DeleteTags",
"ec2:DescribeAccountAttributes",
"ec2:DescribeInternetGateways",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:DetachNetworkInterface",
"ec2:RevokeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"kms:CreateKey",
"kms:DescribeKey",
"kms:EnableKeyRotation",
"kms:GetKeyPolicy",
"kms:GetKeyRotationStatus",
"kms:ListResourceTags",
"kms:ScheduleKeyDeletion",
"kms:TagResource",
"kms:UntagResource"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"mq:CreateBroker",
"mq:CreateConfiguration",
"mq:CreateTags",
"mq:CreateUser",
"mq:DeleteBroker",
"mq:DeleteTags",
"mq:DeleteUser",
"mq:DescribeBroker",
"mq:DescribeConfiguration",
"mq:DescribeConfigurationRevision",
"mq:DescribeUser",
"mq:RebootBroker",
"mq:UpdateBroker",
"mq:UpdateConfiguration",
"mq:UpdateUser"
],
"Resource": "*"
}
]
})
}
試してみる
サンプルコード
DynamoDBとSQSのモジュールを作って、main.tf
で呼び出すようにしています。
ディレクトリ構成は以下になっています。
このサンプルコードを使って、Pikeではどのようにポリシーが生成されるか見ていきます。
├── backend.tfvars
├── main.tf
├── module
│ ├── dynamodb
│ │ └── main.tf
│ └── sqs
│ └── main.tf
└── provider.tf
main.tf
module "sqs" {
source = "./module/sqs"
}
module "dynamodb" {
source = "./module/dynamodb"
}
module/sqs/main.tf
resource "aws_sqs_queue" "this" {
name = "terraform-example-queue"
}
module/dynamodb/main.tf
resource "aws_dynamodb_table" "this" {
hash_key = "partition_key"
range_key = "sort_key"
attribute {
name = "partition_key"
type = "S"
}
attribute {
name = "sort_key"
type = "S"
}
}
インストール
brewでインストールできます。
$ brew tap jameswoolfenden/homebrew-tap
$ brew install jameswoolfenden/tap/pike
ポリシーを生成してみる
まずは、モジュールを呼び出すmain.tf
があるディレクトリでPikeを実行してみます。
$ pike scan .
resource "aws_iam_policy" "terraform_pike" {
name_prefix = "terraform_pike"
path = "/"
description = "Pike Autogenerated policy from IAC"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:CreateTable",
"dynamodb:DeleteTable",
"dynamodb:DescribeContinuousBackups",
"dynamodb:DescribeTable",
"dynamodb:DescribeTimeToLive",
"dynamodb:ListTagsOfResource",
"dynamodb:UpdateTable",
"dynamodb:UpdateTimeToLive"
],
"Resource": [
"*"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"sqs:CreateQueue",
"sqs:DeleteQueue",
"sqs:GetQueueAttributes",
"sqs:ListQueueTags",
"sqs:SetQueueAttributes"
],
"Resource": [
"*"
]
}
]
})
}
ディレクトリを指定して実行可能なので、module単位でポリシーを作成することもできます。
pike scan -d module/dynamodb
resource "aws_iam_policy" "terraform_pike" {
name_prefix = "terraform_pike"
path = "/"
description = "Pike Autogenerated policy from IAC"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:CreateTable",
"dynamodb:DeleteTable",
"dynamodb:DescribeContinuousBackups",
"dynamodb:DescribeTable",
"dynamodb:DescribeTimeToLive",
"dynamodb:ListTagsOfResource",
"dynamodb:UpdateTable",
"dynamodb:UpdateTimeToLive"
],
"Resource": [
"*"
]
}
]
})
}
生成したポリシーをデプロイする
ポリシーを生成できることが分かったので、ポリシーを実際にデプロイしてみます。
$ pike make .
3:30PM DBG terraform init at /Users/sato.masaki/work/src/github.com/msato0731/terraform-sample/pike-demo
3:30PM DBG aws role create/updated arn:aws:iam::111111111111111:role/terraform_pike_20221214063044638700000002
3:30PM DBG arn:aws:iam::111111111111111:role/terraform_pike_20221214063044638700000002
コマンドを実行するとIAMロールとIAMポリシーが作成されます。
Pikeを使うことで、簡単にIAMポリシーの生成ができました。
コマンド実行後に、ディレクトリを確認すると以下のように.pike
ディレクトリが作成されていてIAMポリシーとロールを作成するためのtfファイルが作成されました。
pike makeではこのtfファイルを使って、IAMポリシーとロールを作成しています。
$ tree -a -L 2
├── .pike
│ ├── .terraform
│ ├── .terraform.lock.hcl
│ ├── aws_iam_role.terraform_pike.tf
│ ├── pike.generated_policy.tf
│ ├── terraform.tfstate
│ └── terraform.tfstate.backup
├── .terraform
│ ├── modules
│ ├── providers
│ └── terraform.tfstate
├── .terraform.lock.hcl
├── backend.tfvars
├── main.tf
├── module
│ ├── dynamodb
│ └── sqs
└── provider.tf
おわりに
TerraformのコードからIAMポリシー生成してくれるツールPikeの紹介でした。
臼田さんから教えてもらって面白いツールだなと思ったのでブログにしました。
Terraform実行ユーザーのIAMポリシーに悩んでいる方の助けになるツールかと思います。
現在(2022/12/14時点)は一部機能が、AWS Providerのみに対応しているようです。
今後の発展が楽しみなツールです。
以上、AWS事業本部の佐藤(@chari7311)でした。