[AWS][CFn]GuardDutyの設定

## はじめに

初めまして。なじむです。
クラスメソッドさんのブログ記事、[AWSアカウントを作ったら最初にやるべきこと ～令和元年版～](https://dev.classmethod.jp/cloud/aws/aws-1st-step-new-era-reiwa/)を参考にさせていただき、AWSでの初期設定をCloudFormationで実施していこうという記事をしばらく書いていこうと思います。
今回は「GuardDutyの有効化」をCloudFormationで実施していきます。GuardDuty自体に関してはどこかで記事を書いていこうと思います。
※CloudFormationとは何かをある程度理解している人向けになってしまうと思うのでその点はご了承ください。

## 前提

サンプルコードで実行しているのは以下です。

- GuardDutyを有効にする
- SNSを作成する（今回はメール通知）
- GuardDutyでイベントを検知した時にCloudwatchイベントを使用してSNSに通知する

## サンプルコード
```yaml
---
AWSTemplateFormatVersion: 2010-09-09
Description: GuardDuty

#------------------------------
# Parameters: Your resource list
#------------------------------
Parameters:
  EMailAddress: # スタック作成時に任意のメールアドレスを指定してください。
    Type: String
    Description: Specifies your E-Mail for notify GuardDutyAlert.

#------------------------------
# Resources: Your resource list
#------------------------------
Resources:
  # GuardDutyを有効にする
  GuardDuty:
    Type: AWS::GuardDuty::Detector
    Properties:
      Enable: true

  # SNSを作成する（今回はメール通知）
  ## Topic
  SNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: GuardDutyTopic #任意の名前に変更してください
      Subscription:
      - Endpoint: !Ref EMailAddress
        Protocol: email

  ## Topic Policy
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: default_policy_ID
        Version: 2012-10-17
        Statement:
        - Sid: default_statement_ID
          Effect: Allow
          Principal:
            AWS: "*"
          Action:
          - SNS:GetTopicAttributes
          - SNS:SetTopicAttributes
          - SNS:AddPermission
          - SNS:RemovePermission
          - SNS:DeleteTopic
          - SNS:Subscribe
          - SNS:ListSubscriptionsByTopic
          - SNS:Publish
          - SNS:Receive
          Resource: !Ref SNSTopic
          Condition:
            StringEquals:
              AWS:SourceOwner: !Ref AWS::AccountId
        - Sid: AWSEvents_AlertGuardDutyFindings_Id123
          Effect: Allow
          Principal:
            Service:
            - events.amazonaws.com
          Action: sns:Publish
          Resource: !Ref SNSTopic
      Topics:
      - !Ref SNSTopic

  # GuardDutyでイベントを検知した時にCloudwatchイベントを使用してSNSに通知する
  ## Cloudwatch Rule for GuardDuty
  GuardDutyCWEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: AlertGuardDutyFindings
      Description: Alert to SNS topic when find threats by GuardDuty
      EventPattern: {
                      "source": [
                        "aws.guardduty"
                      ],
                      "detail-type": [
                        "GuardDuty Finding"
                      ]
                    }
      Targets:
      - Arn: !Ref SNSTopic
        Id: Id123
```

## 実行結果

上記テンプレートを用いてスタックを作成した結果です。
初めての場合はGUIから確認した方が分かりやすいので、結果はGUIで確認します。

- GuardDuty
![20191204_132508.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/709fb4d4-0bb7-f20c-22ee-463d60b6aaf7.jpeg)

- SNSTopic
![20191204_132629.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/4dad6127-7210-88f3-97be-698015bceb20.jpeg)

- GuardDutyCWEventRule
![20191204_132657.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/553942dd-a1d8-406a-92fb-3ef12db5e404.jpeg)


## まとめ

今回はCloudFormationでGuardDutyを有効にしようお届けしました。
GuardDutyは1クリックでできるので正直CloudFormationで作らなくても良いかもしれませんが、通知の設定をしないと何かあっても通知が来ないので、そこまでをまとめて実施するようテンプレートにしました。
何かのお役に立てれば幸いですノシ