S3のバケットポリシーで、PrivateLinkからのみ操作可能にする方法
データアナリティクス事業本部の笠原です。
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
を指定します。(他にも、 accesspoint
や control
があります)
$ 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のバージョンが原因だと気づくまでに、結構時間かかりました...。