🪣 🔒 🔗

S3バケットポリシー × VPCエンドポイント

プライベートネットワークからS3へ安全にアクセスする方法を完全図解

🎯 結論ファースト:3分でわかるポイント
🔑 条件キーを使う
aws:sourceVpce(特定エンドポイント)または aws:SourceVpc(VPC全体)を使ってアクセス元を制限
Deny + StringNotEqualsが定番
「指定エンドポイント以外からのアクセスを拒否」するパターンが最も安全で確実
🚪 Gatewayエンドポイントが無料
S3用のGatewayエンドポイントは無料で使える。オンプレ接続が必要な場合はInterfaceを使用
⚠️ 自分を締め出さないよう注意
ポリシー適用後はコンソールからもアクセス不可に。エンドポイントIDの確認を忘れずに

🏦 たとえ話で理解:「秘密のトンネルがある銀行の金庫室」

🎭 登場人物とAWSサービスの対応
🏦
銀行の金庫室
= S3バケット
🚇
秘密の専用トンネル
= VPCエンドポイント
📋
入場許可ルール
= バケットポリシー
👮
ガードマン
= IAM + 条件キー

💡 イメージ:銀行の金庫室(S3)には、正面玄関(インターネット経由)と秘密のトンネル(VPCエンドポイント)があります。
バケットポリシーで「秘密のトンネルからしか入れないルール」を作ると、正面玄関は閉鎖され、
専用トンネルを持つVIP顧客(EC2など)だけが金庫にアクセスできるようになります🔐

🔄 アクセス経路の比較:危険な道 vs 安全なトンネル

🌐
インターネット経由(危険)
公共の道路を通るルート
🖥️ EC2 🌐 Internet Gateway ☁️ パブリックインターネット 🪣 S3
  • データがAWSネットワークの外を通る
  • 通信が盗聴されるリスクあり
  • NATゲートウェイのコストがかかる
  • コンプライアンス要件を満たせない場合も
🔒
VPCエンドポイント経由(安全)
専用の秘密トンネル
🖥️ EC2 🚇 VPCエンドポイント 🔐 AWS内部ネットワーク 🪣 S3
  • データはAWS内部ネットワークのみを通過
  • インターネットを経由しないため安全
  • Gatewayエンドポイントは無料
  • コンプライアンス要件を満たせる

🚪 S3用VPCエンドポイントの2つの種類

🚪 Gateway Endpoint
🎭 たとえ:銀行への専用地下トンネル(無料・VPC内限定)
  • 💰
    無料で利用可能 - データ転送料もかからない
  • 🛣️
    ルートテーブルで制御 - 特定サブネットからのみアクセス
  • 🏠
    VPC内限定 - オンプレミスからは使えない
  • 🎯
    ほとんどのケースでこちらを推奨
🔌 Interface Endpoint
🎭 たとえ:銀行への専用電話回線(有料・外部接続可)
  • 💵
    時間課金 + データ転送料 - コストがかかる
  • 🌍
    オンプレミス・他リージョンから接続可能
  • 🔗
    PrivateLinkを使用 - ENIでプライベートIP付与
  • 🏢
    ハイブリッド環境で必要な場合に使用

🔑 バケットポリシーで使う3つの条件キー

🎯 aws:sourceVpce
特定のVPCエンドポイントからのアクセスのみを許可/拒否する
🎭 たとえ話
「トンネルAのIDカードを持っている人だけ入場OK」
"aws:sourceVpce": "vpce-1a2b3c4d"
🏢 aws:SourceVpc
特定のVPC全体からのアクセスを制御(複数エンドポイントをまとめて許可)
🎭 たとえ話
「A社ビルの社員証を持っている人は全員入場OK」
"aws:SourceVpc": "vpc-111bbb22"
📍 aws:VpcSourceIp
VPCエンドポイント経由でアクセスするプライベートIPアドレスを指定
🎭 たとえ話
「トンネル経由で、さらに部屋番号10.1.1.1の人だけ入場OK」
"aws:VpcSourceIp": "10.1.1.0/24"
⚠️ 重要な注意点

VPCエンドポイント経由のリクエストには aws:SourceIp は使えません!
インターネット経由のアクセスを制限したい場合は aws:SourceIp を使いますが、
VPCエンドポイント経由の場合は代わりに aws:VpcSourceIp を使用してください。

📝 バケットポリシーの書き方パターン

