tavern
tavern copied to clipboard
Support setting MQTT ALPN for use with AWS IoT
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!
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)
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.
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.
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?
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?
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.
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.
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)