NATGatewayを自動作成・削除

とりあえずできたので書き出し
そのうち図を書き足します

# 概要

平日の業務時間中だけサーバを使いたい。さらにNATゲートウェイも使わないので止めたい。
という~~貧乏な人~~コスト意識の高い方向けテンプレート  

## このテンプレートは

NATGWとSSM DocumentとEventBridgeを作るもの
NATGW： テンプレートの起動パラメータによって、作成・削除ができる
SSM Document: このテンプレートで作成したCFn Stackの更新（NATの作成削除を実行）できる
EventBridge： スケジュールでSSM　Documentを実行する


#### 起動パラメータ
+ NATGW 作成フラグ
+ メール通知送信先アドレス
+ NATGWを配置するパブリックサブネット
+ NATGWを経路にするプライベートサブネットのルートテーブル

#### 作成するリソース

| リソース      | 内容                                        |
|---------------|---------------------------------------------|
| NatGateway    | フラグtrueの時のみ作成                      |
| EIP           | フラグtrueの時のみ作成：NAT Gateway用EIP    |
| Route         | フラグtrueの時のみ作成：NAT Gatewayのルート |
| IAM::Role     | SSM Document用のIAMロール                   |
| SNS::Topic    | SSM Automationで使用、終了通知用            |
| SSM::Document | SSM Document                                |
| IAM::Role     | EventBridge用のIAMロール                    |
| Events::Rule  | 起動用スケジュール                          |
| Events::Rule  | 終了用スケジュール                          |

<details>
<summary> ←（ここをクリックすると展開）　CFnテンプレ全体はこちら</summary>

``` yaml


```
</details>

# 詳細

## 1,パラメータ

``` yaml
Parameters:
  CreateNAT:
    Type: String
    AllowedValues: [true, false]
  MailTo:
    Type: String
  PublicSubnetID:
      Type: String
  PrivateRouteTableID:
      Type: String
Conditions:
  isCreateNAT: !Equals [!Ref CreateNAT, "true"]
```

## 2,NAT Gateway

``` yaml
  NAT:
    Type: AWS::EC2::NatGateway
    Condition: isCreateNAT
    Properties:
      AllocationId: !GetAtt 
        - NatGatewayEIP
        - AllocationId
      SubnetId: !Ref PublicSubnetID
  NatGatewayEIP:
    Type: AWS::EC2::EIP
    Condition: isCreateNAT
    Properties:
      Domain: vpc
  PrivateRouteNAT:
    Type: AWS::EC2::Route
    Condition: isCreateNAT
    Properties:
      RouteTableId: !Ref PrivateRouteTableID
      NatGatewayId: !Ref NAT
      DestinationCidrBlock: "0.0.0.0/0"
```

## 3,SSM Document
### 3-1, Role
``` yaml
  AutomationAssumeRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub 'Role-automation-${AWS::StackName}'
      Path: "/"
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Action: sts:AssumeRole
          Principal:
            Service: 
              - ssm.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole
      Policies:
        - PolicyName: inline
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - cloudformation:UpdateStack
                  - sns:Publish
                  - ec2:*
                  - tag:GetResources
                Resource: 
                  - "*"
              - Effect: Allow
                Action: ssm:StartAutomationExecution
                Resource: 
                  - !Sub arn:aws:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$DEFAULT
                  - !Sub arn:aws:ssm:${AWS::Region}::automation-definition/AWS-StopEC2Instance:$DEFAULT
              - Effect: Allow
                Action: iam:PassRole
                Resource:
                - !Sub "arn:aws:iam::${AWS::AccountId}:role/Role-automation-${AWS::StackName}"
                Condition:
                  StringLikeIfExists:
                    iam:PassedToService: ssm.amazonaws.com


```

### 3-2, SNS Topic
``` yaml
  SNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub "SampleTopic-${AWS::StackName}"
      Subscription:
        - Endpoint: !Ref MailTo
          Protocol: email
```

