参考链接中的示例 - X509 注册组指南使用证书链
我正在尝试创建一个安静的服务(.net7 web api),它可以执行以下三件事:
上述所有步骤在我的本地主机(WSL - Ubuntu)实例上运行良好,我可以在其中与我的 DPS 实例通信并执行上述所有 3 个操作。
但是,当我尝试将服务部署到 azure 应用程序服务 (Linux) 实例时,步骤 1 和 2 工作正常,但步骤 #3 失败并出现以下错误 – “找不到 CA 证书”错误代码:401002。如下图:
这是我正在使用的代码片段,在 SDK 示例中被大量引用:
using ProvisioningTransportHandler transport = CertificateHelper.GetTransportHandler(Microsoft.Azure.Devices.Client.TransportType.Mqtt_WebSocket_Only);
var deviceClient = ProvisioningDeviceClient.Create(globalDPSEndpoint, idScope, security, transport);
DeviceRegistrationResult regResult = await deviceClient.RegisterAsync();
if (regResult.Status != ProvisioningRegistrationStatusType.Assigned)
{
return (false, $"Registration status did not assign a hub, so exiting...");
}
else
{
return (true, $"Successfully registered Device:{regResult.DeviceId} to Hub: {regResult.AssignedHub}.");
}
异常是从以下行生成的:
DeviceRegistrationResult regResult = await deviceClient.RegisterAsync();
经过多次谷歌搜索,我发现对于非 Windows 环境,SDK ProvisioningDeviceClient 类需要带有私钥的叶证书和完整的证书链来执行 TLS 握手来注册设备。因此,在通过这两项测试后,它开始从我的本地主机环境工作,但在部署到应用程序服务实例时仍然失败。
但是,如果我尝试使用此处提到的 REST api 注册设备,设备注册 REST API,
通过CURL命令并传递全链.pfx证书和密码,注册成功。它只是无法在应用程序服务 (linux) 环境内部的代码中工作。
我发现并尝试过的一些其他事情:
我想知道是否需要在应用程序服务实例中执行任何其他配置才能正确完成 TLS 握手,因为客户端无法找到 CA 证书来验证链中的叶证书。但同样的事情在本地机器上也可以正常工作。
非常感谢对此的任何帮助!
谢谢。
Azure IoT 设备预配服务 (DPS) 中的“找不到 CA 证书”错误表示证书存在问题以及导致此问题的环境中的一些差异。下面的代码使用 Azure IoT 中心和设备配置服务 (DPS) 在 IoT 场景中注册设备。将证书放在 wwwroot 下并将路径更改为 wwwroot
控制器.cs
[HttpPost("register")]
public async Task<IActionResult> Register()
{
//read cert for file system below for demo purpose
var path = "path to full cert chain pfx : root > intermediate > device/leaf certificate";
isDeviceRegistered = await _dpsService.RegisterDevice(path, password);
return Ok(isDeviceRegistered.Item2);
}
服务.cs
public async Task<(bool, string)> RegisterDevice(string certPath, string password)
{
var cert = new X509Certificate2(certPath, password);
//Check if device already registered
try
{
using var provisioningServiceClient = ProvisioningServiceClient.CreateFromConnectionString(_config["AzureIotHubDPS:ConnectionString"]);
var deviceId = cert.Subject.Replace("CN=", "");
var statResult = await provisioningServiceClient.GetDeviceRegistrationStateAsync(deviceId); // generates exception on registration not found
if (statResult.Status == EnrollmentStatus.Assigned)
{
return (true, $"Device {statResult.RegistrationId} already registered to {statResult.AssignedHub}.");
}
}
catch (ProvisioningServiceClientHttpException ex)
{
var exResponse = JsonConvert.DeserializeObject<ExResponse>(ex.Body);
if (exResponse?.ErrorCode == 404202 && exResponse.Message.Equals("Registration not found."))
{
//Register Device to iothub DPS
var idScope = _config["AzureIotHubDPS:IdScope"];
var globalDPSEndpoint = _config["AzureIotHubDPS:DPSGlobalEndpoint"];
using var security = new SecurityProviderX509Certificate(cert);
using ProvisioningTransportHandler transport = CertificateHelper.GetTransportHandler(Microsoft.Azure.Devices.Client.TransportType.Mqtt_WebSocket_Only);
var deviceClient = ProvisioningDeviceClient.Create(globalDPSEndpoint, idScope, security, transport);
DeviceRegistrationResult regResult = await deviceClient.RegisterAsync(); // produces 500 error with "CA cert not found - works from localhost NOT from app service linux instance in azure"
if (regResult.Status != ProvisioningRegistrationStatusType.Assigned)
{
return (false, $"Registration status did not assign a hub, so exitting...");
}
else
{
return (true, $"Successfully registered Device:{regResult.DeviceId} to Hub: {regResult.AssignedHub}.");
}
}
}
return (false, $"Device registration Failed!");
}