Azure IoT Central でX509のデバイス認証

Azure IoT Central

Azure Iot Centralは、Azure で提供されている IoT を実現するためのSaaS (Software as a Service) プラットフォームです。デバイスさえあれば、テレメトリデータを蓄積、可視化、また、閾値を超えたらメールを送信するなどのアクションを簡単に設定することができます。 しかも、5デバイスまでならば無料で利用できるというプライスモデルで、何ができるかな?と迷っている方もお手軽に始められるところがすごい!

IoT Central は、Azure IoT Hub Device Provisioning Service を利用して、デバイスの認証と管理を行なっています。

f:id:akubicharm:20190508173711p:plain
https://docs.microsoft.com/ja-jp/azure/iot-dps/about-iot-dps

IoT Central にルート証明書、中間証明書を登録し、デバイスにはリーフ証明書とデバイスのプライベートキーとなる証明書を配置することによって、X.509 認証が利用可能になります。

Azure IoT Central のデプロイ

まずは、Azure IoT Central をデプロイします。ボタンを数回クリックするだけで5分くらいで自分専用のIoTの環境が出来上がります。

1. https://apps.azureiotcentral.com/ にアクセスします
2. "新しいアプリケーション" をクリックします

f:id:akubicharm:20190506162516p:plain:w300

3. アプリケーションの作成画面で、アプリケーション作成の情報を入力し"作成"ボタンをクリックします
名称
支払いプランの選択 評価版
アプリケーションテンプレートを選択する サンプルDevkits
Configure your application - アプリケーション名 適当な名称
Configure your appilcation - URL 一意になるFQDN

f:id:akubicharm:20190506163048p:plain:w600

デプロイが終わると、こんなダッシュボードが見えるようになります。既存のテンプレートではシミュレーションデバイスがすでに登録された状態になっています。

f:id:akubicharm:20190506163727p:plain:w600

Azure IoT Central の証明書の作成と登録

証明書の作成スクリプトが提供されているので、そのスクリプトを利用して証明書を作成していきます。

https://github.com/Azure/azure-iot-sdk-c/blob/master/tools/CACertificates/CACertificateOverview.md に記載の手順に沿って、証明書を作成します。

以下は、Bash での作成手順ですので、Power Shell を利用する場合は上記サイトを参照してください。

1. Azure IoT SDKをダウンロードします
方法1: ZIP 形式でダウンロードする場合

(1) https://github.com/Azure/azure-iot-sdk-c にブラウザでアクセスします

(2) 画面右上の"Clone or Download"のプルダウンメニューをクリックし、"Download ZIP" をクリックします

f:id:akubicharm:20190508120713p:plain:w600

(3) ダウンロードしたファイルを展開します

方法2: git clone する場合
git clone https://github.com/Azure/azure-iot-sdk-c
2. 証明証作成の環境を準備します

作業用ディレクトリを作成し、移動します。

mkdir work
cd work

azure-iot-sdk-c/tools/CACertificates/ から *.cnf, *.shファイルをコピーし、シェルスクリプトchmod コマンドで実行可能にします。

