IAM UserとIAM Roleの違い — EC2からS3にアクセスする場合はどちらを使うべきか

EC2上のアプリケーションにS3アクセスを与えようとしたとき、最初に思いつくのは「IAM Userを作ってアクセスキーを発行すればいい」という方法だ。実際、多くの現場でこのパターンが使われてきたが、これは後になって必ず問題を起こす。IAM UserとIAM Roleの違いを正確に理解していないと、セキュリティインシデントの温床になる設計を量産することになる。

TL;DR — IAM UserとIAM Roleの比較

観点IAM UserIAM Role
認証方式長期クレデンシャル(アクセスキー/パスワード)一時的なSTSトークン(自動ローテーション)
主な用途人間のオペレーター、CLIを使う開発者AWSサービス、アプリケーション、クロスアカウントアクセス
EC2からS3アクセス非推奨(アクセスキーをインスタンスに配置するリスク)推奨(インスタンスプロファイル経由で自動取得)
クレデンシャル管理手動ローテーションが必要STSが自動でローテーション
最小権限の実装ユーザー単位またはグループ単位ロール単位、引き受けるエンティティを信頼ポリシーで制御

IAM UserとIAM Roleの仕組みを理解する

IAM Userは「人」に対応するアイデンティティだ。ユーザー名とパスワード、またはアクセスキーID/シークレットアクセスキーというロングタームクレデンシャルを持つ。このクレデンシャルは明示的にローテーションしない限り有効であり続ける。

IAM Roleはそれとは根本的に異なる。Roleは「引き受けるもの」であり、それ自体はクレデンシャルを持たない。エンティティ(EC2インスタンス、Lambda関数、別アカウントのユーザーなど)がRoleを引き受けると(AssumeRole)、AWS Security Token Service(STS)が一時的なクレデンシャルを発行する。このトークンは有効期限付きで、自動的に更新される。

IAM Userのアクセスキーは、金庫の鍵を複製して誰かに渡すようなものだ。IAM Roleは、必要なときだけ開く電子錠に近い。鍵そのものは存在せず、認証されたエンティティだけが一時的にドアを開けられる。

EC2インスタンスにRoleを割り当てる場合、「インスタンスプロファイル」という仕組みを経由する。インスタンスプロファイルはIAM Roleのコンテナであり、EC2はインスタンスメタデータサービス(IMDSv2)を通じてSTSトークンを自動取得する。アプリケーションはAWS SDKを使うだけでよく、クレデンシャルを設定ファイルやコードに埋め込む必要がない。

sequenceDiagram participant App as アプリケーション participant SDK as AWS SDK participant IMDS as IMDSv2 participant STS as AWS STS participant S3 as Amazon S3 App->>SDK: S3 APIを呼び出す SDK->>IMDS: 一時クレデンシャルを要求 IMDS->>STS: インスタンスプロファイルのRole確認 STS-->>IMDS: 一時トークン発行(有効期限付き) IMDS-->>SDK: AccessKeyId / SecretKey / Token SDK->>S3: APIリクエスト(一時トークン付き) S3-->>App: レスポンス
  1. アプリケーションがAWS SDKを呼び出す。
  2. SDKはIMDSv2(http://169.254.169.254/latest/meta-data/iam/security-credentials/)から一時クレデンシャルを取得する。
  3. STSがインスタンスプロファイルに紐付いたRoleのトークンを発行する。
  4. SDKはそのトークンを使ってS3 APIを呼び出す。
  5. トークンは有効期限が近づくと自動更新される。アプリケーション側の処理は不要。

IAM Roleを使うべき理由 — アクセスキーが引き起こす実際の問題

「アクセスキーをEC2に置いておくだけでいいのでは」と思うかもしれない。実際にそのアプローチを取ったチームが後で直面する問題を具体的に見ていく。

症状: あるアプリケーションがS3にアクセスできなくなった。調査すると、~/.aws/credentialsに書かれていたアクセスキーが失効していた。誰かがIAM Userのキーをローテーションしたが、EC2インスタンス上の設定ファイルを更新し忘れていた。

誤診: 最初はS3バケットポリシーの変更を疑った。CloudTrailを確認してもS3側の変更は見当たらない。

実際の原因: IAM Userのアクセスキーは手動管理が前提のため、ローテーション漏れが発生しやすい。複数のEC2インスタンスに同じキーを配布していると、更新箇所の把握自体が困難になる。

正しい対処: インスタンスプロファイルでIAM Roleを割り当てれば、クレデンシャルの管理はSTSが担う。アプリケーションコードもインフラ設定もクレデンシャルを一切保持しない。

もう一つの深刻なリスクは漏洩だ。アクセスキーがコードリポジトリにコミットされた場合、そのキーは即座に無効化するまで有効であり続ける。一時トークンであれば、漏洩しても有効期限が切れれば自動的に無効になる。

EC2からS3にアクセスするIAM Roleの設定手順

Step 1: IAM Roleを作成する

まず、EC2サービスを信頼するIAM Roleを作成する。信頼ポリシーでec2.amazonaws.comを許可することで、EC2インスタンスがこのRoleを引き受けられるようになる。

aws iam create-role \
  --role-name EC2S3AccessRole \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "ec2.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }'

Step 2: 最小権限のIAMポリシーをアタッチする

S3の特定バケットへの読み取りアクセスのみを許可するポリシーを作成してアタッチする。バケット名は実際の環境に合わせて変更すること。

🔽 IAMポリシーJSONを展開する
aws iam put-role-policy \
  --role-name EC2S3AccessRole \
  --policy-name S3ReadOnlyPolicy \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "s3:GetObject",
          "s3:ListBucket"
        ],
        "Resource": [
          "arn:aws:s3:::your-bucket-name",
          "arn:aws:s3:::your-bucket-name/*"
        ]
      }
    ]
  }'

