AWS Site-to-Site VPN経由でS3にアクセスしてみた

AWS Site-to-Site VPN経由でS3にアクセスしてみた

Clock Icon2025.06.01

こんにちは!クラウド事業本部の吉田です。

オンプレミス環境からS3にアクセスしたい時がありますよね?

今回は、AWS Site-to-Site VPN経由でS3にアクセスする方法をまとめてみました!

構成図

オンプレミス→AWSの構成図

大まかな内容としては、下記の通りです。

  • オンプレミスとAWS環境はAWS Site-to-Site VPNで接続する
  • AWS環境のS3のインターフェイスVPCエンドポイント経由でS3にアクセスする

vscode-drop-1748774438534-ehvduaobfim.png

検証環境の構成図

今回の検証では、擬似オンプレミス環境用VPCとAWS環境用VPCを作成し、環境を再現します。

vscode-drop-1748774450413-4qb7k0ydmql.png

検証環境の構成に関しては、下記の記事を参考にしております。
構成以外にもLibreswanに関する所も参考にさせていただきました。

AWS Site-to-Site VPN 接続を検証してみた – TechHarmony

Terraformコード

検証環境のおおよそのリソースをTerraformで作成します。
Terraformコードは、下記のGitHubリポジトリから確認してください。

yoshida-takeshi-classmethod/sample-terraform-site-to-site-vpn-s3

HCP Terraformでデプロイをしているため、デプロイ実行方法に合わせて修正してください。

内容としましては、下記の通りです。

  • 擬似オンプレミス環境
    • ネットワーク
      • VPC
        • CIDRは192.168.0.0/24
      • サブネット
        • プライベートサブネットとパブリックサブネット、それぞれ1つ作成
      • ルートテーブル
        • プライベートサブネットからの通信は、カスタムゲートウェイデバイス用EC2を経由する
      • VPCエンドポイント
        • SSM エンドポイント
          • SSM Session Managerを利用してEC2に接続
      • インターネットゲートウェイ
    • EC2
      • クライアント用EC2
        • オンプレミスにあるクライアントサーバーを想定したEC2
        • プライベートサブネットに配置
      • カスタムゲートウェイデバイス用EC2
        • オンプレミスにあるルーターを想定したEC2
        • パブリックサブネットに配置
        • EIPをアタッチ
        • ネットワークの送信元/送信先チェックをオフ
    • セキュリティグループ
      • EC2用のセキュリティグループとSSMエンドポイント用のセキュリティグループを作成
    • IAMロール
      • SSMとS3(Libreswanインストール用)の権限があるIAMロールをEC2にアタッチ
        • 下記のAWSマネージドポリシーをアタッチ
          • AmazonSSMManagedInstanceCore
          • AmazonS3ReadOnlyAccess
  • AWS環境
    • ネットワーク
      • VPC
        • CIDRは192.168.10.0/24
      • サブネット
        • S3とSTSのインターフェイスVPCエンドポイント用のプライベートサブネットを作成
      • VPCエンドポイント
        • S3インターフェイスエンドポイント
          • 今回はRoute53 インバウンドエンドポイントは利用しないため、プライベートDNSは無効化
        • STSエンドポイント
          • クライアント用EC2上のスイッチロールのため作成
          • こちらもプライベートDNSは無効化
    • セキュリティグループ
      • インターフェイスエンドポイント用セキュリティグループを作成
        • 擬似オンプレミス環境用のVPCのCIDR(192.168.0.0/24)を許可
    • S3バケット
      • バケットのみ作成

手作業一覧

下記の内容は、解説も兼ねて手作業で設定します。

  • スイッチロール用IAMユーザーとS3アクセス用IAMロールを作成
  • S3のバケットポリシー設定
  • AWS Site-to-Site VPN作成
  • Libreswanインストール

スイッチロール用IAMユーザーとS3アクセス用IAMロールを作成

クライアント用EC2上で利用するスイッチロール用IAMユーザーを作成します。
スイッチロール用IAMユーザーのアクセスキーによって、S3アクセス権限があるIAMロールにスイッチロールする形です。

