S3のバケットポリシーで、PrivateLinkからのみ操作可能にする方法

2021.05.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

データアナリティクス事業本部の笠原です。

S3がPrivateLinkに対応したことで、オンプレからS3への接続がかなり楽になりましたね。

DirectConnectからS3に直結!「AWS PrivateLink for Amazon S3」を試してみた | DevelopersIO

今回はS3のバケットポリシーで、特定のPrivateLinkからしかアクセスさせないようにできないか、調査しました。

最初にまとめ

  • ゲートウェイ型エンドポイントと同じように、 aws:sourceVpceにて特定のインタフェース型エンドポイントからのアクセスに制限するようバケットポリシーを書けばOK
  • CLIは最新のv2にしておこう

バケットポリシーの記述を確認

AWSのドキュメントに記載がありました。

AWS PrivateLink for Amazon S3 - Amazon Simple Storage Service

ドキュメントに記載されているバケットポリシーの例です。

{
  "Version": "2012-10-17",
  "Id": "Policy1415115909152",
  "Statement": [
    { "Sid": "Access-to-specific-VPCE-only",
      "Principal": "*",
      "Action": "s3:*",
      "Effect": "Deny",
      "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET2",
                   "arn:aws:s3:::DOC-EXAMPLE-BUCKET2/*"],
      "Condition": {"StringNotEquals": {"aws:sourceVpce": "vpce-1a2b3c4d"}}
    }
  ]
}

この例では、バケット DOC-EXAMPLE-BUCKET2 へのアクセスを VPCエンドポイントID vpce-1a2b3c4d 経由以外からのアクセスを拒否しています。PrivateLinkは「インタフェース型VPCエンドポイント」なので、このポリシーを使えばアクセス経路を制限できそうです。

実際に試してみる

以下の構成で試してみました。

EC2からCLIを使ってPrivateLink経由でS3にアクセスしようと思います。

EC2はAmazon Linux 2のt3.microを使用しました。

比較用のために、EC2はパブリックサブネットに設置して、従来のインターネット経由アクセスをできるようにしておきます。今回の検証では、PrivateLinkはパブリックサブネットに置いても良かったですが、プライベートサブネットに設置しました。

PrivateLink用のセキュリティグループ作成

PrivateLinkに付与するセキュリティグループを事前に用意します。今回は以下のように、VPC内からの443番ポートのアクセスを許可する設定をしました。

S3用のPrivateLink作成

マネジメントコンソールから作りました。

[VPC] → [エンドポイント] → [エンドポイント作成] からS3のPrivateLinkを作成します。

Gateway型とInterface型が選べるようになってますので、今回はInterface型を選択します。

作成対象のVPCとサブネットを指定し、先ほど作成したPrivateLink用のセキュリティグループを選択したら、あとはデフォルト値のままで作成します。エンドポイントのポリシーもそのままにしておきます。

作成が完了すると、プライベートサブネット内にENIが設置され、IPアドレスが付与されます。

また該当のエンドポイントIDとDNS名をメモしておきます。

バケットポリシー

アクセスするバケットのバケットポリシーは以下のようにしました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "access-to-specific-VPC-endpoint-only-for-s3",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::s3-privatelink-test-kasahara/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "vpce-1234567890abcdef"
                }
            }
        }
    ]
}

今回は検証用なので、アクションを絞りました。 aws:sourceVpce で、作成したPrivateLinkのエンドポイントIDを指定します。

CLIを使ってアクセス確認

AWS CLIを使ってアクセスしてみます。

まずは、ポリシーで拒否していないバケット内オブジェクト一覧取得をしてみます。

インターネット経由での取得は以下の通りですね。

$ aws s3 ls s3://s3-privatelink-test-kasahara/
2021-05-28 16:19:33         21 hoge.txt

PrivateLink経由での取得は、 --endpoint-url を指定します。エンドポイントのURLは、マネジメントコンソールにあるDNS名を基に参照しましょう。今回はバケットにアクセスするので、DNS名のサブドメインに bucket を指定します。(他にも、 accesspointcontrol があります)

$ aws s3 --endpoint-url https://bucket.vpce-1234567890abcdef-xxxxxxxx.s3.ap-northeast-1.vpce.amazonaws.com ls s3://s3-privatelink-test-kasahara
2021-05-28 16:19:33         21 hoge.txt

では、ポリシーでPrivateLink以外のアクセスを拒否している、オブジェクトの取得をしてみます。

インターネット経由での取得は以下の通り拒否されました。

$ aws s3 cp s3://s3-privatelink-test-kasahara/hoge.txt .
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden

PrivateLink経由での取得は成功しました。

$ aws s3 --endpoint-url https://bucket.vpce-1234567890abcdef-xxxxxxxx.s3.ap-northeast-1.vpce.amazonaws.com cp s3://s3-privatelink-test-kasahara/hoge.txt .
download: s3://s3-privatelink-test-kasahara/hoge.txt to ./hoge.txt

まとめ

PrivateLink経由からのみ操作可能なS3バケットポリシーについて検証しました。ゲートウェイ型のVPCエンドポイントと同じようにバケットポリシーで制御がかけられます。適切な権限を設定した上で、AWSのサービスを活用しましょう。

おまけ

EC2からCLIでアクセスする際に、デフォルトのAWS CLIのバージョンがv1でした。

$ aws --version
aws-cli/1.18.147 Python/2.7.18 Linux/4.14.231-173.361.amzn2.x86_64 botocore/1.18.6

このバージョンのままですと、 --endpoint-url オプションを指定しても、インターネット経由でアクセスするようで、アクセスが拒否されます。

AWS CLIをv2にアップグレードすることで解決します。

$ aws --version
aws-cli/2.2.7 Python/3.8.8 Linux/4.14.231-173.361.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off

実はAWS CLIのバージョンが原因だと気づくまでに、結構時間かかりました...。