Step 3: インスタンスプロファイルを作成してRoleを紐付ける

EC2はRoleを直接受け取れない。インスタンスプロファイルというラッパーが必要だ。コンソールからRoleを作成した場合は同名のインスタンスプロファイルが自動作成されるが、CLIで作成した場合は手動で行う必要がある。

aws iam create-instance-profile \
  --instance-profile-name EC2S3AccessProfile

aws iam add-role-to-instance-profile \
  --instance-profile-name EC2S3AccessProfile \
  --role-name EC2S3AccessRole

Step 4: 既存のEC2インスタンスにインスタンスプロファイルを割り当てる

起動済みのインスタンスにも後からインスタンスプロファイルを割り当てられる。インスタンスIDは実際の環境のものに置き換えること。

aws ec2 associate-iam-instance-profile \
  --instance-id i-0123456789abcdef0 \
  --iam-instance-profile Name=EC2S3AccessProfile

Step 5: インスタンスからクレデンシャル取得を確認する

割り当て後、インスタンス内からIMDSv2経由でクレデンシャルが取得できることを確認する。トークンが返ってくれば設定は正しい。

# IMDSv2のセッショントークンを取得
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# インスタンスプロファイルのクレデンシャルを確認
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2S3AccessRole

正常であればAccessKeyIdSecretAccessKeyTokenExpirationを含むJSONが返る。Expirationフィールドがあることで、これが一時クレデンシャルであることがわかる。

IAM UserとIAM Role — 使い分けの判断基準

graph TD Q1{"アクセスするのは 人間か?"} Q2{"コンソール/CLIを 使うオペレーターか?"} Q3{"AWSサービスや アプリケーションか?"} Q4{"クロスアカウント アクセスか?"} A1["IAM User (できればIAM Identity Center推奨)"] A2["IAM Role (インスタンスプロファイル)"] A3["IAM Role (信頼ポリシーで制御)"] Q1 -->|Yes| Q2 Q1 -->|No| Q3 Q2 -->|Yes| A1 Q3 -->|EC2 / Lambda / ECS| A2 Q3 -->|No| Q4 Q4 -->|Yes| A3
  1. アクセスするエンティティが人間かどうかを最初に判断する。
  2. 人間であれば、AWSマネジメントコンソールやCLIを使うオペレーターにはIAM Userが適切だ。ただし、企業環境ではIAM Identity Center(旧AWS SSO)経由でRoleを引き受けるパターンが推奨されている。
  3. アプリケーション、AWSサービス、クロスアカウントアクセスには常にIAM Roleを使う。

IAM Userが適切なケースは実際には限られている。主にAWS CLIをローカルで使う開発者や、どうしてもIAM Roleを使えないサードパーティツールとの統合に限定される。それ以外のほぼすべてのケースでIAM Roleが正解だ。

よくある設定ミスと確認コマンド

インスタンスプロファイルが割り当てられているか確認する

aws ec2 describe-instances \
  --instance-ids i-0123456789abcdef0 \
  --query 'Reservations[*].Instances[*].IamInstanceProfile' \
  --output json

RoleにアタッチされているポリシーをCloudTrailで検証する

権限エラーが発生した場合、CloudTrailのAccessDeniedイベントを確認するのが最速だ。どのAPIコール、どのリソースARNで拒否されたかが記録されている。

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=GetObject \
  --start-time 2024-01-01T00:00:00Z \
  --end-time 2024-01-02T00:00:00Z \
  --query 'Events[?contains(CloudTrailEvent, `AccessDenied`)].{Time:EventTime,User:Username,Event:CloudTrailEvent}' \
  --output table

Roleの信頼ポリシーを確認する

「AssumeRoleが失敗する」という問題の大半は信頼ポリシーの設定ミスだ。Principalに正しいサービスが指定されているか確認する。

aws iam get-role \
  --role-name EC2S3AccessRole \
  --query 'Role.AssumeRolePolicyDocument' \
  --output json

IAM UserとIAM Roleの違いを理解した上での次のステップ

EC2からS3へのアクセスにはIAM Roleとインスタンスプロファイルを使うことが、AWSのベストプラクティスとして明確に推奨されている。アクセスキーをインスタンスに配置するアプローチは、管理コストとセキュリティリスクの両面で問題を抱えている。既存の環境でアクセスキーを使っている場合は、インスタンスプロファイルへの移行を優先的に検討してほしい。

次のステップとして、以下のAWS公式ドキュメントを参照することを推奨する。

用語集

用語説明
IAM UserAWSアカウント内の長期クレデンシャルを持つアイデンティティ。主に人間のオペレーター向け。
IAM Role一時的なクレデンシャルを使って引き受けるアイデンティティ。AWSサービスやアプリケーション向け。
インスタンスプロファイルIAM RoleをEC2インスタンスに紐付けるためのコンテナ。EC2はこれを通じてRoleを引き受ける。
STS(Security Token Service)一時的なセキュリティクレデンシャルを発行するAWSサービス。AssumeRole APIを提供する。
IMDSv2(Instance Metadata Service v2)EC2インスタンスがメタデータや一時クレデンシャルを取得するためのサービス。セッショントークンが必須のv2が推奨。

コメント

このブログの人気の投稿

カスタムVPCのEC2インターネット接続不可を解決する — Internet GatewayとRoute Tableの設定手順

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み