Я пытаюсь перенести существующее решение с Azure IoT Hub на использование службы подготовки устройств Azure IoT Hub (DPS).
Устройства аутентифицируют себя с помощью самозаверяющего сертификата X.509.
В целях тестирования я могу сгенерировать сертификат, используя
openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
- Общее имя установлено на
mything1
- Все остальные поля пустые
Затем я могу объединить эти файлы в один файл, используя
openssl pkcs12 -inkey key.pem -in certificate.pem -export -out certificate.p12
Выбор password
в качестве пароля.
У меня тогда есть 3 файла.
certificate.p12
, содержащий сертификат и закрытый ключcertificate.pem
содержащий сертификатkey.pem
содержащий закрытый ключ
Затем я могу зарегистрировать это устройство непосредственно в Центре Интернета вещей, используя
string ThingId = "mything1";
// Register device directly in IoT hub.
{
var certificate = new X509Certificate2(File.ReadAllBytes("certificate.pem"));
string thumb1 = certificate.Thumbprint;
using (var hasher = SHA256.Create())
{
using (var registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString))
{
await registryManager.AddDeviceAsync(new Device(ThingId)
{
Authentication = new AuthenticationMechanism()
{
X509Thumbprint = new X509Thumbprint()
{
PrimaryThumbprint = thumb1,
SecondaryThumbprint = thumb1,
}
},
});
}
}
}
Затем после регистрации устройства я могу подключиться к Центру Интернета вещей в качестве устройства, используя сертификат в качестве аутентификации устройства.
// Vertifying that certificate is ok etc
// by connecting to an IoT Hub
{
var auth = new DeviceAuthenticationWithX509Certificate(ThingId, new X509Certificate2(File.ReadAllBytes("certificate.p12"), "password"));
var client = DeviceClient.Create(iotHubHostname, auth,
new ITransportSettings[] { new AmqpTransportSettings(Microsoft.Azure.Devices.Client.TransportType.Amqp_WebSocket_Only) });
// Report a value just to make sure it works.
TwinCollection props = new TwinCollection();
props["Hello"] = "World";
await client.UpdateReportedPropertiesAsync(props, new CancellationTokenSource(1000 * 30).Token);
}
И это работает, и это решение, которое у меня есть сегодня. Сейчас пытаюсь проделать то же самое, но используя ДПС.
Сначала создайте индивидуальную регистрацию для устройства:
// Create an individual enrollment for device
using (var provisioningServiceClient =
ProvisioningServiceClient.CreateFromConnectionString(provisioningServiceConnectionString))
{
var attestation = X509Attestation.CreateFromClientCertificates(new X509Certificate2(File.ReadAllBytes("certificate.pem")));
IndividualEnrollment individualEnrollment =
new IndividualEnrollment(
ThingId,
attestation);
IndividualEnrollment individualEnrollmentResult =
await provisioningServiceClient.CreateOrUpdateIndividualEnrollmentAsync(individualEnrollment);
}
Затем, после создания регистрации, я смогу проявить себя как устройство.
string globalDeviceEndpoint = "global.azure-devices-provisioning.net";
using (var security = new SecurityProviderX509Certificate(new X509Certificate2(File.ReadAllBytes("certificate.p12"), "password")))
{
ProvisioningDeviceClient provClient = ProvisioningDeviceClient.Create(globalDeviceEndpoint,
s_idScope,
security,
new ProvisioningTransportHandlerHttp());
DeviceRegistrationResult result = await provClient.RegisterAsync(); // Throws exception
Console.WriteLine($"ProvisioningClient AssignedHub: {result.AssignedHub}; DeviceId: {result.DeviceId}");
}
Но это вызывает несанкционированное исключение:
Unhandled exception. Microsoft.Azure.Devices.Provisioning.Client.ProvisioningTransportException: {"errorCode":401002,"trackingId":"f7ec27c8-dbad-4600-8b47-f46aaa0160de","message":"Unauthorized","timestampUtc":"2021-05-20T14:09:00.8491407Z"}
---> Microsoft.Rest.HttpOperationException: Operation returned an invalid status code 'Unauthorized'
at Microsoft.Azure.Devices.Provisioning.Client.Transport.RuntimeRegistration.RegisterDeviceWithHttpMessagesAsync(String registrationId, String idScope, DeviceRegistration deviceRegistration, Nullable`1 forceRegistration, Dictionary`2 customHeaders, CancellationToken cancellationToken)
at Microsoft.Azure.Devices.Provisioning.Client.Transport.RuntimeRegistrationExtensions.RegisterDeviceAsync(IRuntimeRegistration operations, String registrationId, String idScope, DeviceRegistration deviceRegistration, Nullable`1 forceRegistration, CancellationToken cancellationToken)
at Microsoft.Azure.Devices.Provisioning.Client.Transport.ProvisioningTransportHandlerHttp.RegisterAsync(ProvisioningTransportRegisterMessage message, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.Azure.Devices.Provisioning.Client.Transport.ProvisioningTransportHandlerHttp.RegisterAsync(ProvisioningTransportRegisterMessage message, CancellationToken cancellationToken)
at DPSWorkShop.Program.Main(String[] args) in C:\Work\Elux\DPSWorkShop\DPSWorkShop\Program.cs:line 91
at DPSWorkShop.Program.<Main>(String[] args)
Что я здесь делаю не так?
РЕДАКТИРОВАТЬ: Как ответил Раджив здесь: https://stackoverflow.com/a/67641996/6877590 Проблема в основном ограничение: CA: верно.
Чтобы решить эту проблему (для тестирования)
- отредактируйте файл
/usr/lib/ssl/openssl.cnf
- Найдите
[ v3_ca ]
- Изменить CA: true на CA: false