はじめに
VPC内に作成するパブリック・インスタンスやプライベート・インスタンスの通信制御を行うには、AWSのセキュリティーグループを作成して制御を行います。これまで、セキュリティーグループはインスタンスの作成先のVPCでのみ使用することができました。その為、新たにVPCを用意してインスタンスを作成する時には、再度そのVPC用にセキュリティーグループを作成する必要がありました。
今回、2024年10月31日付けで、セキュリティーグループを同一AWSアカウントの複数のVPCへの関連付けを可能にする新規AWSセキュリティーグループVPCアソシエーション機能がリリースされました。
当新機能を使用することにより、セキュリティー・グループの定義本体は1つのVPCでのみ管理することができるようになり、メンテナンス性の向上が期待されます。
本記事では、筆者の個人検証環境において実施した新機能検証結果をご紹介します。
AWSセキュリティーグループVPCアソシエーション機能
VPCのドキュメントにも関連する記述が新たに追加されています。
ドキュメントによると、機能を使用する条件としては以下の点が挙げられています。
- VPCとセキュリティーグループは同一アカウントに属していること
- VPCとセキュリティーグループは同一リージョン内に存在すること
- アカウント側で作成したセキュリティーグループのみ、他VPCへの紐付けが可能
※ デフォルトのセキュリティーグループには、当機能は使用不可。
機能の使い方としては、基本的に以下の流れで実施します。
- 複数VPCを所有している場合、どこか1つのVPCを選択し、そこでセキュリティーグループを定義する。
- 同一AWSアカウントが所有している他のVPCに対し、作成したセキュリティー・グループを関連付ける。
※他のVPC内では、セキュリティー・グループの定義作成は不要。
当機能をサポートしているサービスは、ドキュメントによると下記9つのサービスとなっています。
- Amazon API Gateway (REST APIs only)
- AWS Auto Scaling
- AWS CloudFormation
- Amazon EC2
- Amazon EFS
- Amazon EKS
- Amazon FSx
- AWS PrivateLink
- Amazon Route 53
全てのサービスに対して検証を行うのは大変ですので、今回はEC2とEFSの2点にフォーカスして機能検証を実施しました。
機能検証
-
Main-VPC
- 実際にセキュリティーグループを作成するVPC
- CIDRアドレス範囲は、10.0.0.0/16
- 以下のパブリック・サブネット、プライベート・サブネットをもつ。
- パブリック・サブネットのCIDRアドレス範囲は、10.0.1.0/24
- プライベート・サブネットのCIDRアドレス範囲は、10.0.1.0/24
- 各々のサブネットに対して、EC2インスタンスが1個ずつ稼働。
- 下記3つのセキュリティーグループを定義
- EC2-Public-Security-Group:パブリック・インスタンス用のセキュリティーグループ
- 外部からhttp、https、SSHアクセスできるようにする。
- 外部からインスタンスに対してpingが実行できるようにする。
- EC2-Private-Security-Group:プライベート・インスタンス用のセキュリティーグループ
- パブリック・インスタンスからのsshアクセス、pingが実行できるようにする。
- MountTarget-Security-Group:EFSのマウントターゲットに紐付けるセキュリティーグループ
- パブリック・インスタンス上で、EFSのマウントができるようにする。
- EC2-Public-Security-Group:パブリック・インスタンス用のセキュリティーグループ
-
Remote-VPC
- Main-VPC側で作成したセキュリティーグループの関連付け先VPC
- CIDRアドレス範囲は、20.0.0.0/16
- 以下のパブリック・サブネット、プライベート・サブネットをもつ。
- パブリック・サブネットのCIDRアドレス範囲は、20.0.1.0/24
- プライベート・サブネットのCIDRアドレス範囲は、20.0.1.0/24
- 各々のサブネットに対して、EC2インスタンスが1個ずつ稼働。
-
Main-EFS
- Main-VPC側にマウントするためのEFS
-
Remote-EFS
- Remote-VPC側にマウントするためのEFS
事前準備
AWSのマネジメント・コンソールからでも検証は可能ですが、環境構築が大変なので、いつものようにCloudFormationのコードを作成して、検証を実施しました。今回用意したサンプルコードは以下のものになります。
Remote-VPC作成用コード
RemoteVPC-Stack.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample Script for Creating Remote-VPC Stack (VPC,Public Subnet,Private Subnet,Internet Gateway,Route Table)
Parameters:
AzName:
Description: Set az-name
Type: String
Default: ap-northeast-1a
AllowedValues:
- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d
VPCCidrBlock:
Description: VPC Cidr Block
Type: String
Default: 20.0.0.0/16
PublicSubnetCidrBlock:
Description: Public Subnet Cidr Block for az-name
Type: String
Default: 20.0.1.0/24
PrivateSubnetCidrBlock:
Description: Private Subnet Cidr Block for az-name
Type: String
Default: 20.0.2.0/24
Resources:
RemoteVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidrBlock
EnableDnsHostnames: 'true'
EnableDnsSupport: 'true'
Tags:
- Key: Name
Value: Remote-VPC
RemotePublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref RemoteVPC
CidrBlock: !Ref PublicSubnetCidrBlock
AvailabilityZone: !Ref AzName
Tags:
- Key: Name
Value: RemoteVPC-Public-Subnet
DependsOn: RemoteVPC
RemotePrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref RemoteVPC
CidrBlock: !Ref PrivateSubnetCidrBlock
AvailabilityZone: !Ref AzName
Tags:
- Key: Name
Value: RemoteVPC-Private-Subnet
DependsOn: RemoteVPC
RemoteIGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: RemoteVPC-IGW
DependsOn: RemoteVPC
IGWAttachToRemoteVPC:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref RemoteVPC
InternetGatewayId: !Ref RemoteIGW
RemotePublicRtbl:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref RemoteVPC
Tags:
- Key: Name
Value: RemoteVPC-Public-Rtbl
DependsOn: RemoteIGW
RemotePublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: RemotePublicRtbl
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref RemoteIGW
RemotePublicSubnetRouteTblAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RemotePublicRtbl
SubnetId: !Ref RemotePublicSubnet
DependsOn: RemotePublicRoute
RemotePrivateRtbl:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref RemoteVPC
Tags:
- Key: Name
Value: RemoteVPC-Private-Rtbl
DependsOn: RemotePublicRtbl
RemotePrivateSubnetRouteTblAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RemotePrivateRtbl
SubnetId: !Ref RemotePrivateSubnet
DependsOn: RemotePrivateRtbl
Outputs:
RemoteVPCId:
Description: The ID of Remote-VPC
Value: !Ref RemoteVPC
Export:
Name: !Sub "${AWS::StackName}--VPCId"
RemotePublicSubnetId:
Description: The ID of Public Subnet for Remote-VPC
Value: !Ref RemotePublicSubnet
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetId"
RemotePrivateSubnetId:
Description: The ID of Private Subnet for Remote-VPC
Value: !Ref RemotePrivateSubnet
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetId"
本コード内では、セキュリティーグループの作成は実施していません。後続で使用するCloudFormationコードへのインプットに必要となる下記の情報をエクスポートしています。
- Remote-VPCのVPC ID
- Remote-VPCのパブリック・サブネットID
- Remote-VPCのプライベート・サブネットID
Main-VPC作成用コード
MainVPC-Stack.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample Script for Creating Main-VPC Stack (VPC,Public Subnet,Private Subnet,Internet Gateway,Route Table,Security Group)
Parameters:
AzName:
Description: Set az-name
Type: String
Default: ap-northeast-1a
AllowedValues:
- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d
VPCCidrBlock:
Description: VPC Cidr Block
Type: String
Default: 10.0.0.0/16
PublicSubnetCidrBlock:
Description: Public Subnet Cidr Block for az-name
Type: String
Default: 10.0.1.0/24
PrivateSubnetCidrBlock:
Description: Private Subnet Cidr Block for az-name
Type: String
Default: 10.0.2.0/24
RemoteVPCStackName:
Description: Remote VPC Stack Name
Type: String
Default: RemoteVPC-Stack
Resources:
MainVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidrBlock
EnableDnsHostnames: 'true'
EnableDnsSupport: 'true'
Tags:
- Key: Name
Value: Main-VPC
MainPublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MainVPC
CidrBlock: !Ref PublicSubnetCidrBlock
AvailabilityZone: !Ref AzName
Tags:
- Key: Name
Value: MainVPC-Public-Subnet
DependsOn: MainVPC
MainPrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MainVPC
CidrBlock: !Ref PrivateSubnetCidrBlock
AvailabilityZone: !Ref AzName
Tags:
- Key: Name
Value: MainVPC-Private-Subnet
DependsOn: MainVPC
MainIGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: MainVPC-IGW
DependsOn: MainVPC
IGWAttachToMainVPC:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MainVPC
InternetGatewayId: !Ref MainIGW
MainPublicRtbl:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MainVPC
Tags:
- Key: Name
Value: MainVPC-Public-Rtbl
DependsOn: MainIGW
MainPublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: MainPublicRtbl
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MainIGW
MainPublicSubnetRouteTblAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MainPublicRtbl
SubnetId: !Ref MainPublicSubnet
MainPrivateRtbl:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MainVPC
Tags:
- Key: Name
Value: Main-Private-Rtbl
MainPrivateSubnetRouteTblAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MainPrivateRtbl
SubnetId: !Ref MainPrivateSubnet
EC2PublicSecGrp:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http to client host
VpcId: !Ref MainVPC
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 22
ToPort: 22
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 80
ToPort: 80
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 443
ToPort: 443
- CidrIp: 0.0.0.0/0
IpProtocol: icmp
FromPort: 8
ToPort: -1
Tags:
- Key: Name
Value: EC2-Public-Security-Group
EC2PublicSecGrpAssociation:
Type: AWS::EC2::SecurityGroupVpcAssociation
Properties:
GroupId: !Ref EC2PublicSecGrp
VpcId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--VPCId"
DependsOn: EC2PublicSecGrp
EC2PrivateSecGrp:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow http from EC2-Public-Security-Group
VpcId: !Ref MainVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref EC2PublicSecGrp
- IpProtocol: icmp
FromPort: 8
ToPort: -1
SourceSecurityGroupId: !Ref EC2PublicSecGrp
Tags:
- Key: Name
Value: EC2-Private-Security-Group
EC2PrivateSecGrpAssociation:
Type: AWS::EC2::SecurityGroupVpcAssociation
Properties:
GroupId: !Ref EC2PrivateSecGrp
VpcId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--VPCId"
DependsOn: EC2PrivateSecGrp
Outputs:
MainVPCid:
Description: The ID of Main-VPC
Value: !Ref MainVPC
Export:
Name: !Sub "${AWS::StackName}--VPCId"
MainPublicSubnetId:
Description: The ID of Public Subnet for Main-VPC
Value: !Ref MainPublicSubnet
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetId"
MainPrivateSubnetId:
Description: The ID of Private Subnet for Main-VPC
Value: !Ref MainPrivateSubnet
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetId"
EC2PublicSubnetSecurityGroupId:
Description: The ID of EC2 Public Subnet Security Group
Value: !Ref EC2PublicSecGrp
Export:
Name: !Sub "${AWS::StackName}--PublicSubnetSecGrpId"
EC2PrivateSubnetSecurityGroupId:
Description: The ID of EC2 Private Subnet Security Group
Value: !Ref EC2PrivateSecGrp
Export:
Name: !Sub "${AWS::StackName}--PrivateSubnetSecGrpId"
本コードの実行においては、先のRemote-VPC作成用コードを実行してできたスタック名を他の入力パラメータと同様に指定すれば実行可能です。
今回、当機能のリリースにより、以下のCloudFormationリソースタイプが新たに追加されています。
本コード内では以下の箇所で上記リソースタイプの定義を実施しています。
EC2PublicSecGrpAssociation:
Type: AWS::EC2::SecurityGroupVpcAssociation
Properties:
GroupId: !Ref EC2PublicSecGrp
VpcId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--VPCId"
DependsOn: EC2PublicSecGrp
EC2PrivateSecGrpAssociation:
Type: AWS::EC2::SecurityGroupVpcAssociation
Properties:
GroupId: !Ref EC2PrivateSecGrp
VpcId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--VPCId"
DependsOn: EC2PrivateSecGrp
このリソースタイプには、セキュリティーグループのID、及び、セキュリティーグループの関連付け先VPCのIDを指定します。これをするだけで、Remote-VPC内にあたかもセキュリティーグループが存在しているかのように処理させることが可能になります。
ちなみに、コードの実行においては、このセキュリティーグループの関連付け処理に体感で40秒程要しました。(解除処理時も同様に40秒程要しています。)
本コードでも、後続のコード実行に必要となる情報をエクスポートしています。
EC2インスタンス作成用コード
EC2Instance-Stack.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample Script for Creating Public/Private EC2 Instance
Parameters:
MainVPCStackName:
Description: This stack name is already created MainVPC Stack for provisioning EC2 Instance
Type: String
Default: MainVPC-Stack
RemoteVPCStackName:
Description: This stack name is already created RemoteVPC Stack for provisioning EC2 Instance
Type: String
Default: RemoteVPC-Stack
Resources:
MyKey:
Type: AWS::EC2::KeyPair
Properties:
KeyName: MyEC2Key
PublicKeyMaterial: '{{resolve:ssm:publickeymaterial}}'
Tags:
- Key: Name
Value: My-Key
MainPublicInstance:
Type: AWS::EC2::Instance
Properties:
CreditSpecification:
CPUCredits: standard
InstanceType: t2.micro
KeyName: !Ref MyKey
ImageId: ami-08ce76bae392de7dc
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId:
Fn::ImportValue:
!Sub "${MainVPCStackName}--PublicSubnetId"
GroupSet:
-
Fn::ImportValue:
!Sub "${MainVPCStackName}--PublicSubnetSecGrpId"
Tags:
- Key: Name
Value: MainVPC-Public-instance
MainPrivateInstance:
Type: AWS::EC2::Instance
Properties:
CreditSpecification:
CPUCredits: standard
InstanceType: t2.micro
KeyName: !Ref MyKey
ImageId: ami-08ce76bae392de7dc
NetworkInterfaces:
- AssociatePublicIpAddress: "false"
DeviceIndex: "0"
SubnetId:
Fn::ImportValue:
!Sub "${MainVPCStackName}--PrivateSubnetId"
GroupSet:
-
Fn::ImportValue:
!Sub "${MainVPCStackName}--PrivateSubnetSecGrpId"
Tags:
- Key: Name
Value: MainVPC-Private-instance
RemotePublicInstance:
Type: AWS::EC2::Instance
Properties:
CreditSpecification:
CPUCredits: standard
InstanceType: t2.micro
KeyName: !Ref MyKey
ImageId: ami-08ce76bae392de7dc
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--PublicSubnetId"
GroupSet:
-
Fn::ImportValue:
!Sub "${MainVPCStackName}--PublicSubnetSecGrpId"
Tags:
- Key: Name
Value: Remote-Public-instance
RemotePrivateInstance:
Type: AWS::EC2::Instance
Properties:
CreditSpecification:
CPUCredits: standard
InstanceType: t2.micro
KeyName: !Ref MyKey
ImageId: ami-08ce76bae392de7dc
NetworkInterfaces:
- AssociatePublicIpAddress: "false"
DeviceIndex: "0"
SubnetId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--PrivateSubnetId"
GroupSet:
-
Fn::ImportValue:
!Sub "${MainVPCStackName}--PrivateSubnetSecGrpId"
Tags:
- Key: Name
Value: RemoteVPC-Private-instance
Outputs:
MainPublicInstanceIPaddr:
Description: Public Instance's IP address for MainVPC
Value: !GetAtt MainPublicInstance.PublicIp
MainPrivateInstanceIPaddr:
Description: Private Instance's IP address for MainVPC
Value: !GetAtt MainPrivateInstance.PrivateIp
RemotePublicInstanceIPaddr:
Description: Public Instance's IP address for RemoteVPC
Value: !GetAtt RemotePublicInstance.PublicIp
RemotePrivateInstanceIPaddr:
Description: Private Instance's IP address for RemoteVPC
Value: !GetAtt RemotePrivateInstance.PrivateIp
本コードの実行においては、先の2つのコード実行後に作成される各々のスタック名を入力する必要があります。このコードのポイントは、Remote-VPC側で稼働するインスタンスのネットワーク・インタフェース定義箇所(RemotePublicInstance、RemotePrivateInstanceのNetworkInterfacesを参照)において、サブネットは実際インスタンスが稼働するサブネットを指定しますが、セキュリティーグループについては、Main-VPC側に存在するセキュリティーグループのIDを指定する点になります。
EFS作成用コード
EFS-Stack.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample Script for Creating Elastic File System
Parameters:
MainVPCStackName:
Description: This stack name is already created MainVPC Stack for provisioning EC2 Instance
Type: String
Default: MainVPC-Stack
RemoteVPCStackName:
Description: This stack name is already created RemoteVPC Stack for provisioning EC2 Instance
Type: String
Default: RemoteVPC-Stack
Resources:
MountTargetSecGrp:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow access to EFS from EC2-Public-Security-Group
VpcId:
Fn::ImportValue:
!Sub "${MainVPCStackName}--VPCId"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '2049'
ToPort: '2049'
SourceSecurityGroupId:
Fn::ImportValue:
!Sub "${MainVPCStackName}--PublicSubnetSecGrpId"
Tags:
- Key: Name
Value: MountTarget-SecurityGroup
MountTargetSecGrpAssociation:
Type: AWS::EC2::SecurityGroupVpcAssociation
Properties:
GroupId: !Ref MountTargetSecGrp
VpcId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--VPCId"
DependsOn: MountTargetSecGrp
MainEFS:
Type: AWS::EFS::FileSystem
Properties:
Encrypted: true
FileSystemTags:
- Key: Name
Value: Main-EFS
MainEFSMountTarget:
Type: AWS::EFS::MountTarget
Properties:
FileSystemId: !Ref MainEFS
SubnetId:
Fn::ImportValue:
!Sub "${MainVPCStackName}--PublicSubnetId"
SecurityGroups:
- !Ref MountTargetSecGrp
RemoteEFS:
Type: AWS::EFS::FileSystem
Properties:
Encrypted: true
FileSystemTags:
- Key: Name
Value: Remote-EFS
RemoteEFSMountTarget:
Type: AWS::EFS::MountTarget
Properties:
FileSystemId: !Ref RemoteEFS
SubnetId:
Fn::ImportValue:
!Sub "${RemoteVPCStackName}--PublicSubnetId"
SecurityGroups:
- !Ref MountTargetSecGrp
DependsOn: MountTargetSecGrpAssociation
本コードの実行においては、先の2つのコード実行後に作成される各々のスタック名を入力する必要があります。EC2インスタンスのセキュリティーグループ同様に、Main-VPC側で、EFSのマウントターゲットに紐付けるセキュリティーグループを作成し、Remote-VPC側に作成したセキュリティーの関連付けを行います。
処理のタイミングによっては、セキュリティーグループの関連付け処理が終わる前に、Remote-VPC側でマウントターゲットの作成が始まってしまう可能性があります。その場合、「セキュリティーグループが同一ネットワーク内に存在しない。」と言われてエラーとなってしまいます。その為、DependsOnを指定して、処理の順序付けを行ってあげる考慮が必要となります。
上記3つのCloudFormationコードが全て正常終了することを確認します。
併せて、パブリック・インスタンスとプライベート・インスタンスのIPアドレスを確認しておきます。
AWSマネジメントコンソールでの確認
下記の図に見られるように、セキュリティーグループの画面において、新たに「VPC関連付け-新規」というタブが追加されています。(赤枠参照)
作成されたMain-VPCとRemote-VPCのIDは下記の通りです。
これを踏まえて、残りのセキュリティーグループについて確認します。
上記3つの画面における「VPC関連付け」において、セキュリティーグループIDはMain-VPC側で作成したもの、VPC IDはRemote-VPCのIDが表示されています。
パブリック・インスタンスへのアクセス確認
Main-VPC、Remote-VPC各々のパブリック・インスタンスの画面において、赤枠箇所に見られるように、同一のセキュリティーグループが指定されていることがわかります。
Main-VPC、Remote-VPC各々のパブリック・インスタンスに対し、まずはPingコマンドを発行します。
Microsoft Windows [Version 10.0.22631.4460]
(c) Microsoft Corporation. All rights reserved.
C:\Users\testuser>ping 13.231.122.24
13.231.122.24 に ping を送信しています 32 バイトのデータ:
13.231.122.24 からの応答: バイト数 =32 時間 =9ms TTL=112
13.231.122.24 からの応答: バイト数 =32 時間 =10ms TTL=112
13.231.122.24 からの応答: バイト数 =32 時間 =9ms TTL=112
13.231.122.24 からの応答: バイト数 =32 時間 =10ms TTL=112
13.231.122.24 の ping 統計:
パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 9ms、最大 = 10ms、平均 = 9ms
C:\Users\testuser>ping 57.180.14.209
57.180.14.209 に ping を送信しています 32 バイトのデータ:
57.180.14.209 からの応答: バイト数 =32 時間 =9ms TTL=113
57.180.14.209 からの応答: バイト数 =32 時間 =9ms TTL=113
57.180.14.209 からの応答: バイト数 =32 時間 =10ms TTL=113
57.180.14.209 からの応答: バイト数 =32 時間 =10ms TTL=113
57.180.14.209 の ping 統計:
パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 9ms、最大 = 10ms、平均 = 9ms
いずれのパブリック・インスタンスに対してもping応答が返ってくることが確認できました。続けて、teratermを使用してSSH接続を試みます。
いずれのパブリック・インスタンスに対してもSSH接続できることが確認できました。
これにより、パブリック・インスタンスに対するセキュリティーグループの関連付け機能は問題なく機能していることが確認できました。
プライベート・インスタンスへのアクセス確認
Main-VPC、Remote-VPC各々のパブリック・インスタンスから、プライベート・インスタンスに対してpingコマンドを発行します。
[ec2-user@ip-10-0-1-74 ~]$ ping 10.0.2.28
PING 10.0.2.28 (10.0.2.28) 56(84) bytes of data.
64 bytes from 10.0.2.28: icmp_seq=1 ttl=127 time=3.14 ms
64 bytes from 10.0.2.28: icmp_seq=2 ttl=127 time=0.564 ms
64 bytes from 10.0.2.28: icmp_seq=3 ttl=127 time=0.986 ms
64 bytes from 10.0.2.28: icmp_seq=4 ttl=127 time=0.614 ms
64 bytes from 10.0.2.28: icmp_seq=5 ttl=127 time=1.50 ms
^C
--- 10.0.2.28 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4149ms
rtt min/avg/max/mdev = 0.564/1.360/3.139/0.950 ms
[ec2-user@ip-20-0-1-36 ~]$ ping 20.0.2.48
PING 20.0.2.48 (20.0.2.48) 56(84) bytes of data.
64 bytes from 20.0.2.48: icmp_seq=1 ttl=127 time=2.25 ms
64 bytes from 20.0.2.48: icmp_seq=2 ttl=127 time=0.443 ms
64 bytes from 20.0.2.48: icmp_seq=3 ttl=127 time=0.284 ms
64 bytes from 20.0.2.48: icmp_seq=4 ttl=127 time=0.475 ms
^C
--- 20.0.2.48 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3082ms
rtt min/avg/max/mdev = 0.284/0.862/2.249/0.803 ms
双方いずれも問題なく、pingの応答が返ってきたことがわかります。
セキュリティーグループの関連付けは行いましたが、あくまでも、Main-VPCのプライベート・インスタンスに対しては、Main-VPCのパブリック・インスタンスからのアクセスのみ、Remote-VPCのプライベート・インスタンスに対しては、Remote-VPCのパブリック・インスタンスからのアクセスのみが可能であることに変わりはありません。VPC間の通信をするためには、VPCピアリング等の環境設定が必要です。
次にパブリック・インスタンスからプライベート・インスタンスへのSSH接続を確認するため、事前にPCローカルにあるSSHの秘密鍵を転送し、秘密鍵のアクセス権をchmodで600にしておきます。その上で、実際にパブリック・インスタンスからSSH接続を試みます。
[ec2-user@ip-10-0-1-74 ~]$ ssh -i MyEC2Key.pem ec2-user@10.0.2.28
The authenticity of host '10.0.2.28 (10.0.2.28)' can't be established.
ED25519 key fingerprint is SHA256:z7lv0vssV79ZFuAvgydErw5UQDnh+XHxneqHk0XRwKY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.2.28' (ED25519) to the list of known hosts.
, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
[ec2-user@ip-10-0-2-28 ~]$
[ec2-user@ip-20-0-1-36 ~]$ ssh -i MyEC2Key.pem ec2-user@20.0.2.48
The authenticity of host '20.0.2.48 (20.0.2.48)' can't be established.
ED25519 key fingerprint is SHA256:84he3jDy2w9SztWKbf+5SjUQBvWNVIfL+YHNIAHwFIM.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '20.0.2.48' (ED25519) to the list of known hosts.
, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
[ec2-user@ip-20-0-2-48 ~]$
双方、いずれもSSH接続できることが確認できました。これにより、プライベート・インスタンスに対するセキュリティーグループの関連付け機能は問題なく機能していることが確認できました。
EFSのマウント確認
Main-VPC、Remote-VPCのパブリック・インスタンス上で、事前に下記のコマンドでマウントヘルパー・ユーティリティーを入手しておきます。
$ sudo yum install -y amazon-efs-utils
最後の画面に表示されているマウントヘルパーのコマンドを実行し、マウントできることを確認します。
[ec2-user@ip-10-0-1-74 ~]$ sudo mkdir efs
[ec2-user@ip-10-0-1-74 ~]$ sudo mount -t efs -o tls fs-0c8cbc920ef1bb550:/ efs
[ec2-user@ip-10-0-1-74 ~]$
正常にマウントすることができています。
最後の画面に表示されているマウントヘルパーのコマンドを実行し、マウントできることを確認します。
[ec2-user@ip-20-0-1-36 ~]$ sudo mkdir efs
[ec2-user@ip-20-0-1-36 ~]$ sudo mount -t efs -o tls fs-07373bd95c4bc9167:/ efs
[ec2-user@ip-20-0-1-36 ~]$
こちらも正常にマウントすることができています。
以上のことから、EFSのマウントターゲットのセキュリティーグループにおいても、セキュリティーグループの関連付け機能が正しく機能したことが確認できました。
EFSが1時点でマウントできるVPCは1個のみであり、セキュリティーグループの関連付けをしたからといって、別VPCからも同時に同じEFSをマウントできるわけではありません。同じEFSをマウントしたい場合には、VPCピアリング等のVPC間通信が必要になります。
さいごに
本記事では、2024年10月31日にリリースされた、AWSセキュリティーグループVPCアソシエーション機能の検証結果をご紹介しました。
どこか1つのVPCでのみセキュリティーグループの作成をすれば良くなったことで、リソースのメンテナンス性が向上する良い機能であると感じました。
以前ならば、たとえIaC化していたとしても、VPCを作成するたびに同じようなセキュリティーグループの定義を書く必要があったので、結構手間がかかってましたし、定義変更の際にどこかのVPCのみ修正漏れが発生するというリスクを気にする必要がありました。今回の機能の登場により、コードの修正反映を大きく削減することが可能になったと感じます。
今後も何か新しい機能がリリースされたら、機能検証を継続していきたいと思います。