スイッチロール用IAMユーザーのアクセスキーが流失したとしても、AssumeRoleの権限しかないため、スイッチロール先のIAMロールがわからなければ不正利用できません。
スイッチロールを活用することで、強い権限を持つアクセスキーを流失した時と比べて被害を抑えられます。

スイッチロールに関しては、下記のブログが参考になりますので、ぜひお読みください。

IAM ロールの PassRole と AssumeRole をもう二度と忘れないために絵を描いてみた
AssumeRole(スイッチロール)を理解して、AWSへのデプロイを少しでも安全に実施しよう

セキュリティポリシーによってアクセスキーを発行できない場合は、IAM Roles Anywhereの利用を検討してください。

IAM Roles AnywhereをAWS Private CAと連携させ、AWS外から一時クレデンシャルを取得してみた | DevelopersIO

スイッチロール用IAMユーザーの設定内容

スイッチロール用IAMユーザーを作成していきましょう。

まず、スイッチロール先IAMロールへのAssumeRole権限があるIAMポリシーを作成してください。

スイッチロール先のAssumeRole権限があるIAMポリシー
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"sts:AssumeRole"
			],
			"Resource": "{スイッチロール先のIAMロールのARN}"
		}
	]
}
s3-vpn-demo-dev-assumerole-policy.json
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"sts:AssumeRole"
			],
			"Resource": "arn:aws:iam::XXXXXXXX:role/s3-vpn-demo-dev-s3-access-role"
		}
	]
}

スイッチロール用IAMユーザーを作成し、作成したAssumeRole権限があるIAMポリシーをアタッチしてください。

IAMユーザー作成後は、アクセスキーを発行します。

S3アクセス用IAMロールの設定内容

S3アクセス権限を持つIAMポリシーを作成します。

S3アクセス権限を持つIAMポリシー
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Action": "s3:ListAllMyBuckets",
          "Resource": "arn:aws:s3:::*",
          "Effect": "Allow"
      },
      {
          "Action": [
              "s3:ListBucket",
              "s3:GetBucketLocation"
          ],
          "Resource": "{S3バケットのARN}",
          "Effect": "Allow"
      },
      {
          "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:AbortMultipartUpload",
            "s3:ListMultipartUploadParts",
            "s3:DeleteObject"
          ],
          "Resource": "{S3バケットのARN}/*",
          "Effect": "Allow"
      }
  ]
}
s3-vpn-demo-dev-s3-access-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Action": "s3:ListAllMyBuckets",
          "Resource": "arn:aws:s3:::*",
          "Effect": "Allow"
      },
      {
          "Action": [
              "s3:ListBucket",
              "s3:GetBucketLocation"
          ],
          "Resource": "arn:aws:s3:::s3-vpn-demo-dev-{ランダムID}",
          "Effect": "Allow"
      },
      {
          "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:AbortMultipartUpload",
            "s3:ListMultipartUploadParts",
            "s3:DeleteObject"
          ],
          "Resource": "arn:aws:s3:::s3-vpn-demo-dev-{ランダムID}/*",
          "Effect": "Allow"
      }
  ]
}

S3アクセス用IAMロールを作成します。

スイッチロール用IAMユーザーのAssumeRoleを許可する信頼関係を設定します。

S3アクセス用IAMロールの信頼関係
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Principal": {
              "AWS": "{スイッチロール用IAMユーザーのARN}"
          },
          "Action": "sts:AssumeRole"
      }
  ]
}
信頼関係の設定例
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Principal": {
              "AWS": "arn:aws:iam::XXXXXXXXX:user/s3-vpn-demo-dev-assumerole-user"
          },
          "Action": "sts:AssumeRole"
      }
  ]
}

作成したS3アクセス権限を持つIAMポリシーをアタッチします。

IAMロール名は、先ほど作成したAssumeRole権限があるIAMポリシーで指定した名前にしてください。

S3のバケットポリシー設定

「AWS環境のS3インターフェイスVPCエンドポイント経由でのアクセス、もしくは、特定のIAMユーザー・IAMロールからのアクセス」以外はアクセス拒否をするS3のバケットポリシーを設定します。

