EventBridge の入力トランスフォーマーで AWS Chatbot の通知を少しだけリッチにする

## はじめに
例えばこんな通知を

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/b0ae44b9-0dd1-7862-ae04-0bf8dcfa5e7c.png)

こんな感じに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/2018d8b5-7fc2-cd15-4332-09575c8b94c0.png)


クラスメソッドさんの以下の記事を参考にしています。Step Functions の実行完了について記載されていますが、他のすべてのイベントでも応用できます。

https://dev.classmethod.jp/articles/aws-step-functions-notify-slack-using-chatbot/

AWS Chatbot や EventBridge の設定方法には触れませんので、必要な場合は以下をご参照ください。

https://qiita.com/hayao_k/items/529539bbb07736ea0f41


## EventBridge イベントによる AWS Chatbot の通知

2021 年の 4月に Amazon EventBridge によって処理されるすべてのサービスイベントを AWS Chatbot で通知できるようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2021/04/aws-chatbot-now-expands-coverage-of-aws-services-monitored-through-amazon-eventbridge/

ただし通知の粒度はイベント内容によって異なるのが現状です。

### いい感じに通知してくれるケース
以下は ECR の Basic Scanning の完了イベントのサンプルイベントと AWS Chatbot による通知結果の例です。

```json
{
    "version": "0",
    "id": "85fc3613-e913-7fc4-a80c-a3753e4aa9ae",
    "detail-type": "ECR Image Scan",
    "source": "aws.ecr",
    "account": "123456789012",
    "time": "2019-10-29T02:36:48Z",
    "region": "us-east-1",
    "resources": [
        "arn:aws:ecr:us-east-1:123456789012:repository/my-repository-name"
    ],
    "detail": {
        "scan-status": "COMPLETE",
        "repository-name": "my-repository-name",
        "finding-severity-counts": {
	       "CRITICAL": 10,
	       "MEDIUM": 9
	     },
        "image-digest": "sha256:7f5b2640fe6fb4f46592dfd3410c4a79dac4f89e4782432e0378abcd1234",
        "image-tags": []
    }

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/739f87d9-d75f-5bee-59cb-96f6e0de856d.png)

`$.detail` 部分が整形されて通知されるので、イメージスキャンの結果を把握することができます。

### 情報量が少ないケース
先日 [CloudFormation のイベント通知がサポート](https://aws.amazon.com/jp/about-aws/whats-new/2022/07/aws-cloudformation-event-notifications-amazon-eventbridge-event-driven-applications/) されたのでこちらを例にあげてみます。

スタックステータスのサンプルイベントと AWS Chatbot の通知結果は以下のとおりです。

```json
{
    "version":"0",
    "id":"6a7e8feb-b491-4cf7-a9f1-bf3703467718",
    "detail-type":"CloudFormation Stack Status Change",
    "source":"aws.cloudformation",
    "account":"111122223333",
    "time":"2017-12-22T18:43:48Z",
    "region":"us-west-1",
    "resources":[
        "arn:aws:cloudformation:us-west-1:111122223333:stack/teststack"
    ],
    "detail":{
        "stack-id":"arn:aws:cloudformation:us-west-1:111122223333:stack/teststack",
        "status-details":{
            "status":"CREATE_COMPLETE",
            "status-reason":""
        },
        "client-request-token":""
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/6085ce21-dc89-77f4-946f-ff5c689f438e.png)


CloudFormation のスタックステータスに関する通知であることはわかりますが、`$.detail` は通知されないので実際のステータスがわかりません。感覚値としてはこのように `$.detail` が割愛されてしまうイベントの方が多い印象です。

## EventBridge の入力トランスフォーマーを活用する
入力トランスフォーマーは EventBridge がイベントをターゲットに渡す前に、イベントのテキストをカスタマイズできる機能です。通常は Amazon SNS などで通知を行う際に生の JSON ではなく、人が読みやすい形に変換するなどの目的で使用します。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-transform-target-input.html

今回は AWS Chatbot で通知される内容をカスタマイズするために JSON を JSON で上書きするようなイメージで使用します。 

イベントの構造と通知内容は以下のような対応になっています。`detail-type`, `region`, `account`, `resources` についてはどのイベントでも通知対象となるようです。特に `resources` は箇条書きとして表示されるので、今回はこのフィールドを活用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/bce441fb-2cb2-a044-03f4-b4375296cb79.png)

EventBridge ルールの入力トランスフォーマーの設定を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/0c6a0c0d-4a1b-7b72-816c-cae0824f2374.png)

入力パスを以下のように定義します。入力パスは JSON パスを使用して元のイベント内の項目を参照し、それらの値を変数に格納することができます。ここでは `$.detail` から `stack-id`, `status`, `status-reason` を変数として定義しています。

