升级IoT Edge runtime 1.3.0后模块向edgeHub发消息报400错误
问题描述
观察到的行为:
自定义IoT Edge模块向edge hub发送消息失败,返回 400 "missing request body" 错误。
IoT Edge守护进程输出日志如下:
Jul 13 16:43:34 kalki-VirtualBox aziot-edged[8415]: 2022-07-13T11:13:34Z [INFO] - <-- POST /modules/KalkiioEdgeIoTModule/genid/637922543947991885/sign?api-version=2018-06-28 {"content-type": "application/json; charset=utf-8", "host": "/var/run/iotedge/workload.sock:0", "content-length": "189"} Jul 13 16:43:34 kalki-VirtualBox aziot-edged[8415]: 2022-07-13T11:13:34Z [INFO] - --> 400 {"content-type": "application/json"}
自定义模块输出日志如下:
executing HTTP request fails, status=400, response_buffer={"message":"missing request body"}
- 版本相关表现:IoT Edge runtime 1.2.10及更早版本中,该自定义模块可正常向edge hub发送消息;故障出现在安装1.3.0版本runtime的全新设备上,部署配置及其他环境设置均未修改
- 已尝试排查操作:参考1.3.0版本发布公告的注意事项,为edgeHub模块添加环境变量
SslProtocols,取值为tls1.0, tls1.1, tls1.2,问题未解决 - 模块基础信息:基于Azure IoT Device SDK (C)开发
- 核心疑问:是否需要对自定义模块做特定调整,才能兼容最新版本的IoT Edge runtime?
解答
这个故障是1.3.0版本IoT Edge对workload API签名接口的校验逻辑收紧导致的,和TLS协议配置无关,具体修复方案如下:
- 优先升级模块依赖的Azure IoT C Device SDK版本
1.3.0版本的aziot-edged修正了旧版本对/sign接口请求体的宽松校验逻辑,要求请求必须携带格式正确的JSON参数体。v1.3.9之前的Azure IoT C SDK存在调用签名接口时的格式bug:会对请求体做多余的字符串转义、或者缺失必填字段,导致服务端无法正常解析请求体,返回missing request body错误。
将模块依赖的Azure IoT C Device SDK升级到v1.3.9及以上稳定版本,重新编译部署模块即可直接解决问题,不需要修改业务代码。 - 临时兼容方案(仅作过渡使用)
如果暂时无法升级SDK版本,可以在edgeDaemon模块配置中添加环境变量IOTEDGE_WORKLOADAPI_SIGN_LEGACY_BEHAVIOR=true,重启aziot-edged服务后,runtime会兼容旧SDK的不规范请求格式。注意该兼容开关会在后续大版本更新中移除,不建议长期使用。 - 特殊场景排查
如果模块中没有使用官方SDK的默认签名逻辑,而是自行实现了调用workload Unix套接字的HTTP请求,需要检查请求体是否符合接口规范:POST/sign接口必须携带标准JSON格式请求体,包含keyId、algo、data三个必填字段,不要对JSON内容做额外的字符串转义,同时保证Content-Length请求头的值和实际请求体长度完全一致。
补充说明:之前尝试配置的
SslProtocols环境变量,用于解决1.3.0版本默认禁用TLS1.0/1.1导致的旧设备TLS握手失败问题,和本次400请求格式错误的场景不匹配,因此没有效果。
内容的提问来源于stack exchange,提问作者sakuraku
相关产品推荐
相关产品推荐

