MQTT ゲートウェイを介してデバイスを IoT Platform に接続する際、カスタム証明書を使用してアイデンティティを検証し、証明書の共通名 (CN) を使用して登録できます。このトピックでは、Alibaba Cloud Function Compute (FC) を使用したサードパーティ検証によって、デバイスを IoT Platform に接続する方法を説明します。
Important notes
The steps in this topic are performed as a regular user. If an operation requires administrative permissions, prefix the command with sudo.
前提条件
専用の Enterprise Edition インスタンスを購入済みであること。このトピックでは、中国 (上海) リージョンにあるインスタンスを例として使用します。詳細については、「Enterprise Edition インスタンスの購入」をご参照ください。
背景情報
IoT Platform は、デバイスの接続と通信を可能にする MQTT ゲートウェイ機能を提供します。FC を用いたサードパーティ検証、カスタム証明書、Online Certificate Status Protocol (OCSP)、認証用のカスタム通信トピックなどの機能を使用して、さまざまなビジネスシナリオをサポートできます。
MQTT ゲートウェイを介したデバイス認証と通信の詳細については、「MQTT ゲートウェイの概要」をご参照ください。
事前準備
このトピックでは、開発環境として Ubuntu 22.04 を使用します。
ステップ1:カスタム証明書の生成
-
Ubuntu オペレーティングシステムにログインします。
-
次のコマンドを実行して、デバイス側とサーバー側の両方のルート証明書
root-ca.crtを生成します。openssl req \ -new \ -newkey rsa:2048 \ -days 365 \ -nodes \ -x509 \ -subj "/C=CN/O=Aliyun IOT/CN=IoT CA" \ -keyout root-ca.key \ -out root-ca.crt -
root-ca.crtルート証明書に基づいて、カスタムのサーバー側証明書を生成します。-
次のコマンドを実行して、サーバー側のキーファイル
server.keyを生成します。openssl genrsa -out server.key 2048 -
touch openssl.cnfコマンドを実行して、openssl.cnfという名前のファイルを作成します。 -
vi openssl.cnfコマンドを実行し、ファイルに以下の内容を追加した後、Esc キーを押して:wqと入力し、保存して終了します。[policy_match] countryName = cn stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [req] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_req prompt = no [req_distinguished_name] commonName = Server [req_ext] subjectAltName = @alt_names [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = *.mqtt.iothub.aliyuncs.com DNS.2 = *.igw.iothub.aliyuncs.com -
次のコマンドを実行して、サーバー側のリクエストファイル
server.csrを生成します。openssl req -new -key server.key -config openssl.cnf -out server.csr -
次のコマンドを実行して、サーバー側の証明書ファイル
server.crtを生成します。openssl x509 -req -days 365 -sha256 -in server.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out server.crt -extensions v3_req -extfile openssl.cnf -
次のコマンドを実行して、サーバー側証明書を検証します。
openssl verify -CAfile root-ca.crt server.crt
-
-
root-ca.crtルート証明書に基づいて、カスタムのデバイス側証明書を生成します。-
次のコマンドを実行して、デバイス側のキーファイル
client.keyを生成します。openssl genrsa -out client.key 2048 -
次のコマンドを実行して、デバイス側の証明書リクエストファイル
client.csrを生成します。CN をClient_123に設定します。openssl req -new -key client.key -out client.csr -subj "/CN=Client_123" -
次のコマンドを実行して、デバイス側の証明書ファイル
client.crtを生成します。openssl x509 -req -days 365 -sha256 -in client.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out client.crt -
次のコマンドを実行して、デバイス側証明書を検証します。
openssl verify -CAfile root-ca.crt client.crt
-
ステップ2:認証用のFC関数の作成
-
上部のメニューバーで、[中国 (上海)] リージョンを選択します。 [Services] ページで、[Create Service] をクリックします。
-
[Create Service] パネルで、[Service Name] に IoT_Service などを入力し、[OK] をクリックします。
-
[Functions] ページで、[Create Function] をクリックします。
-
[Create Function] ページで、次のパラメーターを設定し、[Create] をクリックします。
作成方法として [Create with Built-in Runtime] を選択します。 関数名には
three_party_authを入力します。 リクエストハンドラータイプには、[Event Handler] を選択します。 ランタイムには、[Python 3.9] を選択します。 -
[関数の詳細] ページで、サンプルコードを次のコードに置き換え、[コードのデプロイ] をクリックします。
認証関数は、デバイス証明書の CN を deviceName として返します。
# -*- coding: utf-8 -*- import logging import json import time import enum import random import string class Request: def __init__(self, json_str): self.clientId = None self.username = None self.password = None self.certificateCommonName = None for key, value in json.loads(json_str).items(): setattr(self, key, value) class Response: def __init__(self): self.deviceName = None self.result = 'true' self.message = 'success' def handler(self, request): # デバイス証明書の CN を deviceName として返します。 self.deviceName = request.certificateCommonName return json.dumps(self.__dict__) def handler(event, context): request = Request(event) return Response().handler(request)
ステップ3:ゲートウェイの作成
-
[インスタンス概要] ページで、対象の専用 Enterprise Edition インスタンスをクリックします。
-
左側のナビゲーションペインで、[デバイス管理] > [ゲートウェイ] を選択し、[ゲートウェイの追加] をクリックします。
-
次のパラメーターを設定し、[OK] をクリックします。
[サーバー証明書] には、
server.crtの内容を使用します。[サーバー証明書のプライベートキー] には、server.keyの内容を使用します。[デバイスルート証明書] には、root-ca.crtの内容を使用します。パラメーターの詳細については、「ゲートウェイの追加」をご参照ください。[プロトコル] には [MQTT] を選択します。[カスタムポート] には
1883を入力します。[認証タイプ] には [サードパーティ認証] を選択します。[データパススルーを有効にする] には [いいえ] を選択します。[デバイスX.509証明書認証を有効にする] には [いいえ] を選択します。[OCSPを有効にする] には [無効] を選択します。[デバイス認証FCサービス] にはIoT_Serviceを選択します。[デバイス認証FC関数] にはthree_party_authを選択します。[認可] にはAliyunIOTAccessingFCRoleを選択します。 -
ゲートウェイリストで、[ゲートウェイURL] をコピーして保存します。
ステップ4:デバイス側プログラムの開発
-
Ubuntu オペレーティングシステムに戻ります。
-
次のコマンドを実行して、必要なライブラリをインストールします。
sudo apt-get install build-essential gcc make cmake cmake-gui cmake-curses-gui sudo apt-get install libssl-dev -
次のコマンドを実行して、オープンソースの Paho MQTT ライブラリをインストールします。
git clone https://github.com/eclipse/paho.mqtt.c.git mkdir build && cd build cmake ../paho.mqtt.c -DPAHO_WITH_SSL=TRUE -DCMAKE_INSTALL_PREFIX="/usr/lib" make -j sudo make install && cd .. -
touch aiot_mqtt_demo.cコマンドを実行して、aiot_mqtt_demo.cという名前のデバイスシミュレーターファイルを作成します。 -
vi aiot_mqtt_demo.cコマンドを実行してファイルを開き、次の内容を追加します。#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "MQTTClient.h" int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) { printf("message recv < topic [%s], payload [%s]\n", topicName, (char *)message->payload); MQTTClient_freeMessage(&message); MQTTClient_free(topicName); return 1; } int main(int argc, char* argv[]) { MQTTClient client; MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer; int rc; /* MQTTクライアントを作成します。 プレースホルダーの値を置き換えてください。 */ const char *host = "ssl://iot-0****.igw.iothub.aliyuncs.com:1883"; const char *client_id = "12345"; MQTTClient_create(&client, host, client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL); MQTTClient_setCallbacks(client, NULL, NULL, msgarrvd, NULL); /* 接続パラメーター (証明書、ユーザー名、パスワード) を設定します。 プレースホルダーの値を置き換えてください。 */ ssl_opts.trustStore = "root-ca.crt"; ssl_opts.privateKey = "client.key"; ssl_opts.keyStore = "client.crt"; conn_opts.ssl = &ssl_opts; conn_opts.username = "sdk_test01"; conn_opts.password = "hello123"; /* MQTT接続を確立します。 */ if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) { printf("Failed to connect, return code %d\n", rc); exit(EXIT_FAILURE); } printf("connect success username %s, password %s\n", conn_opts.username, conn_opts.password); /* トピックをサブスクライブします。 */ MQTTClient_subscribe(client, "/user/aiot_mqtt_demo_downraw", 1); /* ループ内でメッセージを生成して発行します。 */ MQTTClient_message pubmsg = MQTTClient_message_initializer; const char *topic = "/user/aiot_mqtt_demo_upraw"; pubmsg.payload = "Hello Service!"; pubmsg.payloadlen = (int)strlen(pubmsg.payload); pubmsg.qos = 1; for(int i = 0; i < 100; i++) { MQTTClient_publishMessage(client, topic, &pubmsg, NULL); printf("message send > topic [%s], payload [%s]\n", topic, (char *)pubmsg.payload); sleep(10); } /* クライアントを切断して破棄します。 */ MQTTClient_disconnect(client, 10000); MQTTClient_destroy(&client); return rc; } -
コード内で、実際のデバイス情報に基づいてパラメーターを変更し、Esc キーを押して
:wqと入力してaiot_mqtt_demo.cファイルを保存します。パラメーター
説明
host
デバイス接続用の MQTT ゲートウェイエンドポイント。形式は
ssl://${Gateway-Endpoint}:${Port-Number}です。${Gateway-Endpoint}と${Port-Number}は、ステップ3で取得した [ゲートウェイURL] のドメイン名とカスタムポートです。client_id
(オプション) クライアント ID。ID は最大 64 文字のカスタム値である必要があります。クライアントを識別しやすくするために、デバイスの MAC アドレスまたはシリアル番号 (SN) を使用します。
ssl_opts.trustStore
デバイス側のルート証明書ファイル
root-ca.crtへのパス。ssl_opts.privateKey
デバイス側のキーファイル
client.keyへのパス。ssl_opts.keyStore
デバイス側の証明書ファイル
client.crtへのパス。conn_opts.username
MQTT 接続のユーザー名。
ユーザー名は 4~32 文字で、文字、数字、ハイフン (-)、アンダースコア (_)、アットマーク (@)、ピリオド (.)、コロン (:) を使用できます。ユーザー名はプロダクト内で一意である必要があります。
conn_opts.password
MQTT 接続のパスワード。
パスワードは 1~32 文字で、文字、数字、ハイフン (-)、アンダースコア (_)、アットマーク (@)、ピリオド (.)、コロン (:) を使用できます。
上記の手順を完了すると、ディレクトリには次のファイルが含まれます。
build
paho.mqtt.c
aiot_mqtt_demo.c
client.crt
client.csr
client.key
openssl.cnf
root-ca.crt
root-ca.key
server.crt
server.csr
server.key
ステップ5:コンパイルと実行
-
次のコマンドを実行して、デバイスプログラムファイル
aiot_mqtt_demo.cをコンパイルして実行します。gcc -o aiot_mqtt_demo aiot_mqtt_demo.c -lpaho-mqtt3cs ./aiot_mqtt_demoプログラムが正常に実行されると、FC 認証関数によって返された deviceName (
Client_123) が、IoT Platform のデバイスの DeviceName として使用されます。IoT Platform コンソールのインスタンスの [デバイス管理] > [デバイス] ページに、Client_123という名前のデバイスが自動的に作成されます。デバイスのステータスは [オンライン] です。 -
(オプション) デバイスから報告されたデータを表示するには、IoT Platform コンソールに移動し、インスタンスの [監視と運用] > [デバイスログ] ページを表示します。[監視と運用] > [デバイスログ] に移動し、[クラウドランタイムログ] タブをクリックします。[プロダクト] ドロップダウンリストから、ゲートウェイプロダクトを選択します。[操作] 列で、[表示] をクリックします。[詳細の表示] ダイアログボックスで、トピックが
/user/aiot_mqtt_demo_uprawで、内容がHello Service!であることを確認します。ステータスが 200 であれば、メッセージが正常に報告されたことを示します。