🥇
パターン1:特定のVPCエンドポイントからのみアクセス許可(推奨)
Deny + StringNotEquals で「それ以外を拒否」する安全なパターン
🎭 たとえ話
「秘密のトンネル(vpce-1a2b3c4d)から来た人以外は、全員入場お断り!」
💡 なぜDeny + NotEqualsなのか?
Allowだけだと、他のポリシーで許可されていれば入れてしまう。Denyは最優先なので確実にブロックできる。
bucket-policy.json
{
    "Version": "2012-10-17",
    "Id": "VPCEndpointOnlyAccess",
    "Statement": [
        {
            "Sid": "Access-to-specific-VPCE-only",
            "Effect": "Deny",  // ← 拒否ルール
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::my-secure-bucket",
                "arn:aws:s3:::my-secure-bucket/*"
            ],
            "Condition": {
                "StringNotEquals": {  // ← 「〜でない場合」
                    "aws:sourceVpce": "vpce-1a2b3c4d"  // ← あなたのエンドポイントIDに置き換え
                }
            }
        }
    ]
}
🥈
パターン2:特定のVPC全体からのアクセスを許可
同じVPC内に複数のエンドポイントがある場合に便利
🎭 たとえ話
「A社ビル(vpc-111bbb22)のどのトンネルから来ても入場OK。それ以外はNG」
💡 使いどころ
同一VPC内に複数のGateway/Interfaceエンドポイントがあり、まとめて許可したい場合
bucket-policy-vpc.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyAccessFromOutsideVPC",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::my-secure-bucket",
                "arn:aws:s3:::my-secure-bucket/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpc": "vpc-111bbb22"  // ← あなたのVPC IDに置き換え
                }
            }
        }
    ]
}
🥉
パターン3:複数のVPCエンドポイントを許可
開発環境・本番環境など、複数環境からのアクセスを許可
bucket-policy-multi.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowMultipleVPCEndpoints",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",  // ← アップロードのみ制限する例
            "Resource": "arn:aws:s3:::my-secure-bucket/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": [
                        "vpce-1111111",  // 本番環境
                        "vpce-2222222"   // 開発環境
                    ]
                }
            }
        }
    ]
}

🚀 設定手順:ステップバイステップ

1
🔍 VPCエンドポイントを確認 or 作成
まず、S3用のGateway VPCエンドポイントが作成されているか確認します。なければ新規作成が必要です。
# 既存のVPCエンドポイントを一覧表示 aws ec2 describe-vpc-endpoints \ --filters "Name=service-name,Values=com.amazonaws.ap-northeast-1.s3" \ --query "VpcEndpoints[*].[VpcEndpointId,VpcId,State]" \ --output table
2
📝 エンドポイントIDをメモ
表示された vpce-xxxxxxxxx 形式のIDをコピーしておきます。
💡 ヒント:VPCエンドポイントがない場合は、VPCコンソール → エンドポイント → エンドポイントを作成 から作成してください。
3
📋 バケットポリシーを作成
上記のポリシーテンプレートを使って、JSONファイルを作成します。エンドポイントIDとバケット名を置き換えてください。
# ポリシーファイルを作成 cat > bucket-policy.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Sid": "Access-to-specific-VPCE-only", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::YOUR-BUCKET-NAME", "arn:aws:s3:::YOUR-BUCKET-NAME/*" ], "Condition": { "StringNotEquals": { "aws:sourceVpce": "vpce-YOUR-ENDPOINT-ID" } } } ] } EOF
4
🚀 バケットポリシーを適用
AWS CLIを使ってS3バケットにポリシーを適用します。
# バケットポリシーを適用 aws s3api put-bucket-policy \ --bucket YOUR-BUCKET-NAME \ --policy file://bucket-policy.json # 適用されたポリシーを確認 aws s3api get-bucket-policy \ --bucket YOUR-BUCKET-NAME \ --output text | jq .
5
動作確認
VPCエンドポイントを経由するEC2からアクセスできることと、それ以外からアクセスできないことを確認します。
# VPCエンドポイント経由のEC2から(成功するはず) aws s3 ls s3://YOUR-BUCKET-NAME/ # ローカルPC等から(Access Deniedになるはず) aws s3 ls s3://YOUR-BUCKET-NAME/

⚠️ 陥りやすい罠と対策

🔒 自分を締め出してしまう
ポリシーを適用すると、AWSコンソールからもアクセスできなくなります。IAMユーザーがインターネット経由でアクセスするため、拒否されます。
✅ 対策
ルートユーザーでログインするか、アカウントレベルのS3設定から復旧できます。適用前にエンドポイントIDを二重確認!
🌍 リージョン不一致
VPCエンドポイントとS3バケットは同じリージョンにある必要があります。異なるリージョンでは機能しません。
✅ 対策
バケットとエンドポイントのリージョンが一致していることを事前に確認してください。
🛣️ ルートテーブル設定漏れ
Gatewayエンドポイントを作成しても、EC2があるサブネットのルートテーブルに紐づけないと機能しません。
✅ 対策
エンドポイント作成時に適切なルートテーブルを選択。または後から「ルートテーブルの管理」で追加。
📛 Allowだけではダメ
EffectをAllowにしただけでは、他のポリシーで許可されている場合にインターネット経由でもアクセスできてしまいます。
✅ 対策
確実にブロックするには「Deny + StringNotEquals」パターンを使用。Denyは最優先で評価されます。

📊 実践ユースケース

🏥 医療データの保護
HIPAA等のコンプライアンス要件で、患者データがインターネットを通らないことを保証する必要がある場合
# 医療データバケットへのアクセスを # 院内VPCエンドポイントのみに制限 "aws:sourceVpce": "vpce-hospital-vpc"
💳 金融データの保護
PCI-DSS準拠のため、クレジットカード情報を含むデータはプライベートネットワーク経由のみでアクセス
# 決済システムVPCからのみ許可 "aws:SourceVpc": "vpc-payment-system"
🔬 研究データの分離
機密性の高い研究データを、特定の研究チームのみがアクセスできるよう制限
# 複数の研究チームVPCから許可 "aws:sourceVpce": [ "vpce-research-team-a", "vpce-research-team-b" ]
🏭 本番/開発環境の分離
本番環境のS3バケットには本番VPCからのみ、開発バケットには開発VPCからのみアクセス可能に
# 環境ごとにバケットとVPCを紐づけ Production: "aws:SourceVpc": "vpc-prod" Development: "aws:SourceVpc": "vpc-dev"

❓ よくある質問(FAQ)

Q. VPCエンドポイント経由とインターネット経由を両方許可したい場合は?
Denyステートメントを使わず、必要な許可のみをAllowで追加します。ただし、インターネット経由を許可する場合は、セキュリティ上の理由がないか再検討することをお勧めします。VPCエンドポイント経由に統一する方が安全です。
Q. Gateway EndpointとInterface Endpoint、どちらを使うべき?
Gateway Endpoint推奨の場合:VPC内のEC2からS3にアクセスする一般的なケース。無料で使えます。
Interface Endpoint必須の場合:VPN/Direct Connect経由でオンプレミスからS3にプライベートアクセスしたい場合、または異なるリージョンのVPCからアクセスしたい場合。
Q. ポリシー適用後にコンソールからアクセスできなくなりました。どうすれば?
AWSアカウントのルートユーザーでログインし、S3コンソールからバケットポリシーを削除または修正してください。ルートユーザーはバケットポリシーに関係なくアクセスできます。また、別のIAMユーザーでCloudShellからエンドポイント経由でアクセスすることも可能です。
Q. Lambda関数からS3にアクセスする場合も同じ設定が必要?
LambdaをVPC内に配置している場合は、同じVPCエンドポイント経由でアクセスできます。VPC外のLambdaの場合はVPCエンドポイントを使用できないため、別の条件(aws:SourceAccount等)での制限を検討してください。

🎓 まとめ

🔑
条件キーを使う
aws:sourceVpce で特定エンドポイント
aws:SourceVpc でVPC全体を指定
Deny + NotEqualsパターン
「指定以外は拒否」で
確実にブロック
🚪
Gatewayが基本
VPC内からなら無料の
Gatewayエンドポイントを選択
⚠️
締め出し注意
コンソールアクセス不可に注意
エンドポイントIDを要確認
🏦 銀行の金庫室(S3)を守る最強のセキュリティ:

📋 入場ルール(バケットポリシー)で「秘密のトンネル(VPCエンドポイント)から来た人だけ入場OK」と設定!
🚇 これで正面玄関(インターネット)は完全閉鎖され、VIP専用トンネルを持つ人だけがアクセスできます。

コンプライアンス要件もバッチリ満たせる、鉄壁のS3セキュリティを実現しよう!🛡️

Created by SSuzuki1063

AWS SAP Learning Resources