この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちはオンジーこと恩塚です!
パパッと検証でEC2を起動してセッションマネージャーでコマンドを試したいっていうときに今までマネジメントコンソールからポチポチやってたのですが、一発で構築したくなってCloudFormationテンプレートを作ってみました。
テンプレート(yamlファイル)
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
EnvironmentName:
Type: String
Default: xxxxxxxx-env
VPCCIDR:
Type: String
Default: 10.192.0.0/16
PrivateSubnetCIDR:
Type: String
Default: 10.192.0.0/24
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Ec2InstanceType:
Type: String
Default: t3.nano
KeyPair:
Type: String
Default: xxxxx-key
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-VPC
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Ref PrivateSubnetCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PrivateSubnet
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PrivateRouteTable
PrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet
RouteTableId: !Ref PrivateRouteTable
EndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EndpointSecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-EndpointSecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !Ref VPCCIDR
EndpointSSM:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointSSMMessages:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointEC2Messages:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointS3:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PrivateRouteTable
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcEndpointType: Gateway
VpcId: !Ref VPC
EC2IAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${EnvironmentName}-SSM-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- Ref: EC2IAMRole
InstanceProfileName: !Sub ${EnvironmentName}-EC2InstanceProfile
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EC2SecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-EC2SecurityGroup
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref Ec2InstanceType
SubnetId: !Ref PrivateSubnet
ImageId: !Ref Ec2ImageId
SecurityGroupIds:
- !Ref EC2SecurityGroup
IamInstanceProfile: !Ref EC2InstanceProfile
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 100
VolumeType: gp2
EbsOptimized: true
SourceDestCheck: true
KeyName: !Ref KeyPair
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-EC2Instance
Outputs:
VPC:
Value: !Ref VPC
Export:
Name: !Sub ${EnvironmentName}-VPC
VPCCIDR:
Value: !Ref VPCCIDR
Export:
Name: !Sub ${EnvironmentName}-VPCCIDR
PrivateSubnet:
Value: !Ref PrivateSubnet
Export:
Name: !Sub ${EnvironmentName}-PrivateSubnet
PrivateRouteTable:
Value: !Ref PrivateRouteTable
Export:
Name: !Sub ${EnvironmentName}-PrivateRouteTable
SecurityGroup:
Value: !Ref EndpointSecurityGroup
Export:
Name: !Sub ${EnvironmentName}-EndpointSecurityGroup
EndpointSSM:
Value: !Ref EndpointSSM
Export:
Name: !Sub ${EnvironmentName}-EndpointSSM
EndpointSSMMessages:
Value: !Ref EndpointSSMMessages
Export:
Name: !Sub ${EnvironmentName}-EndpointSSMMessages
EndpointEC2Messages:
Value: !Ref EndpointEC2Messages
Export:
Name: !Sub ${EnvironmentName}-EndpointEC2Messages
EndpointS3:
Value: !Ref EndpointS3
Export:
Name: !Sub ${EnvironmentName}-EndpointS3
EC2SecurityGroup:
Value: !Ref EC2SecurityGroup
Export:
Name: !Sub ${EnvironmentName}-EC2SecurityGroup
EC2Instance:
Value: !Ref EC2Instance
Export:
Name: !Sub ${EnvironmentName}-EC2Instance
ざっくり解説
キーペアは作成済みのものを指定しています。
またスタックの作成方法については他記事でたくさん紹介されているので割愛します。
このテンプレートで作成しているのは以下の通りです。
- VPC
- サブネット
- ルートテーブル
- VPCエンドポイント
- IAMロール
- EC2インスタンス
大事なところだけ抜き出して紹介します!
EndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EndpointSecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-EndpointSecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !Ref VPCCIDR
エンドポイントに設定するセキュリティグループはインバウンドルールでVPCからの443ポートへのHTTPS通信を許可する必要があります。
EndpointSSM:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointSSMMessages:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointEC2Messages:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
SubnetIds:
- !Ref PrivateSubnet
VpcEndpointType: Interface
VpcId: !Ref VPC
EndpointS3:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PrivateRouteTable
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcEndpointType: Gateway
VpcId: !Ref VPC
プライベートサブネットにあるEC2インスタンスにセッションマネージャーで繋ぐには全部で4つのVPCエンドポイントが必要になるのでこの部分で作成しています。
- com.amazonaws.region.ssm
- com.amazonaws.region.ec2messages
- com.amazonaws.region.ssmmessages
- com.amazonaws.region.s3
EC2IAMRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${EnvironmentName}-SSM-role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
セッションマネージャーでアクセスするためにはIAMポリシーのAmazonSSMManagedInstanceCoreがアタッチされているIAMロールがEC2インスタンスに設定されている必要があります。
作成したIAMロールをEC2のインスタンスプロファイルで指定します。
以上になります!