AWS Chalice を使って、Slack App (Slack Bolt for Python) を作成してみた

AWS Chaliceを使って、検証用のSlack Appを作ってみました。
2023.07.05

AWS事業本部の梶原@福岡オフィスです。

SlackAppの作り方はわりともう後発感があるので、以下をコンセプトに各サービスやフレームワークを選定して検証用のアプリを作ってみました。

  • 生成系AIの検証環境(PoC環境)を考えているので言語はPython
  • 本番想定でなく、検証用に環境を作る
  • なるべく標準的なフレームワークや純正によせる
  • なるべくAWSによせる。
  • なるべくコーディングを減らす
  • 一撃♪(後片付けも)

ということで、検証用の環境をぱぱっと作成検証して、後片付けも一撃でできるアプリの作成を目指してみます。 上記を独断と偏見で判断しAWS Chalice, Slack Bolt for Pythonの組み合わせで作成してみました。

Slack Appとして作成することで、「ちょっと試してみてー」、と手軽に検証を依頼できるのも良いところかと思います。

はじめに

以下の技術、サービスを使っています。詳しくは参考情報や、リンクなどをご参照ください

  • Slack (Slack Bolt for Python)
    • Slack 純正のSDK
  • AWS Chalice(Python Serverless Microframework for AWS)
    • ちょっと情報は少ない感はあるのですが、Pythonかつ、AWSへのデプロイと削除が1撃で手軽にできるので選択しました。

前提条件

  • AWS アカウント(以下サービスを使用しています)また権限が必要です
    • AWS IAM
    • AWS Lambda
    • Amazon API Gateway
    • Amazon S3
    • AWS Chalice
  • Slack
    • アプリケーションがインストール可能なこと

事前準備

AWS 環境設定

AWS Chaliceでデプロイをおこなうので、事前にCredential等を設定してください

$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [ap-northeast-1]: 
Default output format [None]:

Pythonの環境設定

Python 3.9 の環境設定をします。

以降の処理はPython3.9 のvenv環境での実行を想定しています

$ python3.9 --version
Python 3.9.17
$ python3.9 -m venv .venv39
$ source .venv39/bin/activate
(.venv39) $ python --version
Python 3.9.17
(.venv39) $ pip --version
pip 23.1.2 from xxxxx/.venv39/lib/python3.9/site-packages/pip (python 3.9)

AWS Chalice のインストール

$ pip install chalice
$ chalice --version
chalice 1.29.0, python 3.9.17

※以下の手順のslack-boltのdeploy.shの実行でもインストールはされます

やってみた

Slack Bolt for Pythonのclone

実際は、AWS Chalice の部分だけで良いのですが、まとめて取得します。

$ git clone https://github.com/slackapi/bolt-python.git

AWS Chalice Appの実装

Slack Bolt for Python にAWS Chaliceのサンプルがあるので流用します。

$ cd bolt-python/examples/aws_chalice/

AWS Chaliceの動作確認

Slackのアプリの実装の前に、AWS Chaliceのデプロイが正常に行えるか確認します

AWS Chaliseの環境設定

OAuth認証インストール用のサンプル設定を複製します。

$ cp -p .chalice/config.json.oauth .chalice/config.json

実際は、Slackの設定等を行うのですが、一旦、デフォルトのファイルでデプロイを実施し、デプロイの確認をします。

config.json のmanage_iam_role(ロールの作成オプション)がfalseなので、trueとしてロールを作成してください

config.jsonは以下のようになります

{
  "version": "2.0",
  "app_name": "bolt-python-chalice",
  "stages": {
    "dev": {
      "api_gateway_stage": "api",
      "environment_variables": {
        "SLACK_SIGNING_SECRET": "xxx",
        "SLACK_CLIENT_ID": "111.111",
        "SLACK_CLIENT_SECRET": "xxx",
        "SLACK_SCOPES": "app_mentions:read,channels:history,im:history,chat:write",
        "SLACK_INSTALLATION_S3_BUCKET_NAME": "",
        "SLACK_STATE_S3_BUCKET_NAME": ""
      },
      "manage_iam_role": true
    }
  }
}

AWS Chaliseのデプロイ(デプロイ動作確認)

$ ./deploy.sh

deproy.shの中身は以下です。個別に実施し動作確認しつつやっても問題ないかと思います。

一度、実施したのちは、chalice deployのみでAWSへデプロイ可能です。

#!/bin/bash

