SJ blog
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日以内にローテーション
  • 信頼ポリシーとアクセス許可ポリシーは別物