🗽

Slack コマンドを dump する方法

2021/11/01に公開

目的

Slack コマンドの HTTP リクエストをまるごと dump したいです。
この記事では認証について扱わないです。

dump するためのローカルサーバ

とりあえずHTTPリクエストを dump するためのローカルサーバ(Go)を立てます。

ソースコード

package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"

	"github.com/sirupsen/logrus"
)

func main() {
	http.HandleFunc("/hello", helloHandler)
	http.ListenAndServe(":8000", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	dumpedReq, err := httputil.DumpRequest(r, true)
	if err != nil {
		logrus.Error(err)
	}
	fmt.Println(string(dumpedReq))

	w.Write([]byte("Hello, world!"))
}

起動

$ go run ./...

Slackのリモートサーバから叩けるように ngrok で公開

Slack コマンドは、ローカルではなく、Slackbot というクライアントから Slack 側のサーバで送られるようなので、ローカルサーバ(localhost)は Webhook 用の URL に設定することはできません。

ngrok を使って、リモートサーバから叩けるようにローカルサーバを一時的に公開します(終わったらさっさと切りましょう)。

$ ngrok http 8000

HTTPS URL をコピーします (これを URL A と置きます)。

Slack アプリ+コマンドを作成

https://api.slack.com/interactivity/slash-commands

作ったアプリをインストールする。

先ほど作成した URL A を slash コマンドの URL に設定します。

実際に Slack でコマンドを実行します。

/hello

ローカルサーバに dump されたリクエストが表示される

ローカルサーバに dump されたリクエストが表示されます。
(セキュリティ観点からいくつか隠していますが、実際は全て確認できます)

POST /hello HTTP/1.1
Host: <hostname>
Accept: application/json,*/*
Accept-Encoding: gzip,deflate
Content-Length: 100
Content-Type: application/x-www-form-urlencoded
User-Agent: Slackbot 1.0 (+https://api.slack.com/robots)
X-Forwarded-For: <ip address>
X-Forwarded-Proto: https
X-Slack-Request-Timestamp: <timestamp>
X-Slack-Signature: v0=<長い文字列>

token=<token>&team_id=<team_id>&team_domain=<team_domain>&channel_id=<channel_id>&channel_name=general&user_id=<slack user id>&user_name=zawawahoge&command=%2Fhello&text=&api_app_id=<api_app_id>&is_enterprise_install=false&response_url=https%3A%2F%2Fhooks.slack.com....&trigger_id=<trigger_id>

まとめ

ローカルに立てたサーバを ngrok で公開し、SlackコマンドのURLとして設定すると、Slackbot からのリクエストを確認できます。

おまけ

Slack コマンドを受けるサーバはこのままだと、どこからも叩かれる危険なサーバになるので、実際のサーバでは、何らかの方法でリクエストを認証する必要があります。
そのために、 X-SlackSignature というものがあり、 HMAC を用いてデータ完全性や信頼性をチェックすることができます。
(この辺もおいおい記事にします。)

Discussion