【AWS】CloudFormtionでブログサービスを構築してみた(01.Network編)

# 01.はじめに
[【AWS】CloudFormtionでブログサービスを構築してみた(概要編)](https://qiita.com/1k5/items/4f6d61373e80f824bd9a)の続きである。
今回から実際のコードを記述する。
`この記事で扱うものはコンポーネントは下記である。`
1.VPC

2.Internet Gateway

3.Route Table

4.セキュリティグループ

5.サブネット

6.VPCエンドポイント

7.Route53(ゾーン登録のみ)
　※後続の証明書発行でゾーン登録が
　　必要になるのでこのタイミングでゾーンだけ作成しておく。[参考](https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/dns-validation.html)
　　　
# 02.構成図
構成図にすると下記のようになる。
![構成図２-Network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1050566/bdfcfecd-6ae0-38f7-1785-a0a31889ef5c.png)


# 03.IP採番とセキュリティグループ

◆IPアドレス
|対象|Cidr |
|:-:|:---------:|
|VPC|10.0.0.0/21|
|Public Sunbet A|10.0.1.0/24|
|Private Sunbet A1|10.0.2.0/24|
|Private Sunbet A2|10.0.3.0/24|
|Public Sunbet C|10.0.4.0/24|
|Private Sunbet C1|10.0.5.0/24|
|Private Sunbet C2|10.0.6.0/24|

※Private Sunbet C2には特にサーバ等は配置しないが、サブネットグループで使用するために配置している。

◆セキュリティグループ
|対象|プロトコル |Source   |
|:-:|:---------:|:-------:|
|ALB|https http     |0.0.0.0/0|
|EC2|http       |ALBのみ  |
|RDS|Mysql       |EC2のみ  |
|VPCエンドポイント|https       |VPCのCidrのみ  |


# 04.テンプレートファイル
```yaml:network.yml
AWSTemplateFormatVersion: 2010-09-09
Description: Network

# ------------------------------------------------------------#
#  パラメーター
# ------------------------------------------------------------#
Parameters:

#ドメイン名を指定
  HostedZoneName:
    Type: String
    Description: Type of this domain name.

# ------------------------------------------------------------#
#  リソース
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
#  VPC
# ------------------------------------------------------------#
  CFVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/21
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
      - Key: Name
        Value: CFVPC

# ------------------------------------------------------------#
#  Internet Gateway
# ------------------------------------------------------------#
  igwName:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: CFigw
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref CFVPC
      InternetGatewayId: !Ref igwName

# ------------------------------------------------------------#
#  Route Table
# ------------------------------------------------------------#
  RouteTable:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachGateway
    Properties:
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CF-PublicSubnet_RouteTable
  Route:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref igwName

# ------------------------------------------------------------#
#  Public Sunbet A
# ------------------------------------------------------------#
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: 10.0.1.0/24
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CFPublicSubnetA
  PublicRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref RouteTable

# ------------------------------------------------------------#
#  Private Sunbet A1
# ------------------------------------------------------------#
  PrivateSubnetA1:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: 10.0.2.0/24
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CFPrivateSubnetA1
# ------------------------------------------------------------#
#  Private Sunbet A2
# ------------------------------------------------------------#
  PrivateSubnetA2:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: 10.0.3.0/24
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CFPrivateSubnetA2
# ------------------------------------------------------------#
#  Public Sunbet C
# ------------------------------------------------------------#
  PublicSubnetB:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: 10.0.4.0/24
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CFPublicSubnetB
  PublicRouteTableAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetB
      RouteTableId: !Ref RouteTable
# ------------------------------------------------------------#
#  Private Sunbet C1
# ------------------------------------------------------------#
  PrivateSubnetC1:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: 10.0.5.0/24
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CFPrivateSubnetC1
# ------------------------------------------------------------#
#  Private Sunbet C2
# ------------------------------------------------------------#
  PrivateSubnetC2:
    Type: AWS::EC2::Subnet
    DependsOn: AttachGateway
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: 10.0.6.0/24
      VpcId: !Ref CFVPC
      Tags:
        - Key: Name
          Value: CFPrivateSubnetC2

# ------------------------------------------------------------#
#  ALB Security Group
# ------------------------------------------------------------#
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: CF-ALB-SG
      GroupDescription: Allow HTTPS access from internet
      VpcId: !Ref CFVPC
      SecurityGroupIngress:
        # https
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: "0.0.0.0/0"
        # http
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"
      Tags:
        - Key: Name
          Value: CF-ALB-SG

# ------------------------------------------------------------#
#  EC2 Security Group
# ------------------------------------------------------------#
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    DependsOn: ALBSecurityGroup
    Properties:
      GroupName: CF-EC2-SG
      GroupDescription: Allow HTTP access from ALB
      VpcId: !Ref CFVPC
      SecurityGroupIngress:
        # http
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref ALBSecurityGroup
      Tags:
        - Key: Name
          Value: CF-EC2-SG
# ------------------------------------------------------------#
#  RDS Security Group
# ------------------------------------------------------------#
  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    DependsOn: EC2SecurityGroup
    Properties:
      GroupDescription: Allow RDS access from EC2
      VpcId: !Ref CFVPC
      SecurityGroupIngress:
        # DB
        - FromPort: 3306
          ToPort: 3306
          IpProtocol: tcp
          SourceSecurityGroupId: !Ref EC2SecurityGroup
      Tags:
        - Key: Name
          Value: CF-RDS-SG

#------------------------------------------------------------#
#VPCエンドポイントの設定
#------------------------------------------------------------#
# ------------------------------------------------------------#
#  VPCendpoint Security Group
# ------------------------------------------------------------#
  VPCendpointSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: VPCendpointSecurityGroup
      VpcId: !Ref CFVPC
      SecurityGroupIngress:
        # https
        - FromPort: 443
          ToPort: 443
          IpProtocol: tcp
          CidrIp: !GetAtt CFVPC.CidrBlock
      Tags:
        - Key: Name
          Value: CF-VPCendpoint-SG
#------------------------------------------------------------#
#  EndpointSSM
#------------------------------------------------------------#
  EndpointSSM:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      SecurityGroupIds:
        - !Ref VPCendpointSecurityGroup
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm"
      SubnetIds:
        - !Ref PrivateSubnetA1
        - !Ref PrivateSubnetC1
      VpcEndpointType: Interface
      VpcId: !Ref CFVPC
#------------------------------------------------------------#
#  EndpointSSMMessages
#------------------------------------------------------------#
  EndpointSSMMessages:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      SecurityGroupIds:
        - !Ref VPCendpointSecurityGroup
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssmmessages"
      SubnetIds:
        - !Ref PrivateSubnetA1
        - !Ref PrivateSubnetC1
      VpcEndpointType: Interface
      VpcId: !Ref CFVPC
#------------------------------------------------------------#
#  EndpointEC2Messages
#------------------------------------------------------------#
  EndpointEC2Messages:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      PrivateDnsEnabled: true
      SecurityGroupIds:
        - !Ref VPCendpointSecurityGroup
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2messages"
      SubnetIds:
        - !Ref PrivateSubnetA1
        - !Ref PrivateSubnetC1
      VpcEndpointType: Interface
      VpcId: !Ref CFVPC

  
# ------------------------------------------------------------#
# Route53
# ------------------------------------------------------------#
# ------------------------------------------------------------#
#  HostZone
# ------------------------------------------------------------#
  Route53HostedZone:
    Type: AWS::Route53::HostedZone
    Properties:
      Name: !Sub "${HostedZoneName}"
      HostedZoneTags:
        -
          Key: Name
          Value: DNS-Zone
          
Outputs:

#サブネット
  PublicSubnetA:
      Value: !Ref PublicSubnetA
      Export:
        Name: PublicSubnetA-Outputs
  PublicSubnetB:
      Value: !Ref PublicSubnetB
      Export:
        Name: PublicSubnetB-Outputs
  PrivateSubnetA1:
      Value: !Ref PrivateSubnetA1
      Export:
        Name: PrivateSubnetA1-Outputs
  PrivateSubnetA2:
      Value: !Ref PrivateSubnetA2
      Export:
        Name: PrivateSubnetA2-Outputs
  PrivateSubnetC1:
      Value: !Ref PrivateSubnetC1
      Export:
        Name: PrivateSubnetC1-Outputs
  PrivateSubnetC2:
      Value: !Ref PrivateSubnetC2
      Export:
        Name: PrivateSubnetC2-Outputs
#セキュリティグループ
  EC2SecurityGroup:
      Value: !Ref EC2SecurityGroup
      Export:
        Name: EC2SecurityGroup-Outputs
  ALBSecurityGroup:
      Value: !Ref ALBSecurityGroup
      Export:
        Name: ALBSecurityGroup-Outputs
  RDSSecurityGroup:
      Value: !Ref RDSSecurityGroup
      Export:
        Name: RDSSecurityGroup-Outputs
#VPC
  CFVPC:
      Value: !Ref CFVPC
      Export:
        Name: CFVPC-Outputs
#Route53HostZone(ACMの証明書発行で使う)
  HostZone:
      Value: !Ref Route53HostedZone
      Export:
        Name: CFHostZone-Outputs
```

# 05.テスト
ネットワークコンポーネントを配置したのみなので実施しない。

# 参考文献
https://dev.classmethod.jp/articles/cloudformation-tips-focused-on-refs/

https://dev.classmethod.jp/articles/session-manager-ec2-cloudformation/

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-using-cli.html

★次回はこちら
[【AWS】CloudFormtionでブログサービスを構築してみた(02.EC2,RDS,ALB編)](https://qiita.com/1k5/items/5acca0ee627ec37b56da)