你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
在本操作指南文章中,你将在不使用 Azure IoT DPS 设备 SDK 的情况下,通过 HTTPS 使用 X.509 证书来预配设备。 大多数语言提供用于发送 HTTP 请求的库,但在本文中,你将使用 cURL 命令行工具通过 HTTPS 发送和接收请求,而不是专注于特定的语言。
可以在 Linux 或 Windows 计算机上执行本文中的步骤。 如果在适用于 Linux 的 Windows 子系统 (WSL) 上运行或者在 Linux 计算机上运行,可以在本地系统上的 Bash 提示符下输入所有命令。 如果在 Windows 上运行,请在本地系统上的 GitBash 提示符下输入所有命令。
本文提供了多个路径,具体取决于你选择使用的注册条目和 X.509 证书的类型。 安装必备组件后,请务必先阅读概述,然后继续。
Prerequisites
如果没有 Azure 订阅,请在开始之前创建一个免费帐户。
完成快速入门中的步骤 :使用 Azure 门户设置 IoT 中心设备预配服务。
确保已在计算机上安装 Python 3.7 或更高版本。 可以通过运行
python --version或python3 --version来检查 Python 版本。如果在 Windows 中运行,请安装最新版本的 Git。 确保将 Git 添加到可供命令窗口访问的环境变量。 请参阅软件自由保护组织提供的 Git 客户端工具,了解要安装的最新版
git工具,其中包括 Git Bash,这是一个命令行应用,可以用来与本地 Git 存储库交互。 在 Windows 上,在 Git Bash 提示符中输入本地系统上的所有命令。Azure CLI。 在本文中,有两个选项可用于运行 Azure CLI 命令:
- 使用 Azure Cloud Shell,这是一个交互式 Shell,可在浏览器中运行 CLI 命令。 建议使用此选项,因为无需安装任何插件。 如果是首次使用 Cloud Shell,请登录到 Azure 门户。 按照 Cloud Shell 快速入门中的步骤启动 Cloud Shell 并选择 Bash 环境。
- (可选)在本地计算机上运行 Azure CLI。 如果已安装 Azure CLI,请运行
az upgrade以将 CLI 和扩展升级到当前版本。 要安装 Azure CLI,请参阅安装 Azure CLI。
如果在 Linux 或 WSL 环境中运行,请打开 Bash 提示符以在本地运行命令。 如果在 Windows 环境中运行,请打开 GitBash 提示符。
概述
本文介绍了三种方案,你执行的初始步骤是不同的。 如果要:
完成所选方案的步骤后,可以继续 注册设备 并 发送遥测消息。
创建设备证书
在本文中,你将使用 X.509 证书通过单独注册或注册组向 DPS 进行身份验证。
如果使用的是单独注册,则可以使用自签名 X.509 证书或由设备证书加上一个或多个签名证书组成的证书链。 如果使用的是注册组,则必须使用证书链。
重要说明
对于 X.509 注册身份验证,设备证书的使用者公用名称 (CN) 将用作设备的注册 ID。 注册 ID 是一个不区分大小写的字符串,包含字母数字字符和以下特殊字符:'-'、'.'、'_'、':'。 最后一个字符必须是字母数字或短划线 ('-')。 DPS 支持最大长度为 128 个字符的注册 ID;但是,X.509 证书的使用者公用名称限制为 64 个字符。 如果在以下步骤中更改设备证书的使用者公用名称,请确保名称符合此格式。
使用自签名证书
若要创建用于单独注册的自签名证书,请导航到要在其中创建证书的目录并执行以下步骤:
运行以下命令:
winpty openssl req -outform PEM -x509 -sha256 -newkey rsa:4096 -keyout device-key.pem -out device-cert.pem -days 30 -extensions usr_cert -addext extendedKeyUsage=clientAuth -subj "//CN=my-x509-device"重要说明
仅当需要在 Windows 平台上使用 Git 来转义字符串时,才需要为使用者名称 (
//CN=my-x509-device) 提供额外的西文斜杠。当系统要求“输入 PEM 通行短语:”时,请使用通行短语
1234。如果系统要求“验证 - 输入 PEM 通行短语:”,请再次使用通行短语
1234。现在应在运行
openssl命令的目录中生成公钥证书文件 (device-cert.pem) 和私钥文件 (device-key.pem)。证书文件的使用者公用名称 (CN) 设置为
my-x509-device。私钥文件受通行短语的保护:
1234。证书文件采用 Base64 编码。 若要查看证书文件的使用者公用名称 (CN) 和其他属性,请输入以下命令:
winpty openssl x509 -in device-cert.pem -text -nooutCertificate: Data: Version: 3 (0x2) Serial Number: 77:3e:1d:e4:7e:c8:40:14:08:c6:09:75:50:9c:1a:35:6e:19:52:e2 Signature Algorithm: sha256WithRSAEncryption Issuer: CN = my-x509-device Validity Not Before: May 5 21:41:42 2022 GMT Not After : Jun 4 21:41:42 2022 GMT Subject: CN = my-x509-device Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: 00:d2:94:37:d6:1b:f7:43:b4:21:c6:08:1a:d6:d7: e6:40:44:4e:4d:24:41:6c:3e:8c:b2:2c:b0:23:29: ... 23:6e:58:76:45:18:03:dc:2e:9d:3f:ac:a3:5c:1f: 9f:66:b0:05:d5:1c:fe:69:de:a9:09:13:28:c6:85: 0e:cd:53 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 63:C0:B5:93:BF:29:F8:57:F8:F9:26:44:70:6F:9B:A4:C7:E3:75:18 X509v3 Authority Key Identifier: keyid:63:C0:B5:93:BF:29:F8:57:F8:F9:26:44:70:6F:9B:A4:C7:E3:75:18 X509v3 Extended Key Usage: TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption 82:8a:98:f8:47:00:85:be:21:15:64:b9:22:b0:13:cc:9e:9a: ed:f5:93:b9:4b:57:0f:79:85:9d:89:47:69:95:65:5e:b3:b1: ... cc:b2:20:9a:b7:f2:5e:6b:81:a1:04:93:e9:2b:92:62:e0:1c: ac:d2:49:b9:36:d2:b0:21
使用证书链
如果使用的是注册组,则必须使用证书链进行身份验证。 对于单独注册,可以使用证书链或自签名证书。
若要创建证书链,请按照创建 X.509 证书链中的说明进行操作。 对于本文,你只需要一台设备,因此可以在为第一个设备创建私钥和证书链后停止。
完成后,应会得到以下文件:
| 证书 | 文件 | 说明 |
|---|---|---|
| 根 CA 证书。 | certs/azure-iot-test-only.root.ca.cert.pem | 将上传到 DPS 并验证。 |
| 中间 CA 证书 | certs/azure-iot-test-only.intermediate.cert.pem | 将用于在 DPS 中创建注册组。 |
| device-01 私钥 | private/device-01.key.pem | 由设备用于在向 DPS 进行身份验证期间验证设备证书的所有权。 |
| device-01 证书 | certs/device-01.cert.pem | 用于通过 DPS 创建单独注册条目。 |
| device-01 完整链证书 | certs/device-01-full-chain.cert.pem | 由设备提供,用于向 DPS 进行身份验证和注册。 |
使用单独注册
若要创建用于本文的单独注册,请使用 az iot dps enrollment create 命令。
以下命令使用指定的设备证书为 DPS 实例创建一个使用默认分配策略的单独注册条目。
az iot dps enrollment create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --attestation-type x509 --certificate-path {path to your certificate}
替换资源组和 DPS 实例的名称。
注册 ID 是设备的注册 ID,对于 X.509 注册,此 ID 必须与设备证书的使用者公用名称 (CN) 相匹配。
证书路径是设备证书的路径。
注意
如果使用 Cloud Shell 运行 Azure CLI 命令,则可以在运行命令之前使用上传按钮将证书文件上传到云驱动器。
使用注册组
若要创建用于本文的注册组,请使用 az iot dps enrollment-group create 命令。
以下命令使用中间 CA 证书为 DPS 实例创建一个使用默认分配策略的注册组条目:
az iot dps enrollment-group create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --certificate-path {path_to_your_certificate}
替换资源组和 DPS 实例的名称。
注册 ID 是一个不区分大小写的字符串,包含字母数字字符和以下特殊字符:
'-'、'.'、'_'、':'。 最后一个字符必须是字母数字或短划线 ('-')。 它可以是你选择用于注册组的任何名称。证书路径是中间证书的路径。 如果你已按照使用证书链中的说明进行操作,则文件名为 certs/azure-iot-test-only.intermediate.cert.pem。
注意
如果使用 Cloud Shell 运行 Azure CLI 命令,则可以在运行命令之前使用上传按钮将证书文件上传到云驱动器。
注意
如果需要,可以根据以前使用 DPS 上传和验证的签名证书创建注册组(请参阅下一部分)。 为此,请使用 --ca-name 指定证书名称,并在 --certificate-path 命令中省略 az iot dps enrollment-group create 参数。
上传并验证签名证书
如果将证书链用于单独注册或注册组,则必须将设备证书签名链中的至少一个证书上传到 DPS 并对其进行验证。
对于单个注册,此证书可以是设备证书链中的任何签名证书。
对于注册组,此证书可以是在注册组上设置的证书,也可以是其注册链中的任何证书(包括根 CA 证书)。
若要上传并验证证书,请使用 az iot dps certificate create 命令:
az iot dps certificate create -g {resource_group_name} --dps-name {dps_name} --certificate-name {friendly_name_for_your_certificate} --path {path_to_your_certificate} --verified true
替换资源组和 DPS 实例的名称。
证书路径是签名证书的路径。 对于本文,建议上传根 CA 证书。 如果你已按照使用证书链中的说明进行操作,则文件名为 certs/azure-iot-test-only.root.ca.cert.pem。
证书名称只能包含字母数字字符或以下特殊字符:
-._。 不允许包含空格。 例如“azure-iot-test-only-root”。
注意
如果使用 Cloud Shell 运行 Azure CLI 命令,则可以在运行命令之前使用上传按钮将证书文件上传到云驱动器。
注意
本部分的步骤会在上传时自动验证证书。 你还可以手动验证证书。 有关详细信息,请参阅中间或根 CA 的手动验证。
注册设备
调用注册设备 REST API 以通过 DPS 预配设备。
使用以下 curl 命令:
curl -L -i -X PUT --cert [path_to_your_device_cert] --key [path_to_your_device_private_key] -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31
其中:
-L告知 curl 遵循 HTTP 重定向。–i告知 curl 在输出中包含协议标头。 这些标头并非绝对必要,但它们可能很有用。-X PUT告知 curl 此命令是 HTTP PUT 命令。 对于此 API 调用是必需的。--cert [path_to_your_device_cert]告知 curl 在何处查找设备的 X.509 证书。 如果设备私钥受通行短语保护,你可以在证书路径后面添加一个冒号,然后再添加该通行短语,例如:--cert my-device.pem:1234。如果使用自签名证书,则设备证书文件包含单个 X.509 证书。 如果按照 “使用自签名证书”中的说明作,文件名为 device-cert.pem ,私钥传递短语为
1234,因此请使用--cert device-cert.pem:1234。如果使用证书链(例如,在通过注册组进行身份验证时),设备证书文件必须包含有效的证书链。 该证书链必须包括设备证书和任何签名证书,最高证书级别为已验证的证书。 如果你已按照使用证书链中的说明创建证书链,则文件路径为 certs/device-01-full-chain.cert.pem,因此请使用
--cert certs/device-01-full-chain.cert.pem。
--key [path_to_your_device_private_key]告知 curl 在何处查找设备的私钥。-H 'Content-Type: application/json'告知 DPS 我们正在发布 JSON 内容,其值必须是“application/json”-H 'Content-Encoding: utf-8'告知 DPS 我们对消息正文使用的编码。 请根据你的操作系统/客户端设置适当的值;但是,值通常是utf-8。-d '{"registrationId": "[registration_id]"}',–d参数是发布的消息的“数据”或正文。 它必须是 JSON,格式为 '{"registrationId":"[registration_id"}'。 对于 curl,需要将它括在单引号中;否则需要转义 JSON 中的双引号。 对于 X.509 注册,注册 ID 是设备证书的使用者公用名称 (CN)。最后,最后一个参数是要发布到的 URL。 对于“常规”(即非本地)DPS,将使用全局 DPS 终结点 global.azure-devices-provisioning.net:
https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31。 您必须将[dps_scope_id]和[registration_id]替换为相应的值。
例如:
如果你已按照使用自签名证书中的说明进行操作:
curl -L -i -X PUT --cert device-cert.pem:1234 --key device-key.pem -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"registrationId": "my-x509-device"}' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-x509-device/register?api-version=2021-06-01如果你已按照使用证书链中的说明进行操作:
curl -L -i -X PUT --cert certs/device-01-full-chain.cert.pem --key private/device-01.key.pem -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"registrationId": "device-01"}' https://global.azure-devices-provisioning.net/0ne00111111/registrations/device-01/register?api-version=2021-06-01
成功的调用提供类似于以下示例的响应:
HTTP/1.1 202 Accepted
Date: Sat, 27 Aug 2022 17:53:18 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Location: https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-x509-device/register
Retry-After: 3
x-ms-request-id: 05cdec07-c0c7-48f3-b3cd-30cfe27cbe57
Strict-Transport-Security: max-age=31536000; includeSubDomains
{"operationId":"5.506603669bd3e2bf.b3602f8f-76fe-4341-9214-bb6cfb891b8a","status":"assigning"}
响应包含操作 ID 和状态。 在本例中,状态设置为 assigning。 DPS 注册可能是一个长时间运行的操作,因此它以异步方式完成。 通常情况下,您会使用 操作状态查询 REST API 进行轮询,以确定设备是否已分配或出现故障。
DPS 的有效状态值为:
assigned:状态调用中的返回值指示设备分配到的 IoT 中心。assigning:操作仍在运行。disabled:DPS 中已禁用注册记录,因此无法分配设备。failed:分配失败。 在响应中的registrationState记录中返回errorCode和errorMessage,用于指示失败的原因。unassigned
若要调用“操作状态查找”API,请使用以下 curl 命令:
curl -L -i -X GET --cert [path_to_your_device_cert] --key [path_to_your_device_private_key] -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/operations/[operation_id]?api-version=2019-03-31
使用与 注册设备 请求中相同的 ID 范围、注册 ID 和证书和密钥。 使用“注册设备”响应中返回的操作 ID。
例如,以下命令针对创建自使用自签名证书的自签名证书。 (需要修改 ID 范围和操作 ID。)
curl -L -i -X GET --cert ./device-certPUT --cert device-cert.pem:1234 --key device-key.pem -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-x509-device/operations/5.506603669bd3e2bf.b3602f8f-76fe-4341-9214-bb6cfb891b8a?api-version=2021-06-01
以下输出显示了已成功分配的设备响应。 请注意 status 属性为 assigned,registrationState.assignedHub 属性设置为在其中预配了设备的 IoT 中心。
HTTP/1.1 200 OK
Date: Sat, 27 Aug 2022 18:10:49 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
x-ms-request-id: 8f211bc5-3ed8-4c8b-9a79-e003e756e9e4
Strict-Transport-Security: max-age=31536000; includeSubDomains
{
"operationId":"5.506603669bd3e2bf.b3602f8f-76fe-4341-9214-bb6cfb891b8a",
"status":"assigned",
"registrationState":{
"x509":{
},
"registrationId":"my-x509-device",
"createdDateTimeUtc":"2022-08-27T17:53:19.5143497Z",
"assignedHub":"MyExampleHub.azure-devices.net",
"deviceId":"my-x509-device",
"status":"assigned",
"substatus":"initialAssignment",
"lastUpdatedDateTimeUtc":"2022-08-27T17:53:19.7519141Z",
"etag":"IjEyMDA4NmYyLTAwMDAtMDMwMC0wMDAwLTYzMGE1YTBmMDAwMCI="
}
}
记下设备 ID 和分配的 IoT 中心。 在下一部分,你将使用它们来发送遥测消息。
发送遥测消息
调用 IoT 中心发送设备事件 REST API 将遥测数据发送到设备。
使用以下 curl 命令:
curl -L -i -X POST --cert [path_to_your_device_cert] --key [path_to_your_device_private_key] -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"temperature": 30}' https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13
其中:
-X POST告知 curl 此命令是 HTTP POST 命令。 对于此 API 调用是必需的。--cert [path_to_your_device_cert]告知 curl 在何处查找设备的 X.509 证书。 如果设备私钥受通行短语保护,你可以在证书路径后面添加一个冒号,然后再添加该通行短语,例如:--cert my-device.pem:1234。--key [path_to_your_device_private_key]告知 curl 在何处查找设备的私钥。-H 'Content-Type: application/json'告知 IoT 中心我们正在发布 JSON 内容,其值必须是“application/json”。-H 'Content-Encoding: utf-8'告知 IoT 中心我们对消息正文使用的编码。 请根据你的操作系统/客户端设置适当的值;但是,值通常是utf-8。-d '{"temperature": 30}',–d参数是发布的消息的“数据”或正文。 对于本文,我们将发布单个温度数据点。 内容类型指定为 application/json,因此对于此请求,正文为 JSON。 对于 curl,需要将它括在单引号中;否则需要转义 JSON 中的双引号。最后一个参数是要发布到的 URL。 对于“发送设备事件”API,该 URL 是:
https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13。请将
[assigned_iot_hub_name]替换为设备分配到的 IoT 中心的名称。请将
[device_id]替换为注册设备时分配的设备 ID。 对于通过注册组预配的设备,设备 ID 是注册 ID。 对于单独注册,可以选择性地指定一个与注册条目中的注册 ID 不同的设备 ID。
例如:
如果你已按照使用自签名证书中的说明进行操作:
curl -L -i -X POST --cert device-cert.pem:1234 --key device-key.pem -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"temperature": 30}' https://MyExampleHub.azure-devices.net/devices/my-x509-device/messages/events?api-version=2020-03-13如果你已按照使用证书链中的说明进行操作:
curl -L -i -X POST --cert certs/device-01-full-chain.cert.pem --key private/device-01.key.pem -H 'Content-Type: application/json' -H 'Content-Encoding: utf-8' -d '{"temperature": 30}' https://MyExampleHub.azure-devices.net/devices/my-x509-device/messages/events?api-version=2020-03-13
成功的调用具有类似于以下示例的响应:
HTTP/1.1 204 No Content
Content-Length: 0
Vary: Origin
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: aa58c075-20d9-4565-8058-de6dc8524f14
Date: Wed, 31 Aug 2022 18:34:44 GMT
后续步骤
若要详细了解如何使用 X.509 证书进行证明,请参阅 X.509 证书证明。
若要详细了解如何上传和验证 X.509 证书,请参阅 如何使用设备预配服务验证 X.509 CA 证书。