S3のVPC Endpointを作成した場合、アクセス元がPrivateサブネットにあれば弊社Godai Nakamuraのblog(*1)にある通りcurl等を利用してインターネットの任意のサイトへアクセスはできないが、S3へはVPC Endpointを作成した事でアクセス可能となった事を確認をするといったシンプルな話で済みます。
しかしPublicサブネットの場合は、デフォルトルート(0.0.0.0/0)がIGWに向いているためIGW経由でもVPC Endpoint経由でもS3へアクセス出来るため上の手法は通用しません。
従って実際にどの経路でアクセスがされたのかを見極めるには少し深い確認をする必要があります。
Publicサブネットのルートテーブルの例 (S3のVPC Endpointの経路設定済み) (*2)
ytamu@SilverMachine:~$ aws ec2 describe-route-tables --route-table-id=rtb-0b9d6fda75bce0adf --query 'RouteTables[].Routes[]' --output table ------------------------------------------------------------------------------------------------------------- | DescribeRouteTables | +----------------------+---------------------------+-------------------------+-------------------+----------+ | DestinationCidrBlock | DestinationPrefixListId | GatewayId | Origin | State | +----------------------+---------------------------+-------------------------+-------------------+----------+ | 10.0.0.0/16 | | local | CreateRouteTable | active | | 0.0.0.0/0 | | igw-01d45a55298df7dad | CreateRoute | active | | | pl-61a54008 | vpce-0a7e08b0a117fddb5 | CreateRoute | active | +----------------------+---------------------------+-------------------------+-------------------+----------+ ytamu@SilverMachine:~$ ytamu@SilverMachine:~$ date;aws ec2 describe-prefix-lists --prefix-list-ids=pl-61a54008 Thu May 16 07:40:22 UTC 2019 { "PrefixLists": [ { "Cidrs": [ "52.219.0.0/20", "54.231.224.0/21", "52.219.16.0/22", "52.219.68.0/22" ], "PrefixListId": "pl-61a54008", "PrefixListName": "com.amazonaws.ap-northeast-1.s3" } ] } ytamu@SilverMachine:~$
このルートテーブルを見た瞬間、S3関連のIPアドレス帯が4つ指定されているのでロンゲストマッチでVPC Endpointに向く(IGWを経由しない)筈だし問題ないであろうと思えたりもしますが、設定後には実際に通信を発生させ動作確認(裏どり)はしておきたいものです。
確認方法の1つの例として、CloudTrailのログから確認するといった手法があるので今回メモ代わりに残します。
これからやる事を一行で纏めると
「当該PublicサブネットにいるEC2インスタンスからS3へ何らかのアクションを実行し、CloudTrailの対象ログにあるCloudTrailEventの内容から経路を判断する」です。
CloudTrailにイベントログとして残りさえすればどのようなオペレーションでも良い筈(*3)ですが、今回は一時的に適当なS3bucketを作成しそのログから経路を確認します。
簡易検証環境の構成はざっくり以下です。
|
EC2(Amazon Linux2)からS3bucketを作成して削除します。
(膨大な量のCloudTrailのログを追いやすくなるので同時にdateを叩いておくと後に幸せになれます)
# S3bucket作成 [ec2-user@ip-10-0-0-225 ~]$ date;aws s3 mb s3://via-vpce-test Thu May 16 07:52:32 UTC 2019 make_bucket: via-vpce-test [ec2-user@ip-10-0-0-225 ~]$
# S3bucket削除 (お掃除が目的) [ec2-user@ip-10-0-0-225 ~]$ date;aws s3 rb s3://via-vpce-test Thu May 16 07:52:41 UTC 2019 remove_bucket: via-vpce-test [ec2-user@ip-10-0-0-225 ~]$
そして、IGW経由となるようルーティングテーブルを設定し直し(VPC EndpointとPublicサブネットの関連づけを外し)、今度は上の内容をS3bucket名: via-igw-testとして再度実施します。(こちらは差分確認しなくて良いなら別にやらなくて良いです)
# S3のVPC Endpointから PublicサブネットのルートテーブルをRemove ytamu@SilverMachine:~$ aws ec2 modify-vpc-endpoint --vpc-endpoint-id vpce-0a7e08b0a117fddb5 --remove-route-table-ids=rtb-0b9d6fda75bce0adf --reset-policy { "Return": true } ytamu@SilverMachine:~$
実施が完了したらCloudTrailからS3bucketを作成した対象ログを突き止めます。
ytamu@SilverMachine:~$ aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateBucket
"EventName": "CreateBucket" ログが対象日時前後で見つかる筈です。
マネージドコンソールを利用して確認(*5)した方が楽だと思われます。
# CloudTrailのログ反映には少々時間がかかるのでまだ出力されていなければ珈琲でも飲みながら待ちましょう。そして参照リージョンを間違え珈琲も冷めてしまう事があるので気をつけましょう。<-自分への戒め
S3bucket作成した対象ログのCloudTrailEventの中身を確認すると以下のような感じになっており
"vpcEndpointId": "vpce-0a7e08b0a117fddb5" といった今回作成したVPC EndpointのID情報が2箇所見て取れます。
CloudTrailEvent[]の中が JSONのなかにJSONといった感じで人の目に優しくないビジュアルな為、今回はjqコマンドツールを利用して整形しています。
また、不本意ですが色々と伏せた方がよさげな情報がドバドバ出たので一部結果を XXXX といった形で手動で置き換えています。
ytamu@SilverMachine:~$ aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventId,AttributeValue=3b44035b-5a47-433d-aee4-deb02606ee7c --query 'Events[].CloudTrailEvent[]' --output text |jq { "eventVersion": "1.05", "userIdentity": { "type": "AssumedRole", "principalId": "XXXXXXXXXXXXXXXXXXXXX:i-XXXXXXXXXXXXXXXXX", "arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/S3FullAccess-Role/i-0942293cad73b36c3", "accountId": "XXXXXXXXXXXX", "accessKeyId": "XXXXXXXXXXXXXXXXXXXX", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2019-05-16T07:28:34Z" }, "sessionIssuer": { "type": "Role", "principalId": "XXXXXXXXXXXXXXXXXXXXX", "arn": "arn:aws:iam::XXXXXXXXXXXX:role/S3FullAccess-Role", "accountId": "XXXXXXXXXXXX", "userName": "S3FullAccess-Role" } } }, "eventTime": "2019-05-16T07:52:34Z", "eventSource": "s3.amazonaws.com", "eventName": "CreateBucket", "awsRegion": "ap-northeast-1", "sourceIPAddress": "10.0.0.225", "userAgent": "[aws-cli/1.16.102 Python/2.7.14 Linux/4.14.114-103.97.amzn2.x86_64 botocore/1.12.92]", "requestParameters": { "CreateBucketConfiguration": { "LocationConstraint": "ap-northeast-1", "xmlns": "http://s3.amazonaws.com/doc/2006-03-01/" }, "bucketName": "via-vpce-test", "host": [ "via-vpce-test.s3.ap-northeast-1.amazonaws.com" ] }, "responseElements": null, "additionalEventData": { "SignatureVersion": "SigV4", "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256", "AuthenticationMethod": "AuthHeader", "vpcEndpointId": "vpce-0a7e08b0a117fddb5" }, "requestID": "XXXXXXXXXXXXXXXX", "eventID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "eventType": "AwsApiCall", "recipientAccountId": "XXXXXXXXXXXX", "vpcEndpointId": "vpce-0a7e08b0a117fddb5" } ytamu@SilverMachine:~$
今回、VPC Endpoint経由とIGW経由のCloudTrailEventの差分は以下の通りでした。
"vpcEndpointId"の有無の違いだけでなく、
"sourceIPAddress"がVPC Endpoint経由の場合はEC2のプライベートIPアドレスであり、IGW経由の場合はAWSのグローバルIPアドレスとなっている事がわかります。
ytamu@SilverMachine:~$ aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventId,AttributeValue=3b44035b-5a47-433d-aee4-deb02606ee7c --query 'Events[].CloudTrailEvent[]' --output text |jq > /tmp/via-vpce-test ytamu@SilverMachine:~$ aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventId,AttributeValue=81a05480-c6cd-4168-bca1-0929ce9c637b --query 'Events[].CloudTrailEvent[]' --output text |jq > /tmp/via-igw-test ytamu@SilverMachine:~$ diff -u /tmp/via-igw-test /tmp/via-vpce-test --- /tmp/via-igw-test 2019-05-16 22:57:04.000000000 +0900 +++ /tmp/via-vpce-test 2019-05-16 22:56:47.000000000 +0900 @@ -5,11 +5,11 @@ "principalId": "XXXXXXXXXXXXXXXXXXXX":i-XXXXXXXXXXXXXXXXX", "arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/S3FullAccess-Role/i-XXXXXXXXXXXXXXXXX", "accountId": "XXXXXXXXXXXX", - "accessKeyId": "XXXXXXXXXXXXXXXXXXXX", + "accessKeyId": "XXXXXXXXXXXXXXXXXXXX", "sessionContext": { "attributes": { "mfaAuthenticated": "false", - "creationDate": "2019-05-16T12:51:42Z" + "creationDate": "2019-05-16T07:28:34Z" }, "sessionIssuer": { "type": "Role", @@ -20,30 +20,32 @@ } } }, - "eventTime": "2019-05-16T13:33:09Z", + "eventTime": "2019-05-16T07:52:34Z", "eventSource": "s3.amazonaws.com", "eventName": "CreateBucket", "awsRegion": "ap-northeast-1", - "sourceIPAddress": "54.199.166.59", + "sourceIPAddress": "10.0.0.225", "userAgent": "[aws-cli/1.16.102 Python/2.7.14 Linux/4.14.114-103.97.amzn2.x86_64 botocore/1.12.92]", "requestParameters": { "CreateBucketConfiguration": { "LocationConstraint": "ap-northeast-1", "xmlns": "http://s3.amazonaws.com/doc/2006-03-01/" }, - "bucketName": "via-igw-test", + "bucketName": "via-vpce-test", "host": [ - "via-igw-test.s3.ap-northeast-1.amazonaws.com" + "via-vpce-test.s3.ap-northeast-1.amazonaws.com" ] }, "responseElements": null, "additionalEventData": { "SignatureVersion": "SigV4", "CipherSuite": "ECDHE-RSA-AES128-GCM-SHA256", - "AuthenticationMethod": "AuthHeader" + "AuthenticationMethod": "AuthHeader", + "vpcEndpointId": "vpce-0a7e08b0a117fddb5" }, - "requestID": "XXXXXXXXXXXXXXXX", - "eventID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", + "requestID": "XXXXXXXXXXXXXXXX", + "eventID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "eventType": "AwsApiCall", - "recipientAccountId": "XXXXXXXXXXXX" + "recipientAccountId": "XXXXXXXXXXXX", + "vpcEndpointId": "vpce-0a7e08b0a117fddb5" } ytamu@SilverMachine:~$
参考URI
*1...VPC Endpointを使ってS3にアクセスしてみる
http://blog.serverworks.co.jp/tech/2015/08/31/vpc-endpoint/
*2...ゲートウェイ VPC エンドポイント
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpce-gateway.html
*3...AWS CloudTrail を使用して Amazon S3 API コールのログを記録する
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/cloudtrail-logging.html
*4...jq
https://stedolan.github.io/jq/
*5...CloudTrailの基本
http://blog.serverworks.co.jp/tech/2018/03/05/cloudtrail_basic/