AWSの IAM ポリシーを Terraform で書く仕事が降ってきました。
一般的な方法で実装しようとしたものの、ポリシーが長くなり可読性が低いと感じました。
そこで、Terraform で IAM ポリシーをできるだけ見やすく書く方法がないか調べたので、備忘録としてまとめます。
一般的な書き方
一般的には、以下のようにIAMポリシーを記述し、IAMユーザにアタッチします。
# IAMポリシー
resource "aws_iam_policy" "sample_policy" {
name = "sample-policy"
description = "Sample policy for qiita"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ec2:Describe*",
]
Effect = "Allow"
Resource = "*"
},
]
})
}
# IAMポリシーをIAMユーザーにアタッチする
resource "aws_iam_user_policy_attachment" "sample_policy_attachment" {
user = aws_iam_user.sample_user.name
policy_arn = aws_iam_policy.sample_policy.arn
}
今回直面した課題
今回定義する必要があったIAM ポリシーは、以下の3種類でした。
- IPを制限するポリシー
- Athenaのポリシー
- Glueのポリシー
これらを1つのポリシーにまとめて記述すると、どうしても記述量が多くなってしまいます。
作成時は問題ありませんが、後から実装の経緯を知らない人が見たときに、理解しづらいと感じるのではないかと思いました。
解決策
3種類のポリシーを分け、最後にまとめるような記述としました。※ポリシーの中身は仮です
aws_iam_policy_document を使うことで、ポリシーを論理的な単位ごとに分割して管理でき、最終的に1つの IAM ポリシーとしてまとめることができます。
# IP制限のポリシー
data "aws_iam_policy_document" "ip_restriction_policy" {
statement {
effect = "Deny"
actions = ["*"]
resources = ["*"]
condition {
test = "NotIpAddress"
variable = "aws:SourceIp"
values = ["{IP Address}"]
}
# ~略~
}
}
# Athenaのポリシー
data "aws_iam_policy_document" "athena_policy" {
statement {
sid = "AthenaQueryExecution"
effect = "Allow"
actions = [
"s3:ListBucket"
]
# ~略~
}
}
# Glueのポリシー
data "aws_iam_policy_document" "glue_policy" {
statement {
sid = "GlueAccess"
effect = "Allow"
actions = [
"glue:GetDatabases"
]
# ~略~
}
}
# ポリシーを1つにまとめる
data "aws_iam_policy_document" "combined_sample_policy" {
source_policy_documents = [
data.aws_iam_policy_document.ip_restriction_policy.json,
data.aws_iam_policy_document.athena_policy.json,
data.aws_iam_policy_document.glue_policy.json,
]
}
# 1つにまとめたポリシーをIAMポリシーとして定義する
resource "aws_iam_policy" "sample_policy" {
name = "sample-policy"
description = "Sample policy for qiita"
policy = data.aws_iam_policy_document.combined_sample_policy.json
}
# IAMポリシーをIAMユーザーにアタッチする
resource "aws_iam_user_policy_attachment" "sample_policy_attachment" {
user = aws_iam_user.sample_user.name
policy_arn = aws_iam_policy.sample_policy.arn
}
terraform apply 時に -target を指定する場合は、IAM ポリシーと IAM ユーザーへのアタッチの両方を指定する必要があります。
(ポリシーのみ apply すると、ユーザーに反映されないため)
terraform apply -target=module.iam.aws_iam_policy.sample_policy -target=module.iam.aws_iam_user_policy_attachment.sample_policy_attachment
この書き方のメリット
- ポリシーごとに責務が分かれ、可読性が高い
- Athena / Glue などの権限を再利用しやすい
- 後からポリシーを追加・削除しやすい
終わりに
今回は、Terraform で IAM ポリシーが長くなってしまったときの対処方法をまとめました。
正解は1つではないと思いますが、
「後から読む人のことを考える」という点では、この書き方はかなり楽だと感じています。