Azure / azure-iot-cli-extension

Azure IoT extension for Azure CLI
Other
83 stars 66 forks source link

[bug] Issue sending device to cloud messages #327

Open ericvruder opened 3 years ago

ericvruder commented 3 years ago

Describe the bug I am having an issue sending device to cloud message (send-d2c-message) to my iot hub.

To Reproduce The following commands fails

az iot device send-d2c-message -n 'hub-name' --data 'hello' -d 'device-name' --verbose

With the following message:

Using policy 'iothubowner' for IoT Hub interaction.
[WinError 10054] An existing connection was forcibly closed by the remote host
Command ran in 2.898 seconds (init: 0.232, invoke: 2.665)

If I change the hub name, it fails with the following message:

Unable to find IoT Hub: XXXX in current subscription SSSS.
Command ran in 1.583 seconds (init: 0.289, invoke: 1.294)

So it's not a incorrect hub name

If I change the device id to one that is not registered, then it fails with the same message, so I can't confirm whether or not that is the issue. Although I am copy-pasting from the device overview tab in the hub.

Expected behavior Expect the message to be sent through

Environment (please complete the following information):

c-ryan-k commented 3 years ago

Hey @ericvruder - sorry for the delay in responding. We're doing a bit of work refactoring our c2d message internals, but I'll make sure we look into this. Could you kindly verify this issue still reproduces? Just to make sure it wasn't a transient connectivity or service error.

ericvruder commented 3 years ago

Yes, after updating both my az cli and az iot cli, it still fails with the same message.

Using policy 'iothubowner' for IoT Hub interaction.
[WinError 10054] An existing connection was forcibly closed by the remote host
Command ran in 3.647 seconds (init: 0.291, invoke: 3.357)
c-ryan-k commented 3 years ago

@ericvruder thanks - one more question, are you using a non-symmetric key authenticated device? Our MQTT messaging and device simulation currently aren't compatible with certificate-based authentication - we have code merged in to display this as an error when sending messages but it hasn't been released as of yet.

ericvruder commented 3 years ago

They are all authenticated with symmetric keys.

I tried without sending a --login parameter, which would result in it using the iothubowner policy, which has all permissions. This is the example I sent you.

If I used the --login parameter with the connection string for the iothubowner policy, it would result in almost the same error.

[WinError 10054] An existing connection was forcibly closed by the remote host

It's just missing the "using iothubowner policy" that was present before.

If I try to use one of the connection strings from the device, it complains that it is missing the SharedAccessKeyName property from the connection string.

The command failed with an unexpected error. Here is the traceback:
IoT Hub connection string has missing property: SharedAccessKeyName
Traceback (most recent call last):
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\knack/cli.py", line 231, in invoke
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 657, in execute
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 720, in _run_jobs_serially
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 691, in _run_job
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 328, in __call__
  File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/command_operation.py", line 121, in handler
  File "c:\azurecliextensions\azure-iot\azext_iot\operations\hub.py", line 2051, in iot_device_send_message
    target = discovery.get_target(
  File "c:\azurecliextensions\azure-iot\azext_iot\iothub\providers\discovery.py", line 145, in get_target
    return self.get_target_by_cstring(connection_string=cstring)
  File "c:\azurecliextensions\azure-iot\azext_iot\iothub\providers\discovery.py", line 140, in get_target_by_cstring
    return IotHubTarget.from_connection_string(cstring=connection_string).as_dict()
  File "c:\azurecliextensions\azure-iot\azext_iot\iothub\models\iothub_target.py", line 23, in from_connection_string
    decomposed = parse_iot_hub_connection_string(cs=cstring)
  File "c:\azurecliextensions\azure-iot\azext_iot\common\_azure.py", line 33, in parse_iot_hub_connection_string
    return _parse_connection_string(cs, validate, "IoT Hub")
  File "c:\azurecliextensions\azure-iot\azext_iot\common\_azure.py", line 18, in _parse_connection_string
    raise ValueError(
ValueError: IoT Hub connection string has missing property: SharedAccessKeyName
c-ryan-k commented 3 years ago

@ericvruder sorry for the back and forth - but are you using a device connection string for this command or a hub connection string? This command requires an IoT Hub connection string (essentially, --login is a "global" parameter for our commands that require auth against an existing hub) - and that might be why you're getting the missing property: SharedAccessKeyName error.

I understand it's a bit confusing in this aspect , as other device simulators / SDKs ask for a device connection string to simulate the device, but in this case we use the --login parameter in order to interact with the hub entity without being logged in to an AZ CLI context.

ericvruder commented 3 years ago

Hey @c-ryan-k ,

Don't worry about it! I'm having a blast working with the iot hub, so I am more than happy to help in any way I can.

So, the original attempt was without the --login parameter. It told me that it would then use the iothubowner policy - which I assumed would be the iothubowner shared access policy connection string. This would fail with the original message

Using policy 'iothubowner' for IoT Hub interaction.
[WinError 10054] An existing connection was forcibly closed by the remote host
Command ran in 2.910 seconds (init: 0.299, invoke: 2.611)

I then went into the Shared access policies tab and grab the connection string for the policy it mentioned above. This is the connection string I used:

image

If we say that the connection string's value for that policy is CONNSTRING, I would then use the following command, exactly, to try and send a d2c message;

az iot device send-d2c-message -d 'PC0167878' -l 'CONNSTRING'

We can see here that the device does exist in the IoT devices tab: image

This would lead to the following error:

[WinError 10054] An existing connection was forcibly closed by the remote host

Using the device's connection string, as you mentioned, leads to the missing property: SharedAccessKeyName, I only used this to try and figure out what was going on.