You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js模块与Azure IoT Edge通信报自签名证书链错误如何解决?

问题描述

我正尝试在Azure IoT Edge设备上部署使用Node.js开发的温度数据模拟设备,已按流程生成证书并添加到Node.js模块中,导入证书后模块日志出现如下报错:

Could not connect: mqtt.js returned Failure on first connection (Not authorized): self signed certificate in certificate chain error

我的config.toml配置如下,为排除DNS问题,我先后尝试使用主机名和IP地址配置,得到的报错完全一致:

hostname = "10.90.27.150"

trust_bundle_cert = "file:///home/edge/certificates/certs/azure-iot-test-only.root.ca.cert.pem"

[edge_ca]

cert = "file:///home/edge/certificates/certs/iot-edge-device-ca-10.90.27.150-full-chain.cert.pem"

pk = "file:///home/edge/certificates/private/iot-edge-device-ca-10.90.27.150.key.pem"

我使用的模块代码如下:

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

'use strict';

var fs = require('fs');
var Protocol = require('azure-iot-device-mqtt').Mqtt;
// 取消下方某一传输协议的注释,并在fromConnectionString中修改对应参数即可测试其他传输方式
// var Protocol = require('azure-iot-device-http').Http;
// var Protocol = require('azure-iot-device-amqp').Amqp;
var Client = require('azure-iot-device').Client;
var Message = require('azure-iot-device').Message;

// 1) 获取下游设备的连接字符串,并追加字符串GatewayHostName=<edge设备主机名>;
// 2) Azure IoT Edge设备主机名是部署本示例的Azure IoT Edge设备config.yaml中设置的主机名
//
// 最终生成的连接字符串格式如下:
//  "HostName=<iothub主机名>;DeviceId=<设备ID>;SharedAccessKey=<设备密钥>;GatewayHostName=<edge设备主机名>"
var deviceConnectionString = "HostName=*removed*-devices.net;DeviceId=Virtual_Humidity_Simulator;SharedAccessKey=*removed*;GatewayHostName=10.90.27.150" //process.env.DEVICE_CONNECTION_STRING;

// Edge "所有者"根CA证书路径
var edge_ca_cert_path = "./azure-iot-test-only.root.ca.cert.pem";

// fromConnectionString必须指定来自任意传输协议包的传输构造函数
var client = Client.fromConnectionString(deviceConnectionString, Protocol);

var connectCallback = function (err) {
  if (err) {
    console.error('Could not connect: ' + err.message);
  } else {
    console.log('Client connected');
    client.on('message', function (msg) {
      console.log('Id: ' + msg.messageId + ' Body: ' + msg.data);
      // 使用MQTT时下方代码无操作
      client.complete(msg, printResultFor('completed'));
      // AMQP和HTTP传输协议支持完成、拒绝或放弃消息
      // 完成消息时,发送C2D消息的服务会收到消息已处理的通知
      // 拒绝消息时,服务会收到消息不会被设备处理的通知,对应方法为client.reject(msg, callback)
      // 放弃消息时,IoT Hub会立即尝试重发该消息,对应方法为client.abandon(msg, callback)
      // MQTT逻辑更简单:默认接收消息,不支持拒绝或放弃消息
    });

    // 每2秒创建一条消息并发送到IoT Hub
    var sendInterval = setInterval(function () {
      var windSpeed = 10 + (Math.random() * 4); // 范围: [10, 14]
      var temperature = 20 + (Math.random() * 10); // 范围: [20, 30]
      var humidity = 60 + (Math.random() * 20); // 范围: [60, 80]
      var data = JSON.stringify({ deviceId: 'myFirstDownstreamDevice', windSpeed: windSpeed, temperature: temperature, humidity: humidity });
      var message = new Message(data);
      message.properties.add('temperatureAlert', (temperature > 28) ? 'true' : 'false');
      console.log('Sending message: ' + message.getData());
      client.sendEvent(message, printResultFor('send'));
    }, 2000);

    client.on('error', function (err) {
      console.error(err.message);
    });

    client.on('disconnect', function () {
      clearInterval(sendInterval);
      client.removeAllListeners();
      client.open(connectCallback);
    });
  }
};