オンプレミスからS3へのアクセス制御について、整理します。

  • インターフェイスVPCエンドポイント用のセキュリティグループで、オンプレミスのプライベートIPからのアクセスを許可
    • こちらはTerraformによって、すでに設定済みです
  • バケットポリシーによって、S3インターフェイスVPCエンドポイント経由のアクセスを許可
    • 厳密にいえば、S3インターフェイスVPCエンドポイント経由のアクセスを拒否しないようにします。実際のアクセス許可の権限は、S3アクセス用のIAMロールに付与する形です。

vscode-drop-1748774546106-wav9j5c3or.png

ただ、S3インターフェイスVPCエンドポイント経由のアクセスのみ許可するポリシーだと、マネージドコンソールからアクセスできなくなります。
AWSアカウントにログインするIAMユーザー、IAMロールからのアクセスも許可してください。
詳細は、下記の記事を参照してください。

S3でVPCエンドポイント経由のアクセスのみに制限したけど特定のIAMユーザーはアクセスできるようにするバケットポリシーを作ってみた | DevelopersIO

バケットポリシーは、下記の通りです。

バケットポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::{S3バケット}",
        "arn:aws:s3:::{S3バケット名}/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": "{VPCエンドポイントID}",
          "aws:PrincipalArn": [
            "{IAMロールもしくはIAMユーザーのARN}"
          ]
        }
      }
    }
  ]
}

私の検証環境では、aws:PrincipalArn条件キーで下記のIAMロールのARNを指定しています。

  • 検証AWSアカウントアクセス用IAMロール
    • 検証AWSアカウントへスイッチロールして作業しているので、IAMロールを指定しています。
    • IAMユーザで、AWSアカウントにアクセスしている場合は、IAMユーザを指定してください。
  • Terraformデプロイ用IAMロール
バケットポリシー例
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::s3-vpn-demo-dev-{ランダムID}",
        "arn:aws:s3:::s3-vpn-demo-dev-{ランダムID}/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": "vpce-0eaa2b0b5087a074b",
          "aws:PrincipalArn": [
            "{検証AWSアカウントアクセス用IAMロールのARN}",
            "{Terraformデプロイ用IAMロールのARN}"
          ]
        }
      }
    }
  ]
}

下記の記事のように、S3バケットポリシーのaws:VpcSourceIp条件キーでオンプレミスのプライベートIPを許可する形でも構いません。

S3バケットへのアクセスをオンプレミスサーバーのプライベートIPアドレスで制限する方法2選 | DevelopersIO

AWS Site-to-Site VPN 作成

メインリソースであるAWS Site-to-Site VPNを作成していきます。
作成手順は、下記の記事を参考にしております。

AWS入門ブログリレー2024〜AWS Site-to-Site VPN編〜 | DevelopersIO

また、Libreswanに関する部分は下記の記事を参考にしております。

AWS Site-to-Site VPN 接続を検証してみた – TechHarmony

カスタマーゲートウェイ作成

カスタマーゲートウェイを作成します。

  • 名前
    • s3-vpn-demo-dev-cgw
  • BGP ASN
    • 65000
  • IPアドレス
    • カスタマーゲートウェイ用EC2のEIP

vscode-drop-1748774581678-bw0vm4snyl.png
vscode-drop-1748774581678-4m9p0ev66ax.png
vscode-drop-1748774581679-l3ulo5u3xid.png

VGW作成

VGWを作成します。

  • 名前
    • s3-vpn-demo-dev-vgw
  • ASN
    • デフォルト

vscode-drop-1748774605011-qm7eppfkood.png
vscode-drop-1748774605011-vuff8apkedp.png
vscode-drop-1748774605012-l9prtpkxmj.png

VGWをVPCにアタッチ

VGWをVPCにアタッチします。

vscode-drop-1748774632086-5prmcq5q2ev.png
vscode-drop-1748774632086-nzlgho0sbp.png
vscode-drop-1748774632086-n1l1bhvcx2s.png

ルートテーブル作成

続いてVGW向けのルートがあるルートテーブルを作成します。

  • 名前
    • s3-vpn-demo-vpn-rtb
  • ルート
    • 送信先
      • 192.168.0.0/24(擬似オンプレミス環境用のVPCのCIDR)
    • ターゲット
      • s3-vpn-demo-dev-vgw(作成したVGW)

AWS環境のインターフェイスVPCエンドポイント用のサブネットを明示的に関連付けてください。

