まず結論
EC2 から S3 にアクセスさせたいなら、アプリケーションに長期 Access Key を配る設計は避けます。基本は IAM Role を EC2 にアタッチし、Instance Metadata Service 経由で一時認証情報を使わせる 形です。
もうひとつ見落としやすいのが iam:PassRole です。S3 を読む権限そのものと、「その権限を持つ Role を EC2 に渡せる権限」は別物です。ここを混ぜると、権限設計が雑になり、事故の入口になります。
この記事では、EC2 に S3 権限を渡すときの考え方を、実務と試験対策の両方で使える粒度に整理します。
やってはいけない設計
EC2 上のアプリケーションに、次のような設定を置く設計は避けるべきです。
AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxx
動くことは動きます。だから厄介です。ただし、長期 Access Key は漏れた瞬間にそのまま使われます。AMI、ログ、環境変数、デプロイ成果物、Git リポジトリ、運用メモ。漏れる場所はいくらでもあります。
EC2 で動くワークロードに AWS API を呼ばせるなら、まず IAM Role を使う前提で考えます。
正しい基本形: IAM Role を EC2 にアタッチする
EC2 には IAM Role を直接「置く」のではなく、Instance Profile を通じて関連付けます。アプリケーションは AWS SDK や CLI の標準認証プロバイダチェーンを使い、一時認証情報を取得します。
典型的な構成はこうです。
| 要素 | 役割 |
|---|---|
| IAM Policy | S3 に対して何ができるかを定義する |
| IAM Role | EC2 が引き受ける権限の入れ物 |
| Trust Policy | その Role を EC2 サービスが引き受けられることを許可する |
| Instance Profile | IAM Role を EC2 インスタンスに関連付けるための器 |
たとえば特定バケットを読み取り専用にするなら、権限は最小限にします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::example-bucket/*"
}
]
}
s3:* を付ければ話が早い、という発想はだいたい後で自分を殴ります。まず必要な API と対象リソースを絞ります。
iam:PassRole は何を許可しているのか
ここが試験でも実務でも混ざりやすい点です。
S3 にアクセスできる Role を作っただけでは、誰でもその Role を EC2 に付けられるわけではありません。EC2 作成者や変更者には、対象 Role をサービスへ渡すための iam:PassRole が必要です。
つまり権限は二段階です。
- EC2 が引き受ける Role に、S3 操作権限がある
- 操作者に、その Role を EC2 に渡す iam:PassRole がある
たとえば、運用担当者に特定 Role だけを渡せるようにするなら、PassRole の対象を絞ります。
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/ec2-s3-readonly-role",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
}
この条件を入れると、「その Role を EC2 に渡す」用途に限定しやすくなります。Role の中身が強いほど、PassRole の範囲は慎重に絞るべきです。
よくある事故パターン
よくある失敗は、S3 権限ではなく PassRole 側を広げすぎることです。
| 事故パターン | 何がまずいか |
|---|---|
iam:PassRole の Resource が *
|
強い Role を任意のサービスに渡せる可能性がある |
EC2 Role に AmazonS3FullAccess を雑に付ける |
不要なバケット操作まで許可される |
| Access Key をアプリ設定に保存する | 漏えい時に長期利用される |
| Trust Policy と権限ポリシーを混同する | 「誰が引き受けるか」と「何ができるか」が崩れる |
例えば、EC2 には読み取りだけでよいのに、バケット削除や書き込みまで許可しているケースがあります。これは便利ではなく、ただの爆弾です。
設計時のチェックリスト
最低限、次を確認します。
- Access Key を配っていないか
- EC2 Role の S3 権限は必要最小限か
- 対象バケット、prefix、操作 API を絞っているか
- iam:PassRole の Resource が特定 Role に限定されているか
-
iam:PassedToServiceで EC2 向けに制限できているか - CloudTrail で Role の利用や PassRole 操作を追えるか
このあたりを押さえておけば、「EC2 から S3 にアクセスできるようにしただけ」の作業が、あとから権限事故になる確率をかなり下げられます。
まとめ
EC2 から S3 を使うなら、長期 Access Key を配るのではなく IAM Role を使います。そして、Role の S3 権限と iam:PassRole は分けて考えます。
- アプリケーションには長期 Access Key を持たせない
- EC2 には Instance Profile 経由で IAM Role を関連付ける
- S3 権限は必要な Action / Resource に絞る
- iam:PassRole は「誰がどの Role を EC2 に渡せるか」を制御する
権限設計は、動けば終わりではありません。あとから読んでも意図が分かる粒度まで絞る。そこまでやって、ようやく運用に乗せてよい設計です。