Below you find the solution as shared by the original poster @Tobias Quadfasel :
In general, I am a bit puzzled why using the managed identity of the device for module-level MSI authentication is the recommended method, because getting it to work properly requires quite some hacking, opening up other security issues on the way.
So the problem is that the azure arc install script sets up the IMDS endpoint to 127.0.0.1:40342
and NOT to 0.0.0.0.40342
. This is probably done for security reasons, such that you can only access the managed identity when on the actual machine (which makes sense). On the other hand, it renders the identity useless when working with containers like in my case using the IoT Hub, because the host 127.0.0.1
can't be accessed (except setting network=host
, which is also not optimal in my view).
In order to use the managed Identity I had to expose the local endpoint somehow such that docker containers could access it. Here is what I did:
I created a daemon on my machine that uses socat
to create a TCP relay between some (unused) port bound to 0.0.0.0
and 127.0.0.1:40342
. Note that this will expose the identity endpoint to your local network. It is fine for my use-case. In more critical use-cases, one should probably take measures to block acces to this port except for the docker host local IP (172.17.0.1
).
Then, all containers that need to access the identity must have at least read-only access to /var/opt/azcmagent/tokens
on the host system. Therefore, in the "container create options" in the IoT Hub, you need to include:
"Mounts": [
{
"Target": "/var/opt/azcmagent/tokens",
"Source": "/var/opt/azcmagent/tokens",
"Type": "bind",
"ReadOnly": true
}
]
in the "HostConfig" section.
Finally, if you don't want to rely on REST API calls in your code but use azure.identity.DefaultAzureCredential
or azure.identity.ManagedIdentityCredential
, you need to set some environment variables. Let's assume for the free port I mentioned above in the TCP relay I used 0.0.0.0:12345
, then the following variables need to be set in the container:
IMDS_ENDPOINT
needs to be set to http://172.17.0.1:12345
and IDENTITY_ENDPOINT
needs to be set to http://172.17.0.1:12345/metadata/identity/oauth2/token
.
Only then everything will work and you can access azure.identity
-based managed identity credentials in your code on an IoT edge module to authenticate against other resources.
If the response helped, do "Accept Answer". If it doesn't work, please let us know the progress. All community members with similar issues will benefit by doing so. Your contribution is highly appreciated.