本記事の内容
- AWSが提供するCloudFormationサービスを利用し、AWSのクラウド環境に最低限のセキュリティ設計を考慮したサーバをさくっと建てる方法を記載した記事です。
- AWSアカウントをすでに持って入れば、本ページに記載のCloudFormationテンプレートを使うことで、10分程でクラウド環境を作成できます。
先日投稿した「【AWS入門】知識ゼロでもこれを読めばAWSを理解しつつ1~2時間後にサーバを建てられる」の記事で手動で構築した環境をCloudFormationを使って作成します。
本記事の手順で以下のような構成のクラウド環境を作成できます。
またAWSの操作画面はサービスリリースと共に更新されていくため、本記事をご覧いただくタイミングによっては、現在の画面と異なる場合があります。その点はご了承頂ければと思います。※本記事内の画面キャプチャーは2022年5月の物となっています。
設計のポイントと意図を以下に記載しておきます。
-
設計のポイント
- クラウド内のネットワークからインターネット接続するためにインターネットゲートウェイを設定
- クラウド内のネットワークをパブリックとプライベートなネットワークに分離
- プライベートネットワークにアプリケーション(AP)サーバを設置
- パブリックネットワークにAPサーバへのSSH接続用の踏み台サーバを設置
- プライベートネットワーク内のAPサーバがインターネット通信を出来るようにするNATゲートウェイをパブリックネットワークに設置
-
設計の意図
- クラウド内のネットワークをパブリック/プライベートに分離。サーバを用途に応じ適切に配置することでセキュリティ向上を図る。
- 各サーバへの通信は、ファイアウォール(AWSではネットワークACLとセキュリティグループという設定がある)で適切に制御する。
- APサーバへの通信は、インターネットからのhttp通信(8080)と踏み台サーバからのSSH接続のみ接続可能とする。
- 踏み台サーバへの通信は、SSH接続のみ許可
- 踏み台サーバのログイン方法も公開鍵認証とし、セキュアなログインを行う。※AWSのEC2サーバは公開鍵認証方式でのログインがデフォルト
実施環境
- Windows 10
- Chrome
- AWS
手順の流れ
- CloudFormationで環境を構築
- 投入したテンプレートの解説
1. CloudFormationで環境を構築
AWSマネジメントコンソールにアクセスし、「CloudFormationサービス」を選択する。
「ファイルの選択」をクリックし、アップロードするテンプレートファイルを選択する。※ファイルは、2.投入したテンプレートの解説に記載の「VPC_CloudFormation_r2_for_Qita.yml」
パラメータとして、EC2にログインする際のキーペアーを設定し、「次へ」をクリックする。※前提として事前にキーペーアを作成を行っていること
画面の末尾に表示されている「スタックの作成」をクリックする。
画面左の欄で表示が「CREATE_IN_PROGRESS」から「CREATE_COMPLETE」に変わったらCloudFormationによる構築が完了。
それぞれの画面で作成されたリソースを確認する
・プライベートサブネット用のセキュリティグループ
インバウンドルールの一行目でHTTP通信の設定を行っている。
二行目の設定でSSH通信を行っており、パブリックサブネットからの通信のみに制限している。
以上の手順でクラウド環境の構築は完了である。
2. 投入したテンプレートの解説
以下が実際に投入したファイルです。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
KeyName:
Description: The Key Pair for the EC2 instance.
Type: "AWS::EC2::KeyPair::KeyName"
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Resources:
#####################################################
# VPC
#####################################################
CFStudyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: CFStudyVPC
#####################################################
# Public Subnet
#####################################################
CFStudyPubSub:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
VpcId: !Ref CFStudyVPC
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: CFStudyPubSub
#####################################################
# Private Subnet
#####################################################
CFStudyPriSub:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.2.0/24
MapPublicIpOnLaunch: false
VpcId: !Ref CFStudyVPC
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: CFStudyPriSub
#####################################################
# Internet Gateway
#####################################################
CFStudyIG:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: CFStudyIG
AttachCfInternetGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId : !Ref CFStudyIG
VpcId: !Ref CFStudyVPC
#####################################################
# RouteTable For Public Subnet
#####################################################
CFStudyRouteTablePubSub:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CFStudyVPC
Tags:
- Key: Name
Value: CFStudyRouteTablePubSub
RouteForPublicSubnet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref CFStudyRouteTablePubSub
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref CFStudyIG
CfAssocciateRouteTableForPublicSubnet:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref CFStudyRouteTablePubSub
SubnetId: !Ref CFStudyPubSub
#####################################################
# NAT-GW and Elastic IP
#####################################################
NatGatewayEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
!GetAtt NatGatewayEIP.AllocationId
SubnetId: !Ref CFStudyPubSub
Tags:
- Key: Name
Value: NatGateway
#####################################################
# RouteTable For Priavte Subnet
#####################################################
CFStudyRouteTablePriSub:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CFStudyVPC
Tags:
- Key: Name
Value: CFStudyRouteTablePriSub
RouteForPrivateSubnet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref CFStudyRouteTablePriSub
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
CfAssocciateRouteTableForPrivateSubnet:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref CFStudyRouteTablePriSub
SubnetId: !Ref CFStudyPriSub
#####################################################
# EC2(Bastion) on Public Subnet
#####################################################
EC2Pub:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref Ec2ImageId
KeyName: !Ref KeyName
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref CFStudyPubSub
GroupSet:
- !Ref EC2SGPub
Tags:
- Key: Name
Value: CFStudySSH
#####################################################
# Security Group for Public Subnet
#####################################################
EC2SGPub:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: CFStudyPubSG
GroupDescription: Security Group for Public Subnet
VpcId: !Ref CFStudyVPC
SecurityGroupIngress:
# ssh
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: '0.0.0.0/0'
#####################################################
# EC2(Aplication Sever) on Private Subnet
#####################################################
EC2Pri:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref Ec2ImageId
KeyName: !Ref KeyName
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: "false"
DeviceIndex: "0"
SubnetId: !Ref CFStudyPriSub
GroupSet:
- !Ref EC2SGPriVate
Tags:
- Key: Name
Value: CFStudyAP
#####################################################
# Security Group for Private Subnet
#####################################################
EC2SGPriVate:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: CFStudyPriSG
GroupDescription: Security Group for Private Subnet
VpcId: !Ref CFStudyVPC
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref EC2SGPub
IpProtocol: tcp
FromPort: 22
ToPort: 22
# Web Access
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: '0.0.0.0/0'
以下が説明です。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
KeyName:
Description: The Key Pair for the EC2 instance.
Type: "AWS::EC2::KeyPair::KeyName"
Ec2ImageId:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
-
AWSTemplateFormatVersion: 2010-09-09
- 上記はテンプレートフォーマットのバージョン宣言で、年月日は固定です。CloudFormationテンプレートの先頭に記載するおまじない。
-
ParametersのKeyName:
- EC2ログイン時に必要なキーペーアをCloudFormation実行時に指定できるようにしたパラメータです。
本項目で設定するキーファイルは、テンプレート内の後半で記載しているEC2の「EC2Pub」や「EC2Pri」の「KeyName: !Ref KeyName」で参照されることで利用できるようになります。
- EC2ログイン時に必要なキーペーアをCloudFormation実行時に指定できるようにしたパラメータです。
-
ParametersのEc2ImageId:
- Amazon linux 2 の最新のAMIのIDを参照するためのパラメータです。
Resources:
#####################################################
# VPC
#####################################################
CFStudyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: CFStudyVPC
-
Resources:
- 以降でAWSのリソースに関する記載を行うという宣言文です。こちらもおまじないです。
-
CFStudyVPC:
- 今回作成するVPCである「CFStudyVPC」の設定を書いています。「Properties」の「CidrBlock: 10.0.0.0/16」でIPアドレスの範囲を指定しております。
- 「- Key: Name Value: CFStudyVPC」の設定でNameタグに「CFStudyVPC」という値を設定して、AWSのコンソールで名前が表示されるようにしています。Key: Nameの指定は他の項目でも利用できますので、頻出です。
#####################################################
# Public Subnet
#####################################################
CFStudyPubSub:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
VpcId: !Ref CFStudyVPC
AvailabilityZone: ap-northeast-1a
Tags:
- Key: Name
Value: CFStudyPubSub
- CFStudyPubSub:
- 「Type: AWS::EC2::Subnet」で指定しているようにサブネット設定となります。
- IPアドレスの範囲は「CidrBlock: 10.0.1.0/24」で設定しています。
- 「MapPublicIpOnLaunch: true」とすることで外部からアクセス可能なパブリックサブネットとなります。
- 「VpcId: !Ref CFStudyVPC」こちらの設定でサブネットを作成するVPCをどこにするか指定しています。
- [AvailabilityZone: ap-northeast-1a」の設定で作成するサブネットは、東京リージョンのAZ(1a)に所属するとしています。
Private Subnetの方の説明は省きます。「MapPublicIpOnLaunch: false」とすることでプライベートサブネットになります。
#####################################################
# Internet Gateway
#####################################################
CFStudyIG:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: CFStudyIG
AttachCfInternetGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId : !Ref CFStudyIG
VpcId: !Ref CFStudyVPC
-
CFStudyIG:
- 作成したVPCをインターネットと通信可能にするためのインターネットゲートウェイの設定となります
-
AttachCfInternetGateway:
- このタグにより作成したインターネットゲートウェイをどこのVPCに関連付けるかの設定を行っています。
#####################################################
# RouteTable For Public Subnet
#####################################################
CFStudyRouteTablePubSub:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CFStudyVPC
Tags:
- Key: Name
Value: CFStudyRouteTablePubSub
RouteForPublicSubnet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref CFStudyRouteTablePubSub
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref CFStudyIG
CfAssocciateRouteTableForPublicSubnet:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref CFStudyRouteTablePubSub
SubnetId: !Ref CFStudyPubSub
-
CFStudyRouteTablePubSub:
- パブリックサブネット用のルートテーブルの設定です。
-
RouteForPublicSubnet:
- このタグによりインターネット向けの通信をインターネットゲートウェイを通るようにルーティングしています。
-
CfAssocciateRouteTableForPublicSubnet:
- 作成したルートテーブルをパブリックサブネットに紐づける設定を行っています。
#####################################################
# NAT-GW and Elastic IP
#####################################################
NatGatewayEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
!GetAtt NatGatewayEIP.AllocationId
SubnetId: !Ref CFStudyPubSub
Tags:
- Key: Name
Value: NatGateway
-
NatGatewayEIP:
- NATゲートウェイに紐づけを行う用のEIP(固定IPアドレス)を作成する設定です。
-
NatGateway:
- NATゲートウェイの設定となります。
- AllocationId: !GetAtt NatGatewayEIP.AllocationId でNATゲートウェイに紐づけるEIPのIDを指定しています。
- SubnetId: !Ref CFStudyPubSub でどこのサブネットにNATゲートウェイを設置するか指定しています。
RouteTable For Priavte Subnet の設定もほぼ同じなので割愛します。
一点だけ違うのは、プライベートサブネットのため「RouteForPrivateSubnet:」のルーティング設定でインターネット向けの通信は直接インターネットゲートウェイにルーティングするのではなく、NATゲートウェイを経由するようにルーティングしています。
#####################################################
# EC2(Bastion) on Public Subnet
#####################################################
EC2Pub:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref Ec2ImageId
KeyName: !Ref KeyName
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
SubnetId: !Ref CFStudyPubSub
GroupSet:
- !Ref EC2SGPub
Tags:
- Key: Name
Value: CFStudySSH
- EC2Pub:
- パブリックサブネットに作成するEC2インスタンス(APサーバ)の設定です
- ImageId: !Ref Ec2ImageId でファイルの先頭のParameterで設定したインスタンスのイメージ(AMI)を指定しています。
- InstanceType EC2の性能を指定しています。小型で大丈夫なのでt2.microを指定しています。必要に応じてインスタンスタイプの設計が必要です。
- NetworkInterfaces:でネットワーク関連の設定です
- AssociatePublicIpAddress: "true" 本設定をtrueにすることで外部からアクセス可能なEC2インスタンスのパブリックIPを有効化しています。
- DeviceIndex: "0" プライマリネットワークインターフェイスとしている。
- SubnetId: !Ref CFStudyPubSub 作成するEC2インスタンスをどこのサブネットに紐づけるか指定を行っている
- GroupSet: EC2インスタンスに紐づけるセキュリティグループ(ファイアウォール的な物)を指定している
#####################################################
# Security Group for Public Subnet
#####################################################
EC2SGPub:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: CFStudyPubSG
GroupDescription: Security Group for Public Subnet
VpcId: !Ref CFStudyVPC
SecurityGroupIngress:
# ssh
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: '0.0.0.0/0'
- EC2SGPub:
- セキュリティグループの設定です。
- GroupName: CFStudyPubSG コンソールで表示される際の表示名の指定
- VpcId: !Ref CFStudyVPC どこのVPCで利用できるように紐づけるかの指定
- SecurityGroupIngress: ファイアウォールで許可する通信ルールの設定
- 正解中のどのサーバからのtcpプロトコルの22番ポートの通信を許可する設定
- 送信元を絞れるGIPをアクセス元が保持している場合は、「CidrIp: '0.0.0.0/0'」のIP部分を変更して指定すること。現状は古オープンでどこのサーバからもアクセス可能である。
EC2(Aplication Sever) on Private Subnet も EC2(Bastion) on Public Subnetの設定とほぼ同様のため割愛する。
正しプライベートサブネットに配置するサーバのためパブリックIPの割り当ては不要であり「AssociatePublicIpAddress: "false"」の設定を行っている。
#####################################################
# Security Group for Private Subnet
#####################################################
EC2SGPriVate:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: CFStudyPriSG
GroupDescription: Security Group for Private Subnet
VpcId: !Ref CFStudyVPC
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref EC2SGPub
IpProtocol: tcp
FromPort: 22
ToPort: 22
# Web Access
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
CidrIp: '0.0.0.0/0'
- EC2SGPriVate:
- プライベートサブネットに存在するEC2インスタンス向けの設定です。
- 「SourceSecurityGroupId: !Ref EC2SGPub」「IpProtocol: tcp」「FromPort: 22」「ToPort: 22」の設定で、本セキュリティグループが設定されるインスタンスへのSSH通信はパブリックサブネット「EC2SGPub」からのみ許可するように設定を行っている。
- SecurityGroupIngress: ファイアウォールで許可する通信ルールの設定
- 正解中のどのサーバからのtcpプロトコルの8080番ポートの通信を許可する設定
- 送信元を絞れるGIPをアクセス元が保持している場合は、「CidrIp: '0.0.0.0/0'」のIP部分を変更して指定すること。現状はフルオープンでどこのサーバからもアクセス可能な状態となります。
本記事は以上です。
クラウド環境の作成の手助けになれば嬉しいです。
参考文献
本記事の作成に当たり、以下の情報も参考にさせて頂きました。ありがとうございました。