AWS Security Hub、Config、GuardDutyのイベントをSlack通知してみた

## はじめに
Security Hub、Config、GuardDutyのイベントを、EventBridge → SNS → Chatbot経由でSlack通知してみたので、その備忘として。

## 構成
構成は以下の通りです。
Security Hub、Config、GuardDutyの特定のイベントをEventBridgeでひろい、SNS、Chatbot経由でSlackに通知します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/e1dd3e44-185c-9b55-e345-79dfa59ecc34.png)

## KMS(CMK)の作成
SNS用のCMKを作成します。
SNSの暗号化は必須ではありませんが、CMKを作成し適用しておきます。
※今回、3つのSNSトピックを作成しますが、AWSサービスからのイベント通知である事から、CMKは1つ作成し、3つのトピックで同じ鍵を使用する事にします。

| 設定項目 | 設定値 |
|:-|:-|
| エイリアス | Events-Key |
| キーのタイプ | 対象 |
| オリジン | AWS_KMS |
| キーの仕様 | SYMMETRIC_DEFAULT |
| キーの使用 | 暗号化および復号化 |
| キーローテーション | 毎年自動的にローテーション |

今回は、EventBridgeから通知を受け取るので、EventBridgeのサービス(`"Service": "events.amazonaws.com"`)からCMKを使えるようPrincipalを設定します。

キーポリシーは以下のようにしました。
```json
{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-3",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow access for Key Administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::XXXXXXXXXXXX:root",
                    "arn:aws:iam::XXXXXXXXXXXX:user/administrator"
                ]
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::XXXXXXXXXXXX:root",
                    "arn:aws:iam::XXXXXXXXXXXX:user/administrator"
                ],
                "Service": "events.amazonaws.com"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::XXXXXXXXXXXX:root",
                    "arn:aws:iam::XXXXXXXXXXXX:user/administrator"
                ],
                "Service": "events.amazonaws.com"
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}
```

## SNSの作成
SNSトピックを作成します。
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/ea0fd55c-f298-6b50-6167-30f917debaab.png)
サブスクリプションは、Chatbot設定時に関連付けるので、ここではトピックの作成のみ行います。
また、Security Hub、Config、GuardDutyのイベントは、それぞれ別のSlackチャンネルに通知するため、SNSトピックを3つ作成します。
| 名前 | アクセスポリシー | 配信再試行ポリシー | 配信ステータスのログ記録 | 暗号化 |
|:-|:-|:-|:-|:-|
| Security-Hub-Notification | デフォルト：トピックの所有者のみがトピックに発行またはサブスクライブできる | デフォルト値 | なし | alias/EVENTS-Key |
| Config-Notification | デフォルト：トピックの所有者のみがトピックに発行またはサブスクライブできる | デフォルト値 | なし | alias/EVENTS-Key |
| GuardDuty-notification | デフォルト：トピックの所有者のみがトピックに発行またはサブスクライブできる | デフォルト値 | なし | alias/EVENTS-Key |

## Slackチャンネルの作成
Security Hub、Config、GuardDutyのイベント通知用のSlackチャンネルを3つ作成します。
作成したSlackチャンネルのIDは、Chatbotの設定で必要になるため、どのAWSサービスからの通知を、どのチャンネルに対してするか、あらかじめ決めておくようにします。

なお、Slackのプライベートチャンネルに通知をする場合、AWS Chatbotアプリを通知するチャンネルに招待しておく必要があります。

## Chatbotの設定
チャットクライアントのセットアップ方法については、以下などを参照ください。

https://aws.amazon.com/jp/builders-flash/202006/slack-chatbot/?awsf.filter-name=*all

チャットクライアントのセットアップが終わったら、Chatbotのチャネル設定をします。
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/17ab4b62-1b01-7721-b56a-5e64a754848a.png)
Security Hub、Config、GuardDutyからのイベント通知用に、以下3つのチャネルを設定しました。
| 設定項目 | Security Hub用 | Config用 | GuardDuty用 |
|:-|:-|:-|:-|
| 設定名 | security_hub_notification | config_notification | guardduty_notification |
| チャネルID | Security HubのEventを通知するSlackチャンネルのチャンネルID | ConfigのEventを通知するSlackチャンネルのチャンネルID | GuardDutyのEventを通知するSlackチャンネルのチャンネルID |
| ログ記録レベル | オフ | オフ | オフ |
| ロールの設定 | チャネルIAMロール | チャネルIAMロール | チャネルIAMロール |
| チャネルロール | AWSChatbot-role | AWSChatbot-role | AWSChatbot-role |
| ガードレールのポリシー | ReadOnlyAccess | ReadOnlyAccess | ReadOnlyAccess |
| マッピング済みのSNS トピック | Security-Hub-Notification | Config-Notification | GuardDuty-Notification |

