Cloudflare Logpush を Slack にポストする

# HTTP destination

> [Enable HTTP destination · Cloudflare Logs docs](https://developers.cloudflare.com/logs/get-started/enable-destinations/http/)

Cloudflare の Logpush には、任意の HTTP エンドポイントにログ出力を行うことができます。

今回は、Cloudflare Logpush --> Cloudflare Workers --> Slack という構成を実装します。

# Logpush リクエスト情報

以下のようなリクエストとなります。

- HTTP POST
- Content-type: application/json
- Content-encoding: gzip
- Body の中身は、ndjson (newline-delimited JSON)
- カスタムヘッダを付けて、ユーザ側で認証の仕組みに利用できる
- 送信先エンドポイントには有効な SSL 証明書が必要
- Logpush 構成時に送信される初回リクエストは gzip 圧縮されないテキストファイルアップロード

## 初回リクエスト

以下のようなリクエストを作成して、テストできます。

```shell
curl "http://localhost:8787/" -X POST \
-d '{"content":"test","filename":"test.txt"}' \
-H "Content-Type: application/json" \ 
# -H "X-Logpush-Auth: mypresharedkey"
```

## 次回以降リクエスト

以下のようなリクエストを作成して、テストできます。

```shell
echo '[{"BotScore":99,"BotScoreSrc":"Machine Learning","CacheCacheStatus":"miss","CacheResponseBytes":2478}, {"BotScore":1,"BotScoreSrc":"Heuristics","CacheCacheStatus":"dynamic","CacheResponseBytes":8346}]' | jq -c '.[]'| perl -p -e 'chomp if eof'| gzip > body.gz

curl "http://localhost:8787/" -X POST \
--data-binary @body.gz \
-H "Content-Type: application/json" \
-H "Content-Encoding: gzip" \ 
# -H "X-Logpush-Auth: mypresharedkey"
```

# Slack 準備

> [Cloudflare Workers から Slack にメッセージする - Qiita](https://qiita.com/khayama/items/45b50c3c458f36118c6c)

上記を参考に Cloudflare Workers から Slack に `chat.postMessage` ができるようにしておきます。

戦略としては

- Logpush の 1 JSON あたり、4000 文字におさめられそうなので、 `chat.postMessage` を使う

  - > [chat.postMessage method | Slack](https://api.slack.com/methods/chat.postMessage)
    >
    > For best results, limit the number of characters in the `text` field to 4,000 characters.

- [files.upload method](https://api.slack.com/methods/files.upload) を使うと1度にスニペットとしてポストできる文字数は増えるが、検索に不便

  - > [JavascriptからSlackにスニペットを投稿する - Qiita](https://qiita.com/denzow/items/c85b673d93bb59405a73)

- `chat.postMessage` の方があとで検索するときに便利だが、JSONごとに分けてポストが急増するとSlack に [Rate Limits](https://api.slack.com/docs/rate-limits) される可能性がある

# Workers コードデプロイ

> [kyouheicf/logpush-http-requests-slack](https://github.com/kyouheicf/logpush-http-requests-slack)

上記のコードを使います。ポイントは以下の点です。勉強になりました。

- Logpush ジョブで設定したカスタム認証ヘッダ `X-Logpush-Auth: mypresharedkey` を検証

  - > [Auth with headers · Cloudflare Workers docs](https://developers.cloudflare.com/workers/examples/auth-with-headers/)

- POST Body は `arrayBuffer` > `Uint8Array` と渡して `TextDecoder` する

  - >  [javascript - Converting between strings and ArrayBuffers - Stack Overflow](https://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers)

- gzip 解凍には [fflate](https://www.npmjs.com/package/fflate) を使用

  - > [TypeScriptにて、lightweightなfflateライブラリを使ってzipファイルの圧縮/解凍をする話](https://zenn.dev/niccari/articles/3350ab065a48ff)

- ndjson を個々の json にバラして、それぞれを Slack に POST したレスポンスを集約して return

  - > [Aggregate requests · Cloudflare Workers docs](https://developers.cloudflare.com/workers/examples/aggregate-requests/)

以下のコマンドで、Cloudflare Workers を使った Logpush 用の HTTP エンドポイントを立ち上げます。

```shell
git clone https://github.com/kyouheicf/logpush-http-requests-slack
# For other dataset (Change directory name)
# git clone https://github.com/kyouheicf/logpush-http-requests-slack logpush-page-shield-events
cd logpush-http-requests-slack

npm install
# For other dataset (Change name to logpush-page-shield-events-slack, etc.)
# sudo vi wrangler.toml
wrangler secret put SLACK_BOT_ACCESS_TOKEN
wrangler secret put SLACK_BOT_ACCESS_CHANNEL
wrangler publish src/index.js
```

# Logpush ジョブ構成

以下のコマンドで、全フィールドが有効な Logpush を作成します。

```shell
export EMAIL='YOUR_EMAIL'
export APIKEY='YOUR_APIKEY'
export ZONE_ID='YOUR_ZONE_ID'

# 全フィールドを指定
export FIELDS=$(curl -s \
-H "X-Auth-Email: $EMAIL" \
-H "X-Auth-Key: $APIKEY" \
"https://api.cloudflare.com/client/v4/zones/$ZONE_ID/logpush/datasets/http_requests/fields" | jq -r '.result | keys | join(",")')
# echo $FIELDS

curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/logpush/jobs" -X POST -d '
{                                              
  "name": "http-dest-http-requests",                                   
  "logpull_options": "fields='$FIELDS'",
  "destination_conf": "https://logpush-http-requests-slack.example.workers.dev?header_X-Logpush-Auth=mypresharedkey&tags=host:example.com,dataset:http_requests",
  "max_upload_bytes": 5000000,
  "max_upload_records": 1000,
  "dataset": "http_requests",
  "enabled": true
}' \
-H "X-Auth-Email: $EMAIL" \
-H "X-Auth-Key: $APIKEY"
```

# 確認

以下のように Workers が起動して、Slack にポストされたことが確認できます。

```shell
% wrangler tail
 ⛅️ wrangler 2.1.15 
--------------------
Successfully created tail, expires at 2022-11-08T23:08:25Z
Connected to logpush-http-requests-slack, waiting for logs...
POST https://logpush-http-requests-slack.example.workers.dev/?tags=host%3Aexample.com%2Cdataset%3Ahttp_requests - Ok @ 11/9/2022, 2:13:26 AM
```

![image-20221109020958813](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20221109020958813.png)

# 感想

あくまでテスト環境のログ確認に使う用途ですが、ChatOps 等で日頃から Slack を使う方にはログ確認も Slack でできると結構便利かなと思います。