AWS Site-to-Site VPN作成

AWS Site-to-Site VPNを作成します。

  • 名前
    • s3-vpn-demo-dev-vpn
  • タイプ
    • 仮想プライベートゲートウェイ
  • 仮想プライベートゲートウェイ
    • s3-vpn-demo-dev-vgw(作成したVGW)
  • カスタマーゲートウェイ
    • 既存
  • カスタマーゲートウェイID
    • s3-vpn-demo-dev-cgw(作成したCGW)
  • ルーティングオプション
    • 静的
  • 静的 IP プレフィックス
    • 192.168.0.0/24(擬似オンプレミス環境用のVPCのCIDR)

vscode-drop-1748774675513-4fzcwri3dqe.png
vscode-drop-1748774675513-pxbxs7l7wir.png
vscode-drop-1748774675513-8npvronyb6.png

Libreswanインストール

オンプレミス上のルーターに見立てたカスタマーゲートウェイデバイス用EC2に、ソフトウェアVPNであるLibreswanをインストールします。
Libreswanのインストール手順は、下記の記事の手順を参考にしております。

AWS Site-to-Site VPN 接続を検証してみた – TechHarmony

下準備

下準備として、LibreswanのVPN設定ファイルとシークレット情報ファイルを作成します。
今回は検証のため、Tunnel 1のみ使用する形とします。

Pre-Shared Key(PSK)を取得するため、AWS Site-to-Site VPNから汎用的な設定ファイルをダウンロードします。

vscode-drop-1748774708339-yvmhm2q15dq.png
vscode-drop-1748774708339-m8tudrxywe.png

Tunnel 1用のPSKを確認します。

汎用設定ファイル内容(PSK部分)
IPSec Tunnel #1
================================================================================
#1: Internet Key Exchange Configuration
(省略)
  - Authentication Method    : Pre-Shared Key
  - Pre-Shared Key           : {Tunnel 1用のPSK}

次に、設定ファイルかマネージドコンソール上で、VPN接続のTunnel 1の外部IPアドレス確認します。

汎用設定ファイル内容(Tunnel 1の外部IPアドレス部分)
IPSec Tunnel #1
================================================================================
(省略)
#3: Tunnel Interface Configuration
(省略)
Outside IP Addresses:
  - Customer Gateway 		        : {カスタマーゲートウェイで設定したIP}
  - Virtual Private Gateway	        : {Tunnel 1の外部IPアドレス}

マネージドコンソール上では、作成したVPN接続を選択し、「トンネルの詳細」から確認できます。

vscode-drop-1748774738137-xz6z2tb33s.png

確認した情報を元に、LibreswanのVPN設定ファイルとシークレット情報ファイルを作成します。

VPN設定ファイル
conn Tunnel1
    authby=secret
    auto=start
    left=%defaultroute
    leftid={カスタマーゲートウェイで設定したIP=カスタマーゲートウェイ用EC2のEIP}
    right={Tunnel 1の外部IPアドレス}
    type=tunnel
    ikelifetime=8h
    keylife=1h
    phase2alg=aes128-sha1;modp2048
    ike=aes128-sha1;modp2048
    keyingtries=%forever
    keyexchange=ike
    leftsubnet=192.168.0.0/24   #擬似オンプレミス環境のVPCのCIDR
    rightsubnet=192.168.10.0/24 #AWS環境のVPCのCIDR
    dpddelay=10
    retransmit-timeout=30s
    dpdaction=restart_by_peer
シークレット情報
{カスタマーゲートウェイで設定したIP} {Tunnel 1の外部IPアドレス}: PSK "{Tunnel 1用のPSK}"

インストール

では、Libreswanの設定をしてきます。

SSM Session Managerを利用して、カスタマーゲートウェイ用EC2にログインしてください。

ルートユーザー切り替え&インストールコマンドを打ちます。

ルートユーザー切り替え&インストールコマンド
sudo su -
dnf install -y libreswan
出力結果
sh-5.2$ sudo su -
[root@gateway ~]# dnf install -y libreswan
Last metadata expiration check: 0:53:36 ago on Thu May 29 00:21:43 2025.
Dependencies resolved.

(省略)

