【ハンズオン】Amazon ConnectからLambdaを実行しEC2インスタンスを操作する

**2018/12/11追記**
**東京リージョンが開設され、フリーダイヤル0120が使えるようになりました。**

# はじめに
前回の記事「[【3分でわかる】Amazon Connectは何がすごいのか？](https://qiita.com/hamham/items/46aa03e7977b32d5ad14)」でAmazon Connectについて概要を書きましたが、今回はハンズオン記事を書こうと思います。


# Amazon Connectでできること
Amazon Connectはコールセンターを簡単に作るサービスですが、それだけではありません。
Lambdaが利用できるので電話を使って特定の処理を実行することが可能です。
例えば以下のようなことができます。

- Amazon Connectの電話番号に発信し、IVRを操作して特定のサーバを起動する
- システムでアラートを検知した際に、担当者に自動で電話してエラーメッセージを読み上げる

今回はAmazon Connectを使って特定のEC2インスタンスを、起動したり停止したりできるようにしてみようと思います。

# 問い合わせフローを作る
Amazon Connectの初期セットアップは省略しますが画面ポチポチでいけます。
そしたら問い合わせフローが作れるようになります。
こんな感じにしてみました。ブラウザからドラッグアンドドロップで簡単に作ることが可能です。

![AmazonConnectFlow.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/2a2f981c-ff81-cb45-1136-6bf9ade05b0b.jpeg)

だいたい見て頂ければフローが想像できると思います。

IVRの入力（DTMFという）を受け付けるところはこんな感じです。
「1」を入力したらインスタンス起動、「2」を入力したらインスタンス停止をさせることにします。

![AmazonConnectDTMF.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/825a231f-6871-1a9a-8a8d-5faa74a7b78c.jpeg)

Lambdaのファンクションのところはこんな感じでARN（Amazon Resource Name）で指定します。
Lambda自体の設定は後述します。

![AmazonConnectLambda.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/b9dd92d6-8e28-6c1e-7025-a347aa4ad3cc.jpeg)

フローが完成したら右上の「保存して発行」をします。
※「保存」だけだと公開されません。

# 電話番号と問い合わせフローの紐付け
Amazon Connetで電話番号を取得し、さきほど作った問い合わせフローと紐付けます。
日本を選んだ場合、フリーダイヤル（0800番号）とダイヤルイン（050番号）が選べます。ここでは050番号にします。

![AmazonConnectNumber.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/8df18ac9-0234-393a-1ed3-e3cbd2905ef9.jpeg)

ここまでできたら、実際に電話番号にかけてみてください。IVRのアナウンスが流れるはずです。

# Lambdaファンクションの設定
ここから先はAmazon Connectの話ではないので、ざっくりレベルで書きます。

## IAMロールの作成
LambdaからEC2インスタンスの起動や停止ができるように権限を与えてやります。
IAMの画面で「ロールの作成」から「Lambda」を選択します。
ポリシーは「AmazonEC2FullAccess」を与えておきます。
※本当はインラインポリシーで"ec2:StartInstances"や"ec2:StopInstances"に絞ったほうがよいです。

## EC2インスタンスの作成
操作するインスタンスがあればそれでよいです。
なければ作っておきましょう。リージョンは問いません。

## Lambda関数の作成
Lambdaファンクションを作成します。
Amazon Connectをシドニーリージョンで開設しているのであれば、Lambdaもシドニーがいいでしょう。
サンプルコードでは、ランタイムは「Node.js 6.10」、ロールはさきほど作ったものを指定します。
"INSTANCE_ID"にEC2のインスタンスIDを指定してください。
サンプルコードのリージョンは東京（ap-northeast-1）にしてます。


### EC2インスタンス起動スクリプト

- Lambda関数名：ec2_start（名前はなんでもよい）

```js:index.js
const INSTANCE_ID = 'i-*****************';
 
var AWS = require('aws-sdk'); 
AWS.config.region = 'ap-northeast-1';
 
function ec2Start(cb){
    var ec2 = new AWS.EC2();
    var params = {
        InstanceIds: [
            INSTANCE_ID
        ]
    };
  
    ec2.startInstances(params, function(err, data) {
        if (!!err) {
            console.log(err, err.stack);
        } else {
            console.log(data);
            cb();
        }
    });
}
exports.handler = function(event, context, callback) {
    console.log('start');
    ec2Start(function() {
        context.done(null, 'Started Instance');
    });
    callback(null, buildResponse());
    function buildResponse() {
    return {
        lambdaResult:"Success"
        };
    }

};
```
### EC2インスタンス停止スクリプト

- Lambda関数名：ec2_stop（名前はなんでもよい）

```js:index.js
const INSTANCE_ID = 'i-*****************';
 
var AWS = require('aws-sdk'); 
AWS.config.region = 'ap-northeast-1';
 
function ec2Stop(cb){
    var ec2 = new AWS.EC2();
    var params = {
        InstanceIds: [
            INSTANCE_ID
        ]
    };
  
    ec2.stopInstances(params, function(err, data) {
        if (!!err) {
            console.log(err, err.stack);
        } else {
            console.log(data);
            cb();
        }
    });
}
exports.handler = function(event, context, callback) {
    console.log('stop');
    ec2Stop(function() {
        context.done(null, 'Stopped Instance');
    });
    callback(null, buildResponse());
    function buildResponse() {
    return {
        lambdaResult:"Success"
        };
    }

};
```
念のためテスト実行して、インスタンスの起動・停止が行えることを確認しましょう。


# 準備完了！と思いきや・・
EC2が停止している状態で、電話してIVRが流れたら1（起動）を押してみてください。
「コマンド実行が成功しました」となると思いきや、「コマンド実行が失敗しました」と流れます。。


# 【これが必要】Amazon ConnectからLambdaを呼び出すための権限付与
これに結構ハマリました。
以下のページを参考にしました。

- [[Amazon Connect] 問い合わせフローの中でLambda関数を実行する](https://dev.classmethod.jp/cloud/aws/amazon-connect-lambda/)

現状、ここだけは[AWS CLI](https://aws.amazon.com/jp/cli/)を使う必要があります。（将来的にはGUIでできるようになりそうですが）
AWS CLIのインストール＆設定は[公式ページ](https://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html)がわかりやすいです。
引数で必要なものは以下の3つです。

- AWSアカウントID
- LambdaのARN（EC2の起動と停止なら2つ）
- Amazon ConnectのARN（Amazon Connectのダッシュボードで確認可能）

```shell-session
$ aws lambda add-permission --function-name arn:aws:lambda:ap-southeast-2:***********:function:ec2_start --statement-id 1 --principal connect.amazonaws.com --action lambda:InvokeFunction --source-account ************ --source-arn arn:aws:connect:ap-southeast-2:************:instance/********-****-****-****-************ --region ap-southeast-2
$ aws lambda add-permission --function-name arn:aws:lambda:ap-southeast-2:***********:function:ec2_stop --statement-id 1 --principal connect.amazonaws.com --action lambda:InvokeFunction --source-account ************ --source-arn arn:aws:connect:ap-southeast-2:************:instance/********-****-****-****-************ --region ap-southeast-2
```
これを実行すると、「"Statement": "{\"Sid・・・・・・allow・・・・・・」とよくわからないものが返ってきますが、おそらく成功してます！
もう1回電話をかけて1（起動）を押してみましょう。
「コマンド実行が成功しました」となり、インスタンスが起動するはずです！

**2018/12/18追記**
**Lambdaの権限付与がAWS CLIを使わずGUIでできるようになりました**
![lambda.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/59155714-c218-608a-839b-5dffc701c114.jpeg)


# 最後に
ということでハンズオンでした。
コールセンター用途以外でもこんな用途で使えたりするのでいろいろと可能性が広がりそうです。