Meraki から取得して DynamoDB に保存した WiFi 位置情報を kibana で見る

# 前提
[Meraki Scanning API 経由で取得した WiFi 位置情報を AWS へ保存する（API Gateway + Lambda + Dynamo DB）](https://qiita.com/dyoshiha/items/f4505ef7dd8262c95f89)の設定が終わっていることが前提です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104747/27e03894-a99f-0e69-3d97-fdb670c71830.png)

# 全体の流れ
* Amazon Elasticsearch Service の使用開始
* DynamoDB テーブルの選択と DynamoDB streams の開始
* IAM ロールの設定（ES＆DynamoDB streams）
* Lambda 関数の作成（※イベントソースマッピングを忘れないよう）
* kibana の設定と可視化

# Amazon Elasticsearch Service の使用開始

## Amazon ES ドメインの作成
Amazon ES の開始にはドメイン作成が必要。

１．AWS マネジメントコンソールにログインして Amazon Elasticsearch Service コンソールを開く
２．「新しいドメインの作成」をクリック
３．「step1:ドメインの定義」では以下の通り入力して「次へ」をクリック

* 「Elasticsearch ドメイン名」： "meraki-locations" 
* 「Elasticsearch のバージョン」：5.5 

※ Amazon 公式チュートリアルによると最新が推奨とのこと。ここでは本日時点での最新 5.5 を選択。

<img width="496" alt="AmazonES1.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/30c51908-1628-b02c-930d-1f335451fa8f.png">

４．「step2:クラスターの設定」では以下の通り入力して「次へ」をクリック。

* 「インスタンス数」： "1"
* 「インスタンスタイプ」："t2.small.elasticsearch"
* 「専用マスターの有効化」：チェックせず
* 「ゾーン対応の有効化」：チェックせず
* 「ストレージタイプ」：EBS
* 「EBSボリュームタイプ」：汎用(SSD)
* 「ボリュームサイズ」：10
* 「自動スナップショットの開始時間」：19:00(UTC)

※ ボリュームサイズの最小値は10GB

<img width="497" alt="AmazonES2.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/e4faaf7c-2100-f5a3-a90c-13d97351337a.png">

５．Amazon ES へアクセスする端末のパブリックIPアドレスを調べる。Amazon 公式チュートリアルによると、Google で「私の IP アドレスは何ですか」と入力すると判明するとのこと。ここで調べた IP アドレスからのアクセスのみ許可するよう、次の項目で設定を行う。
６．「step3:アクセスの設定」では以下の通り入力して「次へ」をクリック：

* 「ネットワーク構成」：「パブリックアクセス」を選択
* 「ドメインアクセスポリシーの設定」：「特定のIPからのドメインへのアクセスを許可」を選択し、続いて現れる「IPアドレス」にパブリック IP アドレスを入力。

７．内容を確認して「確認」をクリック。新ドメイン作成には約10分を要する。
８．「ドメイン ARN」 及び 「エンドポイント」が表示されるのでメモっておく。

# DynamoDB テーブルの選択
## DynamoDB Streams を Enable にする
１．AWS マネジメントコンソールにログインして DynamoDB コンソールを開く
２．「テーブル」＞ "cmxdata" ＞「概要」タブを順にクリック
３．「ストリームの管理」をクリック
４．「新しいイメージ - 変更後に表示される項目全体。」を選択し、「有効化」をクリック
<img width="448" alt="dynamobd1.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/baac3530-9d4c-0350-55e1-b9769743c68a.png">
５．stream ARN が表示されるのでメモっておく。

# IAM ロールの作成
これから作成する Lambda 関数には次の二つの権限が必要となる：

* Amazon ES cluster に対するアクセス権限。これは index の新規レコードを submit するために必要
* DynamoDB stream に対する Read 権限

これらを満たす IAM ロールを以下の手順で作成する。

## IAM ロールの新規作成（Lambda から CloudWatch へログ送信を許可）
１．AWS マネジメントコンソールにログインして IAM コンソールを開く
２．「ロール」＞「ロールの作成」をクリック
３．「AWSサービス」＞「Lambda」＞「次のステップ：アクセス権限」をクリック
<img width="745" alt="IAM1.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/e8622e9e-62ea-8dbd-6db1-14cc16eb3e04.png">

４．"AWSLambdaBasicExecutionRole" にて検索。同名のポリシーが表示が検索結果として表示される（これは Lambda 関数がログを CloudWatch へ送ることを許可するポリシー）のでチェックを入れ、「次のステップ：確認」をクリック
５．「ロール名」に "dynamo2es-lambda-executor" と入力し、「ロールの作成」をクリック

## IAM ロールへの権限追加（ES ＆ DynamoDB stream に対するアクセス権限追加）
以下の手順で、上記で作成した IAM ロール "dynamo2es-lambda-executor" へ Amazon ES クラスタへのアクセス権限を追加する：

１．IAM コンソールから「ロール」＞ "dynamo2es-lambda-executor" をクリック
２．「インラインポリシーの追加」をクリック

<img width="711" alt="IAM2.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/87d2347e-ba16-ebc9-cb66-f59ba15138e9.png">

３．"Policy Generator" が選択されていることを確認し、「選択」をクリック

<img width="587" alt="IAM3.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/e8e956e3-9525-e278-116a-364986f3edac.png">

４．「アクセス許可の編集」では以下の通り入力：

* 「効果」：許可
* 「AWSサービス」："Amazon Elasticsearch Service"
* 「アクション」："AddTags" にチェックを入れる
* 「Amazon リソースネーム（ARN）」：(上記でメモした ES ドメイン ARN を入力 __※注1__)

__※注1）ARN の末尾には /* をつけること：__

```
arn:aws:es:us-east-1:012345678901:domain/meraki-locations/*
```

<img width="375" alt="IAM4.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/03878c7f-87d0-d4f1-5fc8-cfc846a76071.png">


５．「ステートメントの追加」をクリックすると上記入力に対応する行が追加される
６．続いて、以下の通り入力：

* 「効果」：許可
* 「AWSサービス」："Amazon DynamoDB"
* 「アクション」：（以下の４つにチェックを入れる）
 * "dynamodb:DescribeStream"
 * "dynamodb:GetRecords"
 * "dynamodb:GetShardIterator"
 * "dynamodb:ListStreams"
* 「Amazon リソースネーム（ARN）」：(上記でメモした DynamoDB stream ARN を入力__※注2__)

__※注2) stream ARN の例__

```
arn:aws:es:us-east-1:012345678901:table/cmxdata/stream/2017-12-16T09:28:30.062
```

７．「ステートメントの追加」をクリックすると上記入力に対応する行が追加される
８．「次のステップ」をクリック
９．「ポリシーの適用」をクリック

# Lambda 関数の作成

１．AWS マネジメントコンソールにログインして Lambda コンソールを開く
２．「関数の作成」をクリック
３．「設計図」にチェックを入れる
４．「基本的な情報」には以下の通り入力して「関数の作成」をクリック

* 「名前」：cmxreceiver-stream-to-es
* 「ロール」：「既存のロールを選択」
* 「既存のロール」："dynamo2es-lambda-executor"

<img width="632" alt="lambda.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/5486b2b5-2992-20ab-4f4c-dc886cb4231f.png">

５．lambda 関数 "cmxreceiver-stream-to-es" が作成されるので、「設定」タブの中に以下の通り入力して「保存してテスト」をクリック

* 「コードエントリタイプ」：「コードをインラインで編集」
* 「ランタイム」："Python 2.7"
* "lambda_function.py"：（[こちら](https://github.com/dexterlabora/cmxreceiver-lambda-inline/blob/master/src/cmxreceiver-stream-to-es.py#L11)の Python コードを張り付ける。張り付けた後で、ES_ENDPOINT の行の YOUR-ENDPOINT.eu-west-1.es.amazonaws.com をメモった「エンドポイント」へ変更する）

<img width="635" alt="lambda2.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/1b6f0bb3-f310-68d3-75f1-18e82e2c2d9e.png">

６．イベントソースマッピングの設定を行うために CLI コンソールにログインする（GUIでの設定方法がわからなかったためです。すいません。。）
７．以下を実行する：

```
aws lambda create-event-source-mapping --region us-east-1 --function-name cmxreceiver-stream-to-es --event-source (上記で取得したstream arn) --batch-size 100 --starting-position TRIM_HORIZON --profile adminuser
```

# Kibana で確認

１．AWS マネジメントコンソールにログインして Elasticsearch Service コンソールを開く
２．"meraki-locations" > 「概要」を表示
３．Kibana の横のリンクをクリックすると別ウィンドウで Kibana が開く
※ 別ウィンドウで以下のエラーが出た場合には Elasticsearch の IPアドレスによるアクセス制限の設定が間違っている可能性がある。

```
{"Message":"User: anonymous is not authorized to perform: es:ESHttpGet on resource: meraki-locations"}
```

４．kibana の画面が開いたら、以下の通り index に DynamoDB のテーブル名を入力する：

* "index name" に "cmxdata" を入力
* "Time Filter field name" に "I don't want to use the Time Filter" を選択
* "Create" をクリック

<img width="405" alt="kibana1.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/ae560e65-4e93-598a-60be-aba6bb5da471.png">

５．kibana は自動的に最適と思われるデータ型を選択してくれる：

<img width="613" alt="kibana2.png" src="https://qiita-image-store.s3.amazonaws.com/0/104747/d5ae0264-e36c-0a88-6564-37c1f169c66d.png">

６．kibana で各種手順を行うとデータの可視化が可能（操作は省略）

結果のサンプルグラフ（RSSIの大きい順に端末MACアドレスを棒グラフで表示）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/104747/f4115631-36e0-eab0-74ef-9a8520568771.png)


---

[元ネタ１：AWS ElasticSearch & Kibana](https://github.com/dexterlabora/cmxreceiver-lambda-inline#aws-elasticsearch--kibana) 
[元ネタ２：Indexing Amazon DynamoDB Content with Amazon Elasticsearch Service Using AWS Lambda](https://aws.amazon.com/jp/blogs/compute/indexing-amazon-dynamodb-content-with-amazon-elasticsearch-service-using-aws-lambda/) 
[元ネタ３：Amazon Elasticsearch Service の使用開始 | ステップ 2: Amazon ES ドメインを作成する](https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-gsg-create-domain.html)
[元ネタ４：ステップ 3.2: AWS Lambda でイベントソースを追加する](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-ddb-configure-ddb.html)