cp [ダウンロードしたディレクトリ]/azure-iot-sdk-c/tools/CACertificates/*.cnf .
cp [ダウンロードしたディレクトリ]/azure-iot-sdk-c/tools/CACertificates/*.sh .
chmod 700 certGen.sh
3. ルート証明書を作成します
./certGen.sh create_root_and_intermediate

たくさん新しいディレクトリやファイルが作成されていますが、ここから利用していくのは certs/ ディレクトリと private/ ディレクトリにあるファイルです。

4. IoT Centralへルート証明書を登録します

(1) IoT ポータル画面のメニューで"管理→デバイス接続"をクリックします

(2) 管理画面の資格情報エリアで"証明書(X.509)"タブを選択し、フォルダーアイコンのボタンをクリックします

f:id:akubicharm:20190508121215p:plain:w600

(3) ファイル選択ダイアログでルート証明書のファイル certs/azure-iot-test-only.root.ca.cert.pem を選択します

(4) 証明書の確認のために、歯車のボタンをクリックします

f:id:akubicharm:20190508131314p:plain:w600

(5) 証明書の確認ダイアログでリロード(丸い矢印)ボタンをクリックして、確認コードを生成します

f:id:akubicharm:20190508132612p:plain:w600

(6) コピーボタンをクリックして、確認コードをコピーします

f:id:akubicharm:20190508132730p:plain:w600

(7) 中間証明書を作成します

./certGen.sh create_verification_certificate [コピーした確認コード]

(8) 証明書の確認ダイアログに戻って"確認"ボタンをクリックし、ファイル選択ダイアログでcerts/verification-code.cert.pem を選択します

f:id:akubicharm:20190508132922p:plain:w600

(9) 証明書の確認ダイアログの上部に「確認済み」と表示されたことを確認して "Close" ボタンをクリックします

f:id:akubicharm:20190508132955p:plain:w600

バイス登録の準備

以降では、IoT Central用のサンプルプログラム(Python)を利用しますので、IoT Central 用の Python ライブラリが必要です。

1. デバイス用の証明書を作成します
./certGen.sh create_device_certificate mydevice
cd ./certs && cat new-device.cert.pem azure-iot-test-only.intermediate.cert.pem azure-iot-test-only.root.ca.cert.pem > new-device-full-chain.cert.pem

以下のファイルが新たに作成されています。

  • certs/new-device-full-chain.cert.pem
  • private/new-device.key.pem

スクリプト内に証明書ファイルのプレフィックスが固定で new-device と指定されていますので、ファイル名を可変にしたい場合はスクリプトを書き換えてください。

2. 証明書をデバイスにコピーします

次の2つのファイルをデバイス/usr/local/share/ca-certificates ディレクトリにコピーします。

  • certs/new-device-full-chain.cert.pem
  • private/new-device.key.pem
3. デバイスへのパッケージのインストール(Ubuntuの場合)
sudo apt -y update
sudo apt -y install python-pip
4. IoT Central の python ライブラリをインストールします
pip install iotc
5. クライアントプログラムをダウンロードします

github で公開されているサンプルプログラムをダウンロードします。

wget https://raw.githubusercontent.com/Azure/iot-central-firmware/master/RaspberryPi/app.py
6. X.509 認証ができるようにプログラムを編集します

編集前

    8 deviceId = "DEVICE_ID"
    9 scopeId = "SCOPE_ID"
   10 deviceKey = "PRIMARY/SECONDARY device KEY"
   11
   12 iotc = iotc.Device(scopeId, deviceKey, deviceId, IOTConnectType.IOTC_CONNECT_SYMM_KEY)
  • deviceId : IoT Central に登録される時に利用されるデバイスID

  • scopeId : Device Provisioning Service の識別ID。IoT Central のポータルのメニューで"管理→デバイス接続"をクリックして確認できます。 f:id:akubicharm:20190508135555p:plain

  • deviceKey : デバイスに接続するためのキー情報。ここでは、X.509認証に利用する keyfile と certfile のファイルのパスを指定するように変更します。

編集後

     8 deviceId = "dev01"
     9 scopeId = "0ne00057EA0"
    10 deviceKey = {
    11      "keyfile": "/usr/local/share/ca-certificates/private/new-device.key.pem",
    12     "certfile": "/usr/local/share/ca-certificates/certs/new-device-full-chain.cert.pem"
    13 }
    14 
    15 iotc = iotc.Device(scopeId, deviceKey, deviceId, IOTConnectType.IOTC_CONNECT_X509_CERT)

バイスからAzure IoT Centralへの接続

バイスをIoT Cenrtralに登録する方法は2つあります。

  • IoT Centralのポータルで事前登録
  • バイスがアクセスした時に自動登録

方法1: IoT Cenrtralのポータルで事前登録

1. デバイスエクスプローラーでデバイスを登録します

(1) IoT Centralのポータルの左Paneのメニューで "デバイスエクスプローラー" をクリックします

(2) エクスプローラーのテンプレート一覧で "Raspberr Pi (1.0.0)" をクリックします

(3) 右Pane上部の "+" プルダウンメニューの "実際" をクリックします

f:id:akubicharm:20190508140325p:plain

(4)新しいデバイスの作成画面でパラメータを入力し、"作成" をクリックします

f:id:akubicharm:20190508140453p:plain

2. サンプルプログラムを実行します
python app.py

以下のようなログが出力されれば接続成功です。

(1557297237.393921, '- iotc :: connect :: ')
(1557297239.495437, u'- iotc :: _loopAssign :: https://global.azure-devices-provisioning.net/0ne00058A7C/registrations/dev02/operations/4.99da589eb420cb29.8b56c569-372e-4507-ac92-3aba25128ddf?api-version=2018-11-01')
(1557297240.164666, u'- iotc :: _mqttConnect :: iotc-d1c9a56c-8bb6-4db4-9ff5-99c16448cb13.azure-devices.net')
(1557297240.166233, ' - iotc :: _mqttconnect :: created mqtt client. connecting..')
(1557297241.019479, 'mqtt-log : Sending CONNECT (u1, p0, wr0, wq0, wf0, c1, k120) client_id=dev02')
(1557297241.35323, 'mqtt-log : Received CONNACK (0, 0)')
(1557297241.353464, '- iotc :: _onConnect :: rc = 0')
(1557297241.353711, ' - iotc :: _mqttconnect :: on_connect must be fired. Connected ? True')

>>> 中 略  <<<
(1557297242.355496, "mqtt-log : Sending PUBLISH (d0, q0, r0, m6), '$iothub/twin/GET/?$rid=0', ... (1 bytes)")
(1557297242.355664, '- iotc :: MAKE_CALLBACK :: ConnectionStatus')
- [onconnect] => status:0
(1557297242.355846, '- iotc :: _onPublish :: None')
(1557297242.355868, '- iotc :: MAKE_CALLBACK :: MessageSent')
    - [onmessagesent] =>  
(1557297242.53629, u"mqtt-log : Received PUBLISH (d0, q0, r0, m0), '$iothub/twin/res/200/?$rid=0', ...  (276 bytes)")
(1557297242.536373, '- iotc :: _onMessage :: topic($iothub/twin/res/200/?$rid=0) payload({\r\n  "desired": {\r\n    "setCurrent": {\r\n      "value": 0\r\n    },\r\n    "setVoltage": {\r\n      "value": 0\r\n    },\r\n    "fanSpeed": {\r\n      "value": 0\r\n    },\r\n    "activateIR": {\r\n      "value": false\r\n    },\r\n    "$version": 1\r\n  },\r\n  "reported": {\r\n    "$version": 1\r\n  }\r\n})')

方法2: デバイスがアクセスした時に自動登録

1. サンプルプログラムを実行します
python app.py

以下のようなログが出力されて、サンプルプログラムが終了します。

(1557297143.836877, '- iotc :: connect :: ')
(1557297145.821161, u'- iotc :: _loopAssign :: https://global.azure-devices-provisioning.net/0ne00058A7C/registrations/dev02/operations/4.99da589eb420cb29.60660343-17b9-44c0-b940-baba1c034dbb?api-version=2018-11-01')
(1557297149.346818, u'- iotc :: _loopAssign :: https://global.azure-devices-provisioning.net/0ne00058A7C/registrations/dev02/operations/4.99da589eb420cb29.60660343-17b9-44c0-b940-baba1c034dbb?api-version=2018-11-01')
(1557297149.856327, "ERROR : (_mqttConnect) DPS L => {u'status': u'failed', u'registrationState': {u'status': u'failed', u'registrationId': u'dev02', u'lastUpdatedDateTimeUtc': u'2019-05-08T06:32:26.1041395Z', u'errorMessage': u'Custom allocation failed with status code: 401', u'createdDateTimeUtc': u'2019-05-08T06:32:25.9595725Z', u'errorCode': 400209, u'etag': u'IjAwMDA2OTFmLTAwMDAtMDEwMC0wMDAwLTVjZDI3N2ZhMDAwMCI='}, u'operationId': u'4.99da589eb420cb29.60660343-17b9-44c0-b940-baba1c034dbb'}")
2. IoT Centralのポータルでデバイスを確認します

(1) IoT Centralのポータルの左Paneで "デバイスエクスプローラー" をクリックします

(2) エクスプローラで "関連付けが解除されているデバイス" をクリックします

(3) デバイスチェックボックスをチェックして、右上の "関連付け" ボタンをクリックします

f:id:akubicharm:20190508144508p:plain

(4) デバイスを関連づけるダイアログでテンプレートを選択し、"関連付け" をクリックします f:id:akubicharm:20190508144618p:plain

3. 再度、サンプルプログラムを実行します
python app.py

参考