Skip to content

create_from_edge_environment()'s get_twin() only returning properties and no other twin values. #1206

@infused-kim

Description

@infused-kim

Context

  • OS and version used: Oracle Linux 8.10 (Tenable OT OS)
  • Python version: Python 3.12.11
  • pip version: uv 0.8.15 used to create docker image, but installed pip 25.0.1 to get package list
  • list of installed packages:
Click to show package list

(ce-tenable-ot-extractor) appuser@7b4a22d5a924:~$ venv/bin/pip3 list
Package                 Version
----------------------- ------------------
aiohappyeyeballs        2.6.1
aiohttp                 3.12.15
aiosignal               1.4.0
annotated-types         0.7.0
anyio                   4.10.0
APScheduler             3.11.0
arrow                   1.3.0
attrs                   25.3.0
azure-core              1.35.0
azure-iot-device        2.14.0
azure-storage-blob      12.26.0
backoff                 2.2.1
ce_tenable_ot_extractor 0.3.2.dev7+ba48086
certifi                 2025.8.3
cffi                    1.17.1
charset-normalizer      3.4.3
click                   8.2.1
cryptography            45.0.7
defusedxml              0.7.1
deprecation             2.1.0
frozenlist              1.7.0
gql                     4.0.0
graphql-core            3.2.6
idna                    3.10
inflection              0.5.1
isodate                 0.7.2
janus                   2.0.0
markdown-it-py          4.0.0
marshmallow             3.26.1
mdurl                   0.1.2
multidict               6.6.4
numpy                   2.3.2
packaging               25.0
paho-mqtt               1.6.1
pandas                  2.3.1
pip                     25.0.1
propcache               0.3.2
pycparser               2.22
pydantic                2.11.7
pydantic_core           2.33.2
pydantic-extra-types    2.10.5
pydantic-settings       2.10.1
Pygments                2.19.2
PySocks                 1.7.1
pyTenable               1.8.4
python-box              7.3.2
python-dateutil         2.9.0.post0
python-dotenv           1.1.1
pytz                    2025.2
requests                2.32.5
requests-toolbelt       1.0.0
requests-unixsocket2    1.0.1
restfly                 1.5.1
rich                    14.1.0
semver                  3.0.4
shellingham             1.5.4
six                     1.17.0
sniffio                 1.3.1
typer                   0.17.4
types-python-dateutil   2.9.0.20250822
typing_extensions       4.15.0
typing-inspection       0.4.1
tzdata                  2025.2
tzlocal                 5.3.1
urllib3                 2.5.0
yarl                    1.20.1
  • cloned repo: Not used

-support bundle:
support_bundle_2025_09_07_21_33_44_UTC.zip

Description of the issue

I am experiencing the same issue as this person: #821

When I use IoTHubModuleClient.create_from_edge_environment().get_twin(), I only get the properties, but not other module twin data.

Expected twin

This is the twin data I get from the Azure Portal:

{
    "etag": "AAAAAAAAAAM=",
    "deviceId": "kim-tenable-ot-01",
    "deviceEtag": "ODEzNTY3NDk=",
    "moduleId": "tenable-ot-extractor",
    "version": 51625,
    "properties": {
        "desired": {
            "$metadata": {
                "$lastUpdated": "2025-07-24T17:56:03.5921753Z",
                "$lastUpdatedVersion": 3,
                "settings": {
                    "$lastUpdated": "2025-07-24T17:51:56.7026873Z",
                    "$lastUpdatedVersion": 2,
                    "tenable_ot_api_key": {
                        "$lastUpdated": "2025-07-24T17:51:56.7026873Z",
                        "$lastUpdatedVersion": 2
                    },
                    "tenable_ot_url": {
                        "$lastUpdated": "2025-07-24T17:51:56.7026873Z",
                        "$lastUpdatedVersion": 2
                    },
                    "upload_interval": {
                        "$lastUpdated": "2025-07-24T17:51:56.7026873Z",
                        "$lastUpdatedVersion": 2
                    }
                },
                "test-settings": {
                    "$lastUpdated": "2025-07-24T17:56:03.5921753Z",
                    "$lastUpdatedVersion": 3,
                    "foo": {
                        "$lastUpdated": "2025-07-24T17:56:03.5921753Z",
                        "$lastUpdatedBy": "deployment_dev_v0_1_5-0-g41cdd32",
                        "$lastUpdatedByDigest": "638792387321632884",
                        "$lastUpdatedVersion": 3
                    }
                }
            },
            "$version": 3,
            "settings": {
                "tenable_ot_api_key": "XXX=",
                "tenable_ot_url": "https://host.docker.internal",
                "upload_interval": "30"
            }
        },
        "reported": {
            "$metadata": {
                "$lastUpdated": "2025-09-07T19:51:02.6298212Z",
                "connectionStatus": {
                    "$lastUpdated": "2025-09-07T19:51:02.6298212Z"
                },
                "lastHeartbeatTime": {
                    "$lastUpdated": "2025-09-07T19:51:02.6298212Z"
                },
                "moduleStatus": {
                    "$lastUpdated": "2025-09-07T19:51:02.6298212Z"
                }
            },
            "$version": 51622,
            "connectionStatus": "connected",
            "lastHeartbeatTime": "2025-09-07T19:51:02.516048+00:00",
            "moduleStatus": "running"
        }
    },
    "configurations": {
        "deployment_dev_v0_1_3-0-ga3244e0": {
            "status": "Targeted"
        },
        "deployment_dev_v0_1_4-0-gc44df30": {
            "status": "Targeted"
        },
        "deployment_dev_v0_1_4-1-g95f3fc7": {
            "status": "Targeted"
        },
        "deployment_dev_v0_1_5-0-g41cdd32": {
            "status": "Applied"
        }
    },
    "modelId": "",
    "status": "enabled",
    "statusUpdateTime": "0001-01-01T00:00:00.0000000Z",
    "lastActivityTime": "2025-09-07T19:49:30.2062010Z",
    "connectionState": "Connected",
    "cloudToDeviceMessageCount": 0,
    "authenticationType": "sas"
}

