在席管理をSlackとAWSのサーバレスアーキテクチャで解決してみた（iruca API編）



# はじめに
* 私の所属する部門では、信頼関係を築けている優秀なエンジニアに対してリモートワークを許可しています。
* 家庭の事情で毎日オフィスに来れないけど優秀なエンジニア、地方在住の優秀なエンジニア等々、そんなエンジニアの方にプロジェクトに参加して頂くことで、多くの成果を上げてきました。
* 本件はリモートワークに対する記事では無いので多くを語りませんが、リモートワークで課題となるのは、コミュニケーションとなることが多いです。
* 特に”今、在席してるのか？”、”Slackで質問して良いか？”と、在席確認をプロジェクトメンバー間で簡単に共有することが必要となります。
* その課題を解決するのに、[合同会社テンマド](http://10mado.jp/)さんの提供している [iruca](https://iruca.co/) というサービスを利用しています。
<br />
<img width="100px" src="https://d1x1byzx01kdcw.cloudfront.net/img/iruca.svg?v=c889ddab69">
<br />
* 本記事では、Slackで `/iruca out` みたいなSlashコマンドを叩いてirucaのステータスを変更したり確認したりを以下の構成で実現する方法を紹介します。

  ![skitch.38.png](https://qiita-image-store.s3.amazonaws.com/0/39596/3a2f056e-f402-db97-24af-cf03551464d7.png "skitch.38.png")
* どってないコードですが、[iruca APIに対応したLambdaソース](https://github.com/ukitiyan/lambda_iruca/blob/master/lambda_iruca.js) も公開してます。

# irucaとは
* 無料でルームを作って、Slackと同じユーザIDでメンバー登録するだけで、簡単にメンバーの在席確認管理が可能となります。
* Slackと連携できるのとお手軽なのがとても良いです。
* irucaの紹介については、以下の記事を参考にさせて貰っています。
  * [Slackで時差出勤・リモート勤務の在席管理を解決する](http://tech.innovator.jp.net/entry/2016/06/30/132051)
  * [時差出勤・リモート勤務の在席管理を解決する「iruca」の紹介](http://tech.innovator.jp.net/entry/2016/06/29/114923)

# コマンドが公開されてしまう＆コマンドTYPO問題
* そんな便利なirucaですが、使わせて貰ってる中でいくつか問題がありました。
* まず、Slackで以下のコマンド叩くとステータスを変更できるのですが、ステータスが変更される前にSlackで打ったコマンドでステータスの変更内容が見えてしまう（通知が連続してしまう）ので少し恥ずかしい気持ちになることがあります。（Channel分けるとかで回避できる問題ですが）

  * 使えるコマンド <br/>
![skitch.png](https://qiita-image-store.s3.amazonaws.com/0/39596/8cfac3c8-3d4b-cadd-cdc8-bb0c5e50daec.png "skitch.png")
  * コマンドとirucaからの通知が連続する<br />
![skitch.40.png](https://qiita-image-store.s3.amazonaws.com/0/39596/d59f628b-760e-189c-e911-c0b62767e022.png "skitch.40.png")


* また、コード補完に慣れきっている我々は、コマンドを補完無しに打つことが出来ないため、コマンドtypoしてirucaが反応しないということが在りがちです。（どちらもirucaの問題では無いですね）
  * コマンドtypoしてirucaが反応しない<br />
![skitch.41.png](https://qiita-image-store.s3.amazonaws.com/0/39596/98f16547-ef7f-3df3-0c7f-588ff799aaf8.png "skitch.41.png")


# AWSのサーバレスアーキテクチャで解決する
* というか、slashコマンドで対応します。
* 上記の問題は、 `/iruca` みたいなslashコマンドをSlackに登録すれば、解決しちゃいます。
* Slashコマンドを受け付けるAPIと受け付けた内容をiruca APIに投げる仕掛けが必要となりますが、それ用にサーバ立てずにサーバレスで行きましょう！
* 今回はAWSの「API Gateway」と「Lambda」を使います。
* ちょっと確認したらLambdaにslashコマンド用のBluePrintが用意されていたので、サクッといけました。

## slashコマンドを作成する
* Slackを起動しての「Apps & integrations」を選択してください。
<img width="200px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/837f9434-8571-7487-eead-8a0c01b1a1ed.png">

* 検索窓から「Slash Commonds」を選択してください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/a1383e78-98b9-103e-39d3-640317f4934e.png">

* 「Add Configulation」を選択してください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/925cd7a2-1a35-7144-5eb3-a159e15df772.png">

* Choose a Commandに `/iruca` を入力して「Add Command Integration」を選択してください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/85424306-2cbb-9e4e-b989-2e2f7ca693e8.png">

* 画面中段にあるTokenをメモしておいてください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/fdab5330-d1cb-0957-d6c9-cf45358f99de.png">

## 暗号化キーを作成する
* IAM画面から「暗号化キー」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/ba59c5d8-0c80-8dfc-4a27-c6659033f2f5.png"/>

* フィルターを「アジア・パシフィック」に変更後、「キーの作成」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/23664aa0-130e-624b-8db9-dc660698192e.png"/>

* エイリアス（内容は任意）を入力後、次のステップを選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/4917faa5-5691-2862-8056-7b2c5e544a5b.png"/>

* キーの使用アクセス許可で、次のステップでAWS CLIを叩く際に使用するIAMユーザを選択します。（後述しますが、更にLambdaに紐付けるロールも後ほど選択します。）
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/32c9aa06-47c8-3972-4758-aa4da84cfab3.png"/>

* 作成が終わったら、AWS CLIにて `aws kms encrypt --key-id alias/lambda/slack/otto-ec --plaintext "Re4************` と叩いてください。
  * 返却されるKeyIdはロールのポリシー時に利用します。
  * 返却されるCiphertextBlobをLambdaの実装時に利用します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/a88923a1-aa26-0b4b-f1e4-654f4a93deb3.png">

## Lambda用のロールを作成する
* ここで大好きなLambdaの画面に行きたいところですが、グッと抑えて先に暗号化キーにアクセスするための権限割り当てるためのLambda用のロールを作ります。

### ポリシーの作成
* IAM画面から「ポリシーの作成」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/0584bc5d-c521-af0a-259c-d9a1eff14679.png"/>

* 「独自のポリシーを作成」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/e0c0584d-6b8c-8cdc-9301-bf857ad71426.png"/>

* ポリシー名を入力（内容は任意）し、ポリシードキュメントに以下を貼り付けてください。
* 適宜 kms:Decrypt ActionのResourceをAWS CLI実行時に返却されたKeyIdｎに修正してください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/7495eff0-d2f8-a2ae-aac7-65a31edc8417.png"/>

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
        "Effect": "Allow",
        "Action": [
            "kms:Decrypt"
        ],
        "Resource": [
            "arn:aws:kms:ap-northeast-1:******:key/***-***-***-***-***"
        ]
    }
  ]
}

```

### ロールの作成
* IAM画面から「ロールの作成」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/fd1a3626-e2de-eb46-b3b5-3f13548271a3.png"/>

* ロール名を入力（内容は任意）してください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/23a65951-1839-288f-5e00-56fabd8de6c6.png"/>
* ロールタイプは一旦「AWS Lambda」を選択してください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/efdd3003-c016-a06e-7d7b-f54b6c29cc85.png">

* 先程作成したポリシーをアタッチします。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/eb228af9-7c6b-6316-8536-c613bd25b19c.png">

## ロールを暗号化キーに紐付ける
* 先程作成した暗号化キーに上記Lambda用のロールを紐付けます。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/1e90b8ff-7a78-b273-474b-729733efdbba.png">

## Lambdaを実装する
* Lambda画面で「Create a Lambda function」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/21178f27-3e6b-5aa9-c4d8-88222af0eb57.png">

* 検索窓に `slack` と入力して表示される「slack-echo-command」を選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/ea122061-a0cc-d25e-af0a-632b58d71bba.png">

* API Gatewayを定義しちゃいます。
1 API nameを入力（内容は任意）します。
2 Resource nameを入力（内容は任意）します。
3 Methodに `POST` を指定します。
4 Securityに `OPEN` を指定します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/43e12437-7002-84fe-8e5d-9adb19861300.png">

* Nameを入力（内容は任意）します。BluePrintなコードがありますが、iruca APIに対応したソースを[ここ](https://github.com/ukitiyan/lambda_iruca/blob/master/lambda_iruca.js)から取得して貼り付けてください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/287f4ae5-3950-efb9-4909-0a72d3508999.png">

* 貼り付けたコード内にある `irucaRoomCode` `irucaPass` `kmsEncryptedToken` を適宜修正してください。
<img width="350px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/1e2cefed-5c6c-49e7-9c0a-74b1a8c5da9a.png">

* Roleは先程作成したRoleを選択します。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/2674d904-7fa6-1f5b-74e1-8a676e36d020.png">


## API Gatewayでマッピング設定
* Lambdaの作成が終わると、以下の画面になるので、URLをメモしておいてください。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/6898f73c-d63d-fd6d-b3cd-dec52b7df248.png">

* 上記POSTを選択すると、API Gatewayの画面に遷移するので、統合リクエストの本文マッピングテンプレートを以下の内容で追加します。
* Content-Type: `application/x-www-form-urlencoded`
* Body: `{ "body": $input.json("$") }`
<img width="200px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/4b397f45-d0b5-64f9-490e-a78aa779a65a.png">
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/2b170f79-4a36-9921-52e5-a41a36e571aa.png">

* 修正後、APIのデプロイでprodに反映しておきます。
<img width="200px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/d9dd070a-9e52-cf39-4559-93d987caccd6.png">

## 最後にSlashコマンドにURL設定
* API GatewayのエンドポイントURLをslashコマンド画面のURLに貼り付けます。
<img width="400px" src="https://qiita-image-store.s3.amazonaws.com/0/39596/62eeac93-72ef-9cfc-cc59-26c6f57a5f6d.png">

# 動作確認
* irucaと連携してるSlackで以下のコマンドがいけるか確かめてください。
  * 全員のステータス： `/iruca all`
  * メンバーのステータス： `/iruca @userid`
  * 在席： `/iruca on (メッセージ)`
  * 取込中： `/iruca busy (メッセージ)`
  * 離席： `/iruca off (メッセージ)`
  * 外出： `/iruca out (メッセージ)`
  * 休暇： `/iruca vacation (メッセージ)`

# まとめ
* これで、更に気軽に在席管理を行えます。
* `/iru` くらいでコード補完されます。
* ブラウザ開かずに、メンバーのステータスを確認できる `/iruca all` は意外と使えます。
* slashコマンドとlambda連携は簡単なので、他でも色々出来そうですね。

# 変更履歴
* 2016/07/22: 在籍→在席