Lambda Function URLsを使って応答可能なSlack botを作成する

こんにちは。システム開発部のkiwiです。

2022/4/6に、AWS Lambdaで任意の関数にHTTPSエンドポイントを追加することができるLambda Function URLsという機能がリリースされました。

今回はこの機能を使って、ユーザーのメッセージやアクションに応答できるSlack botを作成してみたいと思います。

目次

Lambda Function URLsとは

Lambda Function URLsは、Lambda関数にHTTPSエンドポイントを作成することができる機能です。これまでサーバレス構成でHTTPSエンドポイントを用意する場合、API Gatewayなどを経由してLambdaを実行することが一般的でした。

Lambda Function URLsを使う場合、API Gatewayで用意されているようなリクエストの検証、スロットリング、カスタムドメインなどの高度な機能は利用できません。シンプルにLambdaを実行できるHTTPSエンドポイントが必要な時に便利に利用できます。

また、JavaScript経由で実行するエンドポイントを作成する際に必要なCORS設定については、Lambda Function URLsでも設定することが可能です。

Lambda Function URLsのセキュリティ

作成したエンドポイントのセキュリティタイプは、 AWS_IAMNONE の2種類から設定できます。 AWS_IAM の場合、Lambdaの実行権限を持つAWSのIAMが必要となり、エンドポイントへのリクエストをSigV4署名する必要があります。AWS SDKではなくawscurlなど軽量な仕組みでリクエストを構築する際に便利です。

NONE を設定した場合、URLを知っているユーザーであれば自由にエンドポイント経由でLambdaを実行することができます。リソースポリシーをカスタマイズすることで実行権限を絞る場合(例えば特定のIPアドレスからのみ許可する場合など)はこちらを使います。

また、Lambdaの中で正当なリクエストであることを(署名ヘッダーなどから)検証できる場合などもこちらを設定します。たとえばSlack botのInteractivity機能で使用するエンドポイントは、ヘッダーに含まれる署名を使ってリクエストを検証できるようになっています。Webhookなどの用途でNONEを設定する場合は、きちんとリクエストの検証を行いましょう。

Lambda Function URLsの作成方法

AWS SAMで作成する場合、以下のように設定します。

  Lambda:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: nodejs14.x
      CodeUri: ./
      Handler: app.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      AutoPublishAlias: live
      FunctionUrlConfig:
        AuthType: NONE
      Environment:
        Variables:
          SLACK_BOT_TOKEN: !Ref SlackBotToken
          SLACK_SIGNING_SECRET: !Ref SlackSigningSecret

FunctionUrlConfig というパラメータが新しく追加されています。AuthType(セキュリティ設定)が必須となっており、このほかCorsパラメータによるCORS設定も受け付けています。

通常このパラメータを入れると、$LATEST に対してURLが生成されるようになります。上記の例のように AutoPublishAlias を設定している場合、そのエイリアスに対するURLが生成されます。エイリアスに対して設定したURLをLambdaの管理画面で確認するときは、該当のエイリアスを表示して確認する必要があります。

なお、上記の例では簡単のため各種シークレットを環境変数に設定していますが、実際の運用ではSecrets Manager等を使用してください。

応答可能なSlack botを作成してみる

それでは、この機能を利用して実際にSlack botを作成してみましょう。

今回はSlackから提供されているBolt for JavaScript frameworkのサンプルアプリを使用します。以下のURLにて、Lambdaにデプロイする場合のチュートリアルが公開されていますので、この通りに進めていきます。

https://slack.dev/bolt-js/deployments/aws-lambda

API Gatewayの代わりにURL Functionsを作成する

手順の途中で、Serverless Frameworkのテンプレートであるserverless.ymlを作成する手順が出てきます。チュートリアルではAPI Gatewayを同時に作成するテンプレートとなっていますので、代わりにURL Functionsを作成するように書き換えます。

service: serverless-bolt-js
frameworkVersion: '2'
provider:
  name: aws
  runtime: nodejs12.x
  environment:
    SLACK_SIGNING_SECRET: ${env:SLACK_SIGNING_SECRET}
    SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN}
functions:
  slack:
    handler: app.handler
    url: true
plugins:
  - serverless-offline

Serverless Frameworkでは、urlプロパティを追加することでFunction URLsが生成されます。デフォルトではセキュリティタイプがNONEになります。前述したとおり、Slack AppのWebhookでは正当なリクエストであることをシグネチャを使って検証するようになっているため、追加の認証は不要です。

なお、AWS SAMを使ってエイリアス付きの関数を作成する場合に、セキュリティタイプをNONEに設定しても必要なリソースポリシーが生成されない不具合が発生していますのでご注意ください(SAM v1.45.0時点)。

Slack Appの権限設定

Slack Appの設定については、リポジトリのREADMEに記載されているとおり、App Manifestを設定するのが一番確実です。event_subscriptionsinteractivityにそれぞれrequest_urlとして今回作成したURLを設定します。

動作確認

AppがインストールされているSlackのチャンネルで「hello」と発言したり、メッセージのボタンをクリックしたりすると、Botが反応してくれました。

さいごに

新しく追加されたLambda Function URLsの機能の概要と、実際にWebhookで使用した例についてご紹介しました。

実際にユーザーに使ってもらう場合には、API Gatewayで提供されているキャッシュやスロットリングの制御などが必要になる場面も多いかと思います。しかし、今回のようなWebhook用のURLなど単にHTTPSでLambdaが起動できれば良く、別途セキュリティの担保ができている場合などには、簡潔に設定ができるのでとても便利だと感じました。今後そのようなバックエンドのシステムなどを構築する際には、選択肢の一つとして活用していきたいと思います。

この記事をシェア

掲載内容は、記事執筆時点の情報をもとにしています。