Actually received twin

This is what my python code actually gets. As you can see, it's only the properties key, but it doesn't even include the properties key itself and no metadata.

{
    "desired": {
        "$version": 3,
        "settings": {
            "tenable_ot_api_key": "XXX=",
            "tenable_ot_url": "https://host.docker.internal",
            "upload_interval": "30"
        },
        "test-settings": {
            "foo": "bar"
        }
    },
    "reported": {
        "$version": 51699,
        "connectionStatus": "connected",
        "lastHeartbeatTime": "2025-09-07T21:20:13.223778+00:00",
        "moduleStatus": "running"
    }
}

Attempted solutions

I tried all the suggestions in the other issue, but they didn't help.

I added the dns section to my /etc/docker/daemon.json:

[Kim@tenable-q82xbzqn ~]$ cat /etc/docker/daemon.json
{
  "bip": "172.17.0.254/24",
  "fixed-cidr": "172.17.0.128/25",
  "mtu": 9000,
  "log-driver": "local",
  "dns": ["1.1.1.1"]
}

I also tried the OPs suggestion of adjusting the /etc/aziot/config.toml to add /etc/hosts binds:

# [agent.config]
# image = "mcr.microsoft.com/azureiotedge-agent:1.5"
createOptions = { HostConfig = { Binds = ["/iotedge/storage:/iotedge/storage", "/etc/hosts:/etc/hosts"] } }

I did run sudo iotedge config apply and tried rebooting. But none of this helped.

And I am not using a proxy.

Code sample exhibiting the issue

from pprint import pprint
from azure.iot.device import IoTHubModuleClient

def get_module_twin_edge_env():
    print('Creating client from edge environment...')
    client = IoTHubModuleClient.create_from_edge_environment()

    print('Getting twin...')
    twin = client.get_twin()
    pprint(twin)

    print('Shutting down client...')
    client.shutdown()

def main():
    get_module_twin_edge_env()

if __name__ == "__main__":
    main()

Console log of the issue

The easiest way to reproduce is to exec a shell in an existing IoT Edge module that has python installed and isn't already connected to the IoTHub.

If the main process is already connected, you will get errors like 'azure.iot.device.common.transport_exceptions.ConnectionDroppedError: Unexpected disconnection\n'.

[Kim@tenable-q82xbzqn ~]$ docker ps | grep extractor
6aa2f8e46529   crcentryproduks.azurecr.io/tenable-ot-extractor:develop-0.3.2.dev8-b20084e   "ce_tenable_ot_extra…"    8 minutes ago   Up 8 minutes                                                                                                                  tenable-ot-extractor
[Kim@tenable-q82xbzqn ~]$ docker exec -it 6aa2f8e46529 bash
appuser@6aa2f8e46529:~$ cat > test.py
from pprint import pprint
from azure.iot.device import IoTHubModuleClient

def get_module_twin_edge_env():
    print('Creating client from edge environment...')
    client = IoTHubModuleClient.create_from_edge_environment()

    print('Getting twin...')
    twin = client.get_twin()
    pprint(twin)

    print('Shutting down client...')
    client.shutdown()

def main():
    get_module_twin_edge_env()

if __name__ == "__main__":
    main()
appuser@6aa2f8e46529:~$ python test.py
Creating client from edge environment...
Getting twin...
{'desired': {'$version': 3,
             'settings': {'tenable_ot_api_key': 'XXX=',
                          'tenable_ot_url': 'https://host.docker.internal',
                          'upload_interval': '30'},
             'test-settings': {'foo': 'bar'}},
 'reported': {'$version': 51699,
              'connectionStatus': 'connected',
              'lastHeartbeatTime': '2025-09-07T21:20:13.223778+00:00',
              'moduleStatus': 'running'}}
Shutting down client...
appuser@6aa2f8e46529:~$

Conclusion

Thank you so much in advance for your help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions