S3へのアクセスをEC2のプライベートIPアドレスで制御してみた

2022.12.15

S3バケットポリシーを使用してEC2の持つグローバルIPで制御したことはあったのですが、VPC内のプライベートIPの場合はどうすればよいのだろうと思ったのでやってみました。
今回はGateway型のVPCエンドポイントをS3へアクセスするEC2のプライベートIPアドレスで、S3のアクセスを制限する検証を行いました。

グローバルIPアドレスで制御する場合

グローバルIPアドレスで制御する場合は以下のようにaws:SourceIpを使用して制御できます。
以下のバケットポリシーは特定のグローバルIPアドレス以外からのPutObject、GetObject、ListBucketを禁止するものになります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "S3バケットARN",
                "S3バケットARN/*"
            ],
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "X.X.X.X/32"
                }
            }
        }
    ]
}

上記のポリシーの「X.X.X.X」をグローバルIPアドレスにすることで動作します。
「X.X.X.X」をプライベートIPアドレスにしようとすると以下の画像のようにエラーが発生します。

プライベートIPアドレスで制御する場合

結論としてはドキュメントにも記載されている通りバケットポリシーの条件を「aws:VpcSourceIp」に変更し、VPCエンドポイントを使用してプライベートにアクセスさせることで解決できます。
バケットポリシーは以下のようになります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "S3バケットARN",
                "S3バケットARN/*"
            ],
            "Condition": {
                "NotIpAddress": {
                    "aws:VpcSourceIp": "X.X.X.X/32"
                }
            }
        }
    ]
}

上記のポリシーの「X.X.X.X」をプライベートIPアドレスにすることで動作します。

マネジメントコンソールからS3のVPCエンドポイントを作成する場合は以下のドキュメントを参考にしてください。
ゲートウェイエンドポイントを作成する
Amazon S3 におけるエンドポイント

VPCエンドポイントをCloudFormationで作成してみました。
テンプレートは以下になります。

AWSTemplateFormatVersion: "2010-09-09"

Description: Endpoint

Parameters:
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------# 
  RouteTableId:
    Type: String

  VpcId:
    Type: String

Resources:
# ------------------------------------------------------------#
# Endpoint
# ------------------------------------------------------------# 
  Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      RouteTableIds: 
        - !Ref RouteTableId
      ServiceName: com.amazonaws.ap-northeast-1.s3
      VpcEndpointType: Gateway
      VpcId: !Ref VpcId

以下のAWS CLIコマンドでCloudFormationを実行します。

aws cloudformation create-stack --stack-name CloudFormationスタック名 --template-body file://CloudFormationテンプレートファイル名 --parameters ParameterKey=RouteTableId,ParameterValue=ルートテーブルID ParameterKey=VpcId,ParameterValue=VPCID

VPCエンドポイントとバケットポリシーを設定した状態で、該当のIPアドレスを持つEC2からS3バケット内を以下のコマンドで覗くと成功することが確認できます。
該当のIPアドレスを持っていないEC2からはAccessDeniedで失敗します。

aws s3 ls s3://S3バケット名

さいごに

今回はIPアドレスでアクセスを制御するバケットポリシーの検証をやってみました。
ポリシーの条件周りは使ったことの無いものも多くあるので今後も学習を続けていきたいと思います。