// 通过setOptions方法为Azure IoT设备客户端提供用于设置Edge运行时的X509 Edge根CA证书
var options = {
  ca : fs.readFileSync(edge_ca_cert_path, 'utf-8'),
};

client.setOptions(options, function(err) {
  if (err) {
    console.log('SetOptions Error: ' + err);
  } else {
    client.open(connectCallback);
  }
});

// 控制台打印结果的辅助函数
function printResultFor(op) {
  return function printResult(err, res) {
    if (err) console.log(op + ' error: ' + err.toString());
    if (res) console.log(op + ' status: ' + res.constructor.name);
  };
}

我已尝试按照官方文档生成测试证书、创建设备CA证书的步骤操作,问题仍未解决,请问操作存在什么问题?有没有更清晰的指导方案?


故障排查与解决方案

问题根因

该自签名证书链报错核心是Node.js客户端未正确信任Edge设备的CA证书,或证书本身配置不符合要求,按以下步骤逐一排查即可解决:


排查步骤

  1. 证书路径与读取校验
  • 先在模块运行目录下执行ls ./azure-iot-test-only.root.ca.cert.pem,确认证书文件存在且有可读权限,不要用相对路径,改为证书的绝对路径,比如你主机上的/home/edge/certificates/certs/azure-iot-test-only.root.ca.cert.pem,避免模块工作目录变化导致读不到证书。
  • 读取证书内容校验合法性:执行openssl x509 -in 证书路径 -text -noout,确认证书的有效期、CN字段无异常,且是你生成的根CA证书。
  1. Edge设备CA证书配置校验
  • 你配置的iot-edge-device-ca-10.90.27.150-full-chain.cert.pem必须包含完整的证书链:设备CA证书 + 根CA证书,不要只放单独的设备CA证书。
  • 配置完config.toml后要重启IoT Edge服务:sudo systemctl restart iotedge,执行sudo iotedge check确认所有证书相关的检查项都是绿色通过状态,没有警告或报错。
  1. Node.js客户端额外配置
  • Node.js的TLS栈默认会拒绝不在系统信任库的自签名证书,你除了配置ca参数外,可以先在代码最开头加一行环境变量配置:process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; 测试是否是证书信任逻辑的问题(注意仅测试用,生产环境不要开启),如果加了之后能连通,就确定是证书信任的问题。
  • 如果你用的是Azure IoT Node.js SDK v1.18以上版本,需要额外配置MQTT的传输选项,将options修改为:
var options = {
  ca : fs.readFileSync(edge_ca_cert_path, 'utf-8'),
  mqtt: {
    rejectUnauthorized: true
  }
};
  1. 连接字符串与设备注册校验
  • 确认IoT Hub上注册的Virtual_Humidity_Simulator设备的父设备已经设置为你当前的IoT Edge设备,且设备是启用状态。
  • 确认连接字符串里的GatewayHostName的值,和你Edge设备config.toml里的hostname完全一致,你这里用的是IP就保持两边都是相同的IP。

验证步骤

所有配置修改完成后,先在主机上用MQTT客户端工具测试连接:

mosquitto_pub -h 10.90.27.150 -p 8883 --cafile /home/edge/certificates/certs/azure-iot-test-only.root.ca.cert.pem -u "你的IoT Hub名称.azure-devices.net/Virtual_Humidity_Simulator/?api-version=2021-04-12" -P "你的设备SAS密钥" -t "devices/Virtual_Humidity_Simulator/messages/events/" -m "test"

如果能成功发送消息,再重新打包Node.js模块部署即可。


内容的提问来源于stack exchange,提问作者Alovantous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 12:39:03