【CloudFormation】一撃でプライベートサブネットにEC2を起動し、SSMポートフォワード経由でRDPする
こんにちは、森田です。
本記事では、CloudFormationを用いてプライベートサブネット上にEC2を起動させ、SSMポートフォワード経由でRDP接続できるようにエンドポイントの構築を行います。
構成図
CloudFormationでは、以下のアーキテクチャを構築します。
前提条件
VPC, Private Subnetは作成済みとします。
また、EC2起動のため、事前にキーペアの作成を行っておく必要があります。
使用するCloudFormationテンプレート
以下のCloudFormationテンプレートを実行します。
入力パラメータとして、VPC ID、Subent ID、キーペア名の入力が必要となります。
AWSTemplateFormatVersion: "2010-09-09" Description: AWS Private Subnet EC2 Launch and Connect by SSM Parameters: InstanceType: Type: String Default: "t2.nano" VPCId: Type: String SubnetId: Type: String KeyPairName: Type: String PJPrefix: Type: String Default: "privatelaunch" WindowsLatestAmi: Description: "EC2 AMI image SSM path" Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: /aws/service/ami-windows-latest/Windows_Server-2019-Japanese-Full-Base AllowedValues: - /aws/service/ami-windows-latest/Windows_Server-2019-Japanese-Full-Base - /aws/service/ami-windows-latest/Windows_Server-2019-English-Full-Base Resources: EC2SG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Bastion EC2 Security Group" VpcId: !Ref VPCId Tags: - Key: Name Value: !Sub "${PJPrefix}-ec2-bastion-sg" EndpointSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Bastion Endpoint Security Group" VpcId: !Ref VPCId SecurityGroupIngress: - IpProtocol: tcp FromPort: 443 ToPort: 443 SourceSecurityGroupId: !Ref EC2SG Tags: - Key: Name Value: !Sub "${PJPrefix}-endpoint-bastion-sg" IamRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${PJPrefix}-ec2-bastion-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref IamRole EC2Instance: Type: "AWS::EC2::Instance" Properties: Tags: - Key: Name Value: !Sub "${PJPrefix}-bastion" ImageId: !Ref WindowsLatestAmi InstanceType: !Ref InstanceType KeyName: !Ref KeyPairName DisableApiTermination: false EbsOptimized: false SecurityGroupIds: - !Ref EC2SG SubnetId: !Ref SubnetId IamInstanceProfile: !Ref InstanceProfile SSMVPCEndpoint: Type: "AWS::EC2::VPCEndpoint" Properties: VpcEndpointType: Interface PrivateDnsEnabled: true ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm' VpcId: !Ref VPCId SubnetIds: - !Ref SubnetId SecurityGroupIds: - !Ref EndpointSG SSMMessagesVPCEndpoint: Type: "AWS::EC2::VPCEndpoint" Properties: VpcEndpointType: Interface PrivateDnsEnabled: true ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages' VpcId: !Ref VPCId SubnetIds: - !Ref SubnetId SecurityGroupIds: - !Ref EndpointSG EC2MessagesVPCEndpoint: Type: "AWS::EC2::VPCEndpoint" Properties: VpcEndpointType: Interface PrivateDnsEnabled: true ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2messages' VpcId: !Ref VPCId SubnetIds: - !Ref SubnetId SecurityGroupIds: - !Ref EndpointSG
CloudFormationで作成するメリット
エンドポイントは、時間単位での課金かつ個人的によく削除を忘れやすいリソースだったりします。
また、Private Subnet内のEC2への接続には、エンドポイントが3つ必要となり、作成・削除も手間だったりします。
CloudFormationで作成することで、
- 同じ操作を一括で行うことができる
- スタックの削除では、リソースの削除も一括で行うことができる
ため、作業の簡略化やリソースの削除を忘れを防ぐことができます。
最後に
今回は、Private Subnet 内のEC2へ VPC Endpointから接続を行いましたが、エンドポイントが複数あるため、長時間利用すると結構コストが発生する可能性もあります。
一時的にPublic Subnet の構築が許容できる場合では、
Public Subnetを構築しその中にEC2を起動する方がコストは抑えられますので、機会があればこのCloudFormationも作ってみたいと思います。