Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support setting MQTT ALPN for use with AWS IoT #752

Closed
RFRIEDM-Trimble opened this issue Jan 8, 2022 · 8 comments
Closed

Support setting MQTT ALPN for use with AWS IoT #752

RFRIEDM-Trimble opened this issue Jan 8, 2022 · 8 comments

Comments

@RFRIEDM-Trimble
Copy link

RFRIEDM-Trimble commented Jan 8, 2022

When using MQTT and Paho, I used this guide for the setup to communicate with an AWS IoT broker.

When trying to test my client using tavern, I have been unable to connect to an AWS broker, and suspect it may be from the inability to set the TLS ALPN in tavern. The behavior is no response to CONNACK requests, and failure to connect to the broker.

I am happy to add support for this, but would like some guidance on how the yaml should change to support this.

Thanks!

@michaelboulton
Copy link
Member

From looking at the page it looks like the only thing missing is the bit where it enables ALPN, correct? If so, that should be a fairly easy thing to add (execpt for reaching into the paho-mqtt internals)

@RFRIEDM-Trimble
Copy link
Author

RFRIEDM-Trimble commented Jan 9, 2022

From looking at the page it looks like the only thing missing is the bit where it enables ALPN, correct? If so, that should be a fairly easy thing to add (execpt for reaching into the paho-mqtt internals)

Correct. The code change would be small to support just this one feature.

Instead of calling self._client.tls_set(**self._tls_args), it would be self._client.tls_set_context(ssl_context), where ssl_context would need to be formed by making individual calls to the ssl object. The previous keys could remain the same, but now additionally support set_alpn_protocols().

That said, the current yaml object would not follow documentation, which currently matches argument's for paho's tls_set exactly.

My thought would be the yaml would be changed. Instead of following the paho documentation for tls_set, it will instead follow the SSLContext attributes like so...

ssl_context:
  alpn_protocols:
    - x-amzn-mqtt-ca
  cafile: 
  certfile:
  keyfile: 
  cert_required: True
  tls_version: PROTOCOL_TLSv1_2
  ciphers: 

