プロジェクトで使用するIAMロール・ポリシー・ユーザー・グループをTerraformで一括管理する設計パターンを解説する。 マネージドポリシーとインラインポリシーの使い分け、AWSクォータを踏まえた設計判断を紹介する。
「箱を一括で作り、リソース固有の権限はリソース側で追加する」という設計パターン自体は、Security Groupと共通する考え方として親記事IAMとSecurity Group ─ 2つのアクセス制御レイヤーの設計で解説している。本稿ではIAMに固有の判断に絞る。
1. IAM一括管理の動機と設計方針
課題:IAMロールの散逸
プロジェクトが成長するにつれ、ECS、Lambda、CodeBuild、EC2など各サービスごとにIAMロールが必要になる。 これらを各リソース定義の近くに個別作成すると、以下の問題が生じる。
- ロールの全体像が見えない: どのロールが存在し、何の権限を持つか把握しづらい
- 命名規則の不統一: 作成者・タイミングによって命名がばらつく
- 権限の重複・過剰付与: 似たポリシーが複数箇所で定義され、棚卸しが困難
- 変更時の影響範囲が不明: ポリシー変更がどのサービスに影響するか追跡しにくい
設計方針:一箇所に集約
プロジェクトで使用するIAMロールを 一箇所のTerraformファイルに集約 する。
infrastructure/
|
└── environments/
|
└── prod/
|
└── iam.tf ← 全ロールを宣言的に定義 |
これにより得られるメリット:
- 一覧性: 1ファイルを見れば、環境内の全IAMロール・ポリシー・ユーザーが把握できる
- 命名の統一: 接頭辞・用途・環境名を組み合わせた命名規則を、一箇所で全ロールに適用できる
- レビューの容易さ: IAM変更は必ずこのファイルに集約されるため、PRレビューで権限変更を見落としにくい
- 棚卸しの簡素化: Terraformのstateと宣言を突き合わせることで、不要ロールの検出が容易
2. 管理対象
一括管理の対象とするIAMリソースは以下の通り。
ロール定義では、AssumeRoleを許可するサービスを宣言的に指定する。
AWS以外のPrincipal(クロスアカウントのIAMロール等)からのAssumeRoleが必要な場合は、カスタムのAssumeRoleステートメントで柔軟に対応する。
3. ポリシー設計:マネージドポリシー vs インラインポリシーの使い分け
基本方針
一括管理で アタッチするポリシーは汎用的なものだけ に限定する。
具体的には以下の2種類のみ:
- AWSマネージドポリシー(例:
AmazonECSTaskExecutionRolePolicy) - リソースが
*のカスタムポリシー(例:logs:CreateLogGroupに対してresource = ["*"])
なぜ汎用ポリシーだけなのか
IAMの一括管理はインフラの初期構築フェーズで適用される。この時点では、具体的なリソースARN(S3バケット名、RDSクラスターARN等)がまだ確定していない場合がある。 そのため、特定のARNへのアクセス許可は、一括管理ではなくリソースを作るときに追加する(考え方は親記事の3章)。
インラインポリシーによる詳細権限の追加
リソースを作成するタイミングで、そのリソースへのアクセス権をインラインポリシーとしてロールに追加する。
# 概念例: S3バケットを作るコードの中で、ECSタスクロールへのアクセス権をインラインポリシーで付与する
|
resource "aws_iam_role_policy" "ecs_task_s3_access" {
|
name = "s3-app-bucket-access"
|
role = aws_iam_role.ecs_task.name # 一括管理で作ったロールの名前を参照する
|
|
policy = jsonencode({
|
Version = "2012-10-17"
|
Statement = [
|
{
|
Effect = "Allow"
|
Action = ["s3:GetObject", "s3:PutObject"]
|
Resource = ["${aws_s3_bucket.app.arn}/*"]
|
}
|
]
|
})
|
} |
この方式により、権限の定義がリソース定義の近くに置かれて「何のための権限か」が明確になり、具体的なARNを指定して resource = ["*"] を避けられる。
IAMに固有の利点は、マネージドポリシーのアタッチ数の枠を消費しないことである(4章)。
4. IAMクォータ比較表
IAMロールに対するポリシーの上限値を以下に整理する。
インラインポリシーは個数の上限はないが、エンティティあたりの合計ポリシーサイズ(文字数)に上限がある。ホワイトスペースはカウントされない。 カスタマー管理ポリシーは、1つあたりのサイズが6,144文字までである。
出典: IAM and AWS STS quotas - AWS Identity and Access Management(2026-09-14確認)
設計上のポイント
ロールにアタッチできるマネージドポリシーは既定20、引き上げても最大25である。 汎用ポリシーを役割ごとに細かく分けてアタッチしていくと、この枠は有限な設計資源になる。 一方、インラインポリシーは 個数制限がなく、合計サイズ(ロールの場合10,240文字) が上限となる。
この特性を活かし:
- 汎用的な権限 → マネージドポリシーとしてアタッチ(上限枠を消費するが、再利用性が高い)
- リソース固有の権限 → インラインポリシーで追加(上限枠を消費せず、詳細に設定可能)
という使い分けにより、マネージドポリシーの上限を超えて詳細な権限設定が可能になる。
5. IAMユーザー管理と認証情報の安全な格納
課題:認証情報の散逸
IAMユーザーを作成すると、認証情報(アクセスキーまたはパスワード)が生成される。 この認証情報をどこに保存するかが明確でないと、以下の問題が生じる。
- Terraformの出力やコンソール画面に平文で表示され、Slackやメールで共有される
- 保存先が担当者ごとにバラバラになり、棚卸し不能になる
- 「認証情報はどこにありますか?」という監査時の質問に即答できない
- 退職・異動時に、どの認証情報を無効化すべきか追跡できない
設計方針:作成と同時に安全な格納先へ自動振り分け
IAMユーザーの作成と同時に、認証情報を用途に応じた格納先に自動的に保存する。
terraform output に認証情報の平文は出力されず、格納先のARNまたはパス名だけが出力される。
