VPC Peeringで他AWSアカウントのS3にファイルをアップロードしよう

VPC peeringとVPC interface endpoint(privatelink)を利用して、AWSネットワークで他アカウントのS3にファイルをアップロードする方法を記載した記事です。
2021.12.30

こんにちはクラスメソッドのスジェです。
この前、自分持ちではないS3にファイルをアップロードする方法を調べたことがあります。
その中でVPC Peeringと他アカウントのVPC endpointを通じて、AWSネットワークだけでS3にファイルをアップロードする方法があるので書いてみます。
(インターネットを経由しないで他アカウントのS3バケットにファイルをアップロードすることだけが目的であれば、VPC Gateway Endpointだけでも問題ありません。)

構成

VPC peeringが設定されていない既存の構成は、このようにインターネットを通じてS3にファイルをアップロードしています。
VPC peeringを設定するとこのようにAWSネットワークを通じてファイルをアップロードします。

やってみよう

VPC endpointとは?

VPC エンドポイントを使用すると、Virtual Private Cloud (VPC) とサポートされているサービスの間の接続が有効になります。インターネットゲートウェイ、NAT デバイス、VPN 接続、および AWS Direct Connect 接続は必要ありません。したがって、VPC はパブリックインターネットに公開されません。 - 公式ドキュメント

パブリックインターネットに公開されずAWSネットワークで通信できるようにするサービスです。
インターフェイスエンドポイント(AWS Privatelink)とゲートウェイエンドポイントタイプがあります。
本記事ではインターフェイスエンドポイントを利用します。
また、エンドポイント自体のコストも発生します。
詳細な内容は公式ドキュメントを参考してください。

前提

ピアリングを作成してファイルをアップロードするアカウントをアカウントA
S3を持っているアカウントをアカウントB とします。

手順

本記事ではVPC peeringの設定から始めます。

  1. ピアリング設定
  2. エンドポイント設定
  3. S3作成、ポリシー設定
  4. EC2からファイルアップロード

ピアリング設定

アカウントA からアカウントB にピアリングを作成します。
VPCコンソールの[ピアリング接続]で接続を作成します。

下記のような画面でピアリングを接続するアカウント A のVPCを選びます。
続いてアカウントB のID、VPC ID を記入します。

作成したらアカウントB が接続を許可するまでステータスが承諾の保留中(Pending acceptance) となります。
アカウントB にログインしてVPCコンソールのピアリング接続で承諾の保留中の接続をクリックし[アクション - リクエストの承諾]で接続を完了します。
少し待機したらステータスが変わります。

続いてピアリング接続を作成したVPCのプライベートルートテーブルにピアリング接続のルートを追加します。
送信先(Destination)にはアカウントB のVPCのcidrを記入します。

エンドポイント設定

アカウントB でインターフェイスエンドポイントを作成します。
その前にエンドポイントに適用するセキュリティグループを作成します。
アカウントA のピアリングされたVPCのcidr からの通信を許可するようにインバウンドを設定します。

その後VPCコンソールの[エンドポイント]でエンドポイントを作成します。
s3サービスのinterface タイプ、対象のVPCと作成したセキュリティグループを指定します。必要によってポリシーも設定します。

S3作成

アカウントBでS3を作成してからポリシーを更新します。
既に利用していたS3をそのまま利用する場合はポリシーだけ更新します。
本記事ではsujae-peering-test-1 というバケットを作成し、次の通りにポリシーを設定しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::{アカウントA のID}:role/{アカウントA のEC2に設定されるロール名}"
            },
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::sujae-peering-test-1",
                "arn:aws:s3:::sujae-peering-test-1/*"
            ]
        }
    ]
}

EC2 からファイルアップロード

最後にEC2 からファイルをアップロードしてみます。
まずS3 にアップロードできるようにロールをEC2 に指定します。
アカウントB でS3 ポリシーに設定した{アカウントA のEC2に設定されるロール名}にロール名を設定します。

続いて内部EC2(private subnetのEC2)に接続します。先ずはエンドポイントを指定しなくてS3 にファイルをアップロードすると次のようなコマンドでできます。

aws s3 cp test.txt s3://sujae-peering-test-1/test.txt

既存構成でNAT gatewayが接続されているため、問題なくアップロードが可能でした。ではルートテーブルでNAT gatewayのルートを削除します。

続いてエンドポイント経由でファイルをアップロードしてみます。そのためにエンドポイントのURLが必要になりますがここで確認できます。

下記のコマンドにURL を代入して実行してみます。
もしエラーが発生するとピアリング接続、バケットポリシー、エンドポイントURLなどを確認してみます。

# aws s3 --endpoint-url https://bucket.{エンドポイントのURL} ls s3://{バケット名}
aws s3 --endpoint-url https://bucket.vpce-0700000000000-1234567.s3.ap-northeast-1.vpce.amazonaws.com ls s3://sujae-peering-test-1

アップロードした test.txt が確認できたら、続いてアップロードをしてみます。

# aws s3 --endpoint-url https://bucket.{エンドポイントのURL} cp s3://{バケット名}/test2.txt
aws s3 --endpoint-url https://bucket.vpce-0700000000000-1234567.s3.ap-northeast-1.vpce.amazonaws.com cp test.txt s3://sujae-peering-test-1/test2.txt

バケットでtest2.txt を確認できたら成功です。

他に設定できること

エンドポイントの詳細は 公式 ドキュメントを参照してください。

まず、バケットへの通信だけできるようにエンドポイントのポリシーを設定することができます。

{
  "Version": "2012-10-17",
  "Id": "Policy1415115909151",
  "Statement": [
    { "Sid": "Access-to-specific-bucket-only",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET1",
                   "arn:aws:s3:::DOC-EXAMPLE-BUCKET1/*"]
    }
  ]
}

また、S3 のポリシーにもエンドポイントからの接続だけを許可することもできます。

{
  "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"}}
    }
  ]
}

上記設定の詳細な説明は 公式 ドキュメントを参照してください。

まとめ

こうしてVPC peering を利用してパブリックインターネットを通じないS3 アップロード方法を見てみました。
インターフェイスエンドポイント(privatelink)はS3 へのアップロードだけではなくさまざまなサービスと連携して使うことが多いので、調べてみることをお勧めします。

お読みいただきありがとうございます。
誤字脱字、内容フィードバックはいつもありがとうございます。must01940 gmailでお願いします。