Changes:

  • Renamed ca_certs to cafile
  • Remove enable option (This doesn't seem to parse anyways in v2.0, so perhaps you already did that?)
  • add in alpn_protocols as a list of items.

Yes, looking at Paho's implementation of tls_set, there is a bit going on there that would need to be moved to here to keep behavior the same with respect to defaults.

Does the above approach sound good to you? I can either leave tls as still a valid way to work, add deprecation warning for it, or remove that key entirely.

@RFRIEDM-Trimble
Copy link
Author

I have a working implementation for this now; the tls functionality is unchanged. I can add some unit testing for the new functionality. For system testing, it appears mosquitto supports alpn_protocols, which could be used for this validation.

@michaelboulton
Copy link
Member

I see paho-mqtt supports that in 1.6, Tavern is currently tied to <=1.5.1 because they introduced some kind of a regression in a more recent version. I suppose they may have fixed it in a more recent version though?

@RFRIEDM-Trimble
Copy link
Author

RFRIEDM-Trimble commented May 7, 2022

We've been using new than that for the past few months with tavern and no issues in the paho side of things. Any opposition to bump that max version up so my PR for this can merge?

@aaroncarlucci
Copy link

I noticed this got merged into feature-2.0, so I've been trying to get it setup. New to Tavern here as well. I've been struggling with the configuration options. I've tried a ton of combinations, but what I'm working with so far is:

paho-mqtt:
  connect:
    host: "<account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com"
    port: 443
    timeout: 10
  ssl_context:
    alpn_protocols:
      - x-amzn-mqtt-ca
    ca_certs: "tests/integration/tests/integration/AmazonRootCA1.pem"
    certfile: "tests/integration/test-certificate.pem"
    keyfile: "tests/integration/test-private.key"
    tls_version: PROTOCOL_TLSv1_2

After enabling DEBUG logging, I'm getting the following with my small MQTT test case:

------------------------------------------- Captured log call --------------------------------------------
DEBUG    tavern._core.pytest.util:util.py:129 Nothing to format in global config files
DEBUG    tavern._core.schema.files:files.py:33 Loaded schema from /var/lang/lib/python3.9/site-packages/tavern/_core/schema/tests.jsonschema.yaml
DEBUG    tavern._core.schema.files:files.py:46 Adding plugins to schema: [<stevedore.extension.Extension object at 0x7f7955debbe0>, <stevedore.extension.Extension object at 0x7f7955e52ac0>]
DEBUG    tavern._core.schema.files:files.py:53 No schema defined for requests
INFO     tavern._core.run:run.py:145 Running test : Test alerts
DEBUG    tavern._core.plugins:plugins.py:155 Initialising session for paho-mqtt (<class 'tavern._plugins.mqtt.client.MQTTClient'>)
DEBUG    tavern._core.dict_util:dict_util.py:135 Not formatting something of type '<class 'int'>'
DEBUG    tavern._core.dict_util:dict_util.py:135 Not formatting something of type '<class 'int'>'
DEBUG    tavern._plugins.mqtt.client:client.py:169 Initialising MQTT client with {'connect': {'host': '<account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com', 'port': 443, 'timeout': 10}, 'ssl_context': {'alpn_protocols': ['x-amzn-mqtt-ca'], 'ca_certs': 'tests/integration/tests/integration/AmazonRootCA1.pem', 'certfile': 'tests/integration/test-certificate.pem', 'keyfile': 'tests/integration/test-private.key'}}
DEBUG    tavern._plugins.mqtt.client:client.py:202 TLS is disabled
DEBUG    tavern._plugins.mqtt.client:client.py:208 Paho client args: {}
DEBUG    tavern._core.run:run.py:151 Entering context for paho-mqtt
DEBUG    tavern._plugins.mqtt.client:client.py:488 Connecting to {'host': '<account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com', 'port': 443}
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0.25 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0.5 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:352 MQTT socket opened
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0.75 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:368 MQTT socket closed
WARNING  tavern._plugins.mqtt.client:client.py:336 Client  failed to disconnect cleanly due to Connection Refused: unacceptable protocol version., possibly from a network error
...
...
...
repeating every 2.5 second until 10s timeout

Also tried by adding https:// to the hostname. Perhaps this isn't the ideal place for such a question, but I haven't found much online around pushing Paho to integrate with AWS IoT. Seeing as this feature is under development here, perhaps discussion could be preparatory for pending documentation on for this feature. Feedback anyone can spare is appreciated.

@RFRIEDM-Trimble
Copy link
Author

I noticed this got merged into feature-2.0, so I've been trying to get it setup. New to Tavern here as well. I've been struggling with the configuration options. I've tried a ton of combinations, but what I'm working with so far is:

paho-mqtt:
  connect:
    host: "<account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com"
    port: 443
    timeout: 10
  ssl_context:
    alpn_protocols:
      - x-amzn-mqtt-ca
    ca_certs: "tests/integration/tests/integration/AmazonRootCA1.pem"
    certfile: "tests/integration/test-certificate.pem"
    keyfile: "tests/integration/test-private.key"
    tls_version: PROTOCOL_TLSv1_2

After enabling DEBUG logging, I'm getting the following with my small MQTT test case:

------------------------------------------- Captured log call --------------------------------------------
DEBUG    tavern._core.pytest.util:util.py:129 Nothing to format in global config files
DEBUG    tavern._core.schema.files:files.py:33 Loaded schema from /var/lang/lib/python3.9/site-packages/tavern/_core/schema/tests.jsonschema.yaml
DEBUG    tavern._core.schema.files:files.py:46 Adding plugins to schema: [<stevedore.extension.Extension object at 0x7f7955debbe0>, <stevedore.extension.Extension object at 0x7f7955e52ac0>]
DEBUG    tavern._core.schema.files:files.py:53 No schema defined for requests
INFO     tavern._core.run:run.py:145 Running test : Test alerts
DEBUG    tavern._core.plugins:plugins.py:155 Initialising session for paho-mqtt (<class 'tavern._plugins.mqtt.client.MQTTClient'>)
DEBUG    tavern._core.dict_util:dict_util.py:135 Not formatting something of type '<class 'int'>'
DEBUG    tavern._core.dict_util:dict_util.py:135 Not formatting something of type '<class 'int'>'
DEBUG    tavern._plugins.mqtt.client:client.py:169 Initialising MQTT client with {'connect': {'host': '<account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com', 'port': 443, 'timeout': 10}, 'ssl_context': {'alpn_protocols': ['x-amzn-mqtt-ca'], 'ca_certs': 'tests/integration/tests/integration/AmazonRootCA1.pem', 'certfile': 'tests/integration/test-certificate.pem', 'keyfile': 'tests/integration/test-private.key'}}
DEBUG    tavern._plugins.mqtt.client:client.py:202 TLS is disabled
DEBUG    tavern._plugins.mqtt.client:client.py:208 Paho client args: {}
DEBUG    tavern._core.run:run.py:151 Entering context for paho-mqtt
DEBUG    tavern._plugins.mqtt.client:client.py:488 Connecting to {'host': '<account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com', 'port': 443}
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0.25 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0.5 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:352 MQTT socket opened
DEBUG    tavern._plugins.mqtt.client:client.py:501 Not connected after 0.75 seconds - waiting
DEBUG    tavern._plugins.mqtt.client:client.py:368 MQTT socket closed
WARNING  tavern._plugins.mqtt.client:client.py:336 Client  failed to disconnect cleanly due to Connection Refused: unacceptable protocol version., possibly from a network error
...
...
...
repeating every 2.5 second until 10s timeout

Also tried by adding https:// to the hostname. Perhaps this isn't the ideal place for such a question, but I haven't found much online around pushing Paho to integrate with AWS IoT. Seeing as this feature is under development here, perhaps discussion could be preparatory for pending documentation on for this feature. Feedback anyone can spare is appreciated.

My config looks like this:

paho-mqtt:
  connect:
     host: <account-iot-identifier>-ats.iot.<aws-region>.amazonaws.com

Everything else you posted looks fine. Interesting, logs say that TLS is disabled, that might be a remnant from not specifying the tls group of parameters. Perhaps check you can manually connect using the same certs and that the policies are set up correctly to allow connection.

@michaelboulton
Copy link
Member

I'm going to close this as it should have been fixed by the release of version 2.0 (though, it is missing some test coverage)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants