SAA S3 アクセス制御設計パターン5選|バケットポリシー・Access Points・Presigned URL・VPC Endpoint・クロスアカウント完全攻略
AWS SAA-C03 で頻出の S3 アクセス制御を完全整理。「誰が・どこから・何に対して」の3軸フレームワークで、バケットポリシー × Block Public Access・S3 Access Points・Presigned URL・VPC エンドポイントポリシー・クロスアカウント IAM ロールの5パターンを体系化。Object Ownership による ACL 廃止の現代的推奨まで、試験頻出シナリオを解法パターン早見表で一気に整理する。
「S3 のアクセス制御は IAM だけではない。バケットポリシー・ACL・Access Points・Presigned URL・VPC エンドポイントポリシーを組み合わせた多層防御が SAA の最頻出テーマだ」 — 本記事では「誰が(Principal)・どこから(ネットワーク)・何に対して(バケット/オブジェクト粒度)」の3軸フレームワークで5つの設計パターンを体系化し、試験で迷わず正解を選べる反射を身につける。
※ 本記事はアフィリエイト広告(Amazon アソシエイト等)を含みます
📑 目次
- 結論:S3 アクセス制御の3軸フレームワーク
- パターン1:バケットポリシー × Block Public Access(公開遮断の標準構成)
- パターン2:S3 Access Points(大規模データレイクの多チームアクセス管理)
- パターン3:Presigned URL(期限付き一時アクセスの安全な委任)
- パターン4:VPC エンドポイントポリシー(プライベートアクセス強制)
- パターン5:クロスアカウントアクセス制御(二重許可モデル)
- Object Ownership と ACL の廃止(現代的 S3 セキュリティの前提)
- 試験頻出シナリオ → 解法パターン早見表
- 次のアクション チェックリスト
- 関連記事
- 関連サイト
1. 結論:S3 アクセス制御の3軸フレームワーク
S3 のアクセス制御設問は「誰が(Principal)・どこから(ネットワーク)・何に対して(バケット/オブジェクト粒度)」の3軸で解く。
| 軸 | 問いかけ | 主なメカニズム |
|---|---|---|
| 誰が(Principal) | 同一アカウント?クロスアカウント?パブリック? | IAM ポリシー、バケットポリシー、ACL(廃止推奨) |
| どこから(ネットワーク) | インターネット?VPC 内のみ?特定 VPC エンドポイント? | Block Public Access、VPC エンドポイントポリシー |
| 何に対して(粒度) | バケット全体?特定プレフィックス?一時的なオブジェクト? | S3 Access Points、Presigned URL |
S3 のアクセス判断ロジック(ポリシー評価の順序):
1. 明示的 DENY(どのポリシーでも)→ 即アクセス拒否
2. 明示的 ALLOW が存在する → 許可
3. それ以外 → 暗黙的 DENY(デフォルト拒否)
クロスアカウントアクセスでは IAM ポリシー(リクエスト元アカウント) と バケットポリシー(バケット所有アカウント) の両方が ALLOW していなければならない。どちらか一方では不十分。
2. パターン1:バケットポリシー × Block Public Access(公開遮断の標準構成)
適用シナリオ
- バケットを完全にプライベートに保ち、特定の IAM エンティティのみアクセスを許可したい
- 誤操作による公開設定を組織レベルで防止したい
- S3 をバックエンドとした EC2/Lambda からのアクセスのみ許可したい
アーキテクチャ
[IAM ロール (EC2/Lambda)] → [バケットポリシー(許可)] → [S3 バケット]
↑
Block Public Access(4設定すべて ON)で
インターネットからの到達を遮断
Block Public Access の4設定
| 設定 | 効果 |
|---|---|
| BlockPublicAcls | 新規オブジェクトへのパブリック ACL 付与をブロック |
| IgnorePublicAcls | 既存のパブリック ACL を無視 |
| BlockPublicPolicy | パブリックアクセスを許可するバケットポリシーをブロック |
| RestrictPublicBuckets | パブリックバケットポリシーがあっても、公開アクセスを制限 |
バケットポリシーの基本構造
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/MyEC2Role"
},
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
3. パターン2:S3 Access Points(大規模データレイクの多チームアクセス管理)
適用シナリオ
- 1 つのバケットに複数チームがアクセスし、それぞれ異なるプレフィックスへのアクセス権限が必要
- バケットポリシーが巨大化・複雑化して管理が困難になっている
- チームごとに VPC 経由のみのアクセス制限を設けたい
S3 Access Points の仕組み
[チームA IAM ロール] → [Access Point A(プレフィックス: /team-a/*)] ─→ [S3 バケット]
[チームB IAM ロール] → [Access Point B(プレフィックス: /team-b/*)] ─→ [同一バケット]
[チームC IAM ロール] → [Access Point C(VPC 限定)] ─→ [同一バケット]
Access Points の二重許可モデル
Access Points が機能するには バケットポリシーと Access Point ポリシーの両方 が ALLOW していなければならない。
// バケットポリシー側:Access Point からのアクセスを委任
{
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
"Condition": {
"StringLike": {
"s3:DataAccessPointArn":
"arn:aws:s3:ap-northeast-1:123456789012:accesspoint/*"
}
}
}]
}
// Access Point ポリシー側:チームA に /team-a/* の権限を付与
{
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:role/TeamARole"},
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource":
"arn:aws:s3:ap-northeast-1:123456789012:accesspoint/team-a-ap/object/team-a/*"
}]
}
Access Points の VPC 限定設定
Access Point に VPC を指定すると、その Access Point は指定 VPC からのリクエストのみを受け付ける。
// Access Point 作成時の VPC Configuration(AWS CLI/SDK での設定例)
{
"VpcConfiguration": {
"VpcId": "vpc-xxxxxxxx"
}
}
4. パターン3:Presigned URL(期限付き一時アクセスの安全な委任)
適用シナリオ
- 認証されたユーザーに、一定時間だけ特定オブジェクトへのダウンロード・アップロード権限を付与したい
- S3 バケットをプライベートに保ちつつ、外部ユーザーにコンテンツを共有したい
- フロントエンドから直接 S3 にアップロードさせたい(アプリサーバー経由を避けたい)
Presigned URL の仕組み
① Lambda/EC2 が Presigned URL を生成(署名者の IAM 認証情報で署名)
② URL をクライアントに返す
③ クライアントが Presigned URL を使って S3 へ直接アクセス
(有効期限: IAM ユーザー最大 7日、IAM ロールは最大 12時間)
CloudFront Signed URL vs S3 Presigned URL
| 比較軸 | S3 Presigned URL | CloudFront Signed URL |
|---|---|---|
| 経路 | S3 直接 | CloudFront → S3(OAC 経由) |
| 有効期限の最大 | 7日(IAM ユーザー) / 12時間(ロール) | 任意に設定可能 |
| IP 制限 | 不可 | 可(IP アドレス範囲を指定) |
| コンテンツ保護強度 | 中 | 高(CloudFront OAC でバケット直接アクセスを封鎖) |
| CDN キャッシュ | なし | あり(エッジからの高速配信) |
5. パターン4:VPC エンドポイントポリシー(プライベートアクセス強制)
適用シナリオ
- VPC 内のリソース(EC2・ECS・Lambda in VPC)が S3 へアクセスする際、インターネットを経由させたくない
- 特定のバケットのみ VPC 内からアクセスを許可し、インターネットからの直接アクセスを拒否したい
- 規制要件でデータをプライベートネットワーク内のみに閉じる必要がある
Gateway 型 vs Interface 型 VPC エンドポイント
| 比較軸 | Gateway エンドポイント | Interface エンドポイント(PrivateLink) |
|---|---|---|
| 対象サービス | S3・DynamoDB のみ | 200 以上の AWS サービス + カスタム |
| 料金 | 無料 | 時間課金 + データ転送料 |
| ルーティング | ルートテーブルに自動追加 | ENI(プライベート IP)で接続 |
| DNS 解決 | パブリック DNS のまま(ルートでバイパス) | プライベート DNS で解決 |
| オンプレ経由 | 不可 | DX/VPN 経由でアクセス可能 |
VPC エンドポイントポリシーによるアクセス制限
パターン4-A:特定 VPC エンドポイント経由のみ許可(バケットポリシー側)
{
"Statement": [{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-secure-bucket",
"arn:aws:s3:::my-secure-bucket/*"
],
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "vpce-xxxxxxxx"
}
}
}]
}
パターン4-B:特定 VPC 全体からのみ許可(aws:SourceVpc 条件)
{
"Condition": {
"StringNotEquals": {
"aws:SourceVpc": "vpc-xxxxxxxx"
}
}
}
VPC エンドポイントポリシー側:特定バケットのみアクセスを許可
{
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-secure-bucket",
"arn:aws:s3:::my-secure-bucket/*"
]
}]
}
6. パターン5:クロスアカウントアクセス制御(二重許可モデル)
適用シナリオ
- アカウント A のバケットに、アカウント B の EC2/Lambda からアクセスさせたい
- データ集約バケットに複数の子アカウントからデータを書き込ませたい(マルチアカウントアーキテクチャ)
- サードパーティ SaaS に一部のデータへのアクセスを許可したい
二重許可モデルの仕組み
[アカウントB: EC2]
↓ ① AssumeRole → アカウントB の IAM ロール(s3:GetObject 許可)
↓ ② アカウントA バケットへリクエスト
[アカウントA: S3 バケットポリシー]
→ アカウントB のロール ARN を ALLOW
→ アクセス成功
クロスアカウントでは 必ず両方が ALLOW でなければならない:
| チェックポイント | 設定先 |
|---|---|
| ① リクエスト元 IAM ポリシーで S3 操作を許可 | アカウント B の IAM ロールポリシー |
| ② バケットポリシーでアカウント B のプリンシパルを許可 | アカウント A のバケットポリシー |
バケットポリシー(アカウント A)の例
{
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_B_ID:role/CrossAccountRole"
},
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::account-a-bucket/*"
}]
}
クロスアカウント + S3 Access Points の組み合わせ
クロスアカウントシナリオで複数の接続元を管理する場合、S3 Access Points を使うとバケットポリシーを Access Point ポリシーに委任でき、アカウントごとに Access Point を分けて管理できる。
7. Object Ownership と ACL の廃止(現代的 S3 セキュリティの前提)
ACL は廃止推奨
AWS は現在、ほとんどのユースケースで ACL の使用を推奨していない。新規バケットはデフォルトで「Bucket owner enforced(ACL 無効)」設定で作成される。
| Object Ownership 設定 | ACL | 動作 |
|---|---|---|
| Bucket owner enforced(推奨) | 無効 | すべてのオブジェクトはバケット所有者が所有。バケットポリシーで制御 |
| Object writer | 有効 | オブジェクトをアップロードした IAM エンティティが所有 |
| Bucket owner preferred | 有効 | アップロード時に bucket-owner-full-control ACL があればバケット所有者が所有 |
8. 試験頻出シナリオ → 解法パターン早見表
| シナリオ(要件文キーワード) | 正解パターン | 落とし穴 |
|---|---|---|
| 「プライベートバケットのオブジェクトをアプリユーザーに一時的に配布したい」 | Presigned URL | バケットポリシーでパブリック公開は NG |
| 「VPC 内からのみ S3 アクセスを許可し、インターネット経由を遮断したい」 | Gateway VPC エンドポイント + aws:SourceVpce 条件のバケットポリシー | Interface エンドポイントは有料(コスト最適化設問では誤答になりやすい) |
| 「複数チームが1つのバケットにアクセスするが、プレフィックスごとに権限を分けたい」 | S3 Access Points | バケットポリシーで委任しないと動かない(二重許可モデル) |
| 「別アカウントの Lambda からバケットにデータを書き込みたい」 | IAM ロール(AssumeRole) + バケットポリシー(両方 Allow) | どちらか一方だけでは不可 |
| 「クロスアカウントで PutObject してもバケット所有者がアクセスできるようにしたい」 | Object Ownership: Bucket owner enforced | ACL で bucket-owner-full-control を要求する古いパターンも動くが、現代的推奨は Object Ownership |
| 「特定 IP アドレスからのアクセスのみ許可したい」 | バケットポリシーに aws:SourceIp 条件 | VPC エンドポイント経由は aws:SourceIp が機能しないことがある(aws:SourceVpce を使う) |
| 「バケットポリシーを書かずに S3 をプライベートに保ちたい」 | Block Public Access(全4設定 ON) | デフォルトでも ON だが、明示的に確認する必要がある設問あり |
| 「S3 へのアクセスをコスト効率よくプライベートネットワーク経由にしたい」 | Gateway VPC エンドポイント(無料) | Interface エンドポイントを選ぶと誤答 |
9. 次のアクション チェックリスト
- S3 バケットで Block Public Access の全4項目が ON になっているか確認
- ACL が無効化され、Object Ownership が「Bucket owner enforced」になっているか確認
- クロスアカウントアクセスで「IAM ポリシー AND バケットポリシー」の二重許可を設定したか
- VPC 内から S3 へのアクセスに Gateway VPC エンドポイントを使っているか(インターネット経由を排除)
- Presigned URL の有効期限を最小限に設定しているか(長期共有なら CloudFront Signed URL を検討)
- 複数チームへのアクセス管理に S3 Access Points を活用しているか(バケットポリシーの複雑化を防ぐ)
10. 関連記事
- Amazon S3 完全ガイド
- SAA S3 設計パターン10選
- SAA 暗号化設計パターン(KMS・SSE-S3・SSE-KMS)
- SAA IAM 設計パターン
- VPC エンドポイント(Gateway・Interface・PrivateLink)
- AWS KMS — 鍵管理サービス完全解説
- IAM ポリシー完全ガイド