Diary of a Perpetual Student

Perpetual Student: A person who remains at university far beyond the normal period

next-gen Slack App で AWS のサービスと接続するとき気をつけたいこと3選

年末から Slack App の次世代プラットフォームを試してみています。現在はオープンベータ版となっており、有料の Slack ワークスペースでしか利用できません。

api.slack.com

次世代プラットフォームはこれまでの Slack App を取り巻くエコシステムと大きく変わっています。全部は紹介しきれないのですが、これまでと変わったところを挙げておきます:

  • Slack App を動かすためのインフラを Slack 側が用意してくれる
  • 開発用にローカルにサーバを立てて、Slack のアプリから参照し動作確認できる
  • アプリの設定(この読み取り権限が必要、など)を TypeScript のコードとして表現できる
  • CLI が用意されていて、これを叩いてデプロイなどが可能

試しに作ったもの

今回はお試しとして「ask-anywhere」という Slack App を next-gen platform を利用して作りました。

はてなの Slack ワークスペースには「#ask-hogehoge」という形でいろんな部署に問い合わせることができるチャンネル群があります。ここで、例えば、総務のチャンネルで質問したら、実は経理部門管轄の話で別のチャンネルに案内された、という様子をよく見かけます。

質問を投げるとどの窓口チャンネルに書けば良いか教えてくれるインフォメーションセンターのような Slack App があれば便利かなあと思って作ってみました。動作イメージは以下の通りです:

また、自然言語で入力された質問の解釈には Amazon Lex を利用しました。Alexa と同じ技術を使って、テキストや音声での会話を行う Bot を簡単に作れるサービスです。

aws.amazon.com

構成図は以下の通りになります:

next-gen platform の Slack App で気をつけたいこと

Slack のインフラ上で完結できれば簡単だったのですが、AWS のサービスとの接続を考えると面倒なことがいくつかあったので紹介します。

OIDC できない

GitHub Actions から AWS のリソースにアクセスするときにはアクセスキーの漏洩を嫌って OIDC 認証するのが一般的だと思います。

zenn.dev

これと同様のことを next-gen platform でもやりたかったのですが、残念ながら今はできません。Lex bot との会話をするための IAM ユーザを作り、アクセスキーとシークレットを発行する必要があります。

また、こういった秘匿情報は App にハードコーディングせず、環境変数に格納することが推奨されています。

api.slack.com

deno の公式 aws-sdk がない

next-gen Slack App のランタイムは現在 deno しか選べません。

Amazon Lex とやりとりするために aws-sdk を利用したいのですが、現在 deno 用の公式 aws-sdk は用意されていません。issue は立っているものの Open の状態です。

仕方ないので非公式のものを利用します。今回の実装では、先ほどの issue の discussion 中で紹介されていた aws_api for Deno を利用しました。

import { ApiFactory } from "https://deno.land/x/aws_api@v0.6.0/client/mod.ts";
import { LexRuntimeV2 } from "https://aws-api.deno.dev/v0.3/services/lexruntimev2.ts?docs=full";

...

const api = new ApiFactory({
  credentials: {
    awsAccessKeyId: env["aws_access_key_id"],
    awsSecretKey: env["aws_secret_access_key"],
  },
  region: "ap-northeast-1",
});
const lex = api.makeNew(LexRuntimeV2);
// lex bot に入力したテキストを認識させる
const response = await lex.recognizeText({
  ...
});

外部との通信がそのままではできない

deno はデフォルトの設定だとネットワークアクセスができないことをご存知でしょうか?deno で動く Slack App でも同じようなことが言えて、外部にアクセスする際には許可するドメインを manifest.ts ファイルの outgoingDomains に記す必要があります。

export default Manifest({
  ...
  outgoingDomains: [
    "aws-api.deno.dev",
    "runtime-v2-lex.ap-northeast-1.amazonaws.com",
  ],
  ...
});

sdk による通信など、どのドメインとやりとりしているか自分で分からない場合は、エラーログを見てちまちまとリストに足していけば良いです。例えば、以下のようなエラーが出たら outgoingDomains に aws-api.deno.dev を足す、という感じです。

slack next platform Requires net access to "aws-api.deno.dev", run again with the --allow-net flag

まとめ

next-gen platform の Slack App は(有料ワークスペース限定ですが)現在無料で利用できます。自前でバックエンドの Lambda や ECS を立てたりする必要がないので、インフラ面に関しては気が楽ですね。

一方で、ユースケースによってはやっぱり他のクラウドサービスとも接続したいと思うこともあるでしょう。そんな時には本記事が参考になれば幸いです。

ベータ版のうちに遊ぶと色々面白いと思うので、ぜひ次世代プラットフォームの波に乗っていきましょう。