```json
{
  "account": "$.account",
  "detail-type": "$.detail-type",
  "id": "$.id",
  "region": "$.region",
  "source": "$.source",
  "stack-id": "$.detail.stack-id",
  "status": "$.detail.status-details.status",
  "status-reason": "$.detail.status-details.status-reason",
  "time": "$.time",
  "version": "$.version"
}
````

入力テンプレートはイベントルールのターゲットに渡す情報のテンプレートです。AWS Chatbot で通知できるようするため、元の JSON 構造は崩さずに resources に先ほどの変数を追加しています。

```
{
  "version": <version>,
  "source": <source>,
  "account": <account>,
  "id": <id>,
  "region": <region>,
  "detail-type": <detail-type>,
  "time": <time>,
  "resources": [
    "Stack ID: <stack-id>",
    "Stack Status: <status>",
    "Status Reason: <status-reason>"
  ]
}
```

CloudFormation Stack Status Change のサンプルイベント、入力パス、入力テンプレートを設定後、出力を生成をクリックして、以下のようにカスタマイズ後の JSON が出力されれば OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/a7d2e443-4bd3-e1a4-7f91-c15f750cb32c.png)


カスタマイズ後の通知例が以下です。スタックステータスがわかるようになりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/2c8c13ad-c661-1d66-33be-c242911671df.png)

## その他のカスタマイズ例

### AWS Organizations
冒頭の例です。
CreateAccountResult で正常に作成された AWS アカウントの ID を知りたいケース。
#### サンプルイベント
```json
{
  "version": "0",
  "id": "999cccaa-eaaa-0000-1111-123456789012",
  "detail-type": "AWS Service Event via CloudTrail",
  "source": "aws.organizations",
  "account": "123456789012",
  "time": "2018-08-30T21:42:18Z",
  "region": "us-east-1",
  "resources": [],
  "detail": {
    "eventVersion": "1.05",
    "userIdentity": {
      "accountId": "123456789012",
      "invokedBy": "AWS Internal"
    },
    "eventTime": "2018-08-30T21:42:18Z",
    "eventSource": "organizations.amazonaws.com",
    "eventName": "CreateAccountResult",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "eventID": "0000000-0000-0000-1111-123456789012",
    "readOnly": false,
    "eventType": "AwsServiceEvent",
    "serviceEventDetails": {
      "createAccountStatus": {
        "id": "car-000000000000000000000000000000",
        "state": "SUCCEEDED",
        "accountName": "****",
        "accountId": "123456789012",
        "requestedTimestamp": "Aug 30, 2018 9:42:14 PM",
        "completedTimestamp": "Aug 30, 2018 9:42:18 PM"
      }
    }
  }
}
````

#### イベントパターンの例
```json
{
  "source": ["aws.organizations"],
  "detail-type": ["AWS Service Event via CloudTrail"],
  "detail": {
    "eventName": ["CreateAccountResult"],
    "serviceEventDetails": {
      "createAccountStatus": {
        "state": ["SUCCEEDED"]
      }
    }
  }
}
```

#### 入力パス
```json
{
  "account": "$.account",
  "accountId": "$.detail.serviceEventDetails.createAccountStatus.accountId",
  "detail-type": "$.detail-type",
  "eventName": "$.detail.eventName",
  "id": "$.id",
  "region": "$.region",
  "source": "$.source",
  "state": "$.detail.serviceEventDetails.createAccountStatus.state",
  "time": "$.time",
  "version": "$.version"
}
```
#### 入力テンプレート
```
{
  "version": <version>,
  "id": <id>,
  "detail-type": <detail-type>,
  "source": <source>,
  "account": <account>,
  "time": <time>,
  "region": <region>,
  "resources": [
    "Source: <source> | <eventName>",
    "Create Account Status: <state>",
    "Account ID: <accountId>"
  ]
}
```
#### 通知例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/2018d8b5-7fc2-cd15-4332-09575c8b94c0.png)

### AWS Support
サポートケースのアップデートを知りたいケース。

#### サンプルイベント
```json
{
  "version": "0",
  "id": "93274b19-a740-0c83-d087-f96dc185f9d3",
  "region": "us-east-1",
  "time": "2020-12-22T18:43:48Z",
  "source": "aws.support",
  "detail-type": "Support Case Update",
  "resources": [],
  "detail": {
    "case-id": "case-986719740728-muen-2022-7c9986eac47e55f4",
    "display-id": "9592853861",
    "communication-id": "",
    "event-name": "CreateCase",
    "origin": ""
  },
  "account": "123456789012"
}
```

#### イベントパターンの例
```json
{
  "source": ["aws.support"],
  "detail-type": ["Support Case Update"]
}
```

#### 入力パス
```json
{
  "account": "$.account",
  "detail-type": "$.detail-type",
  "display-id": "$.detail.display-id",
  "event-name": "$.detail.event-name",
  "id": "$.id",
  "region": "$.region",
  "source": "$.source",
  "time": "$.time",
  "version": "$.version"
}
```

#### 入力テンプレート
```
{
  "version": <version>,
  "id": <id>,
  "region": <region>,
  "time": <time>,
  "source": <source>,
  "detail-type": <detail-type>,
  "resources": [
    "Case ID: <display-id>",
    "Event Name: <event-name>",
    "Link: https://support.console.aws.amazon.com/support/home#/case/?displayId=<display-id>"
  ],
  "account": <account>
}
```

#### 通知例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/0da7e58b-9a36-a091-8b4f-9fa7e2da5184.png)


以上です。
参考になれば幸いです。