Disclaimer: This repo DOES NOT contain production ready code (very limited error handling etc.) and only demonstrates the approach.
This repo demonstrates different options for integrating a custom IoT Agent with Azure IoT Identity Service.
While these samples are written in C# .NET 6, it is definetely possible to implement them using other programming languages. It basically comes down to being able to communicate over Unix domain sockets and potentially doing interop with the native OpenSSL library.
Refer to this documenation to understand concepts behind Azure IoT Identity Service.
It is also important to understand different identity types and available authnetication options.
The implementation is tested on Raspberry Pi 3 B+ with the Infineon Optiga SLB9670 TPM 2.0
Azure IoT Edentity Service is configured to use PKCS#11 integration with this TPM chip and to request certificate through EST.
For details on how to configure this refer to this repo.
To run these samples, you'll need to follow these steps:
- Setup your Cloud services (DPS and IoT Hub).
- Install the Azure IoT Identity Service
- Configure it. If you want to use it with an HSM and/or EST, refer to this repo.
- Authorize you client application so it can interact with the services through Unix domain sockets.
- Clone this repo and go into one of the project folders
- Download and install .NET 6
- Excecute
dotnet run
if you are the user whom the authorization is configured for OR run e.g.sudo -u <username> dotnet run
if you are not.
This demonstrates how to implement a custom IoT agent using module identities.
Module identites are e.g. used for IoT Edge modules and are within the scope of a specific device. Module identities can also be used without IoT Edge on simple IoT devices. Module identities currently do not support x509 authentication, they only support SAS authentiation scheme.
This demonstrates how to implement a custom IoT agent using device identities with x509 client cert based authentication (with keys potentially backed by an HSM). The important part here is that all cryptographic operations are performed by the preconfigured OpenSSL engine which comes with the Keys Service (aka keyd). So if the Keys Service uses an HSM (e.g. TPM) to store the keys, all cryptographic operations will be performed by this HSM and private keys never see the light of day. Unfortunately .NET does not seem to support working with custom OpenSSL engines (see the GitHub issue) which is why I needed to fallback to native interop with libssl.
This GitHub issue was absolutely helpful to understand what needs to be done.
Hint:
- Depending on the CPU architecture the path to libssl might need to be adapted for here. The path can be found using
ldconfig -p|grep ssl
- Also one needs to make sure that the OpenSSL version used by .NET corresponds to the SafeEvpPKeyHandle.OpenSslVersion