### 3-3, SSM Document
``` yaml
  SSMDocumentStartStopResorces:
    Type: AWS::SSM::Document
    Properties:
      DocumentFormat: YAML
      DocumentType: Automation
      Content:
        schemaVersion: "0.3"  
        description: CovProject Remove NATGateway and Start/Stop EC2 Instances(byTag)
        assumeRole: !GetAtt AutomationAssumeRole.Arn
        parameters:
          createFlg:
            type: String
            default: "ture"
            description: true is Create NAT and Start EC2Instance / false is Remove NAT and Stop EC2Instance  
            allowedValues:
              - "true"
              - "false"
        mainSteps: 
          - name: UpdateCFnStack
            action: aws:executeAwsApi
            inputs:
              Service: cloudformation
              Api: update_stack
              StackName: !Ref AWS::StackName
              UsePreviousTemplate: true
              Parameters:
                - ParameterKey: CreateNAT
                  ParameterValue: "{{ createFlg }}"
                - ParameterKey: MailTo
                  UsePreviousValue: True
                - ParameterKey: PublicSubnetID
                  UsePreviousValue: True
                - ParameterKey: PrivateRouteTableID
                  UsePreviousValue: True
              Capabilities:
                - CAPABILITY_NAMED_IAM
            outputs:
              - Name: stackId
                Selector: $.StackId
                Type: String
          - name: WaitCFnStack
            action: aws:waitForAwsResourceProperty
            timeoutSeconds: 300
            inputs:
              Service: cloudformation
              Api: DescribeStacks
              StackName: "{{ UpdateCFnStack.stackId }}"
              PropertySelector: Stacks[0].StackStatus
              DesiredValues:
                - UPDATE_COMPLETE
          - name: CheckIsStart
            action: aws:branch
            inputs:
              Choices:
              - NextStep: StopEC2
                Variable: "{{ createFlg }}"
                StringEquals: "false"
          - name: StartEC2
            action: aws:executeAwsApi
            inputs:
              Service: ssm
              Api: StartAutomationExecution
              DocumentName: AWS-StartEC2Instance
              TargetParameterName: "InstanceId"
              Targets:
                -
                  Key: tag:AutoStop
                  Values: 
                    - 'true'
          - name: StartCompletionNotice
            action: aws:executeAwsApi
            inputs:
              Service: sns
              Api: Publish
              TopicArn: !Ref SNSTopic
              Message: 'Message'
              Subject: 'subject Start'
            isEnd: true
          - name: StopEC2
            action: aws:executeAwsApi
            inputs:
              Service: ssm
              Api: StartAutomationExecution
              DocumentName: AWS-StopEC2Instance
              TargetParameterName: "InstanceId"
              Targets:
                -
                  Key: tag:AutoStop
                  Values: 
                    - 'true'
          - name: StopCompletionNotice
            action: aws:executeAwsApi
            inputs:
              Service: sns
              Api: Publish
              TopicArn: !Ref SNSTopic
              Message: 'Message'
              Subject: 'subject Stop'
            isEnd: true


```

## 4,EventBridge
### 4-1, Role
``` yaml
  EventBridgeRole:    
    Type: AWS::IAM::Role
    Properties: 
      RoleName: !Sub 'Role-events-${AWS::StackName}'
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "events.amazonaws.com"
            Action: sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: StopEc2Role_policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: ssm:StartAutomationExecution
                Resource: !Sub "arn:aws:ssm:ap-northeast-1:${AWS::AccountId}:automation-definition/${SSMDocumentStartStopResorces}:$DEFAULT"
```
### 4-2, EventBridge
``` yaml
  EventRuleEc2Start:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub "${AWS::StackName}StartRule"
      Description: !Sub "${AWS::StackName} Start."
      ScheduleExpression: "cron(00 23 ? * SUN-THU *)"
      State: ENABLED
      Targets:
        - Arn: !Sub "arn:aws:ssm:ap-northeast-1:${AWS::AccountId}:automation-definition/${SSMDocumentStartStopResorces}:$DEFAULT"
          Id: TargetStartCov
          RoleArn: !GetAtt EventBridgeRole.Arn
          Input: "{\"createFlg\":[\"true\"]}"
  EventRuleEc2Stop:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub "${AWS::StackName}StopRule"
      Description: !Sub "${AWS::StackName} Stop."
      ScheduleExpression: "cron(00 11 ? * MON-FRI *)"
      State: ENABLED
      Targets:
        - Arn: !Sub "arn:aws:ssm:ap-northeast-1:${AWS::AccountId}:automation-definition/${SSMDocumentStartStopResorces}:$DEFAULT"
          Id: TargetStopCov
          RoleArn: !GetAtt EventBridgeRole.Arn
          Input: "{\"createFlg\":[\"false\"]}"
```