Installed:
  ldns-1.8.3-2.amzn2023.0.1.x86_64         libreswan-4.12-3.amzn2023.0.2.x86_64         nss-tools-3.90.0-6.amzn2023.0.1.x86_64         unbound-anchor-1.17.1-1.amzn2023.0.7.x86_64         unbound-libs-1.17.1-1.amzn2023.0.7.x86_64

Complete!

カーネルパラメーターを修正します。

カーネルパラメーター修正
echo 'net.ipv4.ip_forward=1' | tee -a /etc/sysctl.d/custom-ip-forwarding.conf
sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf
出力結果
[root@gateway ~]# echo 'net.ipv4.ip_forward=1' | tee -a /etc/sysctl.d/custom-ip-forwarding.conf
net.ipv4.ip_forward=1
[root@gateway ~]# sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf
net.ipv4.ip_forward = 1

/etc/ipsec.confを修正します。

/etc/ipsec.conf修正
vi /etc/ipsec.conf

下記のように修正します。

/etc/ipsec.conf
# /etc/ipsec.conf - Libreswan 4.0 configuration file
#
# see 'man ipsec.conf' and 'man pluto' for more information
#
# For example configurations and documentation, see https://libreswan.org/wiki/

config setup
        # If logfile= is unset, syslog is used to send log messages too.
        # Note that on busy VPN servers, the amount of logging can trigger
        # syslogd (or journald) to rate limit messages.
        #logfile=/var/log/pluto.log
        #
        # Debugging should only be used to find bugs, not configuration issues!
        # "base" regular debug, "tmi" is excessive (!) and "private" will log
        # sensitive key material (not available in FIPS mode). The "cpu-usage"
        # value logs timing information and should not be used with other
        # debug options as it will defeat getting accurate timing information.
        # Default is "none"
        # plutodebug="base"
        # plutodebug="tmi"
        #plutodebug="none"
        #
        # Some machines use a DNS resolver on localhost with broken DNSSEC
        # support. This can be tested using the command:
        # dig +dnssec DNSnameOfRemoteServer
        # If that fails but omitting '+dnssec' works, the system's resolver is
        # broken and you might need to disable DNSSEC.
        # dnssec-enable=no
        #
        # To enable IKE and IPsec over TCP for VPN server. Requires at least
        # Linux 5.7 kernel or a kernel with TCP backport (like RHEL8 4.18.0-291)
        # listen-tcp=yes
        # To enable IKE and IPsec over TCP for VPN client, also specify
        # tcp-remote-port=4500 in the client's conn section.
        ###追記###
        protostack=netkey
        ###追記ここまで###

# if it exists, include system wide crypto-policy defaults
include /etc/crypto-policies/back-ends/libreswan.config

