打刻システムの構築(前編)からの続き。
前編にてSNSを基点に打刻情報をGoogleスプレッドシートへ書き込むところまでが完成した。
後編ではSNSの前面にAPI GatewayとCloudFrontを配置し実際にIFTTTアプリから打刻APIを呼び出せるようにする。
API Gateway
API GatewayをSNSの前面に配置。以下の役割を担う。
- REST APIの呼び出しをトピックへのパブリッシュに変換する
- APIキー、使用量プラン等によるAPI呼び出しのスロットリング
打刻API用ポリシーの作成
API GatewayからSNSへパブリッシュするためのポリシーを作成する。
AWS マネージメントコンソールから IAM を開き ポリシー から ポリシーの作成 Policy Generatorで以下を作成。
- 効果
- 許可
- AWSサービス
Amazon SNS
- アクション
Publish
- Amazon リソースネーム(ARN)
- 打刻システムの構築(前編)で作成した打刻トピックのARN
- ポリシー名
dakoku-sns-publisher
ロギングロールを作成
API GatewayからCloudWatchへログを出力するためのロールを作成する。
AWS マネージメントコンソールから IAM を開き ロール から新しいロール
- ロール名
api-gateway-logging
AWSサービスロール Amazon API Gateway から、ポリシー AmazonAPIGatewayPushToCloudWatchLogs
を選択する。
実行ロールの作成
API GatewayからSNSへパブリッシュするため、先ほど作成した打刻API用ポリシーをアッタチした実行ロールを作成する。
AWS マネージメントコンソールから IAM を開き ロール から新しいロール
- ロール名
dakoku-api-gateway
AWSサービスロール Amazon API Gateway から ポリシーを何も選択せずにロールを作成。
ロール作成後 dakoku-api-gateway
ロールの アクセス許可 タブ ポリシーのアタッチ から dakoku-sns-publisher
を選択しポリシーをアッタチする。
CloudWatchログのロール設定
AWS マネージメントコンソールから API Gateway を開き 設定 から先ほど作成したロギングロールを設定する。
- CloudWatch ログのロール ARN
api-gateway-logging
打刻APIの作成
API Gateway API から新しいAPIを作成する。
- API名
dakoku
リソースの作成
API Gateway API dakoku
の リソース からIFTTT経由で打刻イベントを受ける為のRESTリソースを作成する。
- プロキシリソースとして設定
- オフ
- リソース名
events-ifttt
- リソースパス
/events-ifttt-<任意の英数字の組み合わせ>
- API Gateway CORS を有効にする
- オフ
本来はAPIクライアントの種類を意識せずに /events
で受けたいところだが、IFTTTはカスタムHTTPヘッダを送信できないため、
x-api-key
によるAPIキーの送信が行えない。
このため第三者に公開しないIFTTT専用のRESTリソースを作成し後述のCloudFront側で同リソースへのリクエストに対しIFTTT用のAPIキーをx-api-key
ヘッダ差し込むことで対応する。
Lambda@Edgeでリクエストパラメタに指定されたAPIキーをヘッダに載せ替える事ができれば良いのだが現時点ではリクエストパラメタへのアクセスは出来ない模様。
モデルの作成
特にモデルを利用する機会は無いが、一応リクエスト本文のデータ構造を定義しておく。
API Gateway API dakoku
の モデル から作成する。
- モデル名
- Event
- コンテンツタイプ
- application/json
モデルのスキーマは以下。
{
"title": "Event",
"type": "object",
"properties": {
"subject": {
"type": "string"
},
"event": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"modifiers": {
"type": "array",
"items" : {
"type" : "string"
}
}
},
"required": ["name", "modifiers"]
}
},
"required": ["subject", "event"]
}
各プロパティの意味は以下となる。
- subject
- 打刻を実施する人や物
例)自分、扉 - event.name
- 発生したイベント名
例)office(職場) - event.modifiers
- イベントの修飾子。複数定義可能
例)enter(進入)、leave(退出)
メソッドの作成
API Gateway API dakoku
の events-ifttt
リソースにPOSTメソッドを作成する。
- 統合タイプ
AWSサービス
- AWSリージョン
ap-northeast-1
- AWSサービス
Simple Notification Service (SNS)
- HTTPメソッド
POST
- アクションの種類
アクション名の使用
- アクション
Publish
- 実行ロール
- 打刻API実行ロール
dakoku-api-gateway
のARN - コンテンツの処理
- パススルー
作成したPOST
メソッドの メソッドリクエスト を選択。
認証の設定 から
- APIキーの必要性
- true
リクエスト本文 から
- コンテンツタイプ
application/json
- モデル名
Event
作成したPOST
メソッドの 統合リクエスト を選択。
URLクエリ文字列パラメータ
- TopicArn
- 打刻システムの構築(前編)で作成した打刻トピックのARN
固定値を渡すのでシングルクォートで囲う点に注意 - Message
method.request.body
APIのデプロイ
API Gateway API dakoku
の アクション から APIをデプロイする。
本番環境を意味するprod
というステージ名でデプロイする。
- デプロイされるステージ
[新しいステージ]
- ステージ名
prod
ステージの設定
API Gateway API dakoku
の ステージ prod
からステージの設定を行う。
- API キャッシュを有効化
- 無効
- CloudWatch ログ有効化
- ✓
- ログレベル
ERROR
- リクエスト/レスポンスをすべてログ
無効
- 詳細 CloudWatch メトリクス有効化
- ✓
- スロットリング有効化
- ✓
- レート
10
- バース
100
スロットリングについては基本APIキーで制御するが、デフォルトの値も念のため小さめにしておく。
使用量プラン
API Gateway 使用量プラン から 打刻APIで使用する使用量プランを作成する。
今回使用量プランは想定外の利用が発生しないための安全装置としての位置付け。
- 名前
dakoku-basic
- スロットリングの有効化
有効にする
- レート
1
- バースト
10
- クォータを有効にする
有効にする
1000
リクエスト数/日
次へ
APIステージの追加 から 使用量プランを関連付けるAPIとステージを指定する。
- API
dakoku
- ステージ
prod
次へ
APIキーを関連付けずに 完了
APIキーの作成
API Gateway APIキー からIFTTTから打刻APIを呼び出す際に利用するAPIキーを作成する。
- 名前
- dakoku-ifttt
- APIキー
- 自動生成
保存
使用量プランに追加 から 使用量プラン dakoku-basic
を指定。
テスト
API Gatewayを起点に一連の処理が正しく動作するか確認する。
API Gateway API dakoku
の リソース events-ifttt
の POST から テスト を選択。
リクエスト本文に
{
"subject": "nijohando",
"event" : {
"name": "office",
"modifiers": ["leave"]
}
}
指定してテストを実行する。
- CloudWatchログにLambdaの実行ログが正常に出力
- Googleドライブ上のフォルダ
/dakoku
の下にdakoku_event_<現在の西暦>
というファイル名でGoogleスプレッドシートが作成される - スプレッドシートには月ごとのシートが作成され、以下の打刻情報を1行追加される
2017-03-11T21:25:07.857 | nijohando | office | leave
を確認し正常に動作していることを確認する。
SSL/TLS証明書の発行
打刻APIの独自ドメインとHTTPS化で必要となるSSL/TLS証明書をCertificate Managerで発行しておく。
事前確認
Certification Managerで証明書のリクエストを行う際に所有確認のためAWSから以下のメールアドレスに一気にメールが送信される。
- WhoisのDomain registrant, Technical contact, Administrative contact
- administrator@your_domain
- hostmaster@your_domain
- postmaster@your_domain
- webmaster@your_domain
- admin@your_domain
独自ドメインのWhoisの登録情報が代行になっている場合は上記のいずれかのメールアドレスでメールを受信できるようにしておく必要がある。
証明書のリクエスト
AWSマネージメントコンソールから Certificate Manager を開く。
リージョンを バージニア北部 に切り替え、証明書のリクエスト を押下。
注意点としては東京リージョンではなく、バージニア北部リージョンで証明書を作成する必要がある。
これはCloudFrontにはリージョンの概念は無いが管理上バージニア北部リージョンに属するため東京リージョンで作成した証明書はCloudFront側から利用できない。
- ドメイン名
dakoku.nijohando.jp
確認とリクエストボタンを押下。
前述のメールアドレスに確認メールが来るのでメール文中のリンクを踏んで承認する。
AWSマネージメントコンソールに戻り続行ボタンを押して証明書の発行が完了。
CloudFront
ディストリビューションの作成
打刻API用ディストリビューションを作成する。
AWS マネージメントコンソールから CloudFront を開き Create Distribution
Webの Get Started を選択。
- Origin Domain Name
作成したAPI Gateway prodステージのドメイン
- Origin Path
/prod
- Origin ID
dakoku-api-gateway
- Original SSL Protocols
TLSv1.2
TLSv1.1
TLSv1
- Origin Protocol Policy
HTTPS Only
- Viewer Protocol Policy
HTTPS Only
- Allowed HTTP Methods
GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
- Object Caching
Customize
- Minimum TTL
1
- Maximum TTL
1
- Default TTL
1
- Alternate Domain Names
dakoku.nijohando.jp
打刻API用に作成する独自ドメイン。- Custom SSL Certificate
dakoku.nijohando.jp
打刻API用に作成したSSL証明書。
Create Distribution でディストリビューションを作成。
statusがInProgressからDeployedになるまでしばらくかかる。
Originの追加
既に打刻API用のAPI Gatewayをオリジンとして登録済みではあるが、ここで別のオリジンとして定義する。
最初に登録したオリジンdakoku-api-gateway
は単純に打刻API用のAPI Gatewayへ中継するためのオリジンでx-api-key
ヘッダを送出できるクライアント(IFTTT以外)向けの口。
それに対して追加のオリジンdakoku-api-gateway-events-ifttt
はIFTTT専用の口でx-api-key
ヘッダにIFTTT用のAPIキーを追加して中継するためのオリジン。
つまりマルチオリジン構成だがオリジンの実態は同じAPI Gateway。違いはHTTPヘッダの加工処理の有無だけとなる。
CloudFront の Distributions から作成した打刻APIディストリビューションを選択。Originsタブから Create Origin
- Origin Domain Name
作成したAPI Gateway prodステージのドメイン
- Origin Path
/prod
- Origin ID
dakoku-api-gateway-events-ifttt
- Original SSL Protocols
TLSv1.2
TLSv1.1
TLSv1
- Origin Protocol Policy
HTTPS Only
Origin Custom Headers に以下ヘッダを追加
- x-api-key
- API Gatewayで作成したIFTTT連携用のAPIキー
dakoku-ifttt
の値
Behaviorの追加
Behaviorを追加し、非公開のIFTTT用URLでアクセスが来た場合はオリジンdakoku-api-gateway-events-ifttt
を利用するように定義する。
CloudFront の Distributions から作成した打刻APIディストリビューションを選択。Behaviorsタブから Create Behavior で新規に作成。
- Path Pattern
events-ifttt-<任意の英数字の組み合わせ>
(API Gateway側で作成したevents-iftttリソースのパス)- Origin
dakoku-api-gateway-events-ifttt
- Viewer Protocol Policy
HTTPS Only
- Allowed HTTP Methods
GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
- Object Caching
Customize
- Minimum TTL
1
- Maximum TTL
1
- Default TTL
1
Route 53に独自ドメインを登録
打刻API用のドメインを追加する。
Hosted zones から自ドメインを選択、Create Record Set でレコードを作成する。
- Name
dakoku
- Type
A IPv4 address
- Alias
Yes
- Alias target
- Cloudfrontで作成したディストリビューションのFQDN
Create でレコードを作成。
テスト
curlからAPIを叩いて動作を確認する。
curl -H "Content-Type: application/json" \
-X POST \
-d '{"subject": "nijohando", "event": {"name": "office", "modifiers": ["enter"]}}' \
https://dakoku.nijohando.jp/events-ifttt-xxxxxxxxxxxx
Googleスプレッドシートに打刻情報が保存されれば以上でサーバサイドの準備は完了。
IFTTTの設定
最後にクライアントサイドの設定を行う。
iOS用のIFTTTアプリから出勤/退勤用アプレットを作成する。
出勤用アプレットの作成
My Applets から + で新規アプレットを作成。
then Locationサービスを選択。
Choose trigger から You enter an area を選択、職場の付近を設定。
that Makerサービスを選択。
Choose action から Make a web request を選択。
- URL
https://dakoku.nijohando.kjp/events-ifttt-xxxxxxxxxxxx
- Method
POST
- Content Type
application-json
Bodyに以下のJSONを定義。
{
"subject": "nijohando",
"event": {
"name": "office",
"modifiers": ["enter"]
}
}
退勤用アプレット
My Applets から + で新規アプレットを作成。
then Locationサービスを選択。
Choose trigger から You exit an area を選択、職場の付近を設定。
that Makerサービスを選択。
Choose action から Make a web request を選択。
- URL
https://dakoku.nijohando.kjp/events-ifttt-xxxxxxxxxxxx
- Method
POST
- Content Type
application-json
Bodyに以下のJSONを定義。
{
"subject": "nijohando",
"event": {
"name": "office",
"modifiers": ["leave"]
}
}
実地試験開始
何もしなくても出勤、退勤時刻が自動的にGoogleスプレッドシートに記録されていくので精神衛生上非常に良い。
但しジオフェンスの張り方に工夫が必要。
狭すぎると地理的影響(ビル、地下、基地局)などにより測位誤差が大きくなったタイミングで境界を越えイベントが発生してしまう為、最初は大きめ張り、
そこから職場の地理的特性を見ながらフェンスの広さや中心を調整していくのが良さそうだ。