※今回は、通知のみの利用という事もあり、ガードレールポリシーに「ReadOnlyAccess」を指定していますが、EventBridge経由の通知であれば、恐らく「AmazonEventBridgeReadOnlyAccess」の指定でよさそう(未検証)。

## EventBridgeの設定
Security Hub、Config、GuardDutyから通知するイベント設定をします。
EventBridgeの画面で、新規ルールを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/0e279afa-fbb1-631f-214b-8a15e6f451d8.png)
名前を入力し、タイプに「スタンダード」を選択、イベントバス名は「default」のままにし、イベントパターンの設定をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/804f7cd6-4969-5738-34f7-b129d96096bc.png)
イベントパターンのイベントソースに「AWSのサービス」を選択し、AWSのサービスとイベントタイプを選択します(下図は、Security Hubのイベント設定の例)。
必要に応じて、通知を行う重大度やワークフローステータスを変更します。

※Security Hubの場合、導入初期は多くの通知が来る事があるので、最初は重大度などをクリティカルなものに絞るようにするとよいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/d2e6204d-0046-c10f-02ad-d110003e58e4.png)
イベントパターンの設定が終わったら、イベントパターンにマッチしたイベントの通知先を選択します。
ターゲットタイプに「AWSのサービス」、ターゲットを選択で「SNSトピック」を選択し、事前に作成しておいた通知用のSNSトピックを選択します。
![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/34bf4c99-c5b8-89ec-92d3-ea846f1cf657.png)
ターゲットの設定が終わったら、イベントルールの設定内容を確認し、イベントルールを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/22b005b1-83d8-8ad9-956e-e5b3e8014399.png)
今回は、以下3つのイベントルールを作成しました。

| ルール名 | タイプ | イベントバス名 | ターゲット | ターゲットタイプ |
|:-|:-|:-|:-|:-|
| SecurityHub-Finding-To-Slack | スタンダード | default | Security-Hub-Notification | SNSトピック |
| Config-Notification-To-Slack | スタンダード | default | Config-Notification | SNSトピック |
| GuardDuty-Notification-To-Slack | スタンダード | default | GuardDuty-notification | SNSトピック |

また、イベントパターンは、ルール毎に以下のように設定しました。
#### SecurityHub-Finding-To-Slackのイベントパターン
```json
{
  "source": ["aws.securityhub"],
  "detail-type": ["Security Hub Findings - Imported"],
  "detail": {
    "findings": {
      "Severity": {
        "Label": ["CRITICAL", "HIGH", "MEDIUM", "LOW"]
      },
      "Workflow": {
        "Status": ["NEW"]
      }
    }
  }
}
```
#### Config-Notification-To-Slackのイベントパターン
```json
{
  "source": ["aws.config"],
  "detail-type": ["Config Configuration Item Change"]
}
```
#### GuardDuty-Notification-To-Slackのイベントパターン
```json
{
  "source": ["aws.guardduty"],
  "detail-type": ["GuardDuty Finding"]
}
```

## 設定の確認・検証
ここまで設定が終わったら、実際にSlackに通知がされるか確認します。
各サービスから、以下のような通知が来れば、設定完了です。

- Security HubのFinding通知
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/db09351d-84e9-6a08-0131-751c40ef0611.png)
- Configからの通知
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/ba3286fb-6071-28da-de94-634f2f67a45c.png)
- GuardDutyからの通知
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2554521/2c65dfe6-d748-9f92-eb7d-ec9466b1ba82.png)

## おわりに
AWS管理コンソールでの比較的簡単な操作で、Security Hub、Config、GuardDutyのイベントをSlack通知できるようになりました。

現在、EventBridgeおよびChatbotは多くのAWSサービスに対応しており、簡易的な通知で問題ないのであれば、監視や通知の仕組みを簡単に構築でき、とても便利だと思います。