# It is best to add your IPsec connections as separate files
# in /etc/ipsec.d/
include /etc/ipsec.d/*.conf

事前準備で作成したVPN設定ファイルとシークレット情報ファイルを配置します。

VPN設定ファイル作成
vi /etc/ipsec.d/aws-vpn.conf
/etc/ipsec.d/aws-vpn.conf
conn Tunnel1
    authby=secret
    auto=start
    left=%defaultroute
    leftid={カスタマーゲートウェイで設定したIP=カスタマーゲートウェイ用EC2のEIP}
    right={Tunnel 1の外部IPアドレス}
    type=tunnel
    ikelifetime=8h
    keylife=1h
    phase2alg=aes128-sha1;modp2048
    ike=aes128-sha1;modp2048
    keyingtries=%forever
    keyexchange=ike
    leftsubnet=192.168.0.0/24   #擬似オンプレミス環境のVPCのCIDR
    rightsubnet=192.168.10.0/24 #AWS環境のVPCのCIDR
    dpddelay=10
    retransmit-timeout=30s
    dpdaction=restart_by_peer
シークレット情報ファイル
vi /etc/ipsec.d/aws.secrets
/etc/ipsec.d/aws.secrets
{カスタマーゲートウェイで設定したIP} {Tunnel 1の外部IPアドレス}: PSK "{Tunnel 1用のPSK}"

ipsecデーモンを起動します。

ipsecデーモン起動
sudo systemctl start ipsec
sudo systemctl status ipsec
出力結果
[root@gateway ~]# sudo systemctl start ipsec
[root@gateway ~]# systemctl status ipsec
● ipsec.service - Internet Key Exchange (IKE) Protocol Daemon for IPsec
     Loaded: loaded (/usr/lib/systemd/system/ipsec.service; disabled; preset: disabled)
     Active: active (running) since Thu 2025-05-29 02:14:48 UTC; 2s ago
       Docs: man:ipsec(8)
             man:pluto(8)
             man:ipsec.conf(5)
    Process: 31183 ExecStartPre=/usr/libexec/ipsec/addconn --config /etc/ipsec.conf --checkconfig (code=exited, status=0/SUCCESS)
    Process: 31185 ExecStartPre=/usr/libexec/ipsec/_stackmanager start (code=exited, status=0/SUCCESS)
    Process: 31392 ExecStartPre=/usr/sbin/ipsec --checknss (code=exited, status=0/SUCCESS)
    Process: 31393 ExecStartPre=/usr/sbin/ipsec --checknflog (code=exited, status=0/SUCCESS)
   Main PID: 31404 (pluto)
     Status: "Startup completed."
      Tasks: 3 (limit: 1057)
     Memory: 3.6M
        CPU: 398ms
     CGroup: /system.slice/ipsec.service
             └─31404 /usr/libexec/ipsec/pluto --leak-detective --config /etc/ipsec.conf --nofork

May 29 02:14:48 gateway pluto[31404]: adding UDP interface lo [::1]:500
May 29 02:14:48 gateway pluto[31404]: adding UDP interface lo [::1]:4500
May 29 02:14:48 gateway pluto[31404]: loading secrets from "/etc/ipsec.secrets"
May 29 02:14:48 gateway pluto[31404]: loading secrets from "/etc/ipsec.d/aws.secrets"
May 29 02:14:48 gateway pluto[31404]: "Tunnel1" #1: initiating IKEv2 connection
May 29 02:14:48 gateway pluto[31404]: "Tunnel1" #1: sent IKE_SA_INIT request to 52.69.21.113:500
May 29 02:14:48 gateway pluto[31404]: "Tunnel1" #1: sent IKE_AUTH request {cipher=AES_CBC_128 integ=HMAC_SHA1_96 prf=HMAC_SHA1 group=MODP2048}
May 29 02:14:49 gateway pluto[31404]: "Tunnel1" #1: initiator established IKE SA; authenticated peer using authby=secret and ID_IPV4_ADDR '52.69.21.113'
May 29 02:14:49 gateway pluto[31404]: "Tunnel1" #2: initiator established Child SA using #1; IPsec tunnel [192.168.0.0-192.168.0.255:0-65535 0] -> [192.168.10.0-192.168.10.255:0-65535 0] {ESPinUDP=>0xc0dcfa84 <0x307c4050 xfrm=AES_CBC_12>
May 29 02:14:49 gateway pluto[31404]: packet from 52.195.22.12:4500: INFORMATIONAL request has no corresponding IKE SA; message dropped

AWS Site-to-Site VPNのTunnel 1のステータスがアップになっていることを確認します。

vscode-drop-1748774774588-hm50gpngywb.png

疎通確認

クライアント用EC2にログインして、S3にアクセスできるか確認します。
まず、SSM Session Managerでクライアント用EC2にログインしてください。

ログイン後は、aws configureでスイッチロール用IAMユーザーのアクセスキー・シークレットキーを設定してください。

aws configure
aws configure

スイッチロール用のプロファイルを設定します。

プロファイル設定
vi ~/.aws/config

下記の内容を追記してください。

追記部分
[profile s3-access]
region = ap-northeast-1
role_arn = {スイッチロール先のIAMロールのARN}
source_profile = default
config例
[profile s3-access]
region = ap-northeast-1
role_arn = arn:aws:iam::XXXXXXXXX:role/s3-vpn-demo-dev-s3-access-role
source_profile = default

次に、下記のAWS_ENDPOINT_URL_<SERVICE>変数を設定します。

AWS_ENDPOINT_URL_<SERVICE>変数設定
export AWS_ENDPOINT_URL_STS=https://{STSエンドポイントのDNS}
export AWS_ENDPOINT_URL_S3=https://bucket.{S3インターフェイスエンドポイントのDNS}
AWS_ENDPOINT_URL_<SERVICE>変数設定例
export AWS_ENDPOINT_URL_STS=https://vpce-0738357019fe789a0-3pg8jpx4.sts.ap-northeast-1.vpce.amazonaws.com
export AWS_ENDPOINT_URL_S3=https://bucket.vpce-0eaa2b0b5087a074b-c09ptdtj.s3.ap-northeast-1.vpce.amazonaws.com

AWS_ENDPOINT_URL_<SERVICE>変数を設定する理由を説明します。

結論を言いますと、 aws s3コマンドだけでS3にアクセスできるようにするためです。

順に説明します。

AWS CLIの--profileオプションでスイッチロール用のプロファイルを指定でき、スイッチロールしたIAMロールの権限を利用してコマンドを実行できます。

プロファイル指定したコマンド例
aws s3 ls --profile s3-access

また、AWS CLIの--endpoint-urlオプションで、エンドポイントのURLを指定できます。
今回の検証環境では、S3のインターフェイスVPCエンドポイントのプライベートDNSを有効化していないため、エンドポイント固有のDNSを利用する必要があります。

(ちなみにプライベートDNSを有効化したインターフェイスVPCエンドポイントに対して、オンプレミス環境から名前解決するには、Route 53インバウンドエンドポイントを利用する必要があります。)

エンドポイントURLを指定したコマンド例
aws s3 ls --profile s3-access --endpoint-url https://bucket.{S3インターフェイスエンドポイントのDNS}

ただ、今回の検証環境では、上記のAWS CLIコマンドは成功しません。

閉域ネットワーク環境ではSTSのエンドポイントであるsts.amazonaws.comへの名前解決の経路がなく、スイッチロール(AssumeRole)が実行できないためです。

vscode-drop-1748774790959-84lz31teq7j.png

そのため、STSのVPCエンドポイントを経由してスイッチロールをする必要があります。

vscode-drop-1748774798302-0q9fm3e01f4.png

ただし、AWS CLIの--endpoint-urlオプションは1つのエンドポイントURLしか指定できないので、STSのVPCエンドポイントを指定することができません。

解決方法の1つとしては、下記のように複数の処理に分割することが挙げられます。

  • --endpoint-urlオプションでSTSのVPCエンドポイントを指定し、aws sts assume-roleコマンドを実行
  • 一時的なクレデンシャルを環境変数に設定
  • --endpoint-urlオプションでS3のVPCエンドポイントを指定したaws s3コマンドを実行

ただ、手順が増えて少々手間がかかります。

そこで、特定のサービスに使用されるエンドポイントを指定できるAWS_ENDPOINT_URL_<SERVICE>変数を利用します。
この変数を利用することで、STSとS3それぞれのサービスをアクセスする際に、サービスの固有のエンドポイント経由でアクセスできるようになります。

環境変数:
AWS_ENDPOINT_URL_<SERVICE> - 特定のサービスに使用されるカスタムエンドポイントを指定します。SERVICE は AWS のサービス 識別子に置き換えられます。すべてのサービス固有の変数については、「サービス固有のエンドポイント: サービス固有の識別子のリスト」を参照してください。

引用:Using endpoints in the AWS CLI - Set service-specific endpoints

S3にアクセスできる準備ができました。
S3コマンドを打ってみましょう。
疎通確認用のファイルをS3にアップロードしてみます。

S3アップロードコマンド
cd ~/
touch test.txt
aws s3 cp ./test.txt s3://{S3バケット名}/ --profile s3-access
出力結果
sh-5.2$ cd ~/
sh-5.2$ touch test.txt
sh-5.2$ aws s3 cp ./test.txt s3://s3-vpn-demo-dev-og7mtpnd/ --profile s3-access
upload: ./test.txt to s3://s3-vpn-demo-dev-og7mtpnd/test.txt

マネージドコンソール上で、S3にファイルが配置されていることを確認してみます。

vscode-drop-1748774837661-yqrp1g9hyf.png

無事、疎通確認用のファイルがアップロードされていました。

さいごに

次回は、この環境にRoute53 インバウンドエンドポイントを導入して検証してみようと思います!

以上、クラウド事業本部の吉田でした!

参考記事

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.