[AWS] VPC Endpoint で S3 にアクセスするときはリージョン指定に注意が必要な件

VPC Endpointで利用できるのはVPCと同じリージョンのエンドポイントのみです。一方で、S3はリージョンを明示しなくてもアクセスできてしまうので、気をつけなければいけないという話。
2018.04.05

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

こんにちは、菊池です。

小ネタです。S3やDynamoDBなど、AWSのパブリックサービスへのアクセスにVPC Endpointを利用すると、パブリックIPを持たないEC2インスタンスからもAWSネットワークを経由してアクセスが可能です。この、VPC Endpointを経由したアクセスですが、利用できるのはVPCと同じリージョンのエンドポイントのみとなります。

VPC Endpointを経由するアクセス

VPC Endpontはリージョンに紐付くサービスなので、その先のエンドポイントにルーティングできるのも同じリージョンのサービスに限定されます。

注意したいのは、S3の場合です。S3のバケット名は全リージョンでユニークなので、AWS CLIなどでアクセスする際には、リージョンを明示的に指定しなくてもバケット名のみでアクセスすることが可能です。しかし、アクセスするリージョンを明示的に指定するか、また、指定のリージョンがアクセス元と同一のリージョンかによって、VPC Endpointが利用できるかが異なります。

  • 同一のS3リージョンを明示的に指定:VPC Endpoint利用可能
  • 異なるS3リージョンを明示的に指定:VPC Endpointを利用しない(Internet Gatewayを利用する)
  • S3のリージョンを明示的に指定しない:VPC Endpointを利用しない(Internet Gatewayを利用する)

という動作になります。図に表すと以下のイメージです。

注意したいのは、アクセス元のEC2がプライベートサブネットにあるケースです。この場合、Internet Gatewayへの経路を持ちませんので、リージョンを明示的に指定していない場合、「VPC Endpointがあるのにアクセスできない」という状況になります。

動作検証

実際に試してみました。

以下のように、S3へのVPC Endpointをルートに持つSubnetからコマンドを実行します。(SSHで接続するため、接続元IPのみInternet Gatewayに向けています)

まずは--region ap-northeast-1を明示してアクセスしてみます。

$ aws s3api --region ap-northeast-1 list-objects --bucket BucketName
{
    "Contents": [
        {
            "LastModified": "2018-04-04T17:56:48.000Z",
            "ETag": "\"3ecd07d1fb24f65d4625xxxxxxxxxxxx\"",
            "StorageClass": "ONEZONE_IA",
            "Key": "testdata",
            "Owner": {
                "DisplayName": "XXXXXXXXXX",
                "ID": "4b74cb703f805e7b3102f39010d5429db939d4e62ddbxxxxxxxxxxxxxxxxxxxx"
            },
            "Size": 3202610
        }
    ]
}

これは問題なくアクセスできています。次に、リージョンを明示せずにアクセスしてみます。

$ aws s3api list-objects --bucket BucketName

HTTPSConnectionPool(host='s3.amazonaws.com', port=443): Max retries exceeded with url: /BucketName?encoding-type=url (Caused by ConnectTimeoutError(<botocore.awsrequest.AWSHTTPSConnection object at 0x7fdd57114450>, 'Connection to s3.amazonaws.com timed out. (connect timeout=60)'))

この場合にはアクセスできずにタイムアウトしています。また、エラーからエンドポイントs3.amazonaws.comにアクセスしようとしていることがわかります。

コマンドでリージョンを明示しなくても、aws configureでデフォルトリージョンを指定できます。ここでap-northeast-1を指定した上であれば、以下のようにアクセス可能です。

$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]:
$ aws s3api list-objects --bucket BucketName
{
    "Contents": [
        {
            "LastModified": "2018-04-04T17:56:48.000Z",
            "ETag": "\"3ecd07d1fb24f65d4625xxxxxxxxxxxx\"",
            "StorageClass": "ONEZONE_IA",
            "Key": "testdata",
            "Owner": {
                "DisplayName": "XXXXXXXXXX",
                "ID": "4b74cb703f805e7b3102f39010d5429db939d4e62ddbxxxxxxxxxxxxxxxxxxxx"
            },
            "Size": 3202610
        }
    ]
}

また、リージョンを明示的に指定しても、他のリージョンはアクセスできません。

$ aws s3 --region us-west-2 ls BucketName

HTTPSConnectionPool(host='s3.us-west-2.amazonaws.com', port=443): Max retries exceeded with url: /BucketName?delimiter=%2F&prefix=&encoding-type=url (Caused by ConnectTimeoutError(<botocore.awsrequest.AWSHTTPSConnection object at 0x7f1e11283d90>, 'Connection to s3.us-west-2.amazonaws.com timed out. (connect timeout=60)'))

この場合には、s3.us-west-2.amazonaws.comにアクセスしようとしていることがわかります。

まとめ

以上です。

これまで、なんとなくVPC Endpointを使ってきましたが、気づかなかった制約でハマるポイントがありましたので紹介しました。S3へのアクセスはリージョンを明示指定しなくてもアクセスできますが、余計なトラブルを避けるため、明示的に指定するのを基本とするのがよいかと思います。