AWS IoTで証明書からデバイスを特定してみる

こんにちは、CX事業本部の夏目です。

IoTシステムのバックエンドをサーバーレスで開発しています。

今回、デバイスにデバイスIDをもたせたくない、けど送られたデータの区別はしたいということで、MQTTの通信に使う証明書からデバイスの特定をしてみました。

やってみる

デバイス -> IoT Rule -> Lambdaという構成にしてやってみようと思います。

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.7
      Timeout: 60
      MemorySize: 256
      CodeUri: src
      Handler: index.handler
      Policies:
        - arn:aws:iam::aws:policy/AWSIoTFullAccess
      Events:
        IoTRule:
          Type: IoTRule
          Properties:
            AwsIotSqlVersion: 2016-03-23
            Sql: SELECT principal() as principal FROM 'iot/rule'
import boto3

iot = boto3.client('iot')


def handler(event, context):
    principal = event['principal']
    arn = get_certificate_arn(principal)
    things = get_linked_things(arn)
    return things


def get_certificate_arn(principal):
    resp = iot.describe_certificate(certificateId=principal)
    return resp['certificateArn']


def get_linked_things(certificate_arn):
    resp = iot.list_principal_things(principal=certificate_arn)
    return resp['things']

解説

IoT RuleのSQLでは組み込み関数としてprincipal()があります。
端的に言うと、デバイスがMQTTで接続する際に使用している証明書のIDを返す関数です。
(何を使ってPublishしたかによって値が変わります。具体的な内容はドキュメントを見てください)

証明書のIDをIoT RuleのSQLで取得できたのであとは、AWS SDKを使ってデバイスの特定を行います。

IoTのlist_principal_thingsという関数で証明書に紐づくデバイスの一覧を取得できます。
注意する点としては、引数としてprincipalを要求されますが必要な値は証明書のARNという点です。
(ここでは、証明書の詳細を取得してARNを取得しましたが、リージョンやAWSのアカウントIDがわかれば、自分で生成することもできます)

まとめ

証明書から紐づくデバイスを参照することができました。
証明書が1つのデバイスに紐づく場合にしか使用できませんが、こんなこともできるんだと心の片隅にでも覚えてもらえれば幸いです。