security
A
信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
IAMロール vs IAMユーザー — 使い分けと設計原則
IAMユーザーとIAMロールの違い、AssumeRoleの仕組み、EC2/Lambda/クロスアカウントでのロール設計、長期クレデンシャルを避けるべき理由を解説します。
一言結論
EC2・Lambda・ECS等のAWSサービスには必ずIAMロールを使い、CI/CDはOIDC連携でアクセスキーを完全排除することが現代のベストプラクティスであり、長期クレデンシャルであるアクセスキーを環境変数やコードに持たせることは漏洩リスクが高く避けるべきだ。
IAMユーザーとIAMロールの本質的な違い
IAMユーザーは「人」に対応する長期クレデンシャル(アクセスキーID+シークレットキー)を持つエンティティだ。一方IAMロールは「誰でも引き受けられる権限セット」であり、引き受けた主体に一時的なクレデンシャル(STS)を発行する。
現代のAWSベストプラクティスでは、アプリケーションやAWSサービスにIAMユーザーのアクセスキーを持たせることは禁止に近い扱いだ。
長期クレデンシャルの問題
# ❌ 悪い例: アプリケーションにアクセスキーをハードコード
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
# → ソースコードへの混入、漏洩リスク、ローテーション忘れなどの問題
IAMユーザーのアクセスキーは:
- 有効期限がない(明示的にローテーションしない限り永続)
- 漏洩した場合の影響が長期にわたる
- MFAの強制が難しい(プログラムアクセスの場合)
IAMロールとSTS一時クレデンシャル
# ✅ 良い例: EC2インスタンスプロファイルでロールを割り当て
# → インスタンスメタデータから自動取得(アプリはキーを持たない)
# STSの一時クレデンシャル取得(手動でAssumeRoleする場合)
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/AppRole \
--role-session-name my-session \
--duration-seconds 3600
STS一時クレデンシャルは:
- 有効期限が1時間〜12時間(ロール設定による)
- 漏洩しても短時間で無効化される
- CloudTrailに
sts:AssumeRoleとして記録される
ロールの信頼ポリシー(Trust Policy)
ロールには「誰が引き受けられるか」を定義する信頼ポリシーが必要だ。これはアイデンティティポリシーとは別のポリシードキュメントだ。
// EC2インスタンスが引き受けられるロールの信頼ポリシー
{
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
// Lambda関数が引き受けられるロール
{
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
// クロスアカウントAssumeRole(MFA必須条件付き)
{
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}]
}
インスタンスプロファイルの仕組み
EC2にIAMロールを割り当てる際は「インスタンスプロファイル」というコンテナを介する。AWS CLIやコンソールからロールを割り当てると自動作成されるが、CloudFormationでは明示的に作成が必要だ。
# CloudFormation例
MyInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref MyRole
MyInstance:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref MyInstanceProfile
IAMユーザーが有効な場面
IAMロールが使えない(または不便な)ケースではIAMユーザーが適切だ:
| ユースケース | 推奨 |
|---|---|
| 人間のコンソールログイン | IAMユーザー(+MFA)またはIDフェデレーション |
| AWS CLI(開発環境、個人) | IAMユーザーのアクセスキー(定期ローテーション) |
| EC2/Lambda等のAWSサービス | IAMロール(必須) |
| CI/CD(GitHub Actions等) | OIDC連携でIAMロール(アクセスキー不要) |
| クロスアカウントアクセス | IAMロール(必須) |
| 外部ベンダーへのアクセス付与 | IAMロール(External ID付き) |
External IDでのなりすまし防止
クロスアカウントロールを外部ベンダーに提供する場合、External IDの設定が重要だ。「混乱した代理(Confused Deputy)」攻撃を防ぐ。
{
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::VENDOR_ACCOUNT:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-secret-id-12345"
}
}
}]
}
IAMユーザーのアクセスキー管理
やむを得ずアクセスキーを使う場合のベストプラクティス:
# 90日以上使われていないキーを検出
aws iam generate-credential-report
aws iam get-credential-report --query 'Content' --output text | \
base64 -d | awk -F',' '$11 != "N/A" && $11 < "2025-01-01" {print $1, $11}'
# キーのローテーション: 新キー作成→アプリ更新→旧キー無効化→旧キー削除
aws iam create-access-key --user-name AppUser
# (アプリケーション側でキーを更新)
aws iam update-access-key --access-key-id OLD_KEY_ID --status Inactive
aws iam delete-access-key --access-key-id OLD_KEY_ID
まとめ
- AWSサービス(EC2/Lambda等)には必ずIAMロールを使う
- クロスアカウントアクセスはロール+外部ベンダーはExternal ID
- CI/CDはOIDC連携でアクセスキー完全排除
- やむを得ないIAMユーザーのキーは90日以内にローテーション
- 信頼ポリシーとアクセス許可ポリシーは別物