Slack へ Events API で投稿をモニタリング、投稿にアクションする Slack Bot 作成

2021年2月8日

概要

やりたいこと

slackbotを作って、Slackに通知があったら自動でアクションをとりたい。

最終的に AWS アラートに対して色々なアクションを行う Slack Bot を作成したい。

Slack Bot

こちらの記事を見ると 5 種類の作り方がある。

  1. Incoming webhooks
  2. Slash command
  3. Bot users (RTM API)
  4. Bot users (Events API)
  5. Bot users (フル)

今回は 4 の Events API を利用する。

スコープ

API を実行する際の権限のこと。Bot 用と User 用の 2 種類ある。

  • Bot Token Scopes  : Bot(プログラム)からアクションしたい場合
  • User Token Scopes  : ユーザとしてアクションしたい場合

手順

投稿用 Slack App 作成

最初にシンプルな Slack チャンネルにメッセージを投稿する Slack App を作成する。

以下のリンクから Slack App を作成する。

App Name と Slack Workspace を入力。

サイドバー「OAuth & Permission」の Scopes セクションがある。
Bot Token Scopes と User Token Scopes の両方に以下のスコープを追加。

ページ上部の「Install App to Workspace」でアプリをワークスペースに追加する。

Slack Workspace との連携後に、アクセストークンが発行される。

Slack チャンネル Slackbot を追加する。以下のコマンドで入れる。

/invite @sec-aws-alert

Bot ユーザのトークンで Slack チャンネルに投稿。

curl -X POST 'https://slack.com/api/chat.postMessage' \
-d 'token=xoxb-xxxxxxxxx' \
-d 'channel=#test-sec-alert' \
-d 'text=テキスト'

以下のように Slack チャンネルに投稿できた。

投稿をモニタリングする Slack App 作成

続いて投稿をモニタリングする Slack App を作成する。

Slack App のスコープには以下を選択。

プライベートチャンネルでもモニタリング・投稿する場合は以下のスコープを選択する。

Slack bot 用アプリデプロイ

下記を参考に、API Gateway + Lambda を作成する。

発行された inveke url をメモする。

Slack APP Event Subscriptions 登録

サイドバー「Event Subscriptions」より、Enable Events を On にし、上記で取得した invoke url を Request URL に登録する。

Subscribe to bot events に以下2つを設定。
message.groupsはプライベートチャンネル用。

対象のチャンネルに slack bot を招待した状態で、アラートを投げる。

Slack Events API 再送対応(X-Slack-Retry-Numヘッダー)

下記を参考に、X-Slack -Retry-Num ヘッダーの有無による再送処理判定を Lambda Function に追加する。

初めに、ヘッダーを Lambda で受け取れるよう API Gateway で Lambda プロキシ統合を有効化する。

  1. API Gateway コンソール
  2. API を選択
  3. リソース
  4. POST を選択
  5. 統合リクエスト
  6. lambda 統合プロキシにチェック
  7. APIを再デプロイ

これで Lambda にヘッダー含むリクエスト情報が送られるようになる。

以下のように Lambda を修正。

  • リクエスト情報から header と body を取得
  • header に X-Slack-Retry-Num が存在する場合、Slack Events API 再送を防止
def handle_slack_event(request: dict, context) -> str:
    header = request['headers']
    slack_event = json.loads(request['body'])

    logging.info(json.dumps(header))
    logging.info(json.dumps(slack_event))

    if 'X-Slack-Retry-Num' in header:
        logging.info('X-Slack-Retry-Num: ' + header['X-Slack-Retry-Num'])
        return 200

エラー

Your request URL responded with an HTTP error. Update your URL to receive a new request and challenge value.

Slack からの challenge を受け取る際にエラー。

以下2つの現象

  • 最初から Lambda プロキシ統合を有効にして作成すると challenge が通らない
  • Lambda まで届いていない

Lambda 統合プロキシを有効化した状態で Slack からの challenge を受ける場合、レスポンスを以下のようにする。

  if "challenge" in slack_event:
        #return slack_event.get("challenge")
        return {
            'statusCode': 200,
            'body': slack_event.get("challenge")
        }

参考

Slack APIを使用してメッセージを送信する

Slack Botの種類と大まかな作り方

[slack]もしかしてRTMはもう使えなくなったのか(2020/03/11)?

AWS初心者でもわかる! ブラウザ上で完結! AWS+Slack Event APIを使ったSlackボット超入門

Slack & monitor private messages

AWS, Slack

Posted by さいき