0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Kong Gatewayで実装!リクエストが失敗したらSlackWebhookで通知

Posted at

背景

Kong Gatewayを使ってAPIにアクセスする時には、もしリクエストが失敗したら通知して欲しいですね。通常のやり方はLog系のプラグインでLogを保存してから、3rd partyの製品(ELK)でAlertを設定して通知することです。でも他の製品を使うとデプロイも面倒だし、ライセンスや設定内容も必要だし、できればKong内部で実現したいな。。という要望があると思います。
今回は、Exit Transformer プラグインを使って、リクエストがエラーだったらLuaスクリプトでSlack Webhookを叩くことをメモします。このプラグインは、Lua 関数を使用して、Kong 応答終了メッセージを変換およびカスタマイズすることができます。メッセージ、ステータスコード、ヘッダーの変更から、Kong 応答の構造の完全な変換まで、さまざまな機能があります。

プラグインを試す

まずはページ上にある例を試してみよう。

サービスとルートを作成

$ http :8001/services name=example.com host=mockbin.org
$ http -f :8001/services/example.com/routes hosts=example.com

失敗させるため key auth プラグインを実装

$ http :8001/services/example.com/plugins name=key-auth

Luaスクリプトを作成

以下のコードでは、x-some-headerのヘッダーを追加し、メッセージの最後に, arrを追加した。
この内容をtransform.luaとして保存する。

    -- transform.lua
    return function(status, body, headers)
      if not body or not body.message then
        return status, body, headers
      end

      headers = { ["x-some-header"] = "some value" }
      local new_body = {
        error = true,
        status = status,
        message = body.message .. ", arr!",
      }

      return status, new_body, headers
    end

スクリプトを使ってプラグインをデプロイ

   http -f :8001/services/example.com/plugins \
     name=exit-transformer \
     config.functions=@transform.lua

動作確認

ここまで設定したらアクセスしてみましょう。ヘッダーと最後のメッセージarrがちゃんとレスポンスに追加されました。

❯ http :8000 Host:example.com
HTTP/1.1 401 Unauthorized
Connection: keep-alive
Content-Length: 73
Content-Type: application/json; charset=utf-8
Date: Fri, 10 Feb 2023 07:36:15 GMT
Server: kong/3.1.1.3-enterprise-edition
WWW-Authenticate: Key realm="kong"
X-Kong-Response-Latency: 2
x-some-header: some value

{
    "error": true,
    "message": "No API key found in request, arr!",
    "status": 401
}

Webhookをスクリプトに実装

今回はSlackのWebhookを利用します。メッセージに内容を追加した後にWebhookをキックする実装にします。

...
      local httpc = require("resty.http").new()

      -- Single-shot requests use the `request_uri` interface.
      local res, err = httpc:request_uri("https://hooks.slack.com/services/xxxxxx/xxxxxx/xxxxxxxx", {
          method = "POST",
          body = '{"text": "Hello, world."}',
          headers = {
              ["Content-Type"] = "application/json",
          },
      })
      if not res then
          ngx.log(ngx.ERR, "request failed: ", err)
          return
      end

      return status, new_body, headers
...

リクエストを送るために、lua-resty-httpを利用しています。一般的にはrequireを利用してリクエストを出しますが、nginx イベント ループでうまく機能するとは思わない心配があります。つまり、hooks.slack.com からの応答を待機している間、nginx が他のリクエストを処理できなくなる可能性があります。

もう一つ注意すべきところは、外部のライブラリを呼び出しているため、untrusted_luaパラメータをOnにする必要があります。これをしないと以下のようなエラーが出ます。

2023/02/10 02:19:13 [error] 2175#0: *15812 lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/kong/tools/sandbox.lua:88: require 'ssl.https' not allowed within sandbox

もう一度動作確認

さてさっきのAPIにもう一度アクセスしてSlackのメッセージを確認しましょう!

❯ http :8000 Host:example.com
HTTP/1.1 401 Unauthorized
Connection: keep-alive
Content-Length: 73
Content-Type: application/json; charset=utf-8
Date: Mon, 13 Feb 2023 13:28:42 GMT
Server: kong/3.1.1.3-enterprise-edition
WWW-Authenticate: Key realm="kong"
X-Kong-Response-Latency: 0
x-some-header: some value

{
    "error": true,
    "message": "No API key found in request, arr!",
    "status": 401
}

iShot_2023-02-13_22.29.31.png

きたーーーーーーーーーーーーー!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?