node.js - 无法让模块通信与 Node.JS 和 Azure IOT Edge 一起使用
问题描述
我正在尝试将一个设备部署到我的 Edge 设备,该设备使用 Node.js 模拟临时数据。我已经完成了我的证书并将其添加到我的 Node.Js 模块并导入了我得到的证书
无法连接:mqtt.js 在第一次连接时返回失败(未授权):证书链中的自签名证书错误
在模块的日志中。这就是我在 config.toml 中的内容。我尝试使用主机名得到了与使用 IP 地址相同的结果。(想删除 DNS 作为一个问题)
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;
// Uncomment one of these transports and then change it in fromConnectionString to test other transports
// 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) Obtain the connection string for your downstream device and to it
// append this string GatewayHostName=<edge device hostname>;
// 2) The Azure IoT Edge device hostname is the hostname set in the config.yaml of the Azure IoT Edge device
// to which this sample will connect to.
//
// The resulting string should look like the following
// "HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>;GatewayHostName=<edge device hostname>"
var deviceConnectionString = "HostName=*removed*-devices.net;DeviceId=Virtual_Humidity_Simulator;SharedAccessKey=*removed*;GatewayHostName=10.90.27.150" //process.env.DEVICE_CONNECTION_STRING;
// Path to the Edge "owner" root CA certificate
var edge_ca_cert_path = "./azure-iot-test-only.root.ca.cert.pem";
// fromConnectionString must specify a transport constructor, coming from any transport package.
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);
// When using MQTT the following line is a no-op.
client.complete(msg, printResultFor('completed'));
// The AMQP and HTTP transports also have the notion of completing, rejecting or abandoning the message.
// When completing a message, the service that sent the C2D message is notified that the message has been processed.
// When rejecting a message, the service that sent the C2D message is notified that the message won't be processed by the device. the method to use is client.reject(msg, callback).
// When abandoning the message, IoT Hub will immediately try to resend it. The method to use is client.abandon(msg, callback).
// MQTT is simpler: it accepts the message by default, and doesn't support rejecting or abandoning a message.
});
// Create a message and send it to the IoT Hub every two seconds
var sendInterval = setInterval(function () {
var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
var temperature = 20 + (Math.random() * 10); // range: [20, 30]
var humidity = 60 + (Math.random() * 20); // range: [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);
});
}
};
// Provide the Azure IoT device client via setOptions with the X509
// Edge root CA certificate that was used to setup the Edge runtime
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);
}
});
// Helper function to print results in the console
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);
};
}
我尝试按照此处的步骤操作: https ://docs.microsoft.com/en-us/azure/iot-edge/how-to-create-test-certificates?view=iotedge-2020-11#create-iot-边缘设备 CA 证书
我也尝试了这里的步骤: https ://docs.microsoft.com/en-us/azure/iot-edge/how-to-create-test-certificates?view=iotedge-2020-11
但我无法让它工作。谁能告诉我我做错了什么或有更好的方向给我?
解决方案
证书,是将所有者身份与他的公钥绑定的文件。该债券由称为证书颁发机构 (CA) 的可靠第三方签署和确认。
设备 CA 证书是一种自签名证书,仅适用于开发和测试场景,不适用于生产。
如果您使用的是自签名证书,则意味着它不安全,这就是您收到此错误的原因。因此,您可以通过在请求中设置以下内容来解决它。
rejectUnauthorized: false
但是请记住,如果您打开未经授权的证书,您将根本不会受到保护,并且会因未验证身份而受到 MITM 攻击。
另一种更安全的方法是在 http 请求请求中指定您期望的 CA,如下所示:
ca: [fs.readFileSync([certificate path], {encoding: 'utf-8'})]
从Node 版本 7.3.0开始,NODE_EXTRA_CA_CERTS
引入环境变量以传入 CA 证书文件。这允许使用文件中的额外证书来扩展“根”CA。
查看以下文档以获取更多信息:
推荐阅读
- c# - VB.NET 中是否有等效的“动态”类型或其他方式来实现相同的行为?
- elasticsearch - 我可以根据来自另一个查询的数据将计算布尔列添加到 Elasticsearch Kibana 查询吗?
- office-js - 使用 office js 将自定义图标添加到收件箱摘要
- windows - 如何修复:“Git”不是 CMD 的识别命令,但 git comman 在 GIT CMD CLI 中有效?
- optimization - 给定一些约束,最小化两个列表元素的峰值差异
- javascript - 用数组javascript查找最长的字谜
- r - 从 CSV 文件在 R 中创建 SQLite DB:为什么 DB 文件为 0KB 且不包含表?
- javascript - 仅在单击按钮时才反应更新状态,而不是在输入中写入内容时更新状态
- java - 重新排列最后N - Java
- html - 在纯 CSS 中仅缩放图像的一部分