Lambda＋APIGateway+SQSのSlackアプリで本番・開発環境を整備する


この記事は [AWS LambdaとServerless Advent Calendar 2020](https://qiita.com/advent-calendar/2020/lambda)の15日目の記事です。


# はじめに
前回の記事 [Slackに共有されたファイルをサーバーレスでGoogle Driveにアップロードする仕組みを作るまで](https://qiita.com/kasshiiii/items/15f70cf28bd5c21d4b6d) で紹介したサーバーレスで構築したSlackアプリで、本番環境と開発環境を整備しました。

# 整備の経緯
前回の記事でも[今後の課題](https://qiita.com/kasshiiii/items/15f70cf28bd5c21d4b6d#%E7%92%B0%E5%A2%83%E6%95%B4%E5%82%99%E3%81%A8%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E4%BB%8A%E5%BE%8C%E3%81%AE%E8%AA%B2%E9%A1%8C)にあげていた通り、改修のために利用を控えてもらった上でタイムアタックのように改修作業しており、リリースの環境が整っていないという課題がありました。この課題を解決すべく取り組みました。

# アプリのアーキテクチャ
[前回の記事](https://qiita.com/kasshiiii/items/15f70cf28bd5c21d4b6d#%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3)の再掲になりますが、今回環境整備したアーキテクチャはこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322392/837f67bf-062e-f881-e095-91a54ad8d5c2.png)

# SQSをトリガーとするLambda
## Lambdaのバージョン管理
SQSからメッセージを受けるLambda([前回記事での説明](https://qiita.com/kasshiiii/items/15f70cf28bd5c21d4b6d#lambdagoogle-drive%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89))は、まずシンプルに、バージョンとエイリアスによるバージョン管理の機能を適用します。

実に一般的な使い方とは思いますが、、
バージョンは修正のたびに最新バージョンの`$LATEST`から切り離しています。
エイリアスは以下のようにバージョンにあてて利用します。

|エイリアス名  |使い方  |
|---|---|
|`dev`  | いわゆる「開発環境」 常に最新バージョンの`$LATEST`にあてる |
|`prd`  | いわゆる「本番環境」 devでのテスト確認済のバージョンをあてる|

## SQSとの接続での環境分岐
続いて、SQSとの接続での環境分岐です。
SQSは現在Lambdaのエイリアスの機能のように環境を分けるような機能がないため、2つの環境用にQueue2つを用意します。
その上で、Lambdaのコード上での分岐を行います。

```python
def lambda_handler(event, context):
    
    event_str =  json.dumps(event)
    event_dict = json.loads(event_str)
    
    sqstype = event_dict['Records'][0]['eventSourceARN'].split(':')[5]

    SLACK_OATH_TOKEN = '' #この後の処理でSlackのトークンを環境で使い分けるため、ここで環境の分岐
    if sqstype == '本番環境用のQueueの名前':
        SLACK_OATH_TOKEN = ('本番環境用のSlackトークン')
    elif sqstype == '開発環境用のQueueの名前':
        SLACK_OATH_TOKEN = ('開発環境用のSlackトークン')

```

`event`JSONの`eventSourceARN`に`arn:aws:sqs:(region):(account_id):(queue_name)`となっているため、最後のQueueの名前を取得し、判定することで環境の分岐を行います。


# API GatewayとLambda
基本的には [【AWS】API GatewayのステージとLambda のエイリアスを対応させる](https://qiita.com/szk3/items/298dfc8bb86ba802617f) こちらの記事を参考に設定しているので、詳細の説明は本記事では省略します。
## 注意点
API GatewayとLambdaを連携する場合Lambdaの設定画面のトリガーにAPIGatewayが設定されていると思うのですが、API GatewayのステージとLambdaのエイリアスを対応させると下の画像のようにトリガーにAPI Gatewayがいなくなってしまいます。しかし、これはこれで正しい設定です。「トリガーを追加」から該当のAPI Gatewayを設定すると動かなくなるので、ご注意ください。(まさに踏みました…)
![Yj2tAIa35NiD54E1607999346_1607999418.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322392/bb363096-471e-0a64-d27f-5344241231ba.png)

# (おまけ) Slackアプリ
Slackアプリは、1つアプリで複数環境に分けるような機能はないため、Slackのサポートに問い合わせてみました。

**「ワークスペースをわけて本番用と開発用のアプリを作成する」**という妥協案はありながら、
実現したい要件は、

- ユーザーごとにアプリの利用権限を設定したい。(＝開発用アプリは開発者のみ使えるようにしたい)
- 同ワークスペース内で複数のアプリを利用したい。

として、妙案がないか問い合わせしたところ、以下のような回答をいただきました。

- 現在のところ「メンバーごとにアプリの利用を制限する」という機能が無いため、基本的には開発用途のワークスペースを設ける方法が手堅い。
- 「特定のメンバーにのみ使用させたい」という場合は下記の方法を検討するのはあり。

```
1. 一度当該アプリを承認した状態で特定のメンバーにアプリをインストールしてもらう。
2. 再び同じアプリに制限をかけることで、ひとまず他のメンバーはそのアプリをインストールできなくなるが、このときすでにインストールされているアプリは使用を継続できる。
```

2つ目にあげていただいた特定メンバーにインストールしてもらうのは正攻法ではないと思ったので、今回はサポートの方が手堅いとおっしゃっていて妥協案でもあった**「ワークスペースをわけて本番用と開発用のアプリを作成する」**を採用して、アプリで環境を分けています。

# おわりに
サーバーレスアプリケーションの環境整備についてはまだ深掘りされた分野でもないように思うので、またサーバーレスで何か開発する際に調査して色々試してみようかと思います。