IAM UserとIAM Roleの違い — EC2からS3にアクセスする場合はどちらを使うべきか
EC2上のアプリケーションにS3アクセスを与えようとしたとき、最初に思いつくのは「IAM Userを作ってアクセスキーを発行すればいい」という方法だ。実際、多くの現場でこのパターンが使われてきたが、これは後になって必ず問題を起こす。IAM UserとIAM Roleの違いを正確に理解していないと、セキュリティインシデントの温床になる設計を量産することになる。
TL;DR — IAM UserとIAM Roleの比較
| 観点 | IAM User | IAM 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を使うだけでよく、クレデンシャルを設定ファイルやコードに埋め込む必要がない。
- アプリケーションがAWS SDKを呼び出す。
- SDKはIMDSv2(
http://169.254.169.254/latest/meta-data/iam/security-credentials/)から一時クレデンシャルを取得する。 - STSがインスタンスプロファイルに紐付いたRoleのトークンを発行する。
- SDKはそのトークンを使ってS3 APIを呼び出す。
- トークンは有効期限が近づくと自動更新される。アプリケーション側の処理は不要。
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
正常であればAccessKeyId、SecretAccessKey、Token、Expirationを含むJSONが返る。Expirationフィールドがあることで、これが一時クレデンシャルであることがわかる。
IAM UserとIAM Role — 使い分けの判断基準
- アクセスするエンティティが人間かどうかを最初に判断する。
- 人間であれば、AWSマネジメントコンソールやCLIを使うオペレーターにはIAM Userが適切だ。ただし、企業環境ではIAM Identity Center(旧AWS SSO)経由でRoleを引き受けるパターンが推奨されている。
- アプリケーション、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 User | AWSアカウント内の長期クレデンシャルを持つアイデンティティ。主に人間のオペレーター向け。 |
| IAM Role | 一時的なクレデンシャルを使って引き受けるアイデンティティ。AWSサービスやアプリケーション向け。 |
| インスタンスプロファイル | IAM RoleをEC2インスタンスに紐付けるためのコンテナ。EC2はこれを通じてRoleを引き受ける。 |
| STS(Security Token Service) | 一時的なセキュリティクレデンシャルを発行するAWSサービス。AssumeRole APIを提供する。 |
| IMDSv2(Instance Metadata Service v2) | EC2インスタンスがメタデータや一時クレデンシャルを取得するためのサービス。セッショントークンが必須のv2が推奨。 |
コメント
コメントを投稿