CloudFormationでCloudWatch EventsとLambdaを構築

# CloudFormation概要
忘備録的に記載致します。

JSONファイルやYAMLファイルへ構築したいAWSサービスの設定項目を記載し、
CloudFormationへ読み込ませることで記載したサービスの構築が自動化できる。

■ 公式リンク
[公式ページ](https://aws.amazon.com/jp/cloudformation/)
[ブラックベルト](https://d1.awsstatic.com/webinars/jp/pdf/services/20181128-AWS-BlackBelt-CloudFormation.pdf)

# 構築

## 構成

EC2とかであればすぐ検索できるかと思いますので、
前回の記事のCloudWatch EventsとLambdaの連携する箇所を構築します。
※Lambdaのコードも前回の記事を参照をお願い致します。
[【前回：AWS Configの通知内容をLambdaで成形】](https://qiita.com/tomoki_s/items/0d3b249da6ce9cbafdeb)

![CFn.PNG](https://qiita-image-store.s3.amazonaws.com/0/316662/e08015f6-dbe7-0e27-f0ce-5f6421435d2b.png)


## CloudFormation

テンプレート
CloudFormationのパラメータはLambdaへ渡す為のものとなります。

```yaml

AWSTemplateFormatVersion: 2010-09-09
Description: CFn test
Parameters: 
    変数名:CloudFormationで使用できる変数
        Type: String
        Description:(変数の説明文) 
    S3Name:
        Type: String
    ZipF:
        Type: String
    P3Handler:
        Type: String
Resources:
    以下AWSサービスの内容
```
### 今回のパラメータの意図

LambdaのコードはYAMLファイルへ直書きをせずS3へ保存し、それを参照させます。

- S3Name:python3のコードを保存したS3バケット名
- ZipF:python3のコードを記載したファイル名
- P3Handler:上記ファイル名から｢.zip｣を外した文字

## CloudWatch Events
YAMLファイルの記載内容
内容はGUIでEventsのルールを作成するとイベントパターンが閲覧できる為、
実際に作成したいイベントを手で設定してみると参考になります。

### IAMの設定変更検知

```yaml

EventRule:
    Type: 'AWS::Events::Rule'
    Properties:
      Description: EventRule
      EventPattern:
        source:
          - aws.config
        detail-type:
          - Config Configuration Item Change
        detail:
          configurationItem:
            resourceType:
              - 'AWS::IAM::User'
              - 'AWS::IAM::Group'
              - 'AWS::IAM::Role'
              - 'AWS::IAM::Policy'
      State: ENABLED
      Targets:
        - Arn: !GetAtt 
            - LambdaTestFunction
            - Arn
          Id: TargetFunctionV1
    DependsOn:
      - LambdaTestFunction
```

### ルールの準拠・非準拠検知

```yaml

  EventRule:
    Type: 'AWS::Events::Rule'
    Properties:
      Description: EventRule
      EventPattern:
        source:
          - aws.config
        detail-type:
          - Config Rules Compliance Change
      State: ENABLED
      Targets:
        - Arn: !GetAtt 
            - LambdaTestFunction
            - Arn
          Id: TargetFunctionV1
    DependsOn:
      - LambdaTestFunction
```

### 項目の補足

resourceType:IAMの項目を記載し、IAMの設定変更を通知対象にする。
Targets:CloudWatch Eventsへ関連づけるLambdaを記載
[公式参考ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html)

## CloudWatch EventsへLambdaのロールを付与

```yaml

  PermissionForEventsToInvokeLambda:
    Type: 'AWS::Lambda::Permission'
    Properties:
      FunctionName: !Ref LambdaTestFunction
      Action: 'lambda:InvokeFunction'
      Principal: events.amazonaws.com
      SourceArn: !GetAtt 
        - EventRule
        - Arn
```
[公式参考ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html)

## Lambda

```yaml

  LambdaTestFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        S3Bucket: !Ref S3Name
        S3Key: !Ref ZipF
      Environment:
        Variables:
      FunctionName: Config-item-change-test
      Handler: P3Handler.lambda_handler
      Runtime: python3.6
      Timeout: '3'
      Role: !GetAtt 
        - LambdaExecutionRole
        - Arn
```

### 項目の補足

- S3Bucket: python3のコードを保存したS3バケット名
- S3Key:python3のコードを記載したファイル名
- Handler:上記ファイル名から｢.zip｣を外した文字

[公式参考ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)

## 今回作成したLambda用のPolicy作成と付与

```yaml
  LambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: lambdatest
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                  - 's3:PutAnalyticsConfiguration'
                  - 's3:PutAccelerateConfiguration'
                  - 's3:ReplicateObject'
                  - 's3:PutEncryptionConfiguration'
                  - 's3:PutBucketTagging'
                  - 's3:PutLifecycleConfiguration'
                  - 's3:PutObjectTagging'
                  - 's3:PutBucketVersioning'
                  - 's3:PutMetricsConfiguration'
                  - 's3:PutReplicationConfiguration'
                  - 's3:PutObjectVersionTagging'
                  - 's3:PutBucketCORS'
                  - 's3:PutInventoryConfiguration'
                  - 's3:PutObject'
                  - 's3:PutBucketNotification'
                  - 's3:PutBucketWebsite'
                  - 's3:PutBucketRequestPayment'
                  - 's3:PutBucketLogging'
                  - 's3:ListBucket'
                  - 'sns:Publish'
                Resource:
                  - '*'
```
[公式参考ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)

## すべてを一つにまとめる
テンプレートの「Resources:」から次の行へインデントを入れ、張り付けていってください。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: CFn test
Parameters: 
    S3Name:
        Type: String
    ZipF:
        Type: String
    P3Handler:
        Type: String
Resources:
  LambdaTestFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        S3Bucket: !Ref S3Name
        S3Key: !Ref ZipF
      Environment:
        Variables:
      FunctionName: Config-item-change-test
      Handler: P3Handler.lambda_handler
      Runtime: python3.6
      Timeout: '3'
      Role: !GetAtt 
        - LambdaExecutionRole
        - Arn
略
```


## CloudFormationでテンプレートのチェック

CloudFormationにはテンプレートが正しいか否かをチェックする事ができます。
AWSリソース単位で作成される為、エラー箇所が表示されます。
それらでエラー解消につながります。

1. CloudFormationのメニュ内　テンプレートのデザインから
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316662/d5e6dcae-ae07-819f-eee8-14653878a14e.png)

1. 右上のファイルアイコンから「開く」を選択し、上記で作成したYAMLファイルを開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316662/40a27d20-acf6-5a35-1b89-761af49678f3.png)

2. YAMLファイルのフォーマットが正しければ以下のようにアイコンと矢印が出ます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316662/251c5f3b-77a1-ec93-c4c3-6ca6d9816659.png)

## CloudFormationで構築

3. アップロードアイコンをクリックすることで、構築に入ります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316662/ceecf5b6-1152-e0bd-d485-98a414daa313.png)

1. 名前やパラメータを入力してください。今回ロールを作成するので、
最後の「AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。」へ
チェックすることを忘れないで下さい。他はデフォルトで問題ありません。

# 最後に
CloudFormationは0からの挑戦だったので使い方を学ぶのが大変でした。
公式ドキュメントが充実し、先駆者様のおかげで使えるようになりました。
間違いがありましたらご指摘いただけると幸いです。