CloudFormationの書き方 覚え書き

## CloudFormationの書き方
すぐ忘れてしまうので備忘録として

### パラメータ Parameters
- GUI等、外部からパラメータを指定する場合の書き方
- ドロップダウンによる選択肢、デフォルト値も指定可能
```yml
Parameters:
    ParamKey1:
      Description: Parameter key1
      Type: String
      AllowedValues:
        - v1
        - v2
        - v3
      Default: v1

```
- 参照方法は、`!Ref` や `${}`
```yml
Resources:
    Resource1:
      # 省略
        SubnetIds:
          - !Ref Subnet1
          - !Ref Subnet2

Tags:
    - Key: Name
      Value: !Sub "${Name1}-suffix"

```

### 条件定義 Conditions
- こういう値のときには作る、作らない等の条件分岐をするための事前定義の書き方 `Equals`、`Or`、`Not`が使える 
```yml
Conditions:
  IsV1: !Equals [!Ref ParamKey1, "v1"]
  IsV1or2: !Or [
      !Equals [!Ref ParamKey1, "v1"],
      !Equals [!Ref ParamKey1, "v2"],
    ]
  IsNotV1: !Not [!Equals [!Ref ParamKey1, "v1"]]
  IsBlank: !Equals [!Ref ParamKey1, ""]
```

### 条件分岐 Condition
- Conditionsで定義した値を元にリソースの作る・作らない、属性を設定する・しない、アウトプットを作る・作らない等の分岐を行う際の書き方

  - ResourceやOutputの条件分岐例
    - IsV1がtrueのときだけ動作する
```yml
Resources:
  Resource1:
    Condition: IsV1
    Type: AWS::CloudFormation::Stack
    Properties:

Outputs:
  MyOutputV1:
    Condition: IsV1
    Value: !Ref ParamKey
    Description: Description Value
```

  - SecurityGroupやIAMPolicyのようにリスト形式の条件分岐例
  - IsV1がtrueのときだけ動作する
  - `!Ref AWS::NoValue`は、対応するリソースプロパティを削除する疑似パラメータ参照となる
  - `!Ref AWS::NoValue`の代わりに、`!Ref ParamValue1`などと定義すればIfに合致しない場合の値を設定できる

```yml
Resources:
  SecurityGroup1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      # 省略
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref XXXX
          Description: XXXXXX
        - !If
          - IsV1
          - IpProtocol: tcp
            FromPort: 8080
            ToPort: 8080
            CidrIp: !Ref XXXX
          - !Ref AWS::NoValue

  Policy1:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # 省略
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Resource: "*"
            Effect: Allow
            Action:
              - ec2:xxxx
          - !If
            - IsV1
            - Resource: !Ref XXXXXX
              Effect: Allow
              Action:
                - xxxx:xxx
            - !Ref AWS::NoValue
```
  - S3のロギング設定など、単一要素の設定の条件分岐する例
  - IsV1がtrueのときだけ設定する

```yml
Resources:
  S3Bucket1:
      Type: AWS::S3::Bucket
      # 省略
      Properties:
        # 省略
        LoggingConfiguration: !If
          - IsV1
          - DestinationBucketName: !Ref xxxxx
            LogFilePrefix: !Ref xxxx
          - !Ref AWS::NoValue
```
### マッピング Mappings
```yml
Parameters:
  ParamEnv:
    Description: Environment
    Type: String
    AllowedValues:
      - develop
      - staging
      - production
Mappings: 
    Env:
      "develop":
        DefaultName: my-develop
      "staging":
        DefaultName: my-staging
      "production":
        DefaultName: my-production
Resources:
# 省略
      Parameters:
        DefaultName: !FindInMap [Env, !Ref ParamEnv, DefaultName]
```

### テンプレートURL TemplateURL
```yml
Mappings: 
  Env:
    "develop":
      TemplateURL: https://xxxxxxx-my-develop-xxxxxx.s3.ap-northeast-1.amazonaws.com/stackroot
        # 省略

Resources:
  NestResource1:
      Type: AWS::CloudFormation::Stack
      Properties:
        TemplateURL: !Sub
          - ${TemplateURL}/neststack/neststack.yml
          - { TemplateURL: !FindInMap [Env, !Ref ParamEnv, TemplateURL] }
        Parameters:
        # 省略
```

### 文字列結合 Sub
```yml
Name1: !Sub
- ${DefaultName}-01
- { DefaultName: !FindInMap [Env, !Ref ParamKey, DefaultName] }

Name2: !Sub ${DefaultName}-${Prefix}-value
```

### AWSアカウントIdやリージョンの参照
- Policy等で記載するシーンの書き方
- ARNを記載するときの書き方
```yml
Principal:
    AWS: !Join
      - ""
      - - "arn:aws:iam::"
        - !Ref "AWS::AccountId"
        - ":root"
Param: !Sub "arn:aws:xxxx:${AWS::Region}:${AWS::AccountId}:${xxxxx}"
```