KonnectのAudit LogをElasticsearchに飛ばして読む

Kong Konnectの[Audit Log](https://docs.konghq.com/konnect/org-management/audit-logging/)はちょっとイケてなくて、現状Webhookで外部に飛ばすしか取得する手段がない。
また`Content-Type`が`text/plain`（[ドキュメント](https://docs.konghq.com/konnect/org-management/audit-logging/reference/#log-formats)では`application/text`となってるが誤り）のみとなっていて、これが原因のためかElasticsearchへの転送が上手く行かなかった。
そのため、ここではKonnectのWebhookから飛んでくるログを受け取るアプリを用意し、[以前立てたElasticsearch/Kibana](https://qiita.com/ipppppei/items/3a9337259bea726a2936)に転送することでAudit LogがKibanaで読めることを確認する。

```mermaid
graph LR
    Konnect --> App
    App --> ES/Kibana
```
なお、ここでの検証内容は個人的な検証であり、出てくるプログラムや手順については誰かしらに保証されるものではない点は注意。

## Elasticseachの準備
構築自体はここでは触れない。[こちらの記事](https://qiita.com/ipppppei/items/3a9337259bea726a2936)で作成した環境で試しているので、構築から確認したい人は当該記事を参照するとよい。
今回はアプリからElasticsearchへの認証にAPIキーを利用する。
そのため、ElasticsearchにAPIキーでログインできるようAPIキーを作成する。
まずKubernetesクラスタからElasticsearchのパスワードとホスト名を取得する。
```sh
ELASTIC_PW=$(kubectl get secret -o yaml quickstart-es-elastic-user -o jsonpath={.data.elastic} -n efk | base64 -d)
ELASTIC_HOST=$(kubectl get ing -n efk quickstart-es -o jsonpath={.spec.rules[].host})
```
ElasticsearchにAPIキーをリクエストする。
```sh
curl -k -u "elastic:${ELASTIC_PW}" -X POST "https://${ELASTIC_HOST}/_security/api_key" -H "Content-Type: application/json" -d '{
  "name": "my-api-key",
  "role_descriptors": {
    "my_role": {
      "cluster": ["all"],
      "index": [
        {
          "names": ["*"],
          "privileges": ["all"]
        }
      ]
    }
  }
}'
```
問題なければ以下のようなレスポンスが返ってくる。
```json
{"id":"pUIHo48BfzWzMG4cqZY6","name":"my-api-key","api_key":"WHv3i8rjRCCxxxxxx","encoded":"cFVJSG80OEJmeld6xxxxpSQ0N4UVdWR0ZVSXQ0dw=="}
```
`encoded`の値は後で転送アプリケーションに渡すので控えておく。

## アプリケーションの用意
作成したものを[こちら](https://github.com/imurata/konnect2es)に用意した。
最初にリポジトリをcloneする。
```sh
git clone https://github.com/imurata/konnect2es.git
```
次にコンテナを作成してイメージレジストリに格納する。
```sh
MYREPO=myrepo/konnect2es
docker build --platform linux/amd64 -t $MYREPO .
docker push $MYREPO
```
次にManifestを修正する。
修正すべき箇所は以下となる。
- `deploy.yaml`:  コンテナイメージ名をpushしたものに変更
- `ing.yaml`: ホスト名を自身のものに変更(2箇所)
- `issuer.yaml`: メールアドレスを自身のものに変更
- `secret.yaml`: Elasticsearchのホスト名、APIキー（`encoded`の値）を設定（必要に応じてインデックスも変更）

なお、cert-managerを使ってHTTP01 Challangeで証明書を作成しているが、`Ingress`が不要な人はこのManifestは利用しなくてもOK（ただし[HTTPSのみサポート](https://docs.konghq.com/konnect/org-management/audit-logging/webhook/#main)な点に注意）。自己署名証明書を使う人は`Issuer`の内容を変更する。
また、Ingress ControllerにKong Ingress Controllerを使ってるので、別のものを使ってる人はその点も修正要となる。
変更が終わったらapplyする。
```sh
kubectl create ns konnect2es 
kubectl apply -f ./k8s -n konnect2es
```
問題なく起動すれば以下のようなPodのログが確認できる。
```sh
[2024-05-23 23:49:36 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2024-05-23 23:49:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
[2024-05-23 23:49:36 +0000] [1] [INFO] Using worker: sync
[2024-05-23 23:49:36 +0000] [7] [INFO] Booting worker with pid: 7
```

## Konnectの設定

Konnectの設定はブラウザからも出来るが、ここではAPIを利用して更新してみる。
最初にAPIを発行するために自身のトークンを取得する。
Konnect上で右上の自分のアカウントをクリックし、`Personal Access Tokens`->`Generate Token`からTokenを取得し環境変数に設定する。
```sh
KONNECT_TOKEN=kpat_ER1WQ0xxxx
```
次にAPIを発行してWebhookのエンドポイントを設定する。
curlコマンドの例は[ここ](https://docs.konghq.com/konnect/org-management/audit-logging/webhook/#create-a-webhook)にあるが、curlだとdata内に環境変数を渡すのが少し大変なので、httpieに含まれるhttpコマンドで代用する。
```sh
KONNECT2ES_HOST=$(kubectl get ing -n konnect2es konnect2es-ingress -o jsonpath={.spec.rules[].host})
http PATCH https://global.api.konghq.com/v2/audit-log-webhook \
    Content-Type:application/json \
    Authorization:"Bearer $KONNECT_TOKEN" \
    endpoint="https://${KONNECT2ES_HOST}/webhook" \
    enabled:=true \
    skip_ssl_verification:=true \
    authorization="" \
    log_format="json"
```
登録時は即ログ転送を行うので、その結果を見て設定が上手く行ったかを確認する。
```sh
http GET https://global.api.konghq.com/v2/audit-log-webhook/status \
    Authorization:"Bearer $KONNECT_TOKEN"
```
問題なければ以下のような出力が得られるはずだ。
```json
{
    "last_attempt_at": "2024-05-24T00:45:59Z",
    "last_response_code": 200,
    "webhook_enabled": true,
    "webhook_status": "active"
}
```
## ログの確認

Kibanaにログインし、左サイドバーの`Discover`からデータビューを作成する。
`Index pattern`はSecretのIndexを変更していなければ`konnect`となっているので以下のような感じで作ると問題ない。
![20240524094957.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/65d2779c-fe8e-08b0-2ffa-f09a57610258.png)
作成すると以下のような感じでKonnectのAuditのログが確認できる。
![20240524095134.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/2634bd5e-4722-6462-da6d-01904d7a4f8c.png)


なお、ログの項目の意味については[Log Reference](https://docs.konghq.com/konnect/org-management/audit-logging/reference/)を参考に確認するとよい（足りてない気もするが）。