やりたいこと・課題
- mbedTLSとかが使えない低スペック or 古いマイコンで、AWS IoTにつなぎたい
- 新しいデバイスなら普通にMQTTSで繋げる
- クラウド側の設計を、古いデバイスと新しいデバイスで、なるだけ共通化したい
- マネージド・サービス使って、運用の手間は省きたい
実現方法
デバイスは、TLS無しのHTTPリクエストのクエリパラメータでデータを送信する。
クラウドでHTTPでメッセージを受けて、それをAWS IoTに転送するような仕組みを考える。
割り切る点
- セキュリティ
- TLSが無いので、このままだとリプレイアタックや盗聴などのリスクはある。
- 簡易的な暗号化に使えそうな鍵と、スペックがあれば、それでPayloadのみを暗号化するとベターかもしれない。AESなど。ついでに認証も…
- 別の方法は?
- 機密度が高いデータを送る && Cellularモジュールが使える場合は、SIMの閉域網サービスを使うのもあり
- 機器のログデータとかであれば、何か起きても影響が限定的なこともあるので、今回はこの手段を検討する
- 本当にTLSが使えないのかは、一度確認しても良いかもしれない。RSAをやめてECDSAを使うことでフットプリントの問題などは解決するかもしれない。
- 機密度が高いデータを送る && Cellularモジュールが使える場合は、SIMの閉域網サービスを使うのもあり
- 双方向性
- 基本は上りのみ。
- 下りは、ポーリングする形で実現はできる。ポーリング間隔に応じて遅延が発生するので、リアルタイム性を求める場合は厳しい。
設計
設定
IoT Core
- 特に変わったことはしないためここでは割愛
- 基本的なことはここで学べます( https://aws-iot-core-for-beginners.workshop.aws/ )
Lambda
とてもシンプルです。クエリパラメータをそのままJsonにしてPayloadに突っ込んでます。
Execution roleに、AWS IoTへのアクセスを許可するためのポリシーを入れます。(雑に AWSIoTFullAccess
をセットしました)
import json
import boto3
iot = boto3.client('iot-data')
def lambda_handler(event, context):
message = event['queryStringParameters']
topic = 'data/sensor'
iot.publish(
topic=topic,
qos=0,
payload=json.dumps(message)
)
return {
'statusCode': 200,
'body': json.dumps(event['queryStringParameters'])
}
API Gateway
HTTP API 経由でLambdaを呼びます。
- HTTP APIを選択
- Create an API→Integrations→Lambda→作成したLambda Functionを指定
- API nameは任意
- Configure routes で、Method をGETにし、Resource Pathは、
/publish
にします。
これでURLが決まるので、以下の様に試してみました。ResponseにはIoT CoreにPublishされるJsonと同じものが表示されるようにLambdaの中で処理しています。
CloudFront
HTTPでメッセージを受けられるようにし、オリジンに上記のURLを指定します。
- Create Distribution
- Origin Domain Name にURLを入れる。 xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com
- Origin Pathは空欄
- Origin Protocol Policy はHTTPS Only
- Cache Policyでは、TTLを0に設定(キャッシュしない)
- Origin Request Policyで、Headers=None, Cookies=None, Query strings=All
これで作成。できるまで数分待つ。
完成したら、ブラウザなどでアクセスしてみます。
http://xxxxxxxxxx.cloudfront.net/publish?temperature=40
と打ち込むとメッセージがAWS IoTにPublishされました。
IoT CoreのTestで機能で確認するとこんなかんじでした。
まとめ
これで、HTTP GETのみが喋れるデバイスでもIoT Coreにつなぐことができ、MQTTSで接続しているデバイスとバックエンドの実装を(全てではありませんが)、統一することができます。特にデバイス管理(識別)や認証などは、開発コスト、ハードウェアスペック、通信コスト、セキュリティなどをトータルで考慮しどこまでをどのようにやるか、考える必要がありそうです。