TLSが使えない低スペックなマイコンでのAWS IoTへの接続


やりたいこと・課題

  • mbedTLSとかが使えない低スペック or 古いマイコンで、AWS IoTにつなぎたい
    • 新しいデバイスなら普通にMQTTSで繋げる
    • クラウド側の設計を、古いデバイスと新しいデバイスで、なるだけ共通化したい
    • マネージド・サービス使って、運用の手間は省きたい

実現方法

デバイスは、TLS無しのHTTPリクエストのクエリパラメータでデータを送信する。
クラウドでHTTPでメッセージを受けて、それをAWS IoTに転送するような仕組みを考える。

割り切る点

  • セキュリティ
    • TLSが無いので、このままだとリプレイアタックや盗聴などのリスクはある。
    • 簡易的な暗号化に使えそうな鍵と、スペックがあれば、それでPayloadのみを暗号化するとベターかもしれない。AESなど。ついでに認証も…  
    • 別の方法は?
      • 機密度が高いデータを送る && Cellularモジュールが使える場合は、SIMの閉域網サービスを使うのもあり
        • 機器のログデータとかであれば、何か起きても影響が限定的なこともあるので、今回はこの手段を検討する
      • 本当にTLSが使えないのかは、一度確認しても良いかもしれない。RSAをやめてECDSAを使うことでフットプリントの問題などは解決するかもしれない。
  • 双方向性
    • 基本は上りのみ。
    • 下りは、ポーリングする形で実現はできる。ポーリング間隔に応じて遅延が発生するので、リアルタイム性を求める場合は厳しい。

設計

設定

IoT Core

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を呼びます。
1. HTTP APIを選択
2. Create an API→Integrations→Lambda→作成したLambda Functionを指定
3. API nameは任意
4. Configure routes で、Method をGETにし、Resource Pathは、 /publish にします。

これでURLが決まるので、以下の様に試してみました。ResponseにはIoT CoreにPublishされるJsonと同じものが表示されるようにLambdaの中で処理しています。

CloudFront

HTTPでメッセージを受けられるようにし、オリジンに上記のURLを指定します。
1. Create Distribution
2. Origin Domain Name にURLを入れる。 xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com
3. Origin Pathは空欄
4. Origin Protocol Policy はHTTPS Only
5. Cache Policyでは、TTLを0に設定(キャッシュしない)
6. 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で接続しているデバイスとバックエンドの実装を(全てではありませんが)、統一することができます。特にデバイス管理(識別)や認証などは、開発コスト、ハードウェアスペック、通信コスト、セキュリティなどをトータルで考慮しどこまでをどのようにやるか、考える必要がありそうです。