# configure aws credentials properly
pip install -U chalice click boto3
pip install -r requirements.txt
# edit .chalice/config.json
rm -rf vendor && mkdir -p vendor/slack_bolt && cp -pr ../../slack_bolt/* vendor/slack_bolt/
chalice deploy

正常にデプロイができれば、以下のようにRest API のURLが返ってくるかと思います。

Resources deployed:
  - Lambda ARN: arn:aws:lambda:ap-northeast-1:123456789012:function:bolt-python-chalice-dev
  - Rest API URL: https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/api/

Rest APIのURLをCurl等でリクエストすると応答が返信されます

(特に中身は実装していないので下記メッセージで問題ありません)

$ curl https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/api/
{"message":"Missing Authentication Token"}

Slack Appsの作成

特に特別な作り方はしていないのでSlackAppsの作成方法は割愛します。

アプリケーション名だけ”bolt-python-chalice”から変更した場合は、ソース上のアプリ名を変更してください。

こちらの公式URLなどを参考にSlack App を作成してください。

Create an app https://api.slack.com/apps?new_app=1

Slack App の設定より以下値を取得します。

項目
app_name bolt-python-chalice
SLACK_SIGNING_SECRET (下記App Credentialの値を設定します)
SLACK_CLIENT_ID (下記App Credentialの値を設定します)
SLACK_CLIENT_SECRET (下記App Credentialの値を設定します)
SLACK_SCOPES app_mentions:read,chat:write

必要な権限は以下の2つとなります

Bot Token Scopes 内容
app_mentions:read メンション時のメッセージを読み取る権限
chat:write チャンネルに書き込む権限

[Event Subscriptions]

Request URL に Rest API URLに “/slack/events” を追加したURLを設定します

https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/api/slack/events

正常にdeproyされていれば、Verifiedのチェックが付くかと思います。

を設定します。

メンションイベントに応答するために、****Subscribe to bot events のapp_mention を追加します。****

Slack OAuth 用のS3 バケットの作成

Slack のOAuth認証用にS3バケットを2つ作成して保持します。今回は検証用のアプリの保持用となりますので本番アプリケーションでは別の保持方法を検討してください。

項目
SLACK_INSTALLATION_S3_BUCKET_NAME slack-installations-s3-hogefuga
SLACK_STATE_S3_BUCKET_NAME slack-state-store-s3-hogefuga

config.jsonの設定

取得した値を.chalice/config.jsonに反映させます。

AWS Chaliseのデプロイ(Slack連携確認)

OAuth認証インストール用のアプリを複製します

$ cp oauth_app.py app.py

サンプルアプリの修正

Sampleのままではうまく動かなかったのでAppの初期化部分を変更してください

# process_before_response must be True when running on FaaS
bolt_app = App(
    process_before_response=True,
    oauth_flow=LambdaS3OAuthFlow(),
)

Chliceの設定を変更して、ポリシーを自動生成からポリシー定義からの作成方法に変更します。

また、AWS Chaliceの便利な自動レイヤー作成設定を有効にします。

.chalice/config.json

{
  "version": "2.0",
  "app_name": "bolt-python-chalice",
  "stages": {
    "dev": {
      "api_gateway_stage": "api",
      "environment_variables": {
        "SLACK_CLIENT_ID": "xxxxxxxxxxxxxxxxxxx",
        "SLACK_CLIENT_SECRET": "xxxxxxxxxxxxx",
        "SLACK_SIGNING_SECRET": "xxxxxxxxxxxxxxxxxxxx",
        "SLACK_SCOPES": "app_mentions:read,chat:write",
        "SLACK_INSTALLATION_S3_BUCKET_NAME": "slack-installations-s3-xxxxxxxxxxxxxx",
        "SLACK_STATE_S3_BUCKET_NAME": "slack-state-store-s3-xxxxxxxxxxxxxx"
      },
      "autogen_policy": false,
        "automatic_layer": true
    }
  }
}

.chalice/policy-dev.json を作成します.

検証でバケットにアクセスする機会があるため、S3 のフル権限を付与していますが、本番運用する場合は適切なポリシー(対象のバケットを絞るなど)に置き換えてください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": "*"
        }
    ]
}

メッセージ送信実装部分

Slackアプリに対して、メンションされた場合(”app_mention”)に、say()でメッセージを返しています。

詳細な実装を行う場合は、この部分をカスタマイズしていくことになります

@bolt_app.event("app_mention")
def handle_app_mentions(body, say, logger):
    logger.info(body)
    say("What's up? I'm a Chalice app :wave:")

デプロイ

めんどくさいLambdaのLayerも自動で作成して、更新デプロイしてくれるのでとても助かります。

$ chalice deploy
...
Creating Rest API
Resources deployed:
  - Lambda Layer ARN: arn:aws:lambda:ap-northeast-1:123456789012:layer:bolt-python-chalice-dev-managed-layer:1
  - Lambda ARN: arn:aws:lambda:ap-northeast-1:123456789012:function:bolt-python-chalice-dev
  - Rest API URL: https://hoge.execute-api.ap-northeast-1.amazonaws.com/api/

Slack App [OAuth & Permissions 設定]

[OAuth & Permissions] Redirect URLs に以下Rest API のURLを設定します

https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/slack/oauth_redirect

Slack Workspase にインストールする

以下のリンクにSlackワークスペースにログインしているユーザからアクセスします(要インストール権限)

https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/api/slack/install

以下のような画面が開くかと思うので、Add to Slackを押下します

「許可する」を押下してください

動作確認

インストールが正常にいけば、任意の部屋に追加したSlack Appを追加して、メンションしてください。

以下のように表示されれば、SlackBotの機能としては正常に動作しています。

リソース削除

不要になった場合は以下コマンドでAWS上のリソースはきれいに削除できます

$ chalice delete

まとめ

Slack Bolt for Python のサンプルコードにAWS Chaliceがあったのですが、そのままでは動かなかったのでちょっと修正しましたが

AWS Chalice でぱぱっとデプロイできる(削除できる)状態になったので、今後生成系AIのPoC環境としてカスタマイズして使おうと思います。

参考情報

爆速 API 開発を実現するサーバーレスアプリケーション開発向けフレームワーク - builders.flash☆ - 変化を求めるデベロッパーを応援するウェブマガジン | AWS

https://github.com/slackapi/bolt-python

Slack | Bolt for Python

Bolt 入門ガイド Slack | Bolt for Python

AWS Chalice https://github.com/aws/chalice