📁 完全なコードはGitHubで公開:GitHub: pipeiac02
シリーズ一覧(全12回)
Phase 1: 基盤構築
Phase 2: ワークフロー
Phase 3: セキュリティ・運用
Phase 4: 開発効率化
1. はじめに
1-1. 今回のゴール
これまで作成したIAMポリシーが最小権限の原則に沿っているか確認します。
| ゴール | 内容 |
|---|---|
| 理解 | 最小権限の原則を深く理解する |
| 確認 | 各ロールの権限が適切か確認する |
| 検証 | セキュリティ強化オプションを学ぶ |
1-2. 前回までの振り返り
第2〜6回で、パイプラインの各コンポーネントを作成しました。
1-3. この記事でやること
各コンポーネントのIAM権限が最小権限の原則に従っているか確認し、さらなるセキュリティ強化オプションを学びます。
2. 比喩で理解する
2-1. IAMを「スタッフ権限」で考える
レストランでも、スタッフごとに権限が異なります。
2-2. 比喩の図解(レストラン)
2-3. なぜ権限を分けるのか?
2-4. AWSでの対応関係
| レストラン | AWS | 例 |
|---|---|---|
| スタッフ | IAMロール | Lambda実行ロール |
| 権限証 | IAMポリシー | S3読み取り許可 |
| エリア | AWSリソース | S3バケット、DynamoDB |
| 仕事内容 | アクション | GetObject、PutObject |
2-5. 最小権限の原則
| 原則 | 説明 | 料理で例えると |
|---|---|---|
| 必要なアクションだけ | 読み取りだけなら書き込み不要 | 料理人は調理だけ、会計は不要 |
| 必要なリソースだけ | 特定のバケットだけ | 厨房Aの冷蔵庫だけ |
| 必要な期間だけ | 一時的な権限は期限付き | アルバイトは営業時間だけ |
3. 最小権限の原則
3-1. なぜ最小権限が重要か
3-2. 実務でのベストプラクティス
| プラクティス | 説明 | 例 |
|---|---|---|
| リソースを限定 |
* を避けて具体的なARNを指定 |
特定のS3バケットだけ |
| アクションを限定 | 必要なアクションだけ許可 |
s3:GetObject だけ |
| 条件を追加 | 特定条件でのみ許可 | 特定のIPからのみ |
| 定期的な見直し | 不要な権限を削除 | 四半期ごとにレビュー |
3-3. ワイルドカード(*)の危険性
# ❌ 危険:全リソースへのアクセス
Resource = "*"
# ✅ 安全:特定リソースのみ
Resource = "arn:aws:s3:::dp-raw-12345/*"
| パターン | リスク | 推奨度 |
|---|---|---|
"*" |
全リソースにアクセス可能 | ❌ 避ける |
arn:aws:s3:::* |
全S3バケット | ⚠️ 注意 |
arn:aws:s3:::dp-* |
dpで始まるバケット | △ 許容 |
arn:aws:s3:::dp-raw-12345/* |
特定バケットのオブジェクト | ✅ 推奨 |
4. 権限の確認
これまで作成した4つのIAMロールが最小権限の原則に従っているか確認します。
4-1. 作成した4つのIAMロール
4-2. Lambda ロールの権限
# iam.tf - aws_iam_policy.lambda_s3
# S3アクセス
Action = ["s3:GetObject"]
Resource = "${aws_s3_bucket.raw.arn}/*"
Action = ["s3:PutObject"]
Resource = "${aws_s3_bucket.processed.arn}/*"
評価: ✅ 良好
- 特定のバケットのみ指定
- 必要なアクションのみ許可
4-3. Crawler ロールの権限
# iam.tf - aws_iam_policy.glue_s3
# S3アクセス
Action = ["s3:GetObject", "s3:ListBucket"]
Resource = [
aws_s3_bucket.processed.arn,
"${aws_s3_bucket.processed.arn}/*"
]
評価: ✅ 良好
- 特定のバケットのみ指定
- 読み取りのみ許可
4-4. Step Functions ロールの権限
# iam.tf - aws_iam_policy.sfn
# Lambda実行
Action = ["lambda:InvokeFunction"]
Resource = [aws_lambda_function.etl.arn] # ✅ 特定のLambdaのみ
# Glue Crawler
Action = ["glue:StartCrawler", "glue:GetCrawler"]
Resource = ["arn:aws:glue:${var.aws_region}:*:crawler/${aws_glue_crawler.main.name}"] # ✅ 特定のCrawlerのみ
評価: ✅ 良好
- 特定のLambda関数のみ指定
- 特定のCrawlerのみ指定
4-5. EventBridge ロールの権限
# iam.tf - aws_iam_policy.eventbridge
# Step Functions起動
Action = ["states:StartExecution"]
Resource = aws_sfn_state_machine.pipeline.arn # ✅ 特定のステートマシンのみ
評価: ✅ 良好
- 特定のステートマシンのみ指定
4-6. 権限サマリー
| ロール | 評価 | リソース指定 |
|---|---|---|
| Lambda | ✅ 良好 | 特定のS3バケットのみ |
| Crawler | ✅ 良好 | 特定のS3バケットのみ |
| Step Functions | ✅ 良好 | 特定のLambda、Crawlerのみ |
| EventBridge | ✅ 良好 | 特定のステートマシンのみ |
すべてのロールが最小権限の原則に従っています。
5. 追加のセキュリティ強化(オプション)
本番環境では、さらに以下の強化を検討できます。
5-1. 条件の追加(Condition)
ポリシーに条件を追加することで、より細かい制御が可能です。
# 特定のVPCからのみアクセス許可
Condition = {
StringEquals = {
"aws:SourceVpc" = "vpc-xxxxx"
}
}
5-2. タグベースのアクセス制御
# 特定のタグを持つリソースのみ
Condition = {
StringEquals = {
"aws:ResourceTag/Environment" = "dev"
}
}
5-3. IPアドレス制限
# 特定のIPアドレスからのみ許可
Condition = {
IpAddress = {
"aws:SourceIp" = ["192.168.1.0/24"]
}
}
5-4. 権限のテスト
権限が正しく設定されているか確認します。
# テストデータをアップロード
aws s3 cp test-data/iam-test.json s3://dp-raw-$(terraform output -raw bucket_suffix)/input/
# 実行状態を確認(5〜10秒後)
SFN_ARN=$(aws stepfunctions list-state-machines --query 'stateMachines[?contains(name, `dp-pipeline`)].stateMachineArn' --output text)
aws stepfunctions list-executions --state-machine-arn $SFN_ARN --max-results 1 --query 'executions[0].{Status:status}'
期待される出力:
{
"Status": "SUCCEEDED"
}
6. まとめ
6-1. この記事でやったこと
| 項目 | 内容 |
|---|---|
| 理解 | 最小権限の原則 |
| 確認 | 4つのロールの権限が適切か? |
| 学習 | 追加のセキュリティ強化オプション |
6-2. 比喩の振り返り
| レストラン | AWS | 今回やったこと |
|---|---|---|
| スタッフ | IAMロール | 権限を確認 |
| 権限証 | IAMポリシー | 最小権限であることを確認 |
| エリア制限 | リソースARN | 特定リソースに限定されていることを確認 |
6-3. 最小権限チェックリスト
| 項目 | 確認 |
|---|---|
Resource = "*" を避けているか |
✅ |
| 必要なアクションだけ許可しているか | ✅ |
| 特定のリソースARNを指定しているか | ✅ |
| マネージドポリシーは必要最小限か | ✅ |
6-4. 権限マップ
6-5. 次回予告
第8回: エラーハンドリング では、障害対応を実装していきます。
- Step Functions のリトライ設定
- エラー時のSNS通知
- Catch/Retry パターン
レストランで言うと「料理失敗時の対応マニュアル」を作っていきます。