はじめに
Amazon S3に対して一時的なアクセス権限を付与したい場合、署名付きURLの使用がまず検討項目に上がると思います。
アクセス権限を付与したいエンドユーザがオンプレミス環境にいて、かつインターネットを経由せずにS3までの通信を行いたいケースでは、AWS PrivateLink for Amazon S3を使用した構成を検討する必要があります。
AWS PrivateLink for Amazon S3を作成すると、以下のような2種類のエンドポイント固有のDNS名が払い出されます。
vpce-xxx-yyy.s3.<Regison名>.vpce.amazonaws.com
vpce-xxx-yyy-<AZ名>.s3.<Region名>.vpce.amazonaws.com
このDNS名を使用して署名付きURLを発行できるのか検証してみたので、その内容についてまとめます。検証のモチベーションについては記事の後段でまとめています。
構成図
以下のような構成を考えます。
VPC-1に配置したEC2 bastion
からTransit GatewayとPrivateLinkを経由してS3にアクセスしたい、というのが要件です。
今回の構成ではVPC-1をオンプレミス環境、EC2をオンプレミスサーバに見立てて検証を行っていきます。
検証手順・結果
リソースの作成
上記構成を作成するために、以下のTerraformコードを使用します。
リソースの作成後、マネジメントコンソールからVPCエンドポイントのDNS名を確認します。
いくつかのDNS名が記載されていますが、vpce.amazonaws.com
というドメインを持つものがエンドポイント固有のS3 DNS名です。
署名付きURLの作成
ローカルの端末からbastion
に対してSSH接続した上で、bastion
内でAWS SDKを使用して署名付きURLを発行します。
署名付きURLの作成には以下のAWS公式ドキュメントで公開されているpythonのサンプルコードを使用します。
注意点として、エンドポイント固有のS3 DNS名を使用して署名付きURLを作成する場合は、以下のようにboto3.client
の実行時にendpoint_url
を指定する必要があります。
endpoint_url
を指定しない場合、パブリックのS3 DNS名(s3.<リージョン名>.vpce.amazonaws.com)を使用して署名付きURLが作成されます。
s3_client = boto3.client(
"s3",
region_name="ap-northeast-1",
endpoint_url="https://bucket.vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com"
)
また、endpoint_urlにはvpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com
というFQDNは使用できないので注意が必要です。VPCエンドポイントに対してアクセスする際に使用する証明書のCNおよびSANには上記のDNS名が含まれないので、証明書エラーが発生します。
[root@ip-10-0-1-241 ~]# HOST="vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com"
[root@ip-10-0-1-241 ~]# echo | openssl s_client -connect ${HOST}:443 -servername ${HOST} \
-showcerts 2>/dev/null \
| openssl x509 -noout -text \
| grep -A1 "Subject Alternative Name"
X509v3 Subject Alternative Name:
DNS:s3.ap-northeast-1.amazonaws.com, DNS:*.control.vpce-xxx-yyy-ap-northeast-1c.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.accesspoint.vpce-xxx-yyy-ap-northeast-1d.s3.ap-northeast-1.vpce.amazonaws.com, DNS:bucket.vpce-xxx-yyy-ap-northeast-1c.s3.ap-northeast-1.vpce.amazonaws.com, DNS:bucket.vpce-xxx-yyy-ap-northeast-1a.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.bucket.vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.control.vpce-xxx-yyy-ap-northeast-1a.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.control.vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.bucket.vpce-xxx-yyy-ap-northeast-1d.s3.ap-northeast-1.vpce.amazonaws.com, DNS:bucket.vpce-xxx-yyy-ap-northeast-1d.s3.ap-northeast-1.vpce.amazonaws.com, DNS:bucket.vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.s3.ap-northeast-1.amazonaws.com, DNS:*.accesspoint.vpce-xxx-yyy-ap-northeast-1c.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.control.vpce-xxx-yyy-ap-northeast-1d.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.accesspoint.vpce-xxx-yyy-ap-northeast-1a.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.bucket.vpce-xxx-yyy-ap-northeast-1a.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.accesspoint.vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.bucket.vpce-xxx-yyy-ap-northeast-1c.s3.ap-northeast-1.vpce.amazonaws.com, DNS:*.s3-control.ap-northeast-1.amazonaws.com, DNS:*.s3-accesspoint.ap-northeast-1.amazonaws.com
S3に対するアクセスのテスト
サンプルコードを実行すると、INFO: Got presigned URL:
に続いて署名付きURLが出力されます。FQDNがendpoint_url
で指定したURLのFQDN: bucket.<エンドポイント固有のS3 DNS名>
と同じになっていることが確認できます。
200 OK
が返されているので、署名付きURLを使用して正常にS3にアクセスできているようです。
(.venv) [root@ip-10-0-1-241 ~]# python3 main.py vpc-endpoint-demo-renewing-bird test.txt get
----------------------------------------------------------------------------------------
Welcome to the Amazon S3 presigned URL demo.
----------------------------------------------------------------------------------------
INFO: Found credentials from IAM Role: bastion_ec2_role
INFO: Got presigned URL: https://bucket.vpce-xxx-yyy.s3.ap-northeast-1.vpce.amazonaws.com/vpc-endpoint-demo-renewing-bird/test.txt?AWSAccessKeyId= ...
Using the Requests package to send a request to the URL.
Status: 200
Reason: OK
----------------------------------------------------------------------------------------
(.venv) [root@ip-10-0-1-241 ~]#
本検証のモチベーション
エンドポイント固有のS3 DNS名を使用せずに、バブリックのS3 DNS名を使用して署名付きURLを作成した場合、閉域網内で署名付きURLを使用するには以下の設定が必要です。
① インタフェースエンドポイント作成時に「プライベートDNS名」を有効にする
② Route 53 Inbound Resolver Endpointを作成する
③ オンプレミスからのDNSクエリがRoute 53のプライベートホストゾーンで名前解決されるようにオンプレ側のDNSに転送設定を行う
構成図にすると以下のような形になります。
社内固有のDNSサーバをオンプレ環境に持つ場合、他の③の設定を入れるのが難しいケースもあると思います。エンドポイント固有のS3 DNS名を使用すれば、このDNS名はRoute 53のパブリックホストゾーンで名前解決が行われるため、②、③の設定を入れることなく署名付きURLを使用することができます。
まとめ
エンドポイント固有のS3 DNS名を使用して署名付きURLを発行できるかについて検証しました。
どなたかの参考になれば幸いです。