SJ blog
security
A

信頼度ランク

S 公式ソース確認済み
A 成功実績多数・失敗例少数
B 賛否両論
C 動作未確認・セキュリティリスク高
Z 個人所感

S3バケットポリシー vs IAMポリシー — 優先順位・使い分け・組み合わせパターン

S3アクセス制御のバケットポリシーとIAMポリシーの評価ロジック、同一アカウントとクロスアカウントの違い、ACLとの関係、バケットポリシーが必要なケースを具体例で解説。

一言結論

S3のクロスアカウントアクセスはバケットポリシーとIAMポリシーの両方のAllowが必須であり、Block Public AccessはポリシーのAllowより優先されるため、VPCエンドポイント経由のみを強制したい場合はバケットポリシーでaws:SourceVpce条件のDenyを使うのが正しいアプローチだ。

S3アクセス制御の全体像

S3アクセス制御には複数のレイヤーがある。

1. バケットポリシー(リソースベース)
2. IAMポリシー(アイデンティティベース)
3. S3 ACL(Access Control List)← レガシー、現在は非推奨
4. アクセスポイントポリシー
5. S3 Block Public Access設定

評価ロジックの基本

同一アカウント内:
  バケットポリシー OR IAMポリシーの一方がAllowでOK
  (明示的Denyがなければ)

クロスアカウント:
  バケットポリシー AND IAMポリシーの両方がAllow必須

バケットポリシーを使うべきケース

IAMポリシーだけではできない制御をバケットポリシーで実現する。

ケース1: パブリックアクセスの制御

// 静的ウェブサイト公開(特定バケットをパブリックに)
{
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-website-bucket/*"
  }]
}

ケース2: VPCエンドポイント経由のみ許可

{
  "Statement": [{
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": [
      "arn:aws:s3:::secure-bucket",
      "arn:aws:s3:::secure-bucket/*"
    ],
    "Condition": {
      "StringNotEquals": {
        "aws:SourceVpce": "vpce-0123456789abcdef0"
      }
    }
  }]
}

ケース3: HTTPSのみ許可(HTTP経由を拒否)

{
  "Statement": [{
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": [
      "arn:aws:s3:::my-bucket",
      "arn:aws:s3:::my-bucket/*"
    ],
    "Condition": {
      "Bool": {
        "aws:SecureTransport": "false"
      }
    }
  }]
}

ケース4: クロスアカウントアクセス

// 別アカウントのロールにアクセス許可
{
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::987654321098:role/DataProcessingRole"
    },
    "Action": [
      "s3:GetObject",
      "s3:ListBucket"
    ],
    "Resource": [
      "arn:aws:s3:::my-bucket",
      "arn:aws:s3:::my-bucket/*"
    ]
  }]
}

ケース5: 特定のKMSキーによる暗号化を強制

{
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "StringNotEqualsIfExists": {
          "s3:x-amz-server-side-encryption-aws-kms-key-id":
            "arn:aws:kms:ap-northeast-1:123456789012:key/xxx"
        }
      }
    }
  ]
}

S3 Block Public Access の優先度

Block Public Access設定はバケットポリシーより優先される

バケットレベルとアカウントレベルの2段階で設定可能:

アカウントレベル: 全バケットに適用(推奨: 全てBlockに設定)
バケットレベル:   個別のバケットに設定

BlockPublicAcls:          ACLによるパブリックアクセスをブロック
IgnorePublicAcls:         既存のパブリックACLを無視
BlockPublicPolicy:        パブリックポリシーの設定をブロック
RestrictPublicBuckets:    パブリックバケットへの匿名アクセスをブロック
# アカウントレベルでBlock Public Accessを有効化
aws s3control put-public-access-block \
  --account-id 123456789012 \
  --public-access-block-configuration '{
    "BlockPublicAcls": true,
    "IgnorePublicAcls": true,
    "BlockPublicPolicy": true,
    "RestrictPublicBuckets": true
  }'

ACLはいつ使うか

S3 ACLは現在非推奨で、デフォルトで無効化されている(Object Ownership: Bucket owner enforced)。

非推奨の理由:
- バケットポリシーで同じことが細かく実現できる
- 管理が複雑(各オブジェクトにACLが付く)
- クロスアカウントのオブジェクル所有権問題が発生しやすい

有効に残っているケース:
- CloudFrontのアクセスログ(OAIを使う古い設定)
- 一部のレガシーシステム

バケットポリシーのサイズ制限

バケットポリシーは20KBの制限がある。複雑なポリシーがこの制限に達した場合は、IAMポリシーへの分散やポリシーの整理が必要だ。

試験頻出パターン

シナリオ解決策
Organizationsメンバーのみアクセス可バケットポリシーに aws:PrincipalOrgID 条件
VPCエンドポイント経由のみ許可aws:SourceVpce 条件でDeny
HTTPS強制aws:SecureTransport: false でDeny
特定プレフィックスへの書き込みのみ許可s3:prefix 条件とPutObjectのAllow

まとめ

S3のアクセス制御はバケットポリシーとIAMポリシーを適切に組み合わせることで実現される。クロスアカウントは両方のAllow必須という原則と、Block Public AccessがポリシーのAllow設定より優先されることを確実に理解しておく。