From 21d52a1eeee1ead5985308ec9ecb170191333215 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 23 Sep 2025 09:47:20 -0700 Subject: [PATCH 1/8] add cipher suite option in mqtt builder --- awsiot/mqtt5_client_builder.py | 34 +++++++++++++++--- awsiot/mqtt_connection_builder.py | 59 +++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/awsiot/mqtt5_client_builder.py b/awsiot/mqtt5_client_builder.py index 432ae114..2789f88e 100644 --- a/awsiot/mqtt5_client_builder.py +++ b/awsiot/mqtt5_client_builder.py @@ -362,7 +362,8 @@ def _builder( return client -def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt5.Client: +def mtls_from_path(cert_filepath, pri_key_filepath, cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. TLS arguments are passed as filepaths. @@ -377,10 +378,15 @@ def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt5.Cl """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(cert_filepath, pri_key_filepath) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) -def mtls_from_bytes(cert_bytes, pri_key_bytes, **kwargs) -> awscrt.mqtt5.Client: +def mtls_from_bytes( + cert_bytes, + pri_key_bytes, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. TLS arguments are passed as in-memory bytes. @@ -395,6 +401,7 @@ def mtls_from_bytes(cert_bytes, pri_key_bytes, **kwargs) -> awscrt.mqtt5.Client: """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls(cert_bytes, pri_key_bytes) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) @@ -406,6 +413,7 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT connection to AWS IoT, @@ -451,11 +459,14 @@ def mtls_with_pkcs11(*, private_key_label=private_key_label, cert_file_path=cert_filepath, cert_file_contents=cert_bytes) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) + def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -476,11 +487,13 @@ def mtls_with_pkcs12(*, tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_pkcs12( pkcs12_filepath=pkcs12_filepath, pkcs12_password=pkcs12_password) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) def mtls_with_windows_cert_store_path(*, cert_store_path: str, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT, @@ -499,6 +512,7 @@ def mtls_with_windows_cert_store_path(*, _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) @@ -506,6 +520,7 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client over websockets to AWS IoT. @@ -543,12 +558,17 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): except Exception as e: transform_args.set_done(e) - return websockets_with_custom_handshake(_sign_websocket_handshake_request, websocket_proxy_options, **kwargs) + return websockets_with_custom_handshake( + _sign_websocket_handshake_request, + websocket_proxy_options, + cipher_suite, + **kwargs) def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client over websockets, @@ -576,6 +596,7 @@ def websockets_with_custom_handshake( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options=tls_ctx_options, use_websockets=True, websocket_handshake_transform=websocket_handshake_transform, @@ -607,6 +628,7 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client using a custom @@ -673,6 +695,7 @@ def direct_with_custom_authorizer( tls_ctx_options = awscrt.io.TlsContextOptions() tls_ctx_options.alpn_list = ["mqtt"] + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options=tls_ctx_options, use_websockets=False, @@ -688,6 +711,7 @@ def websockets_with_custom_authorizer( websocket_proxy_options=None, auth_token_key_name=None, auth_token_value=None, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client using a custom @@ -757,6 +781,7 @@ def websockets_with_custom_authorizer( kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() + tls_ctx_options.cipher_pref = cipher_suite def _sign_websocket_handshake_request(transform_args, **kwargs): # transform_args need to know when transform is done @@ -773,7 +798,7 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): **kwargs) -def new_default_builder(**kwargs) -> awscrt.mqtt5.Client: +def new_default_builder(cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, without any configuration besides the default TLS context options. @@ -782,6 +807,7 @@ def new_default_builder(**kwargs) -> awscrt.mqtt5.Client: """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options=tls_ctx_options, use_websockets=False, **kwargs) diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index 33ce88d3..0bd83dea 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -258,7 +258,11 @@ def _builder( ) -def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt.Connection: +def mtls_from_path( + cert_filepath, + pri_key_filepath, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. TLS arguments are passed as filepaths. @@ -273,10 +277,15 @@ def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt.Con """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(cert_filepath, pri_key_filepath) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) -def mtls_from_bytes(cert_bytes, pri_key_bytes, **kwargs) -> awscrt.mqtt.Connection: +def mtls_from_bytes( + cert_bytes, + pri_key_bytes, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. TLS arguments are passed as in-memory bytes. @@ -291,6 +300,7 @@ def mtls_from_bytes(cert_bytes, pri_key_bytes, **kwargs) -> awscrt.mqtt.Connecti """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls(cert_bytes, pri_key_bytes) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) @@ -302,6 +312,7 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -347,12 +358,15 @@ def mtls_with_pkcs11(*, private_key_label=private_key_label, cert_file_path=cert_filepath, cert_file_contents=cert_bytes) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) + def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -373,11 +387,13 @@ def mtls_with_pkcs12(*, tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_pkcs12( pkcs12_filepath=pkcs12_filepath, pkcs12_password=pkcs12_password) + tls_ctx_options.cipher_suite = cipher_suite return _builder(tls_ctx_options, **kwargs) def mtls_with_windows_cert_store_path(*, cert_store_path: str, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -396,6 +412,7 @@ def mtls_with_windows_cert_store_path(*, _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path) + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options, **kwargs) @@ -404,6 +421,7 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets to AWS IoT. @@ -441,12 +459,17 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): except Exception as e: transform_args.set_done(e) - return websockets_with_custom_handshake(_sign_websocket_handshake_request, websocket_proxy_options, **kwargs) + return websockets_with_custom_handshake( + _sign_websocket_handshake_request, + cipher_suite, + websocket_proxy_options, + **kwargs) def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets, @@ -474,6 +497,7 @@ def websockets_with_custom_handshake( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() + tls_ctx_options.cipher_pref = cipher_suite return _builder(tls_ctx_options=tls_ctx_options, use_websockets=True, websocket_handshake_transform=websocket_handshake_transform, @@ -505,6 +529,7 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -550,8 +575,10 @@ def direct_with_custom_authorizer( auth_token_key_name=auth_token_key_name, auth_token_value=auth_token_value, use_websockets=False, + cipher_suite: awscrt.io.TlsCipherPref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) + def websockets_with_custom_authorizer( region=None, credentials_provider=None, @@ -561,6 +588,7 @@ def websockets_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -590,7 +618,7 @@ def websockets_with_custom_authorizer( auth_authorizer_signature (`str`): The digital signature of the token value in the `auth_token_value` parameter. The signature must be based on the private key associated with the custom authorizer. The signature must be base64 encoded. - Required if the custom authorizer has signing enabled. + Required if the custom authorizer has signing enabled. auth_token_key_name (`str`): Key used to extract the custom authorizer token from MQTT username query-string properties. @@ -612,19 +640,21 @@ def websockets_with_custom_authorizer( use_websockets=True, websockets_region=region, websockets_credentials_provider=credentials_provider, + cipher_suite: awscrt.io.TlsCipherPref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) def _with_custom_authorizer(auth_username=None, - auth_authorizer_name=None, - auth_authorizer_signature=None, - auth_password=None, - auth_token_key_name=None, - auth_token_value=None, - use_websockets=False, - websockets_credentials_provider=None, - websockets_region=None, - **kwargs) -> awscrt.mqtt.Connection: + auth_authorizer_name=None, + auth_authorizer_signature=None, + auth_password=None, + auth_token_key_name=None, + auth_token_value=None, + use_websockets=False, + websockets_credentials_provider=None, + websockets_region=None, + cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + **kwargs) -> awscrt.mqtt.Connection: """ Helper function that contains the setup needed for custom authorizers """ @@ -657,7 +687,8 @@ def _with_custom_authorizer(auth_username=None, kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - if use_websockets == False: + tls_ctx_options.cipher_pref = cipher_suite + if not use_websockets: kwargs["port"] = 443 tls_ctx_options.alpn_list = ["mqtt"] From 618e718d22750bb97bb669639d8f55bdfa4910af Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 29 Sep 2025 15:23:55 -0700 Subject: [PATCH 2/8] fix positional argument --- awsiot/mqtt_connection_builder.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index 0bd83dea..e7e86c91 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -261,7 +261,7 @@ def _builder( def mtls_from_path( cert_filepath, pri_key_filepath, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. @@ -284,7 +284,7 @@ def mtls_from_path( def mtls_from_bytes( cert_bytes, pri_key_bytes, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. @@ -312,7 +312,7 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -366,7 +366,7 @@ def mtls_with_pkcs11(*, def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -393,7 +393,7 @@ def mtls_with_pkcs12(*, def mtls_with_windows_cert_store_path(*, cert_store_path: str, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -421,7 +421,7 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets to AWS IoT. @@ -469,7 +469,7 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets, @@ -529,7 +529,7 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -575,7 +575,7 @@ def direct_with_custom_authorizer( auth_token_key_name=auth_token_key_name, auth_token_value=auth_token_value, use_websockets=False, - cipher_suite: awscrt.io.TlsCipherPref=awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) @@ -588,7 +588,7 @@ def websockets_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -640,7 +640,7 @@ def websockets_with_custom_authorizer( use_websockets=True, websockets_region=region, websockets_credentials_provider=credentials_provider, - cipher_suite: awscrt.io.TlsCipherPref=awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) @@ -653,7 +653,7 @@ def _with_custom_authorizer(auth_username=None, use_websockets=False, websockets_credentials_provider=None, websockets_region=None, - cipher_suite: awscrt.io.TlsCipherPref = awscrt.io.TlsCipherPref.DEFAULT, + cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ Helper function that contains the setup needed for custom authorizers From d0bc6f314bdec6fbe779147421f6008282ec3d1a Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 29 Sep 2025 16:10:07 -0700 Subject: [PATCH 3/8] fix parameter & change parameter naming --- awsiot/mqtt5_client_builder.py | 42 +++++++++++++++---------------- awsiot/mqtt_connection_builder.py | 42 +++++++++++++++---------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/awsiot/mqtt5_client_builder.py b/awsiot/mqtt5_client_builder.py index 2789f88e..75f41a43 100644 --- a/awsiot/mqtt5_client_builder.py +++ b/awsiot/mqtt5_client_builder.py @@ -362,7 +362,7 @@ def _builder( return client -def mtls_from_path(cert_filepath, pri_key_filepath, cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, +def mtls_from_path(cert_filepath, pri_key_filepath, cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. @@ -378,14 +378,14 @@ def mtls_from_path(cert_filepath, pri_key_filepath, cipher_suite=awscrt.io.TlsCi """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(cert_filepath, pri_key_filepath) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_from_bytes( cert_bytes, pri_key_bytes, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. @@ -401,7 +401,7 @@ def mtls_from_bytes( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls(cert_bytes, pri_key_bytes) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -413,7 +413,7 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT connection to AWS IoT, @@ -459,14 +459,14 @@ def mtls_with_pkcs11(*, private_key_label=private_key_label, cert_file_path=cert_filepath, cert_file_contents=cert_bytes) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -487,13 +487,13 @@ def mtls_with_pkcs12(*, tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_pkcs12( pkcs12_filepath=pkcs12_filepath, pkcs12_password=pkcs12_password) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_with_windows_cert_store_path(*, cert_store_path: str, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT, @@ -512,7 +512,7 @@ def mtls_with_windows_cert_store_path(*, _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -520,7 +520,7 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client over websockets to AWS IoT. @@ -560,15 +560,15 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): return websockets_with_custom_handshake( _sign_websocket_handshake_request, - websocket_proxy_options, - cipher_suite, + websocket_proxy_options = websocket_proxy_options, + cipher_pref = cipher_pref, **kwargs) def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client over websockets, @@ -596,7 +596,7 @@ def websockets_with_custom_handshake( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=True, websocket_handshake_transform=websocket_handshake_transform, @@ -628,7 +628,7 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client using a custom @@ -695,7 +695,7 @@ def direct_with_custom_authorizer( tls_ctx_options = awscrt.io.TlsContextOptions() tls_ctx_options.alpn_list = ["mqtt"] - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=False, @@ -711,7 +711,7 @@ def websockets_with_custom_authorizer( websocket_proxy_options=None, auth_token_key_name=None, auth_token_value=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client using a custom @@ -781,7 +781,7 @@ def websockets_with_custom_authorizer( kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref def _sign_websocket_handshake_request(transform_args, **kwargs): # transform_args need to know when transform is done @@ -798,7 +798,7 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): **kwargs) -def new_default_builder(cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: +def new_default_builder(cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, without any configuration besides the default TLS context options. @@ -807,7 +807,7 @@ def new_default_builder(cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=False, **kwargs) diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index e7e86c91..5c5484ef 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -261,7 +261,7 @@ def _builder( def mtls_from_path( cert_filepath, pri_key_filepath, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. @@ -277,14 +277,14 @@ def mtls_from_path( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(cert_filepath, pri_key_filepath) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_from_bytes( cert_bytes, pri_key_bytes, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. @@ -300,7 +300,7 @@ def mtls_from_bytes( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls(cert_bytes, pri_key_bytes) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -312,7 +312,7 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -358,7 +358,7 @@ def mtls_with_pkcs11(*, private_key_label=private_key_label, cert_file_path=cert_filepath, cert_file_contents=cert_bytes) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -366,7 +366,7 @@ def mtls_with_pkcs11(*, def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -387,13 +387,13 @@ def mtls_with_pkcs12(*, tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_pkcs12( pkcs12_filepath=pkcs12_filepath, pkcs12_password=pkcs12_password) - tls_ctx_options.cipher_suite = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_with_windows_cert_store_path(*, cert_store_path: str, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -412,7 +412,7 @@ def mtls_with_windows_cert_store_path(*, _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path) - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -421,7 +421,7 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets to AWS IoT. @@ -461,15 +461,15 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): return websockets_with_custom_handshake( _sign_websocket_handshake_request, - cipher_suite, - websocket_proxy_options, + websocket_proxy_options = websocket_proxy_options, + cipher_pref = cipher_pref, **kwargs) def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets, @@ -497,7 +497,7 @@ def websockets_with_custom_handshake( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=True, websocket_handshake_transform=websocket_handshake_transform, @@ -529,7 +529,7 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -575,7 +575,7 @@ def direct_with_custom_authorizer( auth_token_key_name=auth_token_key_name, auth_token_value=auth_token_value, use_websockets=False, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) @@ -588,7 +588,7 @@ def websockets_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -640,7 +640,7 @@ def websockets_with_custom_authorizer( use_websockets=True, websockets_region=region, websockets_credentials_provider=credentials_provider, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) @@ -653,7 +653,7 @@ def _with_custom_authorizer(auth_username=None, use_websockets=False, websockets_credentials_provider=None, websockets_region=None, - cipher_suite=awscrt.io.TlsCipherPref.DEFAULT, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ Helper function that contains the setup needed for custom authorizers @@ -687,7 +687,7 @@ def _with_custom_authorizer(auth_username=None, kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_suite + tls_ctx_options.cipher_pref = cipher_pref if not use_websockets: kwargs["port"] = 443 tls_ctx_options.alpn_list = ["mqtt"] From 96677e5f2962b27a0c7222cd90784cf896ff88ef Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Fri, 17 Oct 2025 09:43:32 -0700 Subject: [PATCH 4/8] move cipher suite to builder option --- awsiot/mqtt5_client_builder.py | 28 +++++++--------------------- awsiot/mqtt_connection_builder.py | 26 +++++--------------------- 2 files changed, 12 insertions(+), 42 deletions(-) diff --git a/awsiot/mqtt5_client_builder.py b/awsiot/mqtt5_client_builder.py index 75f41a43..e03f4dbd 100644 --- a/awsiot/mqtt5_client_builder.py +++ b/awsiot/mqtt5_client_builder.py @@ -243,6 +243,7 @@ def _builder( use_websockets=False, websocket_handshake_transform=None, use_custom_authorizer=False, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs): username = _get(kwargs, 'username', '') @@ -345,6 +346,9 @@ def _builder( elif ca_filepath or ca_dirpath: tls_ctx_options.override_default_trust_store_from_path(ca_dirpath, ca_filepath) + if cipher_pref is not None: + tls_ctx_options.cipher_pref = cipher_pref + if client_options.port is None: # prefer 443, even for direct MQTT connections, since it's less likely to be blocked by firewalls if use_websockets or awscrt.io.is_alpn_available(): @@ -362,7 +366,7 @@ def _builder( return client -def mtls_from_path(cert_filepath, pri_key_filepath, cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, +def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. @@ -378,14 +382,12 @@ def mtls_from_path(cert_filepath, pri_key_filepath, cipher_pref=awscrt.io.TlsCip """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(cert_filepath, pri_key_filepath) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_from_bytes( cert_bytes, pri_key_bytes, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. @@ -401,7 +403,6 @@ def mtls_from_bytes( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls(cert_bytes, pri_key_bytes) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -413,7 +414,6 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT connection to AWS IoT, @@ -459,14 +459,12 @@ def mtls_with_pkcs11(*, private_key_label=private_key_label, cert_file_path=cert_filepath, cert_file_contents=cert_bytes) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -487,13 +485,11 @@ def mtls_with_pkcs12(*, tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_pkcs12( pkcs12_filepath=pkcs12_filepath, pkcs12_password=pkcs12_password) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_with_windows_cert_store_path(*, cert_store_path: str, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT, @@ -512,7 +508,6 @@ def mtls_with_windows_cert_store_path(*, _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -520,7 +515,6 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client over websockets to AWS IoT. @@ -560,15 +554,13 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): return websockets_with_custom_handshake( _sign_websocket_handshake_request, - websocket_proxy_options = websocket_proxy_options, - cipher_pref = cipher_pref, + websocket_proxy_options, **kwargs) def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client over websockets, @@ -596,7 +588,6 @@ def websockets_with_custom_handshake( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=True, websocket_handshake_transform=websocket_handshake_transform, @@ -628,7 +619,6 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client using a custom @@ -695,7 +685,6 @@ def direct_with_custom_authorizer( tls_ctx_options = awscrt.io.TlsContextOptions() tls_ctx_options.alpn_list = ["mqtt"] - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=False, @@ -711,7 +700,6 @@ def websockets_with_custom_authorizer( websocket_proxy_options=None, auth_token_key_name=None, auth_token_value=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an MQTT5 Client using a custom @@ -781,7 +769,6 @@ def websockets_with_custom_authorizer( kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_pref def _sign_websocket_handshake_request(transform_args, **kwargs): # transform_args need to know when transform is done @@ -798,7 +785,7 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): **kwargs) -def new_default_builder(cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt5.Client: +def new_default_builder(**kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, without any configuration besides the default TLS context options. @@ -807,7 +794,6 @@ def new_default_builder(cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) - """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=False, **kwargs) diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index 5c5484ef..81946210 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -181,6 +181,7 @@ def _builder( use_websockets=False, websocket_handshake_transform=None, use_custom_authorizer=False, + cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs): ca_bytes = _get(kwargs, 'ca_bytes') @@ -202,6 +203,9 @@ def _builder( if port == 443 and awscrt.io.is_alpn_available() and use_custom_authorizer is False: tls_ctx_options.alpn_list = ['http/1.1'] if use_websockets else ['x-amzn-mqtt-ca'] + if cipher_pref != awscrt.io.TlsCipherPref.DEFAULT: + tls_ctx_options.cipher_pref = cipher_pref + socket_options = awscrt.io.SocketOptions() socket_options.connect_timeout_ms = _get(kwargs, 'tcp_connect_timeout_ms', 5000) # These have been inconsistent between keepalive/keep_alive. Resolve both for now to ease transition. @@ -261,7 +265,6 @@ def _builder( def mtls_from_path( cert_filepath, pri_key_filepath, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. @@ -277,14 +280,12 @@ def mtls_from_path( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(cert_filepath, pri_key_filepath) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_from_bytes( cert_bytes, pri_key_bytes, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. @@ -300,7 +301,6 @@ def mtls_from_bytes( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls(cert_bytes, pri_key_bytes) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -312,7 +312,6 @@ def mtls_with_pkcs11(*, private_key_label: str = None, cert_filepath: str = None, cert_bytes=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -358,7 +357,6 @@ def mtls_with_pkcs11(*, private_key_label=private_key_label, cert_file_path=cert_filepath, cert_file_contents=cert_bytes) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -366,7 +364,6 @@ def mtls_with_pkcs11(*, def mtls_with_pkcs12(*, pkcs12_filepath: str, pkcs12_password: str, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -387,13 +384,11 @@ def mtls_with_pkcs12(*, tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_pkcs12( pkcs12_filepath=pkcs12_filepath, pkcs12_password=pkcs12_password) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) def mtls_with_windows_cert_store_path(*, cert_store_path: str, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT, @@ -412,7 +407,6 @@ def mtls_with_windows_cert_store_path(*, _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path) - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options, **kwargs) @@ -421,7 +415,6 @@ def websockets_with_default_aws_signing( region, credentials_provider, websocket_proxy_options=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets to AWS IoT. @@ -461,15 +454,13 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): return websockets_with_custom_handshake( _sign_websocket_handshake_request, - websocket_proxy_options = websocket_proxy_options, - cipher_pref = cipher_pref, + websocket_proxy_options=websocket_proxy_options, **kwargs) def websockets_with_custom_handshake( websocket_handshake_transform, websocket_proxy_options=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection over websockets, @@ -497,7 +488,6 @@ def websockets_with_custom_handshake( """ _check_required_kwargs(**kwargs) tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_pref return _builder(tls_ctx_options=tls_ctx_options, use_websockets=True, websocket_handshake_transform=websocket_handshake_transform, @@ -529,7 +519,6 @@ def direct_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -575,7 +564,6 @@ def direct_with_custom_authorizer( auth_token_key_name=auth_token_key_name, auth_token_value=auth_token_value, use_websockets=False, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) @@ -588,7 +576,6 @@ def websockets_with_custom_authorizer( auth_password=None, auth_token_key_name=None, auth_token_value=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an MQTT connection using a custom @@ -640,7 +627,6 @@ def websockets_with_custom_authorizer( use_websockets=True, websockets_region=region, websockets_credentials_provider=credentials_provider, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) @@ -653,7 +639,6 @@ def _with_custom_authorizer(auth_username=None, use_websockets=False, websockets_credentials_provider=None, websockets_region=None, - cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs) -> awscrt.mqtt.Connection: """ Helper function that contains the setup needed for custom authorizers @@ -687,7 +672,6 @@ def _with_custom_authorizer(auth_username=None, kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - tls_ctx_options.cipher_pref = cipher_pref if not use_websockets: kwargs["port"] = 443 tls_ctx_options.alpn_list = ["mqtt"] From 30f3ab2773df4084176a1dbe13acfd0a9b59ac71 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 20 Oct 2025 09:55:48 -0700 Subject: [PATCH 5/8] fix format --- awsiot/mqtt5_client_builder.py | 8 ++----- awsiot/mqtt_connection_builder.py | 38 ++++++++++++------------------- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/awsiot/mqtt5_client_builder.py b/awsiot/mqtt5_client_builder.py index e03f4dbd..c1a59627 100644 --- a/awsiot/mqtt5_client_builder.py +++ b/awsiot/mqtt5_client_builder.py @@ -366,8 +366,7 @@ def _builder( return client -def mtls_from_path(cert_filepath, pri_key_filepath, - **kwargs) -> awscrt.mqtt5.Client: +def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. TLS arguments are passed as filepaths. @@ -385,10 +384,7 @@ def mtls_from_path(cert_filepath, pri_key_filepath, return _builder(tls_ctx_options, **kwargs) -def mtls_from_bytes( - cert_bytes, - pri_key_bytes, - **kwargs) -> awscrt.mqtt5.Client: +def mtls_from_bytes(cert_bytes, pri_key_bytes, **kwargs) -> awscrt.mqtt5.Client: """ This builder creates an :class:`awscrt.mqtt5.Client`, configured for an mTLS MQTT5 Client to AWS IoT. TLS arguments are passed as in-memory bytes. diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index 81946210..436ec8be 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -262,10 +262,7 @@ def _builder( ) -def mtls_from_path( - cert_filepath, - pri_key_filepath, - **kwargs) -> awscrt.mqtt.Connection: +def mtls_from_path(cert_filepath, pri_key_filepath, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. TLS arguments are passed as filepaths. @@ -283,10 +280,7 @@ def mtls_from_path( return _builder(tls_ctx_options, **kwargs) -def mtls_from_bytes( - cert_bytes, - pri_key_bytes, - **kwargs) -> awscrt.mqtt.Connection: +def mtls_from_bytes(cert_bytes, pri_key_bytes, **kwargs) -> awscrt.mqtt.Connection: """ This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT. TLS arguments are passed as in-memory bytes. @@ -452,10 +446,7 @@ def _sign_websocket_handshake_request(transform_args, **kwargs): except Exception as e: transform_args.set_done(e) - return websockets_with_custom_handshake( - _sign_websocket_handshake_request, - websocket_proxy_options=websocket_proxy_options, - **kwargs) + return websockets_with_custom_handshake(_sign_websocket_handshake_request, websocket_proxy_options, **kwargs) def websockets_with_custom_handshake( @@ -566,7 +557,6 @@ def direct_with_custom_authorizer( use_websockets=False, **kwargs) - def websockets_with_custom_authorizer( region=None, credentials_provider=None, @@ -605,7 +595,7 @@ def websockets_with_custom_authorizer( auth_authorizer_signature (`str`): The digital signature of the token value in the `auth_token_value` parameter. The signature must be based on the private key associated with the custom authorizer. The signature must be base64 encoded. - Required if the custom authorizer has signing enabled. + Required if the custom authorizer has signing enabled. auth_token_key_name (`str`): Key used to extract the custom authorizer token from MQTT username query-string properties. @@ -631,15 +621,15 @@ def websockets_with_custom_authorizer( def _with_custom_authorizer(auth_username=None, - auth_authorizer_name=None, - auth_authorizer_signature=None, - auth_password=None, - auth_token_key_name=None, - auth_token_value=None, - use_websockets=False, - websockets_credentials_provider=None, - websockets_region=None, - **kwargs) -> awscrt.mqtt.Connection: + auth_authorizer_name=None, + auth_authorizer_signature=None, + auth_password=None, + auth_token_key_name=None, + auth_token_value=None, + use_websockets=False, + websockets_credentials_provider=None, + websockets_region=None, + **kwargs) -> awscrt.mqtt.Connection: """ Helper function that contains the setup needed for custom authorizers """ @@ -672,7 +662,7 @@ def _with_custom_authorizer(auth_username=None, kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - if not use_websockets: + if use_websockets == False: kwargs["port"] = 443 tls_ctx_options.alpn_list = ["mqtt"] From 7e4dd31883a1ca32e7d2523e28c0b8c8abaa1e02 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 21 Oct 2025 10:01:01 -0700 Subject: [PATCH 6/8] add cipher_pref in builder doc --- awsiot/mqtt5_client_builder.py | 2 ++ awsiot/mqtt_connection_builder.py | 25 ++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/awsiot/mqtt5_client_builder.py b/awsiot/mqtt5_client_builder.py index c1a59627..9e131641 100644 --- a/awsiot/mqtt5_client_builder.py +++ b/awsiot/mqtt5_client_builder.py @@ -168,6 +168,8 @@ **ca_bytes** (`bytes`): Override default trust store with CA certificates from these PEM formatted bytes. + **cipher_pref** (:class:`awscrt.io.TlsCipherPref`): Cipher preference to use for TLS connection. Default is `TlsCipherPref.DEFAULT`. + **enable_metrics_collection** (`bool`): Whether to send the SDK version number in the CONNECT packet. Default is True. diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index 436ec8be..facf5770 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -111,6 +111,8 @@ **ca_bytes** (`bytes`): Override default trust store with CA certificates from these PEM formatted bytes. + **cipher_pref** (:class:`awscrt.io.TlsCipherPref`): Cipher preference to use for TLS connection. Default is `TlsCipherPref.DEFAULT`. + **enable_metrics_collection** (`bool`): Whether to send the SDK version number in the CONNECT packet. Default is True. @@ -557,6 +559,7 @@ def direct_with_custom_authorizer( use_websockets=False, **kwargs) + def websockets_with_custom_authorizer( region=None, credentials_provider=None, @@ -595,7 +598,7 @@ def websockets_with_custom_authorizer( auth_authorizer_signature (`str`): The digital signature of the token value in the `auth_token_value` parameter. The signature must be based on the private key associated with the custom authorizer. The signature must be base64 encoded. - Required if the custom authorizer has signing enabled. + Required if the custom authorizer has signing enabled. auth_token_key_name (`str`): Key used to extract the custom authorizer token from MQTT username query-string properties. @@ -621,15 +624,15 @@ def websockets_with_custom_authorizer( def _with_custom_authorizer(auth_username=None, - auth_authorizer_name=None, - auth_authorizer_signature=None, - auth_password=None, - auth_token_key_name=None, - auth_token_value=None, - use_websockets=False, - websockets_credentials_provider=None, - websockets_region=None, - **kwargs) -> awscrt.mqtt.Connection: + auth_authorizer_name=None, + auth_authorizer_signature=None, + auth_password=None, + auth_token_key_name=None, + auth_token_value=None, + use_websockets=False, + websockets_credentials_provider=None, + websockets_region=None, + **kwargs) -> awscrt.mqtt.Connection: """ Helper function that contains the setup needed for custom authorizers """ @@ -662,7 +665,7 @@ def _with_custom_authorizer(auth_username=None, kwargs["password"] = auth_password tls_ctx_options = awscrt.io.TlsContextOptions() - if use_websockets == False: + if not use_websockets: kwargs["port"] = 443 tls_ctx_options.alpn_list = ["mqtt"] From 64ccc02f0fcf01d05603b67f63e0e33389ca0fe0 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Thu, 30 Oct 2025 14:06:32 -0700 Subject: [PATCH 7/8] update awscrt to 0.28.3 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c2df83a8..be29ce3c 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ def _load_version(): "Operating System :: OS Independent", ], install_requires=[ - 'awscrt==0.28.1', + 'awscrt==0.28.3', ], python_requires='>=3.8', ) From 79284940cd3eea6f1c079f986524a660f4b7eee5 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Fri, 21 Nov 2025 14:02:26 -0800 Subject: [PATCH 8/8] validate TlsCipherPref --- awsiot/mqtt5_client_builder.py | 5 +++-- awsiot/mqtt_connection_builder.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/awsiot/mqtt5_client_builder.py b/awsiot/mqtt5_client_builder.py index 9e131641..ae9b9750 100644 --- a/awsiot/mqtt5_client_builder.py +++ b/awsiot/mqtt5_client_builder.py @@ -248,6 +248,8 @@ def _builder( cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs): + assert isinstance(cipher_pref, awscrt.io.TlsCipherPref) + username = _get(kwargs, 'username', '') if _get(kwargs, 'enable_metrics_collection', True): username += _get_metrics_str(username) @@ -348,8 +350,7 @@ def _builder( elif ca_filepath or ca_dirpath: tls_ctx_options.override_default_trust_store_from_path(ca_dirpath, ca_filepath) - if cipher_pref is not None: - tls_ctx_options.cipher_pref = cipher_pref + tls_ctx_options.cipher_pref = cipher_pref if client_options.port is None: # prefer 443, even for direct MQTT connections, since it's less likely to be blocked by firewalls diff --git a/awsiot/mqtt_connection_builder.py b/awsiot/mqtt_connection_builder.py index facf5770..75144563 100644 --- a/awsiot/mqtt_connection_builder.py +++ b/awsiot/mqtt_connection_builder.py @@ -186,6 +186,8 @@ def _builder( cipher_pref=awscrt.io.TlsCipherPref.DEFAULT, **kwargs): + assert isinstance(cipher_pref, awscrt.io.TlsCipherPref) + ca_bytes = _get(kwargs, 'ca_bytes') ca_filepath = _get(kwargs, 'ca_filepath') ca_dirpath = _get(kwargs, 'ca_dirpath') @@ -205,8 +207,7 @@ def _builder( if port == 443 and awscrt.io.is_alpn_available() and use_custom_authorizer is False: tls_ctx_options.alpn_list = ['http/1.1'] if use_websockets else ['x-amzn-mqtt-ca'] - if cipher_pref != awscrt.io.TlsCipherPref.DEFAULT: - tls_ctx_options.cipher_pref = cipher_pref + tls_ctx_options.cipher_pref = cipher_pref socket_options = awscrt.io.SocketOptions() socket_options.connect_timeout_ms = _get(kwargs, 'tcp_connect_timeout_ms', 5000)