Gehirn EDJ

はじめに 

Gehirn EDJ Web コンソール

Gehirn EDJ は、マネージドなイベント通知サービスです。初期費用が不要で最低利用期間はありません。EDJ を呼び出すことで様々なサービスに自動的にイベントをルーティングできます。Slack に投稿したり、HTTP API にフックしたり、SMS やメールの送信などを簡単に定義できます。

トピック 

トピックとはサブスクライバ ルールの集合で、MTA などがトピックに通知を送ると、EDJ はトピックに定義されたサブスクライバに通知を転送します。

サブスクライバ 

サブスクライバは、通知の転送先となるアプリケーションのことです。EDJ は、サブスクライバ アプリケーションの API に合うようにメッセージを自動的に整形します。EDJ がサポートしているサブスクライバ アプリケーションは次の通りです。

  • HTTP フック
  • Pushover
  • Gehirn MTA
  • Slack

パブリッシュ API 

メッセージをパブリッシュするには、EDJ API にリクエストを送信するか、コンソールからパブリッシュ機能を使用してメッセージを送信します。

コンソールからパブリッシュする 

EDJ トピックからパブリッシュタブを開きメッセージを入力します。メッセージは「テスト」など任意の文字列です。コンソールは自動的に必要なフォーマットになるように処理をして API にリクエストします。

パブリッシュ API 

EDJ API にメッセージを送信する場合のフォーマットは次の通りです。

{
    "procedure": "publish",
    "arguments": {
        "self": " https://api.gis.gehirn.jp/edj/v1/topics/[EDJ TOPIC ID] ",
        "message": "テストメッセージ2"
    }
}

HTTP Hook 

サブスクライバに HTTP Hook を選択した場合、EDJ は指定されたエンドポイントに次の POST リクエストを行います。

HTTP Hook でエンドポイントに POST される内容 

POST /endpoint HTTP/1.1
Host: api.example.com
Content-Length: 244
Content-Type: application/json; charset=utf-8
User-Agent: GEHIRN EDJ (https://www.gehirn.jp/)
X-EDJ-Topic-Id: X-EDJ-Topic-ID: [EDJ TOPIC ID]
X-EDJ-Signature: e229322e52493eafe885d91e5e726062f335f6f738d46ce9a59b319a192bafc9

{
    "id": "6f2e5013-3d0b-40d2-a77f-9cc3422a1eb3",
    "service": "edj",
    "name": "test",
    "short": "テストメッセージ2",
    "raw": "eyJtZXNzYWdlIjogIlx1MzBjNlx1MzBiOVx1MzBjOFx1MzBlMVx1MzBjM1x1MzBiYlx1MzBmY1x1MzBiODIifQ==",
    "created_at": "2018-06-14T18:50:01Z"
}

X-EDJ-Signature ヘッダの検証 

EDJ が HTTP Hook によってエンドポイントにリクエストを送出する際に、EDJ はサブスクライバ設定時に指定されたシークレットを用いて body 部分を SHA256 で HMAC 計算した値を X-EDJ-Signature ヘッダにセットします。この値を使用して、送られてきたリクエストが EDJ が送った正規のリクエストかどうかを検証することができます。

Node.js を使用して署名を検証する例は次の通りです。

const crypto = require("crypto");

const secret = "[HTTP HOOK HMAC SECRET]";

if (verify(signature, body)) {
    console.log("Valid Signature");
} else {
    console.log("Invalid Signature");
}

function verify(signature, body) {
    return crypto.createHmac("sha256", secret).update(body).digest("hex") === signature;
}