GuardDuty → EventBridge → SNS → Chatbot → Slack

#構成#

GuardDutyから検知　>> Event Bridge をトリガーに SNSトピックに通知 >> SNSトピックに設定されているChatbotに情報送信 >> ChatbotがSlackに通知

というのを CloudFormation でデプロイしていこうと思います。


#Guard Duty から Slack に通知させる#

##全リージョンにデプロイする場合##

###Chatbotでワークスペースを準備する###

- [こちら](https://qiita.com/leomaro7/items/4cc37ea3ca9b03eb0ef1#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9id)の記事を参考にChatbotのワークスペースを作成する。

###CloudFormationStackSet用のIAMロールの作成###

- [こちら](https://qiita.com/leomaro7/items/4cc37ea3ca9b03eb0ef1#iam%E3%83%AD%E3%83%BC%E3%83%AB)の記事を参考にCloudFormationStackSet用のIAMロールを作成する。

###GuardDuty,EventBridge,SNS(CloudFormationStackSet)###

- Guard Duty,SNS,EventBridge は CloudFormationStackSet を使ってデプロイする。　
- 重要度高、**７** 以上のものを通知するようにしています。

参考：[GuardDuty の結果の重要度レベル](https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/guardduty_findings.html#guardduty_findings-severity)

- Guard Duty は **FIFTEEN_MINUTES**、更新頻度をを15分おきに検知するようにしています。

```yaml:GuardDuty.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Notify Slack of guardduty

Resources:
#GuardDuty#
  GDD:
    Type: AWS::GuardDuty::Detector
    Properties:
      Enable: true
      FindingPublishingFrequency: FIFTEEN_MINUTES

#SNS#
  SNST:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: GuardDutyTopic
  SNSTP:
    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 SNST
          Condition:
            StringEquals:
              "AWS:SourceOwner": !Ref "AWS::AccountId"
        - Sid: AWSEvents_AlertGuardDutyFindings_Id123
          Effect: Allow
          Principal:
            Service:
            - "events.amazonaws.com"
          Action: "sns:Publish"
          Resource: !Ref SNST
      Topics:
      - !Ref SNST

#EventBridge#
  ER:
    Type: AWS::Events::Rule
    Properties:
      Name: AlertGuardDutyFindings
      EventPattern: {
                      "source": [
                        "aws.guardduty"
                      ],
                      "detail-type": [
                        "GuardDuty Finding"
                      ],
                      "detail": {
                        "severity": [{
                         "numeric": [">=", 7]
                      }]
                     }
                    }
      State: ENABLED
      Targets:
        - Arn: !Ref SNST
          Id: SNST
      EventBusName: default
```

###Chatbotのチャネルをデプロイする(CloudFormationスタック）###

- CloudFormationスタックでChatbotのチャネルをデプロイする。

```yaml:GuardDuty-Chatbot-SlackChanel.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Create a GuardDuty slack channel

Parameters:
  SnsTopicName:
    Type: String
    Default: GuardDutyTopic
  SlackWorkspaceId:
    Type: String
    Default: XXXXXXXXX
  SlackChannelId:
    Type: String
    Default: YYYYYYYYY

Resources:

#Chatbot用 IAMロール
  GuardDutyIamRole: 
    Type: AWS::IAM::Role
    Properties: 
      RoleName: GuardDutyIamRole
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Action: "sts:AssumeRole"
            Principal:
              Service: "chatbot.amazonaws.com"
      Policies: 
        - PolicyName: GuardDuty-NotificationsOnly-Policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Action:
                  - "cloudwatch:Describe*"
                  - "cloudwatch:Get*"
                  - "cloudwatch:List*"
                Effect: "Allow"
                Resource: "*"

#Chatbot
  GuardDutyConfiguration:
    Type: AWS::Chatbot::SlackChannelConfiguration
    Properties: 
      ConfigurationName: GuardDuty-Chatbot-SlackChanel
      IamRoleArn: !GetAtt GuardDutyIamRole.Arn
      LoggingLevel: ERROR
      SlackChannelId: !Ref SlackChannelId
      SlackWorkspaceId: !Ref SlackWorkspaceId
      SnsTopicArns: 
        - !Sub 'arn:aws:sns:ap-northeast-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:ap-northeast-2:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:ap-northeast-3:${AWS::AccountId}:${SnsTopicName}'
        - !Sub 'arn:aws:sns:ap-south-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:ap-southeast-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:ap-southeast-2:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:ca-central-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:eu-central-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:eu-north-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:eu-west-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:eu-west-2:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:eu-west-3:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:sa-east-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:us-east-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:us-east-2:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:us-west-1:${AWS::AccountId}:${SnsTopicName}' 
        - !Sub 'arn:aws:sns:us-west-2:${AWS::AccountId}:${SnsTopicName}'
```

##1つのリージョンにデプロイする場合##

CloudFormationスタックで、デプロイする。

```yaml:GuardDuty.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Notify Slack of guardduty

Parameters: 
  SnsTopicName:
    Type: String
    Default: GuardDutyTopic
  SlackWorkspaceId:
    Type: String
    Default: XXXXXXXXX
  SlackChannelId:
    Type: String
    Default: YYYYYYYYY

Resources:
#GuardDuty#
  GDD:
    Type: AWS::GuardDuty::Detector
    Properties:
      Enable: true
      FindingPublishingFrequency: FIFTEEN_MINUTES

#SNS#
  SNST:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: GuardDutyTopic
  SNSTP:
    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 SNST
          Condition:
            StringEquals:
              "AWS:SourceOwner": !Ref "AWS::AccountId"
        - Sid: AWSEvents_AlertGuardDutyFindings_Id123
          Effect: Allow
          Principal:
            Service:
            - "events.amazonaws.com"
          Action: "sns:Publish"
          Resource: !Ref SNST
      Topics:
      - !Ref SNST

#EventBridge#
  ER:
    Type: AWS::Events::Rule
    Properties:
      Name: AlertGuardDutyFindings
      EventPattern: {
                      "source": [
                        "aws.guardduty"
                      ],
                      "detail-type": [
                        "GuardDuty Finding"
                      ],
                      "detail": {
                        "severity": [{
                         "numeric": [">=", 7]
                      }]
                     }
                    }
      State: ENABLED
      Targets:
        - Arn: !Ref SNST
          Id: SNST
      EventBusName: default

#Chatbot用 IAMロール
  GuardDutyIamRole: 
    Type: AWS::IAM::Role
    Properties: 
      RoleName: GuardDutyIamRole
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Action: "sts:AssumeRole"
            Principal:
              Service: "chatbot.amazonaws.com"
      Policies: 
        - PolicyName: GuardDuty-NotificationsOnly-Policy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Action:
                  - "cloudwatch:Describe*"
                  - "cloudwatch:Get*"
                  - "cloudwatch:List*"
                Effect: "Allow"
                Resource: "*"

#Chatbot
  GuardDutyConfiguration:
    Type: AWS::Chatbot::SlackChannelConfiguration
    Properties: 
      ConfigurationName: GuardDuty-Chatbot-SlackChanel
      IamRoleArn: !GetAtt GuardDutyIamRole.Arn
      LoggingLevel: ERROR
      SlackChannelId: !Ref SlackChannelId
      SlackWorkspaceId: !Ref SlackWorkspaceId
      SnsTopicArns: 
        - !Sub 'arn:aws:sns:ap-northeast-1:${AWS::AccountId}:${SnsTopicName}' 
```

#動作確認#

GuardDutyでのサンプルが用意されているので、それを利用してテストすることが可能です。

https://docs.aws.amazon.com/ja_jp/guardduty/latest/ug/sample_findings.html