From 6042a8d772e488fe2148cf576c2e50be283ba996 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 11:20:12 -0700 Subject: [PATCH 01/40] remove deprecated samples --- samples/deprecated/fleetprovisioning.md | 311 ------ samples/deprecated/fleetprovisioning.py | 388 -------- samples/deprecated/fleetprovisioning_mqtt5.md | 371 ------- samples/deprecated/fleetprovisioning_mqtt5.py | 376 ------- samples/deprecated/jobs.md | 84 -- samples/deprecated/jobs.py | 396 -------- samples/deprecated/jobs_mqtt5.md | 144 --- samples/deprecated/jobs_mqtt5.py | 405 -------- samples/deprecated/shadow.md | 87 -- samples/deprecated/shadow.py | 426 -------- samples/deprecated/shadow_mqtt5.md | 146 --- samples/deprecated/shadow_mqtt5.py | 433 -------- .../deprecated/utils/command_line_utils.py | 922 ------------------ 13 files changed, 4489 deletions(-) delete mode 100644 samples/deprecated/fleetprovisioning.md delete mode 100644 samples/deprecated/fleetprovisioning.py delete mode 100644 samples/deprecated/fleetprovisioning_mqtt5.md delete mode 100644 samples/deprecated/fleetprovisioning_mqtt5.py delete mode 100644 samples/deprecated/jobs.md delete mode 100644 samples/deprecated/jobs.py delete mode 100644 samples/deprecated/jobs_mqtt5.md delete mode 100644 samples/deprecated/jobs_mqtt5.py delete mode 100644 samples/deprecated/shadow.md delete mode 100644 samples/deprecated/shadow.py delete mode 100644 samples/deprecated/shadow_mqtt5.md delete mode 100644 samples/deprecated/shadow_mqtt5.py delete mode 100644 samples/deprecated/utils/command_line_utils.py diff --git a/samples/deprecated/fleetprovisioning.md b/samples/deprecated/fleetprovisioning.md deleted file mode 100644 index e035f416..00000000 --- a/samples/deprecated/fleetprovisioning.md +++ /dev/null @@ -1,311 +0,0 @@ -# Fleet provisioning - -[**Return to main sample list**](../README.md) - -This sample uses the AWS IoT [Fleet provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html) to provision devices using either a CSR or Keys-And-Certificate and subsequently calls RegisterThing. This allows you to create new AWS IoT Core things using a Fleet Provisioning Template. - -On startup, the script subscribes to topics based on the request type of either CSR or Keys topics, publishes the request to corresponding topic and calls RegisterThing. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": "iot:Publish",
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/certificates/create/json",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create-from-csr/json",
-        "arn:aws:iot:region:account:topic/$aws/provisioning-templates/templatename/provision/json"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Receive"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/certificates/create/json/accepted",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create/json/rejected",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create-from-csr/json/accepted",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create-from-csr/json/rejected",
-        "arn:aws:iot:region:account:topic/$aws/provisioning-templates/templatename/provision/json/accepted",
-        "arn:aws:iot:region:account:topic/$aws/provisioning-templates/templatename/provision/json/rejected"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Subscribe"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create/json/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create/json/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create-from-csr/json/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create-from-csr/json/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/provisioning-templates/templatename/provision/json/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/provisioning-templates/templatename/provision/json/rejected"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Connect",
-      "Resource": "arn:aws:iot:region:account:client/test-*"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS Fleet Provisioning template you want to use to create new AWS IoT Core Things. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -There are many different ways to run the Fleet Provisioning sample because of how many different ways there are to setup a Fleet Provisioning template in AWS IoT Core. **The easiest and most common way is to run the sample with the following**: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning.py --endpoint --cert --key --template_name --template_parameters -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning.py --endpoint --cert --key --template_name --template_parameters --ca_file -``` - -However, this is just one way using the `CreateKeysAndCertificate` workflow. Below are a detailed list of instructions with the different ways to connect. While the detailed instructions do not show it, you can pass `--ca_file` as needed no matter which way you connect via Fleet Provisioning. - -### Fleet Provisioning Detailed Instructions - -#### Aws Resource Setup - -Fleet provisioning requires some additional AWS resources be set up first. These steps assume you have the [AWS CLI](https://aws.amazon.com/cli/) installed and have your AWS credentials for the AWS CLI setup and with sufficient permissions to perform all of the operations in this guide. For instructions on how to setup AWS CLI, see the following: [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). - -You will also need Python version 3 installed to be able to run the `parse_cert_set_result.py` file, which is a helper script to make running this sample easier. You can find Python3 installers for your platform on the [Python website](https://www.python.org/). - -These steps are based on the provisioning setup steps -that can be found at [Embedded C SDK Setup](https://docs.aws.amazon.com/freertos/latest/lib-ref/c-sdk/provisioning/provisioning_tests.html#provisioning_system_tests_setup). - - -First, create the IAM role that will be needed by the fleet provisioning template. Replace `` with a name of the role you want to create. - -``` sh -aws iam create-role \ - --role-name \ - --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"iot.amazonaws.com"}}]}' -``` - -This is the IAM role the Fleet Provisioning template will use to create the new AWS IoT things. However, before it can do so, it will need to have a policy attached to it to give the new role permission to perform the operations it needs. To do this, run the following command and replace `` with the name of the role you created in the previous step. - -``` sh -aws iam attach-role-policy \ - --role-name \ - --policy-arn arn:aws:iam::aws:policy/service-role/AWSIoTThingsRegistration -``` - -The next step is to make a template resource that will be used for provisioning the new AWS IoT Core things. This template tells AWS IoT Core how to setup the new AWS IoT Core Things you create when your Fleet Provisioning role is invoked, setting up material such as the name and tags, for example. - -To create a new Fleet Provisioning template, you can use the following AWS CLI command, replacing `` with the name of the template you wish to create, `` with the name of the role you created two steps prior, and `` with your AWS IoT Core account number. Finally, make sure to replace `` with a valid JSON document as a single line. An example JSON document is provided further below. - -``` sh -aws iot create-provisioning-template \ - --template-name \ - --provisioning-role-arn arn:aws:iam:::role/ \ - --template-body "" \ - --enabled -``` - -For the purposes of this sample, the following template JSON document is presumed to be used: - -
-(see template body) - -```json -{ - "Parameters": { - "DeviceLocation": { - "Type": "String" - }, - "AWS::IoT::Certificate::Id": { - "Type": "String" - }, - "SerialNumber": { - "Type": "String" - } - }, - "Mappings": { - "LocationTable": { - "Seattle": { - "LocationUrl": "https://example.aws" - } - } - }, - "Resources": { - "thing": { - "Type": "AWS::IoT::Thing", - "Properties": { - "ThingName": { - "Fn::Join": [ - "", - [ - "ThingPrefix_", - { - "Ref": "SerialNumber" - } - ] - ] - }, - "AttributePayload": { - "version": "v1", - "serialNumber": "serialNumber" - } - }, - "OverrideSettings": { - "AttributePayload": "MERGE", - "ThingTypeName": "REPLACE", - "ThingGroups": "DO_NOTHING" - } - }, - "certificate": { - "Type": "AWS::IoT::Certificate", - "Properties": { - "CertificateId": { - "Ref": "AWS::IoT::Certificate::Id" - }, - "Status": "Active" - }, - "OverrideSettings": { - "Status": "REPLACE" - } - }, - "policy": { - "Type": "AWS::IoT::Policy", - "Properties": { - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "iot:Connect", - "iot:Subscribe", - "iot:Publish", - "iot:Receive" - ], - "Resource": "*" - } - ] - } - } - } - }, - "DeviceConfiguration": { - "FallbackUrl": "https://www.example.com/test-site", - "LocationUrl": { - "Fn::FindInMap": [ - "LocationTable", - { - "Ref": "DeviceLocation" - }, - "LocationUrl" - ] - } - } -} -``` - -
- -And here is the same JSON document, but as a single line for easier copy-pasting: - -
-(see template body) - -``` json -{"Parameters": {"DeviceLocation": {"Type": "String"},"AWS::IoT::Certificate::Id": {"Type": "String"},"SerialNumber": {"Type": "String"}},"Mappings": {"LocationTable": {"Seattle": {"LocationUrl": "https://example.aws"}}},"Resources": {"thing": {"Type": "AWS::IoT::Thing","Properties": {"ThingName": {"Fn::Join": ["",["ThingPrefix_",{"Ref": "SerialNumber"}]]},"AttributePayload": {"version": "v1","serialNumber": "serialNumber"}},"OverrideSettings": {"AttributePayload": "MERGE","ThingTypeName": "REPLACE","ThingGroups": "DO_NOTHING"}},"certificate": {"Type": "AWS::IoT::Certificate","Properties": {"CertificateId": {"Ref": "AWS::IoT::Certificate::Id"},"Status": "Active"},"OverrideSettings": {"Status": "REPLACE"}},"policy": {"Type": "AWS::IoT::Policy","Properties": {"PolicyDocument": {"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["iot:Connect","iot:Subscribe","iot:Publish","iot:Receive"],"Resource": "*"}]}}}},"DeviceConfiguration": {"FallbackUrl": "https://www.example.com/test-site","LocationUrl": {"Fn::FindInMap": ["LocationTable",{"Ref": "DeviceLocation"},"LocationUrl"]}}} -``` - -
- -You can use this JSON document as the `` in the AWS CLI command. This sample will assume you have used the template JSON above, so you may need to adjust if you are using a different template JSON. Thankfully, all of these steps need to only be done and, now that they are complete, you will need not perform them again. - -#### Creating a certificate-key set from a provisioning claim - -To run the provisioning sample, you'll need a certificate and key set with sufficient permissions. Provisioning certificates are normally created ahead of time and placed on your device, but for this sample, we will just create them on the fly. This is primarily done for example purposes. - -You can also use any certificate set you've already created if it has sufficient IoT permissions. If you wish to do this, you can skip the step that calls `create-provisioning-claim` below and move right to the next step: [Running the sample using a certificate-key set](#running-the-sample-using-a-certificate-key-set) - -We've included a script in the utils folder that creates certificate and key files from the response of calling -`create-provisioning-claim`. These dynamically sourced certificates are **only valid for five minutes**. When running the command, -you'll need to substitute the name of the template you previously created. If on Windows, replace the paths with something appropriate. - -**Note**: The following assumes you are running this command from the `aws-iot-device-sdk-java-v2` folder, which is the main GitHub folder. If you are running this from another folder (like the `samples/Identity` folder), then you will need to adjust the filepaths accordingly. - -```sh -aws iot create-provisioning-claim \ - --template-name \ - | python3 ./utils/parse_cert_set_result.py \ - --path ./tmp \ - --filename provision -``` -* Replace `` with the name of the Fleet Provisioning template you created earlier. - -This will create a certificate and key in the `tmp` folder with file names starting with `provision`. You can now use these temporary keys -to perform the actual provisioning in the section below. - -#### Running the sample using a certificate-key set - -To run the sample with your certificate and private key, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning.py --endpoint --cert --key --template_name --template_parameters '{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}' -``` - -As per normal, replace the `<>` parameters with the proper values. Notice that we provided substitution values for the two parameters in the template body, `DeviceLocation` and `SerialNumber`. - -With that, the sample should run and work as expected! You should then find your have a new AWS IoT Core thing! - -### Run the sample using the certificate signing request workflow - -To run the sample with this workflow, you'll need to create a certificate signing request in addition to the other steps above (creating the role, setting its policy, setting the template JSON, etc). - -First create a certificate-key pair: -``` sh -openssl genrsa -out /tmp/deviceCert.key 2048 -``` - -Next create a certificate signing request from it: -``` sh -openssl req -new -key /tmp/deviceCert.key -out /tmp/deviceCert.csr -``` - -As in the previous workflow, you can [create a temporary certificate set from a provisioning claim](#creating-a-certificate-key-set-from-a-provisioning-claim). Again, this can be skipped if you have a policy and certificate with the proper permissions. - -```sh -aws iot create-provisioning-claim \ - --template-name \ - | python3 ./utils/parse_cert_set_result.py \ - --path ./tmp \ - --filename provision -``` -* Replace `` with the name of the Fleet Provisioning template you created earlier. - -Finally, you can also pass the certificate signing request while invoking the Fleet Provisioning sample. - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning.py --endpoint --cert --key --template_name --template_parameters '{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}' --csr -``` diff --git a/samples/deprecated/fleetprovisioning.py b/samples/deprecated/fleetprovisioning.py deleted file mode 100644 index a47d90fb..00000000 --- a/samples/deprecated/fleetprovisioning.py +++ /dev/null @@ -1,388 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import mqtt, http -from awsiot import iotidentity, mqtt_connection_builder -from concurrent.futures import Future -import sys -import threading -import time -import traceback -import json -from utils.command_line_utils import CommandLineUtils - -# - Overview - -# This sample uses the AWS IoT Fleet Provisioning to provision device using either the keys -# or CSR -# -# -# - Instructions - -# This sample requires you to create a provisioning claim. See: -# https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html -# -# - Detail - -# On startup, the script subscribes to topics based on the request type of either CSR or Keys -# publishes the request to corresponding topic and calls RegisterThing. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_fleet_provisioning() - -# Using globals to simplify sample code -is_sample_done = threading.Event() -mqtt_connection = None -identity_client = None -createKeysAndCertificateResponse = None -createCertificateFromCsrResponse = None -registerThingResponse = None - - -class LockedData: - def __init__(self): - self.lock = threading.Lock() - self.disconnect_called = False - - -locked_data = LockedData() - -# Function for gracefully quitting this sample -def exit(msg_or_exception): - if isinstance(msg_or_exception, Exception): - print("Exiting Sample due to exception.") - traceback.print_exception(msg_or_exception.__class__, msg_or_exception, sys.exc_info()[2]) - else: - print("Exiting Sample:", msg_or_exception) - - with locked_data.lock: - if not locked_data.disconnect_called: - print("Disconnecting...") - locked_data.disconnect_called = True - future = mqtt_connection.disconnect() - future.add_done_callback(on_disconnected) - - -def on_disconnected(disconnect_future): - # type: (Future) -> None - print("Disconnected.") - - # Signal that sample is finished - is_sample_done.set() - - -def on_publish_register_thing(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published RegisterThing request..") - - except Exception as e: - print("Failed to publish RegisterThing request.") - exit(e) - - -def on_publish_create_keys_and_certificate(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published CreateKeysAndCertificate request..") - - except Exception as e: - print("Failed to publish CreateKeysAndCertificate request.") - exit(e) - - -def on_publish_create_certificate_from_csr(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published CreateCertificateFromCsr request..") - - except Exception as e: - print("Failed to publish CreateCertificateFromCsr request.") - exit(e) - - -def createkeysandcertificate_execution_accepted(response): - # type: (iotidentity.CreateKeysAndCertificateResponse) -> None - try: - global createKeysAndCertificateResponse - createKeysAndCertificateResponse = response - if (cmdData.input_is_ci == False): - print("Received a new message {}".format(createKeysAndCertificateResponse)) - - return - - except Exception as e: - exit(e) - - -def createkeysandcertificate_execution_rejected(rejected): - # type: (iotidentity.RejectedError) -> None - exit("CreateKeysAndCertificate Request rejected with code:'{}' message:'{}' status code:'{}'".format( - rejected.error_code, rejected.error_message, rejected.status_code)) - - -def createcertificatefromcsr_execution_accepted(response): - # type: (iotidentity.CreateCertificateFromCsrResponse) -> None - try: - global createCertificateFromCsrResponse - createCertificateFromCsrResponse = response - if (cmdData.input_is_ci == False): - print("Received a new message {}".format(createCertificateFromCsrResponse)) - global certificateOwnershipToken - certificateOwnershipToken = response.certificate_ownership_token - - return - - except Exception as e: - exit(e) - - -def createcertificatefromcsr_execution_rejected(rejected): - # type: (iotidentity.RejectedError) -> None - exit("CreateCertificateFromCsr Request rejected with code:'{}' message:'{}' status code:'{}'".format( - rejected.error_code, rejected.error_message, rejected.status_code)) - - -def registerthing_execution_accepted(response): - # type: (iotidentity.RegisterThingResponse) -> None - try: - global registerThingResponse - registerThingResponse = response - if (cmdData.input_is_ci == False): - print("Received a new message {} ".format(registerThingResponse)) - return - - except Exception as e: - exit(e) - - -def registerthing_execution_rejected(rejected): - # type: (iotidentity.RejectedError) -> None - exit("RegisterThing Request rejected with code:'{}' message:'{}' status code:'{}'".format( - rejected.error_code, rejected.error_message, rejected.status_code)) - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - if return_code == mqtt.ConnectReturnCode.ACCEPTED and not session_present: - print("Session did not persist. Resubscribing to existing topics...") - resubscribe_future, _ = connection.resubscribe_existing_topics() - - # Cannot synchronously wait for resubscribe result because we're on the connection's event-loop thread, - # evaluate result with a callback instead. - resubscribe_future.add_done_callback(on_resubscribe_complete) - - -def on_resubscribe_complete(resubscribe_future): - resubscribe_results = resubscribe_future.result() - print("Resubscribe results: {}".format(resubscribe_results)) - - for topic, qos in resubscribe_results['topics']: - if qos is None: - sys.exit("Server rejected resubscribe to topic: {}".format(topic)) - - -def waitForCreateKeysAndCertificateResponse(): - # Wait for the response. - loopCount = 0 - while loopCount < 10 and createKeysAndCertificateResponse is None: - if createKeysAndCertificateResponse is not None: - break - if not cmdData.input_is_ci: - print('Waiting... CreateKeysAndCertificateResponse: ' + json.dumps(createKeysAndCertificateResponse)) - else: - print("Waiting... CreateKeysAndCertificateResponse: ...") - loopCount += 1 - time.sleep(1) - - -def waitForCreateCertificateFromCsrResponse(): - # Wait for the response. - loopCount = 0 - while loopCount < 10 and createCertificateFromCsrResponse is None: - if createCertificateFromCsrResponse is not None: - break - if not cmdData.input_is_ci: - print('Waiting...CreateCertificateFromCsrResponse: ' + json.dumps(createCertificateFromCsrResponse)) - else: - print("Waiting... CreateCertificateFromCsrResponse: ...") - loopCount += 1 - time.sleep(1) - - -def waitForRegisterThingResponse(): - # Wait for the response. - loopCount = 0 - while loopCount < 20 and registerThingResponse is None: - if registerThingResponse is not None: - break - loopCount += 1 - if not cmdData.input_is_ci: - print('Waiting... RegisterThingResponse: ' + json.dumps(registerThingResponse)) - else: - print('Waiting... RegisterThingResponse: ...') - time.sleep(1) - - -if __name__ == '__main__': - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connected_future = mqtt_connection.connect() - - identity_client = iotidentity.IotIdentityClient(mqtt_connection) - - # Wait for connection to be fully established. - # Note that it's not necessary to wait, commands issued to the - # mqtt_connection before its fully connected will simply be queued. - # But this sample waits here so it's obvious when a connection - # fails or succeeds. - connected_future.result() - print("Connected!") - - try: - # Subscribe to necessary topics. - # Note that is **is** important to wait for "accepted/rejected" subscriptions - # to succeed before publishing the corresponding "request". - - # Keys workflow if csr is not provided - if cmdData.input_csr_path is None: - createkeysandcertificate_subscription_request = iotidentity.CreateKeysAndCertificateSubscriptionRequest() - - print("Subscribing to CreateKeysAndCertificate Accepted topic...") - createkeysandcertificate_subscribed_accepted_future, _ = identity_client.subscribe_to_create_keys_and_certificate_accepted( - request=createkeysandcertificate_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=createkeysandcertificate_execution_accepted) - - # Wait for subscription to succeed - createkeysandcertificate_subscribed_accepted_future.result() - - print("Subscribing to CreateKeysAndCertificate Rejected topic...") - createkeysandcertificate_subscribed_rejected_future, _ = identity_client.subscribe_to_create_keys_and_certificate_rejected( - request=createkeysandcertificate_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=createkeysandcertificate_execution_rejected) - - # Wait for subscription to succeed - createkeysandcertificate_subscribed_rejected_future.result() - else: - createcertificatefromcsr_subscription_request = iotidentity.CreateCertificateFromCsrSubscriptionRequest() - - print("Subscribing to CreateCertificateFromCsr Accepted topic...") - createcertificatefromcsr_subscribed_accepted_future, _ = identity_client.subscribe_to_create_certificate_from_csr_accepted( - request=createcertificatefromcsr_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=createcertificatefromcsr_execution_accepted) - - # Wait for subscription to succeed - createcertificatefromcsr_subscribed_accepted_future.result() - - print("Subscribing to CreateCertificateFromCsr Rejected topic...") - createcertificatefromcsr_subscribed_rejected_future, _ = identity_client.subscribe_to_create_certificate_from_csr_rejected( - request=createcertificatefromcsr_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=createcertificatefromcsr_execution_rejected) - - # Wait for subscription to succeed - createcertificatefromcsr_subscribed_rejected_future.result() - - registerthing_subscription_request = iotidentity.RegisterThingSubscriptionRequest( - template_name=cmdData.input_template_name) - - print("Subscribing to RegisterThing Accepted topic...") - registerthing_subscribed_accepted_future, _ = identity_client.subscribe_to_register_thing_accepted( - request=registerthing_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=registerthing_execution_accepted) - - # Wait for subscription to succeed - registerthing_subscribed_accepted_future.result() - - print("Subscribing to RegisterThing Rejected topic...") - registerthing_subscribed_rejected_future, _ = identity_client.subscribe_to_register_thing_rejected( - request=registerthing_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=registerthing_execution_rejected) - # Wait for subscription to succeed - registerthing_subscribed_rejected_future.result() - - fleet_template_name = cmdData.input_template_name - fleet_template_parameters = cmdData.input_template_parameters - if cmdData.input_csr_path is None: - print("Publishing to CreateKeysAndCertificate...") - publish_future = identity_client.publish_create_keys_and_certificate( - request=iotidentity.CreateKeysAndCertificateRequest(), qos=mqtt.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_create_keys_and_certificate) - - waitForCreateKeysAndCertificateResponse() - - if createKeysAndCertificateResponse is None: - raise Exception('CreateKeysAndCertificate API did not succeed') - - registerThingRequest = iotidentity.RegisterThingRequest( - template_name=fleet_template_name, - certificate_ownership_token=createKeysAndCertificateResponse.certificate_ownership_token, - parameters=json.loads(fleet_template_parameters)) - else: - print("Publishing to CreateCertificateFromCsr...") - csrPath = open(cmdData.input_csr_path, 'r').read() - publish_future = identity_client.publish_create_certificate_from_csr( - request=iotidentity.CreateCertificateFromCsrRequest(certificate_signing_request=csrPath), - qos=mqtt.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_create_certificate_from_csr) - - waitForCreateCertificateFromCsrResponse() - - if createCertificateFromCsrResponse is None: - raise Exception('CreateCertificateFromCsr API did not succeed') - - registerThingRequest = iotidentity.RegisterThingRequest( - template_name=fleet_template_name, - certificate_ownership_token=createCertificateFromCsrResponse.certificate_ownership_token, - parameters=json.loads(fleet_template_parameters)) - - print("Publishing to RegisterThing topic...") - registerthing_publish_future = identity_client.publish_register_thing( - registerThingRequest, mqtt.QoS.AT_LEAST_ONCE) - registerthing_publish_future.add_done_callback(on_publish_register_thing) - - waitForRegisterThingResponse() - exit("success") - - except Exception as e: - exit(e) - - # Wait for the sample to finish - is_sample_done.wait() diff --git a/samples/deprecated/fleetprovisioning_mqtt5.md b/samples/deprecated/fleetprovisioning_mqtt5.md deleted file mode 100644 index 57b00ab8..00000000 --- a/samples/deprecated/fleetprovisioning_mqtt5.md +++ /dev/null @@ -1,371 +0,0 @@ -# Fleet provisioning MQTT5 - -[**Return to main sample list**](../README.md) - -This sample uses the AWS IoT [Fleet provisioning](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html) to provision devices using either a CSR or Keys-And-Certificate and subsequently calls RegisterThing. This allows you to create new AWS IoT Core things using a Fleet Provisioning Template. - -On startup, the script subscribes to topics based on the request type of either CSR or Keys topics, publishes the request to corresponding topic and calls RegisterThing. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": "iot:Publish",
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/certificates/create/json",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create-from-csr/json",
-        "arn:aws:iot:region:account:topic/$aws/provisioning-templates/templatename/provision/json"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Receive"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/certificates/create/json/accepted",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create/json/rejected",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create-from-csr/json/accepted",
-        "arn:aws:iot:region:account:topic/$aws/certificates/create-from-csr/json/rejected",
-        "arn:aws:iot:region:account:topic/$aws/provisioning-templates/templatename/provision/json/accepted",
-        "arn:aws:iot:region:account:topic/$aws/provisioning-templates/templatename/provision/json/rejected"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Subscribe"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create/json/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create/json/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create-from-csr/json/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/certificates/create-from-csr/json/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/provisioning-templates/templatename/provision/json/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/provisioning-templates/templatename/provision/json/rejected"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Connect",
-      "Resource": "arn:aws:iot:region:account:client/test-*"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS Fleet Provisioning template you want to use to create new AWS IoT Core Things. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -There are many different ways to run the Fleet Provisioning sample because of how many different ways there are to setup a Fleet Provisioning template in AWS IoT Core. **The easiest and most common way is to run the sample with the following**: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning_mqtt5.py --endpoint --cert --key --template_name --template_parameters -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning_mqtt5.py --endpoint --cert --key --template_name --template_parameters --ca_file -``` - -However, this is just one way using the `CreateKeysAndCertificate` workflow. Below are a detailed list of instructions with the different ways to connect. While the detailed instructions do not show it, you can pass `--ca_file` as needed no matter which way you connect via Fleet Provisioning. - -## Service Client Notes -### Difference relative to MQTT311 IoTIdentityClient -The IoTIdentityClient with mqtt5 client is almost identical to the mqtt3 one. The only difference is that you would need setup up a Mqtt5 Client and pass it to the IotIdentityClient. -For how to setup a Mqtt5 Client, please refer to [MQTT5 UserGuide](../documents/MQTT5_Userguide.md) and [MQTT5 PubSub Sample](./mqtt5_pubsub.py) - - - - - - - - - - -
Create a IoTIdentityClient with Mqtt5Create a IoTIdentityClient with Mqtt311
- -```python - # Create a Mqtt5 Client - mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint, - port, - cert_filepath, - pri_key_filepath, - ca_filepath, - client_id, - clean_session, - keep_alive_secs, - http_proxy_options, - on_lifecycle_connection_success, - on_lifecycle_stopped) - - # Create the Identity Client from Mqtt5 Client - identity_client = iotidentity.IotIdentityClient(mqtt5_client) -``` - - - -```python - # Create a Mqtt311 Connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint, - port, - cert_filepath, - pri_key_filepath, - ca_filepath, - client_id, - clean_session, - keep_alive_secs, - http_proxy_options) - - # Create the Identity Client from Mqtt311 Connection - identity_client = iotidentity.IotIdentityClient(mqtt_connection) -``` - -
- -### Mqtt5.QoS v.s. Mqtt3.QoS -As the service client interface is unchanged for both Mqtt3 Connection and Mqtt5 Client,the IotIdentityClient will use Mqtt3.QoS instead of Mqtt5.QoS even with a Mqtt5 Client. You could use mqtt3.QoS.to_mqtt5() and mqtt5.QoS.to_mqtt3() to convert the value. - - -### Fleet Provisioning Detailed Instructions - -#### Aws Resource Setup - -Fleet provisioning requires some additional AWS resources be set up first. These steps assume you have the [AWS CLI](https://aws.amazon.com/cli/) installed and have your AWS credentials for the AWS CLI setup and with sufficient permissions to perform all of the operations in this guide. For instructions on how to setup AWS CLI, see the following: [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). - -You will also need Python version 3 installed to be able to run the `parse_cert_set_result.py` file, which is a helper script to make running this sample easier. You can find Python3 installers for your platform on the [Python website](https://www.python.org/). - -These steps are based on the provisioning setup steps -that can be found at [Embedded C SDK Setup](https://docs.aws.amazon.com/freertos/latest/lib-ref/c-sdk/provisioning/provisioning_tests.html#provisioning_system_tests_setup). - - -First, create the IAM role that will be needed by the fleet provisioning template. Replace `` with a name of the role you want to create. - -``` sh -aws iam create-role \ - --role-name \ - --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"iot.amazonaws.com"}}]}' -``` - -This is the IAM role the Fleet Provisioning template will use to create the new AWS IoT things. However, before it can do so, it will need to have a policy attached to it to give the new role permission to perform the operations it needs. To do this, run the following command and replace `` with the name of the role you created in the previous step. - -``` sh -aws iam attach-role-policy \ - --role-name \ - --policy-arn arn:aws:iam::aws:policy/service-role/AWSIoTThingsRegistration -``` - -The next step is to make a template resource that will be used for provisioning the new AWS IoT Core things. This template tells AWS IoT Core how to setup the new AWS IoT Core Things you create when your Fleet Provisioning role is invoked, setting up material such as the name and tags, for example. - -To create a new Fleet Provisioning template, you can use the following AWS CLI command, replacing `` with the name of the template you wish to create, `` with the name of the role you created two steps prior, and `` with your AWS IoT Core account number. Finally, make sure to replace `` with a valid JSON document as a single line. An example JSON document is provided further below. - -``` sh -aws iot create-provisioning-template \ - --template-name \ - --provisioning-role-arn arn:aws:iam:::role/ \ - --template-body "" \ - --enabled -``` - -For the purposes of this sample, the following template JSON document is presumed to be used: - -
-(see template body) - -```json -{ - "Parameters": { - "DeviceLocation": { - "Type": "String" - }, - "AWS::IoT::Certificate::Id": { - "Type": "String" - }, - "SerialNumber": { - "Type": "String" - } - }, - "Mappings": { - "LocationTable": { - "Seattle": { - "LocationUrl": "https://example.aws" - } - } - }, - "Resources": { - "thing": { - "Type": "AWS::IoT::Thing", - "Properties": { - "ThingName": { - "Fn::Join": [ - "", - [ - "ThingPrefix_", - { - "Ref": "SerialNumber" - } - ] - ] - }, - "AttributePayload": { - "version": "v1", - "serialNumber": "serialNumber" - } - }, - "OverrideSettings": { - "AttributePayload": "MERGE", - "ThingTypeName": "REPLACE", - "ThingGroups": "DO_NOTHING" - } - }, - "certificate": { - "Type": "AWS::IoT::Certificate", - "Properties": { - "CertificateId": { - "Ref": "AWS::IoT::Certificate::Id" - }, - "Status": "Active" - }, - "OverrideSettings": { - "Status": "REPLACE" - } - }, - "policy": { - "Type": "AWS::IoT::Policy", - "Properties": { - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "iot:Connect", - "iot:Subscribe", - "iot:Publish", - "iot:Receive" - ], - "Resource": "*" - } - ] - } - } - } - }, - "DeviceConfiguration": { - "FallbackUrl": "https://www.example.com/test-site", - "LocationUrl": { - "Fn::FindInMap": [ - "LocationTable", - { - "Ref": "DeviceLocation" - }, - "LocationUrl" - ] - } - } -} -``` - -
- -And here is the same JSON document, but as a single line for easier copy-pasting: - -
-(see template body) - -``` json -{"Parameters": {"DeviceLocation": {"Type": "String"},"AWS::IoT::Certificate::Id": {"Type": "String"},"SerialNumber": {"Type": "String"}},"Mappings": {"LocationTable": {"Seattle": {"LocationUrl": "https://example.aws"}}},"Resources": {"thing": {"Type": "AWS::IoT::Thing","Properties": {"ThingName": {"Fn::Join": ["",["ThingPrefix_",{"Ref": "SerialNumber"}]]},"AttributePayload": {"version": "v1","serialNumber": "serialNumber"}},"OverrideSettings": {"AttributePayload": "MERGE","ThingTypeName": "REPLACE","ThingGroups": "DO_NOTHING"}},"certificate": {"Type": "AWS::IoT::Certificate","Properties": {"CertificateId": {"Ref": "AWS::IoT::Certificate::Id"},"Status": "Active"},"OverrideSettings": {"Status": "REPLACE"}},"policy": {"Type": "AWS::IoT::Policy","Properties": {"PolicyDocument": {"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["iot:Connect","iot:Subscribe","iot:Publish","iot:Receive"],"Resource": "*"}]}}}},"DeviceConfiguration": {"FallbackUrl": "https://www.example.com/test-site","LocationUrl": {"Fn::FindInMap": ["LocationTable",{"Ref": "DeviceLocation"},"LocationUrl"]}}} -``` - -
- -You can use this JSON document as the `` in the AWS CLI command. This sample will assume you have used the template JSON above, so you may need to adjust if you are using a different template JSON. Thankfully, all of these steps need to only be done and, now that they are complete, you will need not perform them again. - -#### Creating a certificate-key set from a provisioning claim - -To run the provisioning sample, you'll need a certificate and key set with sufficient permissions. Provisioning certificates are normally created ahead of time and placed on your device, but for this sample, we will just create them on the fly. This is primarily done for example purposes. - -You can also use any certificate set you've already created if it has sufficient IoT permissions. If you wish to do this, you can skip the step that calls `create-provisioning-claim` below and move right to the next step: [Running the sample using a certificate-key set](#running-the-sample-using-a-certificate-key-set) - -We've included a script in the utils folder that creates certificate and key files from the response of calling -`create-provisioning-claim`. These dynamically sourced certificates are **only valid for five minutes**. When running the command, -you'll need to substitute the name of the template you previously created. If on Windows, replace the paths with something appropriate. - -**Note**: The following assumes you are running this command from the `aws-iot-device-sdk-java-v2` folder, which is the main GitHub folder. If you are running this from another folder (like the `samples/Identity` folder), then you will need to adjust the filepaths accordingly. - -```sh -aws iot create-provisioning-claim \ - --template-name \ - | python3 ./utils/parse_cert_set_result.py \ - --path ./tmp \ - --filename provision -``` -* Replace `` with the name of the Fleet Provisioning template you created earlier. - -This will create a certificate and key in the `tmp` folder with file names starting with `provision`. You can now use these temporary keys -to perform the actual provisioning in the section below. - -#### Running the sample using a certificate-key set - -To run the sample with your certificate and private key, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning.py --endpoint --cert --key --template_name --template_parameters '{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}' -``` - -As per normal, replace the `<>` parameters with the proper values. Notice that we provided substitution values for the two parameters in the template body, `DeviceLocation` and `SerialNumber`. - -With that, the sample should run and work as expected! You should then find your have a new AWS IoT Core thing! - -### Run the sample using the certificate signing request workflow - -To run the sample with this workflow, you'll need to create a certificate signing request in addition to the other steps above (creating the role, setting its policy, setting the template JSON, etc). - -First create a certificate-key pair: -``` sh -openssl genrsa -out /tmp/deviceCert.key 2048 -``` - -Next create a certificate signing request from it: -``` sh -openssl req -new -key /tmp/deviceCert.key -out /tmp/deviceCert.csr -``` - -As in the previous workflow, you can [create a temporary certificate set from a provisioning claim](#creating-a-certificate-key-set-from-a-provisioning-claim). Again, this can be skipped if you have a policy and certificate with the proper permissions. - -```sh -aws iot create-provisioning-claim \ - --template-name \ - | python3 ./utils/parse_cert_set_result.py \ - --path ./tmp \ - --filename provision -``` -* Replace `` with the name of the Fleet Provisioning template you created earlier. - -Finally, you can also pass the certificate signing request while invoking the Fleet Provisioning sample. - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 fleetprovisioning.py --endpoint --cert --key --template_name --template_parameters '{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}' --csr -``` diff --git a/samples/deprecated/fleetprovisioning_mqtt5.py b/samples/deprecated/fleetprovisioning_mqtt5.py deleted file mode 100644 index f98d67cc..00000000 --- a/samples/deprecated/fleetprovisioning_mqtt5.py +++ /dev/null @@ -1,376 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import mqtt5, http -from awsiot import iotidentity, mqtt5_client_builder -from concurrent.futures import Future -import sys -import threading -import time -import traceback -import json -from utils.command_line_utils import CommandLineUtils - -# - Overview - -# This sample uses the AWS IoT Fleet Provisioning to provision device using either the keys -# or CSR -# -# -# - Instructions - -# This sample requires you to create a provisioning claim. See: -# https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html -# -# - Detail - -# On startup, the script subscribes to topics based on the request type of either CSR or Keys -# publishes the request to corresponding topic and calls RegisterThing. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_fleet_provisioning() - -# Using globals to simplify sample code -is_sample_done = threading.Event() -mqtt5_client = None -identity_client = None -createKeysAndCertificateResponse = None -createCertificateFromCsrResponse = None -registerThingResponse = None -future_connection_success = Future() - -class LockedData: - def __init__(self): - self.lock = threading.Lock() - self.disconnect_called = False - - -locked_data = LockedData() - -# Function for gracefully quitting this sample -def exit(msg_or_exception): - if isinstance(msg_or_exception, Exception): - print("Exiting Sample due to exception.") - traceback.print_exception(msg_or_exception.__class__, msg_or_exception, sys.exc_info()[2]) - else: - print("Exiting Sample:", msg_or_exception) - - with locked_data.lock: - if not locked_data.disconnect_called: - print("Stop the Client...") - locked_data.disconnect_called = True - mqtt5_client.stop() - - -# Callback for the lifecycle event Connection Success -def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.LifecycleConnectSuccessData): - print("Lifecycle Connection Success") - global future_connection_success - future_connection_success.set_result(lifecycle_connect_success_data) - - -# Callback for the lifecycle event on Client Stopped -def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): - # type: (Future) -> None - print("Client Stopped.") - # Signal that sample is finished - is_sample_done.set() - - -def on_publish_register_thing(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published RegisterThing request..") - - except Exception as e: - print("Failed to publish RegisterThing request.") - exit(e) - - -def on_publish_create_keys_and_certificate(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published CreateKeysAndCertificate request..") - - except Exception as e: - print("Failed to publish CreateKeysAndCertificate request.") - exit(e) - - -def on_publish_create_certificate_from_csr(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published CreateCertificateFromCsr request..") - - except Exception as e: - print("Failed to publish CreateCertificateFromCsr request.") - exit(e) - - -def createkeysandcertificate_execution_accepted(response): - # type: (iotidentity.CreateKeysAndCertificateResponse) -> None - try: - global createKeysAndCertificateResponse - createKeysAndCertificateResponse = response - if (cmdData.input_is_ci == False): - print("Received a new message {}".format(createKeysAndCertificateResponse)) - - return - - except Exception as e: - exit(e) - - -def createkeysandcertificate_execution_rejected(rejected): - # type: (iotidentity.RejectedError) -> None - exit("CreateKeysAndCertificate Request rejected with code:'{}' message:'{}' status code:'{}'".format( - rejected.error_code, rejected.error_message, rejected.status_code)) - - -def createcertificatefromcsr_execution_accepted(response): - # type: (iotidentity.CreateCertificateFromCsrResponse) -> None - try: - global createCertificateFromCsrResponse - createCertificateFromCsrResponse = response - if (cmdData.input_is_ci == False): - print("Received a new message {}".format(createCertificateFromCsrResponse)) - global certificateOwnershipToken - certificateOwnershipToken = response.certificate_ownership_token - - return - - except Exception as e: - exit(e) - - -def createcertificatefromcsr_execution_rejected(rejected): - # type: (iotidentity.RejectedError) -> None - exit("CreateCertificateFromCsr Request rejected with code:'{}' message:'{}' status code:'{}'".format( - rejected.error_code, rejected.error_message, rejected.status_code)) - - -def registerthing_execution_accepted(response): - # type: (iotidentity.RegisterThingResponse) -> None - try: - global registerThingResponse - registerThingResponse = response - if (cmdData.input_is_ci == False): - print("Received a new message {} ".format(registerThingResponse)) - return - - except Exception as e: - exit(e) - - -def registerthing_execution_rejected(rejected): - # type: (iotidentity.RejectedError) -> None - exit("RegisterThing Request rejected with code:'{}' message:'{}' status code:'{}'".format( - rejected.error_code, rejected.error_message, rejected.status_code)) - -def on_resubscribe_complete(resubscribe_future): - resubscribe_results = resubscribe_future.result() - print("Resubscribe results: {}".format(resubscribe_results)) - - for topic, qos in resubscribe_results['topics']: - if qos is None: - sys.exit("Server rejected resubscribe to topic: {}".format(topic)) - - -def waitForCreateKeysAndCertificateResponse(): - # Wait for the response. - loopCount = 0 - while loopCount < 10 and createKeysAndCertificateResponse is None: - if createKeysAndCertificateResponse is not None: - break - if not cmdData.input_is_ci: - print('Waiting... CreateKeysAndCertificateResponse: ' + json.dumps(createKeysAndCertificateResponse)) - else: - print("Waiting... CreateKeysAndCertificateResponse: ...") - loopCount += 1 - time.sleep(1) - - -def waitForCreateCertificateFromCsrResponse(): - # Wait for the response. - loopCount = 0 - while loopCount < 10 and createCertificateFromCsrResponse is None: - if createCertificateFromCsrResponse is not None: - break - if not cmdData.input_is_ci: - print('Waiting...CreateCertificateFromCsrResponse: ' + json.dumps(createCertificateFromCsrResponse)) - else: - print("Waiting... CreateCertificateFromCsrResponse: ...") - loopCount += 1 - time.sleep(1) - - -def waitForRegisterThingResponse(): - # Wait for the response. - loopCount = 0 - while loopCount < 20 and registerThingResponse is None: - if registerThingResponse is not None: - break - loopCount += 1 - if not cmdData.input_is_ci: - print('Waiting... RegisterThingResponse: ' + json.dumps(registerThingResponse)) - else: - print('Waiting... RegisterThingResponse: ...') - time.sleep(1) - - -if __name__ == '__main__': - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options, - on_lifecycle_connection_success=on_lifecycle_connection_success, - on_lifecycle_stopped=on_lifecycle_stopped) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - mqtt5_client.start() - - identity_client = iotidentity.IotIdentityClient(mqtt5_client) - - # Wait for connection to be fully established. - # Note that it's not necessary to wait, commands issued to the - # mqtt5_client before its fully connected will simply be queued. - # But this sample waits here so it's obvious when a connection - # fails or succeeds. - future_connection_success.result() - print("Connected!") - - try: - # Subscribe to necessary topics. - # Note that is **is** important to wait for "accepted/rejected" subscriptions - # to succeed before publishing the corresponding "request". - - # Keys workflow if csr is not provided - if cmdData.input_csr_path is None: - createkeysandcertificate_subscription_request = iotidentity.CreateKeysAndCertificateSubscriptionRequest() - - print("Subscribing to CreateKeysAndCertificate Accepted topic...") - createkeysandcertificate_subscribed_accepted_future, _ = identity_client.subscribe_to_create_keys_and_certificate_accepted( - request=createkeysandcertificate_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=createkeysandcertificate_execution_accepted) - - # Wait for subscription to succeed - createkeysandcertificate_subscribed_accepted_future.result() - - print("Subscribing to CreateKeysAndCertificate Rejected topic...") - createkeysandcertificate_subscribed_rejected_future, _ = identity_client.subscribe_to_create_keys_and_certificate_rejected( - request=createkeysandcertificate_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=createkeysandcertificate_execution_rejected) - - # Wait for subscription to succeed - createkeysandcertificate_subscribed_rejected_future.result() - else: - createcertificatefromcsr_subscription_request = iotidentity.CreateCertificateFromCsrSubscriptionRequest() - - print("Subscribing to CreateCertificateFromCsr Accepted topic...") - createcertificatefromcsr_subscribed_accepted_future, _ = identity_client.subscribe_to_create_certificate_from_csr_accepted( - request=createcertificatefromcsr_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=createcertificatefromcsr_execution_accepted) - - # Wait for subscription to succeed - createcertificatefromcsr_subscribed_accepted_future.result() - - print("Subscribing to CreateCertificateFromCsr Rejected topic...") - createcertificatefromcsr_subscribed_rejected_future, _ = identity_client.subscribe_to_create_certificate_from_csr_rejected( - request=createcertificatefromcsr_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=createcertificatefromcsr_execution_rejected) - - # Wait for subscription to succeed - createcertificatefromcsr_subscribed_rejected_future.result() - - registerthing_subscription_request = iotidentity.RegisterThingSubscriptionRequest( - template_name=cmdData.input_template_name) - - print("Subscribing to RegisterThing Accepted topic...") - registerthing_subscribed_accepted_future, _ = identity_client.subscribe_to_register_thing_accepted( - request=registerthing_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=registerthing_execution_accepted) - - # Wait for subscription to succeed - registerthing_subscribed_accepted_future.result() - - print("Subscribing to RegisterThing Rejected topic...") - registerthing_subscribed_rejected_future, _ = identity_client.subscribe_to_register_thing_rejected( - request=registerthing_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=registerthing_execution_rejected) - # Wait for subscription to succeed - registerthing_subscribed_rejected_future.result() - - fleet_template_name = cmdData.input_template_name - fleet_template_parameters = cmdData.input_template_parameters - if cmdData.input_csr_path is None: - print("Publishing to CreateKeysAndCertificate...") - publish_future = identity_client.publish_create_keys_and_certificate( - request=iotidentity.CreateKeysAndCertificateRequest(), qos=mqtt5.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_create_keys_and_certificate) - - waitForCreateKeysAndCertificateResponse() - - if createKeysAndCertificateResponse is None: - raise Exception('CreateKeysAndCertificate API did not succeed') - - registerThingRequest = iotidentity.RegisterThingRequest( - template_name=fleet_template_name, - certificate_ownership_token=createKeysAndCertificateResponse.certificate_ownership_token, - parameters=json.loads(fleet_template_parameters)) - else: - print("Publishing to CreateCertificateFromCsr...") - csrPath = open(cmdData.input_csr_path, 'r').read() - publish_future = identity_client.publish_create_certificate_from_csr( - request=iotidentity.CreateCertificateFromCsrRequest(certificate_signing_request=csrPath), - qos=mqtt5.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_create_certificate_from_csr) - - waitForCreateCertificateFromCsrResponse() - - if createCertificateFromCsrResponse is None: - raise Exception('CreateCertificateFromCsr API did not succeed') - - registerThingRequest = iotidentity.RegisterThingRequest( - template_name=fleet_template_name, - certificate_ownership_token=createCertificateFromCsrResponse.certificate_ownership_token, - parameters=json.loads(fleet_template_parameters)) - - print("Publishing to RegisterThing topic...") - registerthing_publish_future = identity_client.publish_register_thing( - registerThingRequest, mqtt5.QoS.AT_LEAST_ONCE) - registerthing_publish_future.add_done_callback(on_publish_register_thing) - - waitForRegisterThingResponse() - exit("success") - - except Exception as e: - exit(e) - - # Wait for the sample to finish - is_sample_done.wait() diff --git a/samples/deprecated/jobs.md b/samples/deprecated/jobs.md deleted file mode 100644 index 4648ab73..00000000 --- a/samples/deprecated/jobs.md +++ /dev/null @@ -1,84 +0,0 @@ -# Jobs - -[**Return to main sample list**](../README.md) - -This sample uses the AWS IoT [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) Service to describe jobs to execute. [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) is a service that allows you to define and respond to remote operation requests defined through the AWS IoT Core website or via any other device (or CLI command) that can access the [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) service. - -Note: This sample requires you to create jobs for your device to execute. See -[instructions here](https://docs.aws.amazon.com/iot/latest/developerguide/create-manage-jobs.html) for how to make jobs. - -On startup, the sample describes the jobs that are pending execution and pretends to process them, marking each job as complete as it does so. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-Sample Policy -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": "iot:Publish",
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/start-next",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/update",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/get",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/get"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Receive",
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/notify-next",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/start-next/*",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/update/*",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/get/*",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/get/*"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Subscribe",
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/notify-next",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/start-next/*",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/*/update/*",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/get/*",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/*/get/*"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Connect",
-      "Resource": "arn:aws:iot:region:account:client/test-*"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS IoT Core thing you want the device connection to be associated with - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -Use the following command to run the Jobs sample from the `samples` folder: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 jobs.py --endpoint --cert --key --thing_name -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 jobs.py --endpoint --cert --key --thing_name --ca_file -``` diff --git a/samples/deprecated/jobs.py b/samples/deprecated/jobs.py deleted file mode 100644 index 4ac8d40a..00000000 --- a/samples/deprecated/jobs.py +++ /dev/null @@ -1,396 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import mqtt, http -from awsiot import iotjobs, mqtt_connection_builder -from concurrent.futures import Future -import sys -import threading -import time -import traceback -import time -from utils.command_line_utils import CommandLineUtils - -# - Overview - -# This sample uses the AWS IoT Jobs Service to get a list of pending jobs and -# then execution operations on these pending jobs until there are no more -# remaining on the device. Imagine periodic software updates that must be sent to and -# executed on devices in the wild. -# -# - Instructions - -# This sample requires you to create jobs for your device to execute. See: -# https://docs.aws.amazon.com/iot/latest/developerguide/create-manage-jobs.html -# -# - Detail - -# On startup, the sample tries to get a list of all the in-progress and queued -# jobs and display them in a list. Then it tries to start the next pending job execution. -# If such a job exists, the sample emulates "doing work" by spawning a thread -# that sleeps for several seconds before marking the job as SUCCEEDED. When no -# pending job executions exist, the sample sits in an idle state. -# -# The sample also subscribes to receive "Next Job Execution Changed" events. -# If the sample is idle, this event wakes it to start the job. If the sample is -# already working on a job, it remembers to try for another when it's done. -# This event is sent by the service when the current job completes, so the -# sample will be continually prompted to try another job until none remain. - -# Using globals to simplify sample code -is_sample_done = threading.Event() - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_jobs() - -mqtt_connection = None -jobs_client = None -jobs_thing_name = cmdData.input_thing_name - - -class LockedData: - def __init__(self): - self.lock = threading.Lock() - self.disconnect_called = False - self.is_working_on_job = False - self.is_next_job_waiting = False - self.got_job_response = False - - -locked_data = LockedData() - -# Function for gracefully quitting this sample -def exit(msg_or_exception): - if isinstance(msg_or_exception, Exception): - print("Exiting Sample due to exception.") - traceback.print_exception(msg_or_exception.__class__, msg_or_exception, sys.exc_info()[2]) - else: - print("Exiting Sample:", msg_or_exception) - - with locked_data.lock: - if not locked_data.disconnect_called: - print("Disconnecting...") - locked_data.disconnect_called = True - future = mqtt_connection.disconnect() - future.add_done_callback(on_disconnected) - - -def try_start_next_job(): - print("Trying to start the next job...") - with locked_data.lock: - if locked_data.is_working_on_job: - print("Nevermind, already working on a job.") - return - - if locked_data.disconnect_called: - print("Nevermind, sample is disconnecting.") - return - - locked_data.is_working_on_job = True - locked_data.is_next_job_waiting = False - - print("Publishing request to start next job...") - request = iotjobs.StartNextPendingJobExecutionRequest(thing_name=jobs_thing_name) - publish_future = jobs_client.publish_start_next_pending_job_execution(request, mqtt.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_start_next_pending_job_execution) - - -def done_working_on_job(): - with locked_data.lock: - locked_data.is_working_on_job = False - try_again = locked_data.is_next_job_waiting - - if try_again: - try_start_next_job() - - -def on_disconnected(disconnect_future): - # type: (Future) -> None - print("Disconnected.") - - # Signal that sample is finished - is_sample_done.set() - - -# A list to hold all the pending jobs -available_jobs = [] - - -def on_get_pending_job_executions_accepted(response): - # type: (iotjobs.GetPendingJobExecutionsResponse) -> None - with locked_data.lock: - if (len(response.queued_jobs) > 0 or len(response.in_progress_jobs) > 0): - print("Pending Jobs:") - for job in response.in_progress_jobs: - available_jobs.append(job) - print(f" In Progress: {job.job_id} @ {job.last_updated_at}") - for job in response.queued_jobs: - available_jobs.append(job) - print(f" {job.job_id} @ {job.last_updated_at}") - else: - print("No pending or queued jobs found!") - locked_data.got_job_response = True - - -def on_get_pending_job_executions_rejected(error): - # type: (iotjobs.RejectedError) -> None - print(f"Request rejected: {error.code}: {error.message}") - exit("Get pending jobs request rejected!") - - -def on_next_job_execution_changed(event): - # type: (iotjobs.NextJobExecutionChangedEvent) -> None - try: - execution = event.execution - if execution: - print("Received Next Job Execution Changed event. job_id:{} job_document:{}".format( - execution.job_id, execution.job_document)) - - # Start job now, or remember to start it when current job is done - start_job_now = False - with locked_data.lock: - if locked_data.is_working_on_job: - locked_data.is_next_job_waiting = True - else: - start_job_now = True - - if start_job_now: - try_start_next_job() - - else: - print("Received Next Job Execution Changed event: None. Waiting for further jobs...") - - except Exception as e: - exit(e) - - -def on_publish_start_next_pending_job_execution(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - - print("Published request to start the next job.") - - except Exception as e: - exit(e) - - -def on_start_next_pending_job_execution_accepted(response): - # type: (iotjobs.StartNextJobExecutionResponse) -> None - try: - if response.execution: - execution = response.execution - print("Request to start next job was accepted. job_id:{} job_document:{}".format( - execution.job_id, execution.job_document)) - - # To emulate working on a job, spawn a thread that sleeps for a few seconds - job_thread = threading.Thread( - target=lambda: job_thread_fn(execution.job_id, execution.job_document), - name='job_thread') - job_thread.start() - else: - print("Request to start next job was accepted, but there are no jobs to be done. Waiting for further jobs...") - done_working_on_job() - - except Exception as e: - exit(e) - - -def on_start_next_pending_job_execution_rejected(rejected): - # type: (iotjobs.RejectedError) -> None - exit("Request to start next pending job rejected with code:'{}' message:'{}'".format( - rejected.code, rejected.message)) - - -def job_thread_fn(job_id, job_document): - try: - print("Starting local work on job...") - time.sleep(cmdData.input_job_time) - print("Done working on job.") - - print("Publishing request to update job status to SUCCEEDED...") - request = iotjobs.UpdateJobExecutionRequest( - thing_name=jobs_thing_name, - job_id=job_id, - status=iotjobs.JobStatus.SUCCEEDED) - publish_future = jobs_client.publish_update_job_execution(request, mqtt.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_update_job_execution) - - except Exception as e: - exit(e) - - -def on_publish_update_job_execution(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published request to update job.") - - except Exception as e: - exit(e) - - -def on_update_job_execution_accepted(response): - # type: (iotjobs.UpdateJobExecutionResponse) -> None - try: - print("Request to update job was accepted.") - done_working_on_job() - except Exception as e: - exit(e) - - -def on_update_job_execution_rejected(rejected): - # type: (iotjobs.RejectedError) -> None - exit("Request to update job status was rejected. code:'{}' message:'{}'.".format( - rejected.code, rejected.message)) - - -if __name__ == '__main__': - - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connected_future = mqtt_connection.connect() - - jobs_client = iotjobs.IotJobsClient(mqtt_connection) - - # Wait for connection to be fully established. - # Note that it's not necessary to wait, commands issued to the - # mqtt_connection before its fully connected will simply be queued. - # But this sample waits here so it's obvious when a connection - # fails or succeeds. - connected_future.result() - print("Connected!") - - try: - # List the jobs queued and pending - get_jobs_request = iotjobs.GetPendingJobExecutionsRequest(thing_name=jobs_thing_name) - jobs_request_future_accepted, _ = jobs_client.subscribe_to_get_pending_job_executions_accepted( - request=get_jobs_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_get_pending_job_executions_accepted - ) - # Wait for the subscription to succeed - jobs_request_future_accepted.result() - - jobs_request_future_rejected, _ = jobs_client.subscribe_to_get_pending_job_executions_rejected( - request=get_jobs_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_get_pending_job_executions_rejected - ) - # Wait for the subscription to succeed - jobs_request_future_rejected.result() - - # Get a list of all the jobs - get_jobs_request_future = jobs_client.publish_get_pending_job_executions( - request=get_jobs_request, - qos=mqtt.QoS.AT_LEAST_ONCE - ) - # Wait for the publish to succeed - get_jobs_request_future.result() - except Exception as e: - exit(e) - - # If we are running in CI, then we want to check how many jobs were reported and stop - if (cmdData.input_is_ci): - # Wait until we get a response. If we do not get a response after 50 tries, then abort - got_job_response_tries = 0 - while (locked_data.got_job_response == False): - got_job_response_tries += 1 - if (got_job_response_tries > 50): - exit("Got job response timeout exceeded") - sys.exit(-1) - time.sleep(0.2) - - if (len(available_jobs) > 0): - print("At least one job queued in CI! No further work to do. Exiting sample...") - sys.exit(0) - else: - print("ERROR: No jobs queued in CI! At least one job should be queued!") - sys.exit(-1) - - try: - # Subscribe to necessary topics. - # Note that is **is** important to wait for "accepted/rejected" subscriptions - # to succeed before publishing the corresponding "request". - print("Subscribing to Next Changed events...") - changed_subscription_request = iotjobs.NextJobExecutionChangedSubscriptionRequest( - thing_name=jobs_thing_name) - - subscribed_future, _ = jobs_client.subscribe_to_next_job_execution_changed_events( - request=changed_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_next_job_execution_changed) - - # Wait for subscription to succeed - subscribed_future.result() - - print("Subscribing to Start responses...") - start_subscription_request = iotjobs.StartNextPendingJobExecutionSubscriptionRequest( - thing_name=jobs_thing_name) - subscribed_accepted_future, _ = jobs_client.subscribe_to_start_next_pending_job_execution_accepted( - request=start_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_start_next_pending_job_execution_accepted) - - subscribed_rejected_future, _ = jobs_client.subscribe_to_start_next_pending_job_execution_rejected( - request=start_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_start_next_pending_job_execution_rejected) - - # Wait for subscriptions to succeed - subscribed_accepted_future.result() - subscribed_rejected_future.result() - - print("Subscribing to Update responses...") - # Note that we subscribe to "+", the MQTT wildcard, to receive - # responses about any job-ID. - update_subscription_request = iotjobs.UpdateJobExecutionSubscriptionRequest( - thing_name=jobs_thing_name, - job_id='+') - - subscribed_accepted_future, _ = jobs_client.subscribe_to_update_job_execution_accepted( - request=update_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_update_job_execution_accepted) - - subscribed_rejected_future, _ = jobs_client.subscribe_to_update_job_execution_rejected( - request=update_subscription_request, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_update_job_execution_rejected) - - # Wait for subscriptions to succeed - subscribed_accepted_future.result() - subscribed_rejected_future.result() - - # Make initial attempt to start next job. The service should reply with - # an "accepted" response, even if no jobs are pending. The response - # will contain data about the next job, if there is one. - # (Will do nothing if we are in CI) - try_start_next_job() - - except Exception as e: - exit(e) - - # Wait for the sample to finish - is_sample_done.wait() diff --git a/samples/deprecated/jobs_mqtt5.md b/samples/deprecated/jobs_mqtt5.md deleted file mode 100644 index f189f76e..00000000 --- a/samples/deprecated/jobs_mqtt5.md +++ /dev/null @@ -1,144 +0,0 @@ -# Jobs MQTT5 - -[**Return to main sample list**](../README.md) - -This sample uses the AWS IoT [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) Service to describe jobs to execute. [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) is a service that allows you to define and respond to remote operation requests defined through the AWS IoT Core website or via any other device (or CLI command) that can access the [Jobs](https://docs.aws.amazon.com/iot/latest/developerguide/iot-jobs.html) service. - -Note: This sample requires you to create jobs for your device to execute. See -[instructions here](https://docs.aws.amazon.com/iot/latest/developerguide/create-manage-jobs.html) for how to make jobs. - -On startup, the sample describes the jobs that are pending execution and pretends to process them, marking each job as complete as it does so. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-Sample Policy -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": "iot:Publish",
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/start-next",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/update",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/get",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/get"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Receive",
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/notify-next",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/start-next/*",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/update/*",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/get/*",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/jobs/*/get/*"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Subscribe",
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/notify-next",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/start-next/*",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/*/update/*",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/get/*",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/jobs/*/get/*"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Connect",
-      "Resource": "arn:aws:iot:region:account:client/test-*"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS IoT Core thing you want the device connection to be associated with - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -Use the following command to run the Jobs sample from the `samples` folder: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 jobs_mqtt5.py --endpoint --cert --key --thing_name -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 jobs_mqtt5.py --endpoint --cert --key --thing_name --ca_file -``` - - -## Service Client Notes -### Difference relative to MQTT311 IotJobsClient -The IotJobsClient with mqtt5 client is almost identical to the mqtt3 one. The only difference is that you would need setup up a Mqtt5 Client and pass it to the IotJobsClient. -For how to setup a Mqtt5 Client, please refer to [MQTT5 UserGuide](../documents/MQTT5_Userguide.md) and [MQTT5 PubSub Sample](./mqtt5_pubsub.py) - - - - - - - - - - -
Create a IotJobsClient with Mqtt5Create a IotJobsClient with Mqtt311
- -```python - # Create a Mqtt5 Client - mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint, - port, - cert_filepath, - pri_key_filepath, - ca_filepath, - client_id, - clean_session, - keep_alive_secs, - http_proxy_options, - on_lifecycle_connection_success, - on_lifecycle_stopped) - - # Create the Jobs client from Mqtt5 Client - jobs_client = iotjobs.IotJobsClient(mqtt5_client) -``` - - - -```python - # Create a Mqtt311 Connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint, - port, - cert_filepath, - pri_key_filepath, - ca_filepath, - client_id, - clean_session, - keep_alive_secs, - http_proxy_options) - - # Create the Jobs client from Mqtt311 Connection - jobs_client = iotjobs.IotJobsClient(mqtt_connection) -``` - -
- -### Mqtt5.QoS v.s. Mqtt3.QoS -As the service client interface is unchanged for both Mqtt3 Connection and Mqtt5 Client,the IotJobsClient will use Mqtt3.QoS instead of Mqtt5.QoS even with a Mqtt5 Client. You could use mqtt3.QoS.to_mqtt5() and mqtt5.QoS.to_mqtt3() to convert the value. \ No newline at end of file diff --git a/samples/deprecated/jobs_mqtt5.py b/samples/deprecated/jobs_mqtt5.py deleted file mode 100644 index ea0a4fb3..00000000 --- a/samples/deprecated/jobs_mqtt5.py +++ /dev/null @@ -1,405 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import mqtt5, http -from awsiot import iotjobs, mqtt5_client_builder -from concurrent.futures import Future -import sys -import threading -import time -import traceback -import time -from utils.command_line_utils import CommandLineUtils - -# - Overview - -# This sample uses the AWS IoT Jobs Service to get a list of pending jobs and -# then execution operations on these pending jobs until there are no more -# remaining on the device. Imagine periodic software updates that must be sent to and -# executed on devices in the wild. -# -# - Instructions - -# This sample requires you to create jobs for your device to execute. See: -# https://docs.aws.amazon.com/iot/latest/developerguide/create-manage-jobs.html -# -# - Detail - -# On startup, the sample tries to get a list of all the in-progress and queued -# jobs and display them in a list. Then it tries to start the next pending job execution. -# If such a job exists, the sample emulates "doing work" by spawning a thread -# that sleeps for several seconds before marking the job as SUCCEEDED. When no -# pending job executions exist, the sample sits in an idle state. -# -# The sample also subscribes to receive "Next Job Execution Changed" events. -# If the sample is idle, this event wakes it to start the job. If the sample is -# already working on a job, it remembers to try for another when it's done. -# This event is sent by the service when the current job completes, so the -# sample will be continually prompted to try another job until none remain. - -# Using globals to simplify sample code -is_sample_done = threading.Event() - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_jobs() - -mqtt5_client = None -future_connection_success = Future() -jobs_client = None -jobs_thing_name = cmdData.input_thing_name - - -class LockedData: - def __init__(self): - self.lock = threading.Lock() - self.disconnect_called = False - self.is_working_on_job = False - self.is_next_job_waiting = False - self.got_job_response = False - - -locked_data = LockedData() - -# Function for gracefully quitting this sample -def exit(msg_or_exception): - if isinstance(msg_or_exception, Exception): - print("Exiting Sample due to exception.") - traceback.print_exception(msg_or_exception.__class__, msg_or_exception, sys.exc_info()[2]) - else: - print("Exiting Sample:", msg_or_exception) - - with locked_data.lock: - if not locked_data.disconnect_called: - print("Disconnecting...") - locked_data.disconnect_called = True - mqtt5_client.stop() - - -def try_start_next_job(): - print("Trying to start the next job...") - with locked_data.lock: - if locked_data.is_working_on_job: - print("Nevermind, already working on a job.") - return - - if locked_data.disconnect_called: - print("Nevermind, sample is disconnecting.") - return - - locked_data.is_working_on_job = True - locked_data.is_next_job_waiting = False - - print("Publishing request to start next job...") - request = iotjobs.StartNextPendingJobExecutionRequest(thing_name=jobs_thing_name) - publish_future = jobs_client.publish_start_next_pending_job_execution(request, mqtt5.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_start_next_pending_job_execution) - - -def done_working_on_job(): - with locked_data.lock: - locked_data.is_working_on_job = False - try_again = locked_data.is_next_job_waiting - - if try_again: - try_start_next_job() - - -# Callback for the lifecycle event Connection Success -def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.LifecycleConnectSuccessData): - print("Lifecycle Connection Success") - global future_connection_success - future_connection_success.set_result(lifecycle_connect_success_data) - -# Callback for the lifecycle event on Client Stopped -def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): - print("Client Stopped.") - - # Signal that sample is finished - is_sample_done.set() - - - -# A list to hold all the pending jobs -available_jobs = [] - - -def on_get_pending_job_executions_accepted(response): - # type: (iotjobs.GetPendingJobExecutionsResponse) -> None - with locked_data.lock: - if (len(response.queued_jobs) > 0 or len(response.in_progress_jobs) > 0): - print("Pending Jobs:") - for job in response.in_progress_jobs: - available_jobs.append(job) - print(f" In Progress: {job.job_id} @ {job.last_updated_at}") - for job in response.queued_jobs: - available_jobs.append(job) - print(f" {job.job_id} @ {job.last_updated_at}") - else: - print("No pending or queued jobs found!") - locked_data.got_job_response = True - - -def on_get_pending_job_executions_rejected(error): - # type: (iotjobs.RejectedError) -> None - print(f"Request rejected: {error.code}: {error.message}") - exit("Get pending jobs request rejected!") - - -def on_next_job_execution_changed(event): - # type: (iotjobs.NextJobExecutionChangedEvent) -> None - try: - execution = event.execution - if execution: - print("Received Next Job Execution Changed event. job_id:{} job_document:{}".format( - execution.job_id, execution.job_document)) - - # Start job now, or remember to start it when current job is done - start_job_now = False - with locked_data.lock: - if locked_data.is_working_on_job: - locked_data.is_next_job_waiting = True - else: - start_job_now = True - - if start_job_now: - try_start_next_job() - - else: - print("Received Next Job Execution Changed event: None. Waiting for further jobs...") - - except Exception as e: - exit(e) - - -def on_publish_start_next_pending_job_execution(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - - print("Published request to start the next job.") - - except Exception as e: - exit(e) - - -def on_start_next_pending_job_execution_accepted(response): - # type: (iotjobs.StartNextJobExecutionResponse) -> None - try: - if response.execution: - execution = response.execution - print("Request to start next job was accepted. job_id:{} job_document:{}".format( - execution.job_id, execution.job_document)) - - # To emulate working on a job, spawn a thread that sleeps for a few seconds - job_thread = threading.Thread( - target=lambda: job_thread_fn(execution.job_id, execution.job_document), - name='job_thread') - job_thread.start() - else: - print("Request to start next job was accepted, but there are no jobs to be done. Waiting for further jobs...") - done_working_on_job() - - except Exception as e: - exit(e) - - -def on_start_next_pending_job_execution_rejected(rejected): - # type: (iotjobs.RejectedError) -> None - exit("Request to start next pending job rejected with code:'{}' message:'{}'".format( - rejected.code, rejected.message)) - - -def job_thread_fn(job_id, job_document): - try: - print("Starting local work on job...") - time.sleep(cmdData.input_job_time) - print("Done working on job.") - - print("Publishing request to update job status to SUCCEEDED...") - request = iotjobs.UpdateJobExecutionRequest( - thing_name=jobs_thing_name, - job_id=job_id, - status=iotjobs.JobStatus.SUCCEEDED) - publish_future = jobs_client.publish_update_job_execution(request, mqtt5.QoS.AT_LEAST_ONCE) - publish_future.add_done_callback(on_publish_update_job_execution) - - except Exception as e: - exit(e) - - -def on_publish_update_job_execution(future): - # type: (Future) -> None - try: - future.result() # raises exception if publish failed - print("Published request to update job.") - - except Exception as e: - exit(e) - - -def on_update_job_execution_accepted(response): - # type: (iotjobs.UpdateJobExecutionResponse) -> None - try: - print("Request to update job was accepted.") - done_working_on_job() - except Exception as e: - exit(e) - - -def on_update_job_execution_rejected(rejected): - # type: (iotjobs.RejectedError) -> None - exit("Request to update job status was rejected. code:'{}' message:'{}'.".format( - rejected.code, rejected.message)) - - -if __name__ == '__main__': - - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a mqtt5 connection from the command line data - mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options, - on_lifecycle_connection_success=on_lifecycle_connection_success, - on_lifecycle_stopped=on_lifecycle_stopped) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - mqtt5_client.start() - - jobs_client = iotjobs.IotJobsClient(mqtt5_client) - - # Wait for connection to be fully established. - # Note that it's not necessary to wait, commands issued to the - # mqtt5_client before its fully connected will simply be queued. - # But this sample waits here so it's obvious when a connection - # fails or succeeds. - future_connection_success.result() - print("Connected!") - - try: - # List the jobs queued and pending - get_jobs_request = iotjobs.GetPendingJobExecutionsRequest(thing_name=jobs_thing_name) - jobs_request_future_accepted, _ = jobs_client.subscribe_to_get_pending_job_executions_accepted( - request=get_jobs_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_get_pending_job_executions_accepted - ) - # Wait for the subscription to succeed - jobs_request_future_accepted.result() - - jobs_request_future_rejected, _ = jobs_client.subscribe_to_get_pending_job_executions_rejected( - request=get_jobs_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_get_pending_job_executions_rejected - ) - # Wait for the subscription to succeed - jobs_request_future_rejected.result() - - # Get a list of all the jobs - get_jobs_request_future = jobs_client.publish_get_pending_job_executions( - request=get_jobs_request, - qos=mqtt5.QoS.AT_LEAST_ONCE - ) - # Wait for the publish to succeed - get_jobs_request_future.result() - except Exception as e: - exit(e) - - # If we are running in CI, then we want to check how many jobs were reported and stop - if (cmdData.input_is_ci): - # Wait until we get a response. If we do not get a response after 50 tries, then abort - got_job_response_tries = 0 - while (locked_data.got_job_response == False): - got_job_response_tries += 1 - if (got_job_response_tries > 50): - exit("Got job response timeout exceeded") - sys.exit(-1) - time.sleep(0.2) - - if (len(available_jobs) > 0): - print("At least one job queued in CI! No further work to do. Exiting sample...") - sys.exit(0) - else: - print("ERROR: No jobs queued in CI! At least one job should be queued!") - sys.exit(-1) - - try: - # Subscribe to necessary topics. - # Note that is **is** important to wait for "accepted/rejected" subscriptions - # to succeed before publishing the corresponding "request". - print("Subscribing to Next Changed events...") - changed_subscription_request = iotjobs.NextJobExecutionChangedSubscriptionRequest( - thing_name=jobs_thing_name) - - subscribed_future, _ = jobs_client.subscribe_to_next_job_execution_changed_events( - request=changed_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_next_job_execution_changed) - - # Wait for subscription to succeed - subscribed_future.result() - - print("Subscribing to Start responses...") - start_subscription_request = iotjobs.StartNextPendingJobExecutionSubscriptionRequest( - thing_name=jobs_thing_name) - subscribed_accepted_future, _ = jobs_client.subscribe_to_start_next_pending_job_execution_accepted( - request=start_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_start_next_pending_job_execution_accepted) - - subscribed_rejected_future, _ = jobs_client.subscribe_to_start_next_pending_job_execution_rejected( - request=start_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_start_next_pending_job_execution_rejected) - - # Wait for subscriptions to succeed - subscribed_accepted_future.result() - subscribed_rejected_future.result() - - print("Subscribing to Update responses...") - # Note that we subscribe to "+", the MQTT wildcard, to receive - # responses about any job-ID. - update_subscription_request = iotjobs.UpdateJobExecutionSubscriptionRequest( - thing_name=jobs_thing_name, - job_id='+') - - subscribed_accepted_future, _ = jobs_client.subscribe_to_update_job_execution_accepted( - request=update_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_update_job_execution_accepted) - - subscribed_rejected_future, _ = jobs_client.subscribe_to_update_job_execution_rejected( - request=update_subscription_request, - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_update_job_execution_rejected) - - # Wait for subscriptions to succeed - subscribed_accepted_future.result() - subscribed_rejected_future.result() - - # Make initial attempt to start next job. The service should reply with - # an "accepted" response, even if no jobs are pending. The response - # will contain data about the next job, if there is one. - # (Will do nothing if we are in CI) - try_start_next_job() - - except Exception as e: - exit(e) - - # Wait for the sample to finish - is_sample_done.wait() diff --git a/samples/deprecated/shadow.md b/samples/deprecated/shadow.md deleted file mode 100644 index aa250757..00000000 --- a/samples/deprecated/shadow.md +++ /dev/null @@ -1,87 +0,0 @@ -# Shadow - -[**Return to main sample list**](../README.md) - -This sample uses the AWS IoT [Device Shadow](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html) Service to keep a property in sync between device and server. Imagine a light whose color may be changed through an app, or set by a local user. - -Once connected, type a value in the terminal and press Enter to update the property's "reported" value. The sample also responds when the "desired" value changes on the server. To observe this, edit the Shadow document in the AWS Console and set a new "desired" value. - -On startup, the sample requests the shadow document to learn the property's initial state. The sample also subscribes to "delta" events from the server, which are sent when a property's "desired" value differs from its "reported" value. When the sample learns of a new desired value, that value is changed on the device and an update is sent to the server with the new "reported" value. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-Sample Policy -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Publish"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Receive"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get/accepted",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get/rejected",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/accepted",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/rejected",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/delta"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Subscribe"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/get/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/get/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/delta"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Connect",
-      "Resource": "arn:aws:iot:region:account:client/test-*"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS IoT Core thing you want the device connection to be associated with - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run the Shadow sample from the `samples` folder, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 shadow.py --endpoint --cert --key --thing_name -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 shadow.py --endpoint --cert --key --thing_name --ca_file -``` diff --git a/samples/deprecated/shadow.py b/samples/deprecated/shadow.py deleted file mode 100644 index 285883c4..00000000 --- a/samples/deprecated/shadow.py +++ /dev/null @@ -1,426 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from time import sleep -from awscrt import mqtt, http -from awsiot import iotshadow, mqtt_connection_builder -from concurrent.futures import Future -import sys -import threading -import traceback -from uuid import uuid4 -from utils.command_line_utils import CommandLineUtils - -# - Overview - -# This sample uses the AWS IoT Device Shadow Service to keep a property in -# sync between device and server. Imagine a light whose color may be changed -# through an app, or set by a local user. -# -# - Instructions - -# Once connected, type a value in the terminal and press Enter to update -# the property's "reported" value. The sample also responds when the "desired" -# value changes on the server. To observe this, edit the Shadow document in -# the AWS Console and set a new "desired" value. -# -# - Detail - -# On startup, the sample requests the shadow document to learn the property's -# initial state. The sample also subscribes to "delta" events from the server, -# which are sent when a property's "desired" value differs from its "reported" -# value. When the sample learns of a new desired value, that value is changed -# on the device and an update is sent to the server with the new "reported" -# value. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_shadow() - -# Using globals to simplify sample code -is_sample_done = threading.Event() -mqtt_connection = None -shadow_thing_name = cmdData.input_thing_name -shadow_property = cmdData.input_shadow_property - -SHADOW_VALUE_DEFAULT = "off" - - -class LockedData: - def __init__(self): - self.lock = threading.Lock() - self.shadow_value = None - self.disconnect_called = False - self.request_tokens = set() - - -locked_data = LockedData() - -# Function for gracefully quitting this sample - - -def exit(msg_or_exception): - if isinstance(msg_or_exception, Exception): - print("Exiting sample due to exception.") - traceback.print_exception(msg_or_exception.__class__, msg_or_exception, sys.exc_info()[2]) - else: - print("Exiting sample:", msg_or_exception) - - with locked_data.lock: - if not locked_data.disconnect_called: - print("Disconnecting...") - locked_data.disconnect_called = True - future = mqtt_connection.disconnect() - future.add_done_callback(on_disconnected) - - -def on_disconnected(disconnect_future): - # type: (Future) -> None - print("Disconnected.") - - # Signal that sample is finished - is_sample_done.set() - - -def on_get_shadow_accepted(response): - # type: (iotshadow.GetShadowResponse) -> None - try: - with locked_data.lock: - # check that this is a response to a request from this session - try: - locked_data.request_tokens.remove(response.client_token) - except KeyError: - print("Ignoring get_shadow_accepted message due to unexpected token.") - return - - print("Finished getting initial shadow state.") - if locked_data.shadow_value is not None: - print(" Ignoring initial query because a delta event has already been received.") - return - - if response.state: - if response.state.delta: - value = response.state.delta.get(shadow_property) - if value: - print(" Shadow contains delta value '{}'.".format(value)) - change_shadow_value(value) - return - - if response.state.reported: - value = response.state.reported.get(shadow_property) - if value: - print(" Shadow contains reported value '{}'.".format(value)) - set_local_value_due_to_initial_query(response.state.reported[shadow_property]) - return - - print(" Shadow document lacks '{}' property. Setting defaults...".format(shadow_property)) - change_shadow_value(SHADOW_VALUE_DEFAULT) - return - - except Exception as e: - exit(e) - - -def on_get_shadow_rejected(error): - # type: (iotshadow.ErrorResponse) -> None - try: - # check that this is a response to a request from this session - with locked_data.lock: - try: - locked_data.request_tokens.remove(error.client_token) - except KeyError: - print("Ignoring get_shadow_rejected message due to unexpected token.") - return - - if error.code == 404: - print("Thing has no shadow document. Creating with defaults...") - change_shadow_value(SHADOW_VALUE_DEFAULT) - else: - exit("Get request was rejected. code:{} message:'{}'".format( - error.code, error.message)) - - except Exception as e: - exit(e) - - -def on_shadow_delta_updated(delta): - # type: (iotshadow.ShadowDeltaUpdatedEvent) -> None - try: - print("Received shadow delta event.") - if delta.state and (shadow_property in delta.state): - value = delta.state[shadow_property] - if value is None: - print(" Delta reports that '{}' was deleted. Resetting defaults...".format(shadow_property)) - change_shadow_value(SHADOW_VALUE_DEFAULT) - return - else: - print(" Delta reports that desired value is '{}'. Changing local value...".format(value)) - if (delta.client_token is not None): - print(" ClientToken is: " + delta.client_token) - change_shadow_value(value) - else: - print(" Delta did not report a change in '{}'".format(shadow_property)) - - except Exception as e: - exit(e) - - -def on_publish_update_shadow(future): - # type: (Future) -> None - try: - future.result() - print("Update request published.") - except Exception as e: - print("Failed to publish update request.") - exit(e) - - -def on_update_shadow_accepted(response): - # type: (iotshadow.UpdateShadowResponse) -> None - try: - # check that this is a response to a request from this session - with locked_data.lock: - try: - locked_data.request_tokens.remove(response.client_token) - except KeyError: - print("Ignoring update_shadow_accepted message due to unexpected token.") - return - - try: - if response.state.reported is not None: - if shadow_property in response.state.reported: - print("Finished updating reported shadow value to '{}'.".format( - response.state.reported[shadow_property])) # type: ignore - else: - print("Could not find shadow property with name: '{}'.".format(shadow_property)) # type: ignore - else: - print("Shadow states cleared.") # when the shadow states are cleared, reported and desired are set to None - print("Enter desired value: ") # remind user they can input new values - except BaseException: - exit("Updated shadow is missing the target property") - - except Exception as e: - exit(e) - - -def on_update_shadow_rejected(error): - # type: (iotshadow.ErrorResponse) -> None - try: - # check that this is a response to a request from this session - with locked_data.lock: - try: - locked_data.request_tokens.remove(error.client_token) - except KeyError: - print("Ignoring update_shadow_rejected message due to unexpected token.") - return - - exit("Update request was rejected. code:{} message:'{}'".format( - error.code, error.message)) - - except Exception as e: - exit(e) - - -def set_local_value_due_to_initial_query(reported_value): - with locked_data.lock: - locked_data.shadow_value = reported_value - print("Enter desired value: ") # remind user they can input new values - - -def change_shadow_value(value): - with locked_data.lock: - if locked_data.shadow_value == value: - print("Local value is already '{}'.".format(value)) - print("Enter desired value: ") # remind user they can input new values - return - - print("Changed local shadow value to '{}'.".format(value)) - locked_data.shadow_value = value - - print("Updating reported shadow value to '{}'...".format(value)) - - # use a unique token so we can correlate this "request" message to - # any "response" messages received on the /accepted and /rejected topics - token = str(uuid4()) - - # if the value is "clear shadow" then send a UpdateShadowRequest with None - # for both reported and desired to clear the shadow document completely. - if value == "clear_shadow": - tmp_state = iotshadow.ShadowState( - reported=None, - desired=None, - reported_is_nullable=True, - desired_is_nullable=True) - request = iotshadow.UpdateShadowRequest( - thing_name=shadow_thing_name, - state=tmp_state, - client_token=token, - ) - # Otherwise, send a normal update request - else: - # if the value is "none" then set it to a Python none object to - # clear the individual shadow property - if value == "none": - value = None - - request = iotshadow.UpdateShadowRequest( - thing_name=shadow_thing_name, - state=iotshadow.ShadowState( - reported={shadow_property: value}, - desired={shadow_property: value}, - ), - client_token=token, - ) - - future = shadow_client.publish_update_shadow(request, mqtt.QoS.AT_LEAST_ONCE) - - locked_data.request_tokens.add(token) - - future.add_done_callback(on_publish_update_shadow) - - -def user_input_thread_fn(): - # If we are not in CI, then take terminal input - if not cmdData.input_is_ci: - while True: - try: - # Read user input - new_value = input() - - # If user wants to quit sample, then quit. - # Otherwise change the shadow value. - if new_value in ['exit', 'quit']: - exit("User has quit") - break - else: - change_shadow_value(new_value) - - except Exception as e: - print("Exception on input thread.") - exit(e) - break - # Otherwise, send shadow updates automatically - else: - try: - messages_sent = 0 - while messages_sent < 5: - cli_input = "Shadow_Value_" + str(messages_sent) - change_shadow_value(cli_input) - sleep(1) - messages_sent += 1 - exit("CI has quit") - except Exception as e: - print("Exception on input thread (CI)") - exit(e) - - -if __name__ == '__main__': - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connected_future = mqtt_connection.connect() - - shadow_client = iotshadow.IotShadowClient(mqtt_connection) - - # Wait for connection to be fully established. - # Note that it's not necessary to wait, commands issued to the - # mqtt_connection before its fully connected will simply be queued. - # But this sample waits here so it's obvious when a connection - # fails or succeeds. - connected_future.result() - print("Connected!") - - try: - # Subscribe to necessary topics. - # Note that is **is** important to wait for "accepted/rejected" subscriptions - # to succeed before publishing the corresponding "request". - print("Subscribing to Update responses...") - update_accepted_subscribed_future, _ = shadow_client.subscribe_to_update_shadow_accepted( - request=iotshadow.UpdateShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_update_shadow_accepted) - - update_rejected_subscribed_future, _ = shadow_client.subscribe_to_update_shadow_rejected( - request=iotshadow.UpdateShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_update_shadow_rejected) - - # Wait for subscriptions to succeed - update_accepted_subscribed_future.result() - update_rejected_subscribed_future.result() - - print("Subscribing to Get responses...") - get_accepted_subscribed_future, _ = shadow_client.subscribe_to_get_shadow_accepted( - request=iotshadow.GetShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_get_shadow_accepted) - - get_rejected_subscribed_future, _ = shadow_client.subscribe_to_get_shadow_rejected( - request=iotshadow.GetShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_get_shadow_rejected) - - # Wait for subscriptions to succeed - get_accepted_subscribed_future.result() - get_rejected_subscribed_future.result() - - print("Subscribing to Delta events...") - delta_subscribed_future, _ = shadow_client.subscribe_to_shadow_delta_updated_events( - request=iotshadow.ShadowDeltaUpdatedSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_shadow_delta_updated) - - # Wait for subscription to succeed - delta_subscribed_future.result() - - # The rest of the sample runs asynchronously. - - # Issue request for shadow's current state. - # The response will be received by the on_get_accepted() callback - print("Requesting current shadow state...") - - with locked_data.lock: - # use a unique token so we can correlate this "request" message to - # any "response" messages received on the /accepted and /rejected topics - token = str(uuid4()) - - publish_get_future = shadow_client.publish_get_shadow( - request=iotshadow.GetShadowRequest(thing_name=shadow_thing_name, client_token=token), - qos=mqtt.QoS.AT_LEAST_ONCE) - - locked_data.request_tokens.add(token) - - # Ensure that publish succeeds - publish_get_future.result() - - # Launch thread to handle user input. - # A "daemon" thread won't prevent the program from shutting down. - print("Launching thread to read user input...") - user_input_thread = threading.Thread(target=user_input_thread_fn, name='user_input_thread') - user_input_thread.daemon = True - user_input_thread.start() - - except Exception as e: - exit(e) - - # Wait for the sample to finish (user types 'quit', or an error occurs) - is_sample_done.wait() diff --git a/samples/deprecated/shadow_mqtt5.md b/samples/deprecated/shadow_mqtt5.md deleted file mode 100644 index 14ca79cd..00000000 --- a/samples/deprecated/shadow_mqtt5.md +++ /dev/null @@ -1,146 +0,0 @@ -# Shadow MQTT5 - -[**Return to main sample list**](../README.md) - -This sample uses the AWS IoT [Device Shadow](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html) Service to keep a property in sync between device and server. Imagine a light whose color may be changed through an app, or set by a local user. - -Once connected, type a value in the terminal and press Enter to update the property's "reported" value. The sample also responds when the "desired" value changes on the server. To observe this, edit the Shadow document in the AWS Console and set a new "desired" value. - -On startup, the sample requests the shadow document to learn the property's initial state. The sample also subscribes to "delta" events from the server, which are sent when a property's "desired" value differs from its "reported" value. When the sample learns of a new desired value, that value is changed on the device and an update is sent to the server with the new "reported" value. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-Sample Policy -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Publish"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Receive"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get/accepted",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/get/rejected",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/accepted",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/rejected",
-        "arn:aws:iot:region:account:topic/$aws/things/thingname/shadow/update/delta"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Subscribe"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/get/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/get/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/accepted",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/rejected",
-        "arn:aws:iot:region:account:topicfilter/$aws/things/thingname/shadow/update/delta"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": "iot:Connect",
-      "Resource": "arn:aws:iot:region:account:client/test-*"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS IoT Core thing you want the device connection to be associated with - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run the Shadow sample from the `samples` folder, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 shadow_mqtt5.py --endpoint --cert --key --thing_name -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 shadow_mqtt5.py --endpoint --cert --key --thing_name --ca_file -``` - -## Service Client Notes -### Difference relative to MQTT311 IotShadowClient -The IotShadowClient with mqtt5 client is almost identical to mqtt3 one. The only difference is that you would need setup up a Mqtt5 Client and pass it to the IoTShadowClient. -For how to setup a Mqtt5 Client, please refer to [MQTT5 UserGuide](../documents/MQTT5_Userguide.md) and [MQTT5 PubSub Sample](./mqtt5_pubsub.py) - - - - - - - - - - -
Create a IotShadowClient with Mqtt5Create a IotShadowClient with Mqtt311
- -```python - # Create a Mqtt5 Client - mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint, - port, - cert_filepath, - pri_key_filepath, - ca_filepath, - client_id, - clean_session, - keep_alive_secs, - http_proxy_options, - on_lifecycle_connection_success, - on_lifecycle_stopped) - - # Create the shadow client from Mqtt5 Client - shadow_client = iotshadow.IotShadowClient(mqtt5_client) -``` - - - -```python - # Create a Mqtt311 Connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint, - port, - cert_filepath, - pri_key_filepath, - ca_filepath, - client_id, - clean_session, - keep_alive_secs, - http_proxy_options) - - # Create the shadow client from Mqtt311 Connection - shadow_client = iotshadow.IotShadowClient(mqtt_connection) -``` - -
- -### Mqtt5.QoS v.s. Mqtt3.QoS -As the service client interface is unchanged for both Mqtt3 Connection and Mqtt5 Client,the IoTShadowClient will use Mqtt3.QoS instead of Mqtt5.QoS even with a Mqtt5 Client. You could use mqtt3.QoS.to_mqtt5() and mqtt5.QoS.to_mqtt3() to convert the value. \ No newline at end of file diff --git a/samples/deprecated/shadow_mqtt5.py b/samples/deprecated/shadow_mqtt5.py deleted file mode 100644 index a71e8fd0..00000000 --- a/samples/deprecated/shadow_mqtt5.py +++ /dev/null @@ -1,433 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from time import sleep -from awscrt import mqtt5, http -from awsiot import iotshadow, mqtt5_client_builder -from concurrent.futures import Future -import sys -import threading -import traceback -from uuid import uuid4 -from utils.command_line_utils import CommandLineUtils - -# - Overview - -# This sample uses the AWS IoT Device Shadow Service to keep a property in -# sync between device and server. Imagine a light whose color may be changed -# through an app, or set by a local user. -# -# - Instructions - -# Once connected, type a value in the terminal and press Enter to update -# the property's "reported" value. The sample also responds when the "desired" -# value changes on the server. To observe this, edit the Shadow document in -# the AWS Console and set a new "desired" value. -# -# - Detail - -# On startup, the sample requests the shadow document to learn the property's -# initial state. The sample also subscribes to "delta" events from the server, -# which are sent when a property's "desired" value differs from its "reported" -# value. When the sample learns of a new desired value, that value is changed -# on the device and an update is sent to the server with the new "reported" -# value. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_shadow() - -# Using globals to simplify sample code -is_sample_done = threading.Event() -mqtt5_client = None -future_connection_success = Future() -shadow_thing_name = cmdData.input_thing_name -shadow_property = cmdData.input_shadow_property - -SHADOW_VALUE_DEFAULT = "off" - - -class LockedData: - def __init__(self): - self.lock = threading.Lock() - self.shadow_value = None - self.disconnect_called = False - self.request_tokens = set() - - -locked_data = LockedData() - -# Function for gracefully quitting this sample -def exit(msg_or_exception): - if isinstance(msg_or_exception, Exception): - print("Exiting sample due to exception.") - traceback.print_exception(msg_or_exception.__class__, msg_or_exception, sys.exc_info()[2]) - else: - print("Exiting sample:", msg_or_exception) - - with locked_data.lock: - if not locked_data.disconnect_called: - print("Stop the client...") - locked_data.disconnect_called = True - mqtt5_client.stop() - -# Callback for the lifecycle event Connection Success -def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.LifecycleConnectSuccessData): - print("Lifecycle Connection Success") - global future_connection_success - future_connection_success.set_result(lifecycle_connect_success_data) - -# Callback for the lifecycle event on Client Stopped -def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): - # type: (Future) -> None - print("Client Stopped.") - - # Signal that sample is finished - is_sample_done.set() - - -def on_get_shadow_accepted(response): - # type: (iotshadow.GetShadowResponse) -> None - try: - with locked_data.lock: - # check that this is a response to a request from this session - try: - locked_data.request_tokens.remove(response.client_token) - except KeyError: - print("Ignoring get_shadow_accepted message due to unexpected token.") - return - - print("Finished getting initial shadow state.") - if locked_data.shadow_value is not None: - print(" Ignoring initial query because a delta event has already been received.") - return - - if response.state: - if response.state.delta: - value = response.state.delta.get(shadow_property) - if value: - print(" Shadow contains delta value '{}'.".format(value)) - change_shadow_value(value) - return - - if response.state.reported: - value = response.state.reported.get(shadow_property) - if value: - print(" Shadow contains reported value '{}'.".format(value)) - set_local_value_due_to_initial_query(response.state.reported[shadow_property]) - return - - print(" Shadow document lacks '{}' property. Setting defaults...".format(shadow_property)) - change_shadow_value(SHADOW_VALUE_DEFAULT) - return - - except Exception as e: - exit(e) - - -def on_get_shadow_rejected(error): - # type: (iotshadow.ErrorResponse) -> None - try: - # check that this is a response to a request from this session - with locked_data.lock: - try: - locked_data.request_tokens.remove(error.client_token) - except KeyError: - print("Ignoring get_shadow_rejected message due to unexpected token.") - return - - if error.code == 404: - print("Thing has no shadow document. Creating with defaults...") - change_shadow_value(SHADOW_VALUE_DEFAULT) - else: - exit("Get request was rejected. code:{} message:'{}'".format( - error.code, error.message)) - - except Exception as e: - exit(e) - - -def on_shadow_delta_updated(delta): - # type: (iotshadow.ShadowDeltaUpdatedEvent) -> None - try: - print("Received shadow delta event.") - if delta.state and (shadow_property in delta.state): - value = delta.state[shadow_property] - if value is None: - print(" Delta reports that '{}' was deleted. Resetting defaults...".format(shadow_property)) - change_shadow_value(SHADOW_VALUE_DEFAULT) - return - else: - print(" Delta reports that desired value is '{}'. Changing local value...".format(value)) - if (delta.client_token is not None): - print(" ClientToken is: " + delta.client_token) - change_shadow_value(value) - else: - print(" Delta did not report a change in '{}'".format(shadow_property)) - - except Exception as e: - exit(e) - - -def on_publish_update_shadow(future): - # type: (Future) -> None - try: - future.result() - print("Update request published.") - except Exception as e: - print("Failed to publish update request.") - exit(e) - - -def on_update_shadow_accepted(response): - # type: (iotshadow.UpdateShadowResponse) -> None - try: - # check that this is a response to a request from this session - with locked_data.lock: - try: - locked_data.request_tokens.remove(response.client_token) - except KeyError: - print("Ignoring update_shadow_accepted message due to unexpected token.") - return - - try: - if response.state.reported is not None: - if shadow_property in response.state.reported: - print("Finished updating reported shadow value to '{}'.".format( - response.state.reported[shadow_property])) # type: ignore - else: - print("Could not find shadow property with name: '{}'.".format(shadow_property)) # type: ignore - else: - print("Shadow states cleared.") # when the shadow states are cleared, reported and desired are set to None - print("Enter desired value: ") # remind user they can input new values - except BaseException: - exit("Updated shadow is missing the target property") - - except Exception as e: - exit(e) - - -def on_update_shadow_rejected(error): - # type: (iotshadow.ErrorResponse) -> None - try: - # check that this is a response to a request from this session - with locked_data.lock: - try: - locked_data.request_tokens.remove(error.client_token) - except KeyError: - print("Ignoring update_shadow_rejected message due to unexpected token.") - return - - exit("Update request was rejected. code:{} message:'{}'".format( - error.code, error.message)) - - except Exception as e: - exit(e) - - -def set_local_value_due_to_initial_query(reported_value): - with locked_data.lock: - locked_data.shadow_value = reported_value - print("Enter desired value: ") # remind user they can input new values - - -def change_shadow_value(value): - with locked_data.lock: - if locked_data.shadow_value == value: - print("Local value is already '{}'.".format(value)) - print("Enter desired value: ") # remind user they can input new values - return - - print("Changed local shadow value to '{}'.".format(value)) - locked_data.shadow_value = value - - print("Updating reported shadow value to '{}'...".format(value)) - - # use a unique token so we can correlate this "request" message to - # any "response" messages received on the /accepted and /rejected topics - token = str(uuid4()) - - # if the value is "clear shadow" then send a UpdateShadowRequest with None - # for both reported and desired to clear the shadow document completely. - if value == "clear_shadow": - tmp_state = iotshadow.ShadowState( - reported=None, - desired=None, - reported_is_nullable=True, - desired_is_nullable=True) - request = iotshadow.UpdateShadowRequest( - thing_name=shadow_thing_name, - state=tmp_state, - client_token=token, - ) - # Otherwise, send a normal update request - else: - # if the value is "none" then set it to a Python none object to - # clear the individual shadow property - if value == "none": - value = None - - request = iotshadow.UpdateShadowRequest( - thing_name=shadow_thing_name, - state=iotshadow.ShadowState( - reported={shadow_property: value}, - desired={shadow_property: value}, - ), - client_token=token, - ) - - future = shadow_client.publish_update_shadow(request, mqtt5.QoS.AT_LEAST_ONCE) - - locked_data.request_tokens.add(token) - - future.add_done_callback(on_publish_update_shadow) - - -def user_input_thread_fn(): - # If we are not in CI, then take terminal input - if not cmdData.input_is_ci: - while True: - try: - # Read user input - new_value = input() - - # If user wants to quit sample, then quit. - # Otherwise change the shadow value. - if new_value in ['exit', 'quit']: - exit("User has quit") - break - else: - change_shadow_value(new_value) - - except Exception as e: - print("Exception on input thread.") - exit(e) - break - # Otherwise, send shadow updates automatically - else: - try: - messages_sent = 0 - while messages_sent < 5: - cli_input = "Shadow_Value_" + str(messages_sent) - change_shadow_value(cli_input) - sleep(1) - messages_sent += 1 - exit("CI has quit") - except Exception as e: - print("Exception on input thread (CI)") - exit(e) - - -if __name__ == '__main__': - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a mqtt5 connection from the command line data - mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options, - on_lifecycle_connection_success=on_lifecycle_connection_success, - on_lifecycle_stopped=on_lifecycle_stopped) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - mqtt5_client.start() - - shadow_client = iotshadow.IotShadowClient(mqtt5_client) - - # Wait for connection to be fully established. - # Note that it's not necessary to wait, commands issued to the - # mqtt5_client before its fully connected will simply be queued. - # But this sample waits here so it's obvious when a connection - # fails or succeeds. - future_connection_success.result() - print("Connected!") - - try: - # Subscribe to necessary topics. - # Note that is **is** important to wait for "accepted/rejected" subscriptions - # to succeed before publishing the corresponding "request". - print("Subscribing to Update responses...") - update_accepted_subscribed_future, _ = shadow_client.subscribe_to_update_shadow_accepted( - request=iotshadow.UpdateShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_update_shadow_accepted) - - - update_rejected_subscribed_future, _ = shadow_client.subscribe_to_update_shadow_rejected( - request=iotshadow.UpdateShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_update_shadow_rejected) - - # Wait for subscriptions to succeed - result = update_accepted_subscribed_future.result() - update_rejected_subscribed_future.result() - - print("Subscribing to Get responses...") - get_accepted_subscribed_future, _ = shadow_client.subscribe_to_get_shadow_accepted( - request=iotshadow.GetShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_get_shadow_accepted) - - get_rejected_subscribed_future, _ = shadow_client.subscribe_to_get_shadow_rejected( - request=iotshadow.GetShadowSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_get_shadow_rejected) - - # Wait for subscriptions to succeed - get_accepted_subscribed_future.result() - get_rejected_subscribed_future.result() - - print("Subscribing to Delta events...") - delta_subscribed_future, _ = shadow_client.subscribe_to_shadow_delta_updated_events( - request=iotshadow.ShadowDeltaUpdatedSubscriptionRequest(thing_name=shadow_thing_name), - qos=mqtt5.QoS.AT_LEAST_ONCE, - callback=on_shadow_delta_updated) - - # Wait for subscription to succeed - delta_subscribed_future.result() - - # The rest of the sample runs asynchronously. - - # Issue request for shadow's current state. - # The response will be received by the on_get_accepted() callback - print("Requesting current shadow state...") - - with locked_data.lock: - # use a unique token so we can correlate this "request" message to - # any "response" messages received on the /accepted and /rejected topics - token = str(uuid4()) - - publish_get_future = shadow_client.publish_get_shadow( - request=iotshadow.GetShadowRequest(thing_name=shadow_thing_name, client_token=token), - qos=mqtt5.QoS.AT_LEAST_ONCE) - - locked_data.request_tokens.add(token) - - # Ensure that publish succeeds - publish_get_future.result() - - # Launch thread to handle user input. - # A "daemon" thread won't prevent the program from shutting down. - print("Launching thread to read user input...") - user_input_thread = threading.Thread(target=user_input_thread_fn, name='user_input_thread') - user_input_thread.daemon = True - user_input_thread.start() - - except Exception as e: - exit(e) - - # Wait for the sample to finish (user types 'quit', or an error occurs) - is_sample_done.wait() diff --git a/samples/deprecated/utils/command_line_utils.py b/samples/deprecated/utils/command_line_utils.py deleted file mode 100644 index 81f9925e..00000000 --- a/samples/deprecated/utils/command_line_utils.py +++ /dev/null @@ -1,922 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -import argparse -from awscrt import io -from uuid import uuid4 - -class CommandLineUtils: - def __init__(self, description) -> None: - self.parser = argparse.ArgumentParser(description="Send and receive messages through and MQTT connection.") - self.commands = {} - self.parsed_commands = None - - def register_command(self, command_name, example_input, help_output, required=False, type=None, default=None, choices=None, action=None): - self.commands[command_name] = { - "name":command_name, - "example_input":example_input, - "help_output":help_output, - "required": required, - "type": type, - "default": default, - "choices": choices, - "action": action - } - - def remove_command(self, command_name): - if command_name in self.commands.keys(): - self.commands.pop(command_name) - - """ - Returns the command if it exists and has been passed to the console, otherwise it will print the help for the sample and exit the application. - """ - def get_command_required(self, command_name, command_name_alt = None): - if(command_name_alt != None): - if hasattr(self.parsed_commands, command_name_alt): - if(getattr(self.parsed_commands, command_name_alt) != None): - return getattr(self.parsed_commands, command_name_alt) - - if hasattr(self.parsed_commands, command_name): - if(getattr(self.parsed_commands, command_name) != None): - return getattr(self.parsed_commands, command_name) - - self.parser.print_help() - print("Command --" + command_name + " required.") - exit() - - """ - Returns the command if it exists, has been passed to the console, and is not None. Otherwise it returns whatever is passed as the default. - """ - def get_command(self, command_name, default=None): - if hasattr(self.parsed_commands, command_name): - result = getattr(self.parsed_commands, command_name) - if (result != None): - return result - return default - - def get_args(self): - # if we have already parsed, then return the cached parsed commands - if self.parsed_commands is not None: - return self.parsed_commands - - # add all the commands - for command in self.commands.values(): - if not command["action"] is None: - self.parser.add_argument("--" + command["name"], action=command["action"], help=command["help_output"], - required=command["required"], default=command["default"]) - else: - self.parser.add_argument("--" + command["name"], metavar=command["example_input"], help=command["help_output"], - required=command["required"], type=command["type"], default=command["default"], choices=command["choices"]) - - self.parsed_commands = self.parser.parse_args() - # Automatically start logging if it is set - if self.parsed_commands.verbosity: - io.init_logging(getattr(io.LogLevel, self.parsed_commands.verbosity), 'stderr') - - return self.parsed_commands - - def update_command(self, command_name, new_example_input=None, new_help_output=None, new_required=None, new_type=None, new_default=None, new_action=None): - if command_name in self.commands.keys(): - if new_example_input: - self.commands[command_name]["example_input"] = new_example_input - if new_help_output: - self.commands[command_name]["help_output"] = new_help_output - if new_required: - self.commands[command_name]["required"] = new_required - if new_type: - self.commands[command_name]["type"] = new_type - if new_default: - self.commands[command_name]["default"] = new_default - if new_action: - self.commands[command_name]["action"] = new_action - - def add_common_mqtt_commands(self): - self.register_command( - CommandLineUtils.m_cmd_endpoint, - "", - "The endpoint of the mqtt server not including a port.", - True, - str) - self.register_command( - CommandLineUtils.m_cmd_ca_file, - "", - "Path to AmazonRootCA1.pem (optional, system trust store used by default)", - False, - str) - self.register_command( - CommandLineUtils.m_cmd_is_ci, - "", - "If present the sample will run in CI mode (optional, default='None')", - False, - str) - - def add_common_mqtt5_commands(self): - self.register_command( - CommandLineUtils.m_cmd_endpoint, - "", - "The endpoint of the mqtt server not including a port.", - True, - str) - self.register_command( - CommandLineUtils.m_cmd_ca_file, - "", - "Path to AmazonRootCA1.pem (optional, system trust store used by default)", - False, - str) - self.register_command( - CommandLineUtils.m_cmd_is_ci, - "", - "If present the sample will run in CI mode (optional, default='None')", - False, - str) - - def add_common_proxy_commands(self): - self.register_command( - CommandLineUtils.m_cmd_proxy_host, - "", - "Host name of the proxy server to connect through (optional)", - False, - str) - self.register_command( - CommandLineUtils.m_cmd_proxy_port, - "", - "Port of the http proxy to use (optional, default='8080')", - type=int, - default=8080) - - def add_common_topic_message_commands(self): - self.register_command( - CommandLineUtils.m_cmd_topic, - "", - "Topic to publish, subscribe to (optional, default='test/topic').", - default="test/topic") - self.register_command( - CommandLineUtils.m_cmd_message, - "", - "The message to send in the payload (optional, default='Hello World!').", - default="Hello World! ") - - def add_common_logging_commands(self): - self.register_command( - CommandLineUtils.m_cmd_verbosity, - "", - "Logging level.", - default=io.LogLevel.NoLogs.name, - choices=[ - x.name for x in io.LogLevel]) - - def add_common_key_cert_commands(self): - self.register_command(CommandLineUtils.m_cmd_key_file, "", "Path to your key in PEM format.", True, str) - self.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to your client certificate in PEM format.", True, str) - - def add_common_custom_authorizer_commands(self): - self.register_command( - CommandLineUtils.m_cmd_custom_auth_username, - "", - "The name to send when connecting through the custom authorizer (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_authorizer_name, - "", - "The name of the custom authorizer to connect to (optional but required for everything but custom domains)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_authorizer_signature, - "", - "The signature to send when connecting through a custom authorizer (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_password, - "", - "The password to send when connecting through a custom authorizer (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_token_key_name, - "", - "Key used to extract the custom authorizer token (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_token_value, - "", - "The opaque token value for the custom authorizer (optional)") - - def add_common_x509_commands(self): - self.register_command( - CommandLineUtils.m_cmd_x509_endpoint, - "", - "The credentials endpoint to fetch x509 credentials from", - ) - self.register_command( - CommandLineUtils.m_cmd_x509_thing_name, - "", - "Thing name to fetch x509 credentials on behalf of" - ) - self.register_command( - CommandLineUtils.m_cmd_x509_role_alias, - "", - "Role alias to use with the x509 credentials provider" - ) - self.register_command( - CommandLineUtils.m_cmd_x509_key, - "", - "Path to the IoT thing private key used in fetching x509 credentials" - ) - self.register_command( - CommandLineUtils.m_cmd_x509_cert, - "", - "Path to the IoT thing certificate used in fetching x509 credentials" - ) - - self.register_command( - CommandLineUtils.m_cmd_x509_ca, - "", - "Path to the root certificate used in fetching x509 credentials" - ) - - ######################################################################## - # cmdData utils/functions - ######################################################################## - - class CmdData: - # General use - input_endpoint : str - input_cert : str - input_key : str - input_ca : str - input_clientId : str - input_port : int - input_is_ci : bool - input_use_websockets : bool - # Proxy - input_proxy_host : str - input_proxy_port : int - # PubSub - input_topic : str - input_message : str - input_count : int - # Websockets - input_signing_region : str - # Cognito - input_cognito_identity : str - # Custom auth - input_custom_auth_username : str - input_custom_authorizer_name : str - input_custom_authorizer_signature : str - input_custom_auth_password : str - input_custom_authorizer_token_key_name : str - input_custom_authorizer_token_value : str - # Fleet provisioning - input_template_name : str - input_template_parameters : str - input_csr_path : str - # Services (Shadow, Jobs, Greengrass, etc) - input_thing_name : str - input_mode : str - # Shared Subscription - input_group_identifier : str - # PKCS#11 - input_pkcs11_lib_path : str - input_pkcs11_user_pin : str - input_pkcs11_token_label : str - input_pkcs11_slot_id : int - input_pkcs11_key_label : str - # X509 - input_x509_endpoint : str - input_x509_role : str - input_x509_thing_name : str - input_x509_cert : str - input_x509_key : str - input_x509_ca : str - # Basic discovery - input_max_pub_ops : int - input_print_discovery_resp_only : bool - # Jobs - input_job_time : int - # Shadow - input_shadow_property : str - input_shadow_value : str - input_shadow_name : str - # PKCS12 - input_pkcs12_file : str - input_pkcs12_password : str - # Static credentials - input_session_token : str - input_access_key_id : str - input_secret_access_key : str - - def __init__(self) -> None: - pass - - def parse_input_topic(self, cmdUtils): - self.input_topic = cmdUtils.get_command(CommandLineUtils.m_cmd_topic, "test/topic") - if (cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci) != None): - self.input_topic += "/" + str(uuid4()) - - def parse_sample_input_basic_connect(): - # Parse arguments - cmdUtils = CommandLineUtils("Basic Connect - Make a MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", - "Connection port for direct connection. " + - "AWS IoT supports 443 and 8883 (optional, default=8883).", - False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - # Needs to be called so the command utils parse the commands - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_basic_discovery(): - allowed_actions = ['both', 'publish', 'subscribe'] - - cmdUtils = CommandLineUtils("Basic Discovery - Greengrass discovery example.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.remove_command(CommandLineUtils.m_cmd_endpoint) - cmdUtils.register_command(CommandLineUtils.m_cmd_thing_name, "", "The name assigned to your IoT Thing", required=True) - cmdUtils.register_command( - CommandLineUtils.m_cmd_mode, "", - f"The operation mode (optional, default='both').\nModes:{allowed_actions}", default='both') - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", "The region to connect through.", required=True) - cmdUtils.register_command( - CommandLineUtils.m_cmd_max_pub_ops, "", - "The maximum number of publish operations (optional, default='10').", - default=10, type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_print_discovery_resp_only, "", "(optional, default='False').", - default=False, type=bool, action="store_true") - cmdUtils.add_common_proxy_commands() - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.parse_input_topic(cmdUtils) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_thing_name) - cmdData.input_mode = cmdUtils.get_command(CommandLineUtils.m_cmd_mode, "both") - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_region, CommandLineUtils.m_cmd_signing_region) - cmdData.input_max_pub_ops = int(cmdUtils.get_command(CommandLineUtils.m_cmd_max_pub_ops, 10)) - cmdData.input_print_discovery_resp_only = bool(cmdUtils.get_command(CommandLineUtils.m_cmd_print_discovery_resp_only, False)) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_cognito_connect(): - cmdUtils = CommandLineUtils("Cognito Connect - Make a Cognito MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_signing_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_cognito_identity, "", - "The Cognito identity ID to use to connect via Cognito", - True, str) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_signing_region, CommandLineUtils.m_cmd_region) - cmdData.input_cognito_identity = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cognito_identity) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_custom_authorizer_connect(): - cmdUtils = CommandLineUtils( - "Custom Authorizer Connect - Make a MQTT connection using a custom authorizer.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_custom_authorizer_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_custom_authorizer_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_name) - cmdData.input_custom_authorizer_signature = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_signature) - cmdData.input_custom_auth_password = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_password) - cmdData.input_custom_auth_username = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_username) - cmdData.input_custom_authorizer_token_key_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_key_name) - cmdData.input_custom_authorizer_token_value = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_value) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_static_credentials_connect(): - cmdUtils = CommandLineUtils( - "Static Credentials Connect - Make a MQTT connection using Static Credentials.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_session_token, "", "", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_access_key_id, "", "", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_secret_access_key, "", "") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_session_token = cmdUtils.get_command(CommandLineUtils.m_cmd_session_token) - cmdData.input_access_key_id = cmdUtils.get_command(CommandLineUtils.m_cmd_access_key_id) - cmdData.input_secret_access_key = cmdUtils.get_command(CommandLineUtils.m_secret_access_key) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_fleet_provisioning(): - cmdUtils = CommandLineUtils("Fleet Provisioning - Provision device using either the keys or CSR.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_csr, "", "Path to CSR in Pem format (optional).") - cmdUtils.register_command(CommandLineUtils.m_cmd_template_name, "", "The name of your provisioning template.") - cmdUtils.register_command(CommandLineUtils.m_cmd_template_parameters, "", "Template parameters json.") - cmdUtils.register_command(CommandLineUtils.m_cmd_mqtt_version, "", "MQTT Version") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_csr_path = cmdUtils.get_command(CommandLineUtils.m_cmd_csr, None) - cmdData.input_template_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_template_name) - cmdData.input_template_parameters = cmdUtils.get_command_required(CommandLineUtils.m_cmd_template_parameters) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - cmdData.input_mqtt_version = int(cmdUtils.get_command(CommandLineUtils.m_cmd_mqtt_version, 5)) - return cmdData - - def parse_sample_input_jobs(): - cmdUtils = CommandLineUtils("Jobs - Receive and execute operations on the device.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_thing_name, "", "The name assigned to your IoT Thing", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_job_time, "", "Emulate working on a job by sleeping this many seconds (optional, default='5')", default=5, type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_mqtt_version, "", "mqtt version (optional, default='5')", default=5, type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_thing_name) - cmdData.input_job_time = int(cmdUtils.get_command(CommandLineUtils.m_cmd_job_time, 5)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - cmdData.input_mqtt_version = int(cmdUtils.get_command(CommandLineUtils.m_cmd_mqtt_version, 5)) - return cmdData - - def parse_sample_input_mqtt5_custom_authorizer_connect(): - cmdUtils = CommandLineUtils( - "Custom Authorizer Connect - Make a MQTT5 Client connection using a custom authorizer.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_custom_authorizer_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_use_websockets, "", "If set, websockets will be used (optional, do not set to use direct MQTT)") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_custom_authorizer_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_name) - cmdData.input_custom_authorizer_signature = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_signature) - cmdData.input_custom_auth_password = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_password) - cmdData.input_custom_auth_username = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_username) - cmdData.input_custom_authorizer_token_key_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_key_name) - cmdData.input_custom_authorizer_token_value = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_value) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_use_websockets = bool(cmdUtils.get_command(CommandLineUtils.m_cmd_use_websockets, False)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_mqtt5_pkcs11_connect(): - cmdUtils = CommandLineUtils("MQTT5 PKCS11 Connect - Make a MQTT5 Client connection using PKCS11.") - cmdUtils.add_common_mqtt5_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to your client certificate in PEM format.", True, str) - cmdUtils.register_command( - CommandLineUtils.m_cmd_port, - "", - "Connection port. AWS IoT supports 433 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_client_id, - "", - "Client ID to use for MQTT5 connection (optional, default=None).", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_lib, "", "Path to PKCS#11 Library", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_pin, "", "User PIN for logging into PKCS#11 token.", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_token, "", "Label of the PKCS#11 token to use (optional).") - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_slot, "", "Slot ID containing the PKCS#11 token to use (optional).", False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_key, "", "Label of private key on the PKCS#11 token (optional).") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_pkcs11_lib_path = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_lib) - cmdData.input_pkcs11_user_pin = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_pin) - cmdData.input_pkcs11_token_label = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_token) - cmdData.input_pkcs11_slot_id = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_slot, None) - cmdData.input_pkcs11_key_label = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_key, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_mqtt5_pubsub(): - cmdUtils = CommandLineUtils("PubSub - Send and receive messages through an MQTT5 connection.") - cmdUtils.add_common_mqtt5_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command( - CommandLineUtils.m_cmd_port, - "", - "Connection port. AWS IoT supports 433 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_client_id, - "", - "Client ID to use for MQTT5 connection (optional, default=None).", - default="test-" + str(uuid4())) - cmdUtils.register_command( - CommandLineUtils.m_cmd_count, - "", - "The number of messages to send (optional, default='10').", - default=10, - type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.parse_input_topic(cmdUtils) - cmdData.input_count = int(cmdUtils.get_command(CommandLineUtils.m_cmd_count, 10)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_mqtt5_shared_subscription(): - cmdUtils = CommandLineUtils("SharedSubscription - Send and receive messages through a MQTT5 shared subscription") - cmdUtils.add_common_mqtt5_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command( - CommandLineUtils.m_cmd_port, - "", - "Connection port. AWS IoT supports 433 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_client_id, - "", - "Client ID to use for MQTT5 connection (optional, default=None)." - "Note that '1', '2', and '3' will be added for to the given clientIDs since this sample uses 3 clients.", - default="test-" + str(uuid4())) - cmdUtils.register_command( - CommandLineUtils.m_cmd_count, - "", - "The number of messages to send (optional, default='10').", - default=10, - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_group_identifier, - "", - "The group identifier to use in the shared subscription (optional, default='python-sample')", - default="python-sample", - type=str) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.parse_input_topic(cmdUtils) - cmdData.input_count = cmdUtils.get_command(CommandLineUtils.m_cmd_count, 10) - cmdData.input_group_identifier = cmdUtils.get_command(CommandLineUtils.m_cmd_group_identifier, "python-sample") - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_pkcs11_connect(): - cmdUtils = CommandLineUtils("PKCS11 Connect - Make a MQTT connection using PKCS11.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to your client certificate in PEM format.", True, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", - "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_lib, "", "Path to PKCS#11 Library", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_pin, "", "User PIN for logging into PKCS#11 token.", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_token, "", "Label of the PKCS#11 token to use (optional).") - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_slot, "", "Slot ID containing the PKCS#11 token to use (optional).", False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_key, "", "Label of private key on the PKCS#11 token (optional).") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_pkcs11_lib_path = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_lib) - cmdData.input_pkcs11_user_pin = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_pin) - cmdData.input_pkcs11_token_label = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_token) - cmdData.input_pkcs11_slot_id = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_slot, None) - cmdData.input_pkcs11_key_label = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_key, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_pubsub(): - cmdUtils = CommandLineUtils("PubSub - Send and receive messages through an MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_count, "", "The number of messages to send (optional, default='10').", default=10, type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.parse_input_topic(cmdUtils) - cmdData.input_count = int(cmdUtils.get_command(CommandLineUtils.m_cmd_count, 10)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_shadow(): - cmdUtils = CommandLineUtils("Shadow - Keep a property in sync between device and server.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_thing_name, "", "The name assigned to your IoT Thing", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_shadow_property, "", "The name of the shadow property you want to change (optional, default=''", default="") - cmdUtils.register_command(CommandLineUtils.m_cmd_shadow_value, "", "The desired value of the shadow property you want to set (optional)") - cmdUtils.register_command(CommandLineUtils.m_cmd_shadow_name, "", "Shadow name (optional, default='')", type=str) - cmdUtils.register_command(CommandLineUtils.m_cmd_mqtt_version, "", "mqtt version (optional, default='5')", default=5, type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_thing_name) - cmdData.input_shadow_property = cmdUtils.get_command_required(CommandLineUtils.m_cmd_shadow_property) - cmdData.input_shadow_value = cmdUtils.get_command(CommandLineUtils.m_cmd_shadow_value, None) - cmdData.input_shadow_name = cmdUtils.get_command(CommandLineUtils.m_cmd_shadow_name, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - cmdData.input_mqtt_version = int(cmdUtils.get_command(CommandLineUtils.m_cmd_mqtt_version, 5)) - return cmdData - - def parse_sample_input_websocket_connect(): - cmdUtils = CommandLineUtils("Websocket Connect - Make a websocket MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_signing_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_signing_region, CommandLineUtils.m_cmd_region) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_windows_cert_connect(): - cmdUtils = CommandLineUtils("Windows Cert Connect - Make a MQTT connection using Windows Store Certificates.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to certificate in Windows cert store. " - "e.g. \"CurrentUser\\MY\\6ac133ac58f0a88b83e9c794eba156a98da39b4c\"", True, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=auto).", type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_x509_connect(): - cmdUtils = CommandLineUtils("X509 Connect - Make a MQTT connection using X509.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_x509_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_signing_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_signing_region, CommandLineUtils.m_cmd_region) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_x509_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_endpoint) - cmdData.input_x509_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_thing_name) - cmdData.input_x509_role = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_role_alias) - cmdData.input_x509_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_cert) - cmdData.input_x509_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_key) - cmdData.input_x509_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_x509_ca, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_pkcs12_connect(): - # Parse arguments - cmdUtils = CommandLineUtils("PKCS12 Connect - Make a MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs12_file, "", - "Path to the PKCS12 file to use.", True, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs12_password, "", - "The password for the PKCS12 file.", False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", - "Connection port for direct connection. " + - "AWS IoT supports 443 and 8883 (optional, default=8883).", - False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - # Needs to be called so the command utils parse the commands - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_pkcs12_file = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs12_file) - cmdData.input_pkcs12_password = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs12_password) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - - # Constants for commonly used/needed commands - m_cmd_endpoint = "endpoint" - m_cmd_ca_file = "ca_file" - m_cmd_cert_file = "cert" - m_cmd_key_file = "key" - m_cmd_proxy_host = "proxy_host" - m_cmd_proxy_port = "proxy_port" - m_cmd_signing_region = "signing_region" - m_cmd_pkcs11_lib = "pkcs11_lib" - m_cmd_pkcs11_cert = "cert" - m_cmd_pkcs11_pin = "pin" - m_cmd_pkcs11_token = "token_label" - m_cmd_pkcs11_slot = "slot_id" - m_cmd_pkcs11_key = "key_label" - m_cmd_message = "message" - m_cmd_topic = "topic" - m_cmd_verbosity = "verbosity" - m_cmd_custom_auth_username = "custom_auth_username" - m_cmd_custom_auth_authorizer_name = "custom_auth_authorizer_name" - m_cmd_custom_auth_authorizer_signature = "custom_auth_authorizer_signature" - m_cmd_custom_auth_password = "custom_auth_password" - m_cmd_custom_auth_token_key_name = "custom_auth_token_key_name" - m_cmd_custom_auth_token_value = "custom_auth_token_value" - m_cmd_cognito_identity = "cognito_identity" - m_cmd_x509_endpoint = "x509_endpoint" - m_cmd_x509_thing_name = "x509_thing_name" - m_cmd_x509_role_alias = "x509_role_alias" - m_cmd_x509_cert = "x509_cert" - m_cmd_x509_key = "x509_key" - m_cmd_x509_ca = "x509_ca_file" - m_cmd_port = "port" - m_cmd_client_id = "client_id" - m_cmd_is_ci = "is_ci" - m_cmd_thing_name = "thing_name" - m_cmd_mode = "mode" - m_cmd_max_pub_ops = "max_pub_ops" - m_cmd_print_discovery_resp_only = "print_discover_resp_only" - m_cmd_csr = "csr" - m_cmd_template_name = "template_name" - m_cmd_template_parameters = "template_parameters" - m_cmd_job_time = "job_time" - m_cmd_use_websockets = "use_websockets" - m_cmd_count = "count" - m_cmd_group_identifier = "group_identifier" - m_cmd_shadow_property = "shadow_property" - m_cmd_shadow_value = "shadow_value" - m_cmd_shadow_name = "shadow_name" - m_cmd_pkcs12_file = "pkcs12_file" - m_cmd_pkcs12_password = "pkcs12_password" - m_cmd_region = "region" - m_cmd_mqtt_version = "mqtt_version" - m_cmd_session_token = "session_token" - m_cmd_secret_access_key = "secret_access_key" - m_cmd_access_key_id = "access_key_id" From e4a79f5dbb4998fe8ab4b93c18a2d6a3578dd8e1 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 11:28:39 -0700 Subject: [PATCH 02/40] remove more samples and begin updating ci --- .github/workflows/ci.yml | 33 +--- .github/workflows/ci_run_pubsub_cfg.json | 26 --- .../ci_run_windows_cert_connect_cfg.json | 24 --- samples/pubsub.md | 73 -------- samples/pubsub.py | 157 ------------------ samples/windows_cert_connect.md | 104 ------------ samples/windows_cert_connect.py | 59 ------- 7 files changed, 1 insertion(+), 475 deletions(-) delete mode 100644 .github/workflows/ci_run_pubsub_cfg.json delete mode 100644 .github/workflows/ci_run_windows_cert_connect_cfg.json delete mode 100644 samples/pubsub.md delete mode 100644 samples/pubsub.py delete mode 100644 samples/windows_cert_connect.md delete mode 100644 samples/windows_cert_connect.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aff88807..100e0f55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" python builder.pyz build -p ${{ env.PACKAGE_NAME }} - name: configure AWS credentials (MQTT5) - uses: aws-actions/configure-aws-credentials@v2 + uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ env.CI_MQTT5_ROLE }} aws-region: ${{ env.AWS_DEFAULT_REGION }} @@ -72,22 +72,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: configure AWS credentials (PubSub) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_PUBSUB_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run PubSub sample - run: | - python ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_pubsub_cfg.json - - name: run Windows Certificate Connect sample - run: | - python ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_windows_cert_connect_cfg.json - - name: configure AWS credentials (MQTT5 samples) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_MQTT5_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: run MQTT5 PubSub sample run: | python ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pubsub_cfg.json @@ -151,10 +135,6 @@ jobs: with: role-to-assume: ${{ env.CI_PUBSUB_ROLE }} aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run PubSub sample - run: | - source .venv/bin/activate - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_pubsub_cfg.json - name: run PKCS12 sample run: | cert=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id "ci/PubSub/cert" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$cert" > /tmp/certificate.pem @@ -217,14 +197,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: configure AWS credentials (PubSub) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_PUBSUB_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run PubSub sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_pubsub_cfg.json - name: configure AWS credentials (MQTT5 samples) uses: aws-actions/configure-aws-credentials@v4 with: @@ -345,9 +317,6 @@ jobs: - name: run Websocket Connect sample run: | python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_websocket_connect_cfg.json - - name: run PubSub sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_pubsub_cfg.json - name: run PKCS11 Connect sample run: | mkdir -p /tmp/tokens diff --git a/.github/workflows/ci_run_pubsub_cfg.json b/.github/workflows/ci_run_pubsub_cfg.json deleted file mode 100644 index a7a94936..00000000 --- a/.github/workflows/ci_run_pubsub_cfg.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/pubsub.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/PubSub/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/PubSub/key", - "filename": "tmp_key.pem" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_windows_cert_connect_cfg.json b/.github/workflows/ci_run_windows_cert_connect_cfg.json deleted file mode 100644 index e441e832..00000000 --- a/.github/workflows/ci_run_windows_cert_connect_cfg.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/windows_cert_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "windows_cert_certificate": "ci/PubSub/cert", - "windows_cert_certificate_path": "tmp_cert.pem", - "windows_cert_key": "ci/PubSub/key", - "windows_cert_key_path": "tmp_key.pem", - "windows_cert_pfx_key_path": "tmp_pfx.pem" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/samples/pubsub.md b/samples/pubsub.md deleted file mode 100644 index 0ba8ac91..00000000 --- a/samples/pubsub.md +++ /dev/null @@ -1,73 +0,0 @@ -# PubSub - -[**Return to main sample list**](./README.md) - -This sample uses the -[Message Broker](https://docs.aws.amazon.com/iot/latest/developerguide/iot-message-broker.html) -for AWS IoT to send and receive messages through an MQTT connection. - -On startup, the device connects to the server, subscribes to a topic, and begins publishing messages to that topic. The device should receive those same messages back from the message broker, since it is subscribed to that same topic. Status updates are continually printed to the console. This sample demonstrates how to send and receive messages on designated IoT Core topics, an essential task that is the backbone of many IoT applications that need to send data over the internet. This sample simply subscribes and publishes to a topic, printing the messages it just sent as it is received from AWS IoT Core, but this can be used as a reference point for more complex Pub-Sub applications. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Publish",
-        "iot:Receive"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/test/topic"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Subscribe"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/test/topic"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To Run this sample from the `samples` folder, use the following command: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 pubsub.py --endpoint --cert --key -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 pubsub.py --endpoint --cert --key --ca_file -``` diff --git a/samples/pubsub.py b/samples/pubsub.py deleted file mode 100644 index 0229f5df..00000000 --- a/samples/pubsub.py +++ /dev/null @@ -1,157 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import mqtt, http -from awsiot import mqtt_connection_builder -import sys -import threading -import time -import json -from utils.command_line_utils import CommandLineUtils - -# This sample uses the Message Broker for AWS IoT to send and receive messages -# through an MQTT connection. On startup, the device connects to the server, -# subscribes to a topic, and begins publishing messages to that topic. -# The device should receive those same messages back from the message broker, -# since it is subscribed to that same topic. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_pubsub() - -received_count = 0 -received_all_event = threading.Event() - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - if return_code == mqtt.ConnectReturnCode.ACCEPTED and not session_present: - print("Session did not persist. Resubscribing to existing topics...") - resubscribe_future, _ = connection.resubscribe_existing_topics() - - # Cannot synchronously wait for resubscribe result because we're on the connection's event-loop thread, - # evaluate result with a callback instead. - resubscribe_future.add_done_callback(on_resubscribe_complete) - - -def on_resubscribe_complete(resubscribe_future): - resubscribe_results = resubscribe_future.result() - print("Resubscribe results: {}".format(resubscribe_results)) - - for topic, qos in resubscribe_results['topics']: - if qos is None: - sys.exit("Server rejected resubscribe to topic: {}".format(topic)) - - -# Callback when the subscribed topic receives a message -def on_message_received(topic, payload, dup, qos, retain, **kwargs): - print("Received message from topic '{}': {}".format(topic, payload)) - global received_count - received_count += 1 - if received_count == cmdData.input_count: - received_all_event.set() - -# Callback when the connection successfully connects -def on_connection_success(connection, callback_data): - assert isinstance(callback_data, mqtt.OnConnectionSuccessData) - print("Connection Successful with return code: {} session present: {}".format(callback_data.return_code, callback_data.session_present)) - -# Callback when a connection attempt fails -def on_connection_failure(connection, callback_data): - assert isinstance(callback_data, mqtt.OnConnectionFailureData) - print("Connection failed with error code: {}".format(callback_data.error)) - -# Callback when a connection has been disconnected or shutdown successfully -def on_connection_closed(connection, callback_data): - print("Connection closed") - -if __name__ == '__main__': - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options, - on_connection_success=on_connection_success, - on_connection_failure=on_connection_failure, - on_connection_closed=on_connection_closed) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - message_count = cmdData.input_count - message_topic = cmdData.input_topic - message_string = cmdData.input_message - - # Subscribe - print("Subscribing to topic '{}'...".format(message_topic)) - subscribe_future, packet_id = mqtt_connection.subscribe( - topic=message_topic, - qos=mqtt.QoS.AT_LEAST_ONCE, - callback=on_message_received) - - subscribe_result = subscribe_future.result() - print("Subscribed with {}".format(str(subscribe_result['qos']))) - - # Publish message to server desired number of times. - # This step is skipped if message is blank. - # This step loops forever if count was set to 0. - if message_string: - if message_count == 0: - print("Sending messages until program killed") - else: - print("Sending {} message(s)".format(message_count)) - - publish_count = 1 - while (publish_count <= message_count) or (message_count == 0): - message = "{} [{}]".format(message_string, publish_count) - print("Publishing message to topic '{}': {}".format(message_topic, message)) - message_json = json.dumps(message) - mqtt_connection.publish( - topic=message_topic, - payload=message_json, - qos=mqtt.QoS.AT_LEAST_ONCE) - time.sleep(1) - publish_count += 1 - - # Wait for all messages to be received. - # This waits forever if count was set to 0. - if message_count != 0 and not received_all_event.is_set(): - print("Waiting for all messages to be received...") - - received_all_event.wait() - print("{} message(s) received.".format(received_count)) - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") diff --git a/samples/windows_cert_connect.md b/samples/windows_cert_connect.md deleted file mode 100644 index 2b150f4b..00000000 --- a/samples/windows_cert_connect.md +++ /dev/null @@ -1,104 +0,0 @@ -# WindowsCert Connect - -[**Return to main sample list**](./README.md) - -This sample is similar to the [Basic Connect](../basic_connect.md) sample, in that it connects via Mutual TLS (mTLS) using a certificate and key file. However, unlike the Basic Connect where the certificate and private key file are stored on disk, this sample uses a PKCS#12 file stored in the [Windows certificate store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores). This adds a layer of security because the private key file is not just sitting on the computer and instead is hidden securely away in the [Windows certificate store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores). - -**WARNING: Windows only** - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run the Windows certificate connect sample from the `samples` folder, use the following command: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 windows_cert_connect.py --endpoint --cert -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 windows_cert_connect.py --endpoint --cert --ca_file -``` - -### How to setup and run - -To run this sample, you will need the path to your certificate in the [Windows certificate store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores). This will look something like the following: - -``` -CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6 -``` - -Where "CurrentUser\MY" is the store and "A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6" is the certificate's thumbprint. Note that if your certificate and private key are in a [TPM](https://docs.microsoft.com/en-us/windows/security/information-protection/tpm/trusted-platform-module-overview) then you would use them by passing their certificate store path. - -The steps to take a AWS IoT Thing certificate and key with the Windows Certificate Connect sample are listed below: - -1. Create an IoT Thing with a certificate and key if you haven't already. - -2. Combine the certificate and private key into a single `.pfx` file. You will be **prompted for a password while creating this file and it is important that you remember it** for this process. Otherwise you will need to restart and create a new `.pfx` file should you forget the password. - - If you have OpenSSL installed you can run the following to create a `.pfx` file: - ```powershell - openssl pkcs12 -in certificate.pem.crt -inkey private.pem.key -out certificate.pfx - ``` - - Otherwise use [CertUtil](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/certutil) to create the `.pfx` file: - ```powershell - certutil -mergePFX certificate.pem.crt,private.pem.key certificate.pfx - ``` - -3. Add the .pfx file to a Windows certificate store using PowerShell's [Import-PfxCertificate](https://docs.microsoft.com/en-us/powershell/module/pki/import-pfxcertificate) - - ```powershell - $mypwd = Get-Credential -UserName 'Enter password below' -Message 'Enter password below' - Import-PfxCertificate -FilePath certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password $mypwd.Password - ``` - - Replace `$mypwd.Password` with the password of your `.pfx` file. - - Once you run the command, note the certificate thumbprint that is printed out: - - ```powershell - Thumbprint Subject - ---------- ------- - A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6 CN=AWS IoT Certificate - ``` - - In the example above, the certificate's path would be: `CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6`. This is important as you need to pass this path into the `--cert` argument when running this sample. - -4. You can run the sample using the following: - - ```sh - # For Windows: replace 'python3' with 'python' and '/' with '\' - python3 windows_cert_connect.py --endpoint --cert - ``` diff --git a/samples/windows_cert_connect.py b/samples/windows_cert_connect.py deleted file mode 100644 index 7dcf7d72..00000000 --- a/samples/windows_cert_connect.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample is similar to `samples/basic_connect.py` but the certificate -# for mutual TLS is stored in a Windows certificate store. -# -# See `samples/README.md` for instructions on setting up your PC -# to run this sample. -# -# WARNING: Windows only. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_windows_cert_connect() - - -def on_connection_interrupted(connection, error, **kwargs): - # Callback when connection is accidentally lost. - print("Connection interrupted. error: {}".format(error)) - - -def on_connection_resumed(connection, return_code, session_present, **kwargs): - # Callback when an interrupted connection is re-established. - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - -if __name__ == '__main__': - # Create MQTT connection - mqtt_connection = mqtt_connection_builder.mtls_with_windows_cert_store_path( - cert_store_path=cmdData.input_cert, - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - ca_filepath=cmdData.input_ca, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") From fce9ad9bc9eba3e38de6760929bf9d4f2119f26f Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 11:37:34 -0700 Subject: [PATCH 03/40] update mac ci --- .github/workflows/ci.yml | 19 +----- .../workflows/ci_run_pkcs12_connect_cfg.json | 24 ------- samples/pkcs12_connect.md | 64 ------------------- samples/pkcs12_connect.py | 63 ------------------ 4 files changed, 1 insertion(+), 169 deletions(-) delete mode 100644 .github/workflows/ci_run_pkcs12_connect_cfg.json delete mode 100644 samples/pkcs12_connect.md delete mode 100644 samples/pkcs12_connect.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 100e0f55..b67e7138 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,6 +88,7 @@ jobs: osx: runs-on: ${{ matrix.runner }} strategy: + fail-fast: false matrix: runner: - macos-13 @@ -130,24 +131,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: configure AWS credentials (PubSub) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_PUBSUB_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run PKCS12 sample - run: | - cert=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id "ci/PubSub/cert" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$cert" > /tmp/certificate.pem - key=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id "ci/PubSub/key" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$key" > /tmp/privatekey.pem - pkcs12_password=$(aws secretsmanager get-secret-value --region us-east-1 --secret-id "ci/PubSub/key_pkcs12_password" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") - openssl pkcs12 -export -in /tmp/certificate.pem -inkey /tmp/privatekey.pem -out ./pkcs12-key.p12 -name PubSub_Thing_Alias -password pass:$pkcs12_password - source .venv/bin/activate - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_pkcs12_connect_cfg.json - - name: configure AWS credentials (MQTT5 samples) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_MQTT5_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: run MQTT5 PubSub sample run: | source .venv/bin/activate diff --git a/.github/workflows/ci_run_pkcs12_connect_cfg.json b/.github/workflows/ci_run_pkcs12_connect_cfg.json deleted file mode 100644 index f2f96224..00000000 --- a/.github/workflows/ci_run_pkcs12_connect_cfg.json +++ /dev/null @@ -1,24 +0,0 @@ -{ -"language": "Python", -"sample_file": "./aws-iot-device-sdk-python-v2/samples/pkcs12_connect.py", -"sample_region": "us-east-1", -"sample_main_class": "", -"arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--pkcs12_file", - "data": "./pkcs12-key.p12" - }, - { - "name": "--pkcs12_password", - "secret": "ci/PubSub/key_pkcs12_password" - }, - { - "name": "--is_ci", - "data": "true" - } -] -} diff --git a/samples/pkcs12_connect.md b/samples/pkcs12_connect.md deleted file mode 100644 index 5478a2fd..00000000 --- a/samples/pkcs12_connect.md +++ /dev/null @@ -1,64 +0,0 @@ -# PKCS12 Connect - -[**Return to main sample list**](../README.md) - -This sample is similar to the [Basic Connect](../BasicConnect/README.md) sample, in that it connects via Mutual TLS (mTLS) using a certificate and key file. However, unlike the Basic Connect where the certificate and private key file are stored on disk, this sample uses a PKCS#12 file instead. - -**WARNING: MacOS only**. Currently, TLS integration with PKCS12 is only available on MacOS devices. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run the PKCS12 connect use the following command: - -```sh -python3 pkcs12_connect --endpoint --pkcs12_file --pkcs12_password -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -```sh -python3 pkcs12_connect --endpoint --pkcs12_file --pkcs12_password --ca_file -``` - -### How to setup and run - -To use the certificate and key files provided by AWS IoT Core, you will need to convert them into PKCS#12 format and then import them into your Java keystore. You can convert the certificate and key file to PKCS12 using the following command: - -```sh -openssl pkcs12 -export -in -inkey -out -name -password pass: -``` - -Once converted, you can then run the PKCS12 connect sample with the following: - -```sh -python3 pkcs12_connect --endpoint --pkcs12_file --pkcs12_password -``` diff --git a/samples/pkcs12_connect.py b/samples/pkcs12_connect.py deleted file mode 100644 index ad284f73..00000000 --- a/samples/pkcs12_connect.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import http, io -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample shows how to create a MQTT connection using a certificate file and key file. -# This sample is intended to be used as a reference for making MQTT connections. - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - -if __name__ == '__main__': - - io.init_logging(log_level=io.LogLevel.Trace, file_name="stderr") - - # cmdData is the arguments/input from the command line placed into a single struct for - # use in this sample. This handles all of the command line parsing, validating, etc. - # See the Utils/CommandLineUtils for more information. - cmdData = CommandLineUtils.parse_sample_input_pkcs12_connect() - - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_with_pkcs12( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - pkcs12_filepath=cmdData.input_pkcs12_file, - pkcs12_password=cmdData.input_pkcs12_password, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connect_future = mqtt_connection.connect() - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") From 21361eff706d49de60e26d3a70cb613ee0c25b73 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 11:39:35 -0700 Subject: [PATCH 04/40] update linux ci --- .github/workflows/ci.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b67e7138..28b8146b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,8 +97,8 @@ jobs: id-token: write # This is required for requesting the JWT steps: - name: Install boto3 -# Starting from macos14, boto3 is no longer available in macos homebrew python https://github.com/Homebrew/homebrew-core/issues/157500 -# use virtual env to work around. + # Starting from macos14, boto3 is no longer available in macos homebrew python https://github.com/Homebrew/homebrew-core/issues/157500 + # use virtual env to work around. run: | python3 -m venv .venv source .venv/bin/activate @@ -180,11 +180,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: configure AWS credentials (MQTT5 samples) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_MQTT5_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: run MQTT5 PubSub sample run: | python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pubsub_cfg.json From 486926b78f74c346331fd267a20831e2ff1360ed Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 13:22:29 -0700 Subject: [PATCH 05/40] more sample ci cleanup --- .github/workflows/ci.yml | 48 ------------------- .../workflows/ci_run_basic_connect_cfg.json | 26 ---------- .../ci_run_fleet_provisioning_cfg.json | 34 ------------- .github/workflows/ci_run_jobs_cfg.json | 30 ------------ .../ci_run_mqtt5_fleet_provisioning_cfg.json | 34 ------------- .github/workflows/ci_run_mqtt5_jobs_cfg.json | 30 ------------ .../workflows/ci_run_mqtt5_shadow_cfg.json | 30 ------------ .github/workflows/ci_run_shadow_cfg.json | 30 ------------ 8 files changed, 262 deletions(-) delete mode 100644 .github/workflows/ci_run_basic_connect_cfg.json delete mode 100644 .github/workflows/ci_run_fleet_provisioning_cfg.json delete mode 100644 .github/workflows/ci_run_jobs_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_fleet_provisioning_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_jobs_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_shadow_cfg.json delete mode 100644 .github/workflows/ci_run_shadow_cfg.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28b8146b..ad70cd89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -283,15 +283,6 @@ jobs: run: | export PYTHONPATH=${{ github.workspace }}/aws-iot-device-sdk-python-v2/utils:${{ github.workspace }}/aws-iot-device-sdk-python-v2/samples python3 ./test_cases/test_jobs_execution.py --config-file test_cases/mqtt5_jobs_cfg.json - - - name: configure AWS credentials (Connect and PubSub) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_PUBSUB_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run Basic Connect sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_basic_connect_cfg.json - name: run Websocket Connect sample run: | python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_websocket_connect_cfg.json @@ -348,45 +339,6 @@ jobs: - name: run CustomAuthorizerConnect sample run: | python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_custom_authorizer_connect_cfg.json - - name: configure AWS credentials (Shadow) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_SHADOW_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run Shadow sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_shadow_cfg.json - - name: run MQTT5 Shadow sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_shadow_cfg.json - - name: configure AWS credentials (Jobs) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_JOBS_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run Jobs sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_jobs_cfg.json - - name: run MQTT5 Jobs sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_jobs_cfg.json - - name: configure AWS credentials (Fleet provisioning) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_FLEET_PROVISIONING_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run Fleet Provisioning sample - run: | - echo "Generating UUID for IoT thing" - Sample_UUID=$(python3 -c "import uuid; print (uuid.uuid4())") - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_fleet_provisioning_cfg.json --input_uuid ${Sample_UUID} - python3 ${{ env.CI_UTILS_FOLDER }}/delete_iot_thing_ci.py --thing_name "Fleet_Thing_${Sample_UUID}" --region "us-east-1" - - name: run MQTT5 Fleet Provisioning sample - run: | - echo "Generating UUID for IoT thing" - Sample_UUID=$(python3 -c "import uuid; print (uuid.uuid4())") - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_fleet_provisioning_cfg.json --input_uuid ${Sample_UUID} - python3 ${{ env.CI_UTILS_FOLDER }}/delete_iot_thing_ci.py --thing_name "Fleet_Thing_${Sample_UUID}" --region "us-east-1" linux-greengrass-tests: runs-on: ubuntu-22.04 diff --git a/.github/workflows/ci_run_basic_connect_cfg.json b/.github/workflows/ci_run_basic_connect_cfg.json deleted file mode 100644 index 8b3beccc..00000000 --- a/.github/workflows/ci_run_basic_connect_cfg.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/basic_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/PubSub/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/PubSub/key", - "filename": "tmp_key.pem" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_fleet_provisioning_cfg.json b/.github/workflows/ci_run_fleet_provisioning_cfg.json deleted file mode 100644 index 47879668..00000000 --- a/.github/workflows/ci_run_fleet_provisioning_cfg.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/deprecated/fleetprovisioning.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/FleetProvisioning/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/FleetProvisioning/key", - "filename": "tmp_key.pem" - }, - { - "name": "--template_name", - "data": "CI_FleetProvisioning_Template" - }, - { - "name": "--template_parameters", - "data": "{\"SerialNumber\":\"$INPUT_UUID\"}" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_jobs_cfg.json b/.github/workflows/ci_run_jobs_cfg.json deleted file mode 100644 index 7e2a6b08..00000000 --- a/.github/workflows/ci_run_jobs_cfg.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/deprecated/jobs.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/Jobs/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/Jobs/key", - "filename": "tmp_key.pem" - }, - { - "name": "--thing_name", - "data": "CI_Jobs_Thing" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_fleet_provisioning_cfg.json b/.github/workflows/ci_run_mqtt5_fleet_provisioning_cfg.json deleted file mode 100644 index 48a1dea6..00000000 --- a/.github/workflows/ci_run_mqtt5_fleet_provisioning_cfg.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/deprecated/fleetprovisioning_mqtt5.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/FleetProvisioning/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/FleetProvisioning/key", - "filename": "tmp_key.pem" - }, - { - "name": "--template_name", - "data": "CI_FleetProvisioning_Template" - }, - { - "name": "--template_parameters", - "data": "{\"SerialNumber\":\"$INPUT_UUID\"}" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_jobs_cfg.json b/.github/workflows/ci_run_mqtt5_jobs_cfg.json deleted file mode 100644 index ccb5413d..00000000 --- a/.github/workflows/ci_run_mqtt5_jobs_cfg.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/deprecated/jobs_mqtt5.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/Jobs/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/Jobs/key", - "filename": "tmp_key.pem" - }, - { - "name": "--thing_name", - "data": "CI_Jobs_Thing" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_shadow_cfg.json b/.github/workflows/ci_run_mqtt5_shadow_cfg.json deleted file mode 100644 index c3cb6605..00000000 --- a/.github/workflows/ci_run_mqtt5_shadow_cfg.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/deprecated/shadow_mqtt5.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/Shadow/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/Shadow/key", - "filename": "tmp_key.pem" - }, - { - "name": "--thing_name", - "data": "CI_Shadow_Thing" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_shadow_cfg.json b/.github/workflows/ci_run_shadow_cfg.json deleted file mode 100644 index d2a4174c..00000000 --- a/.github/workflows/ci_run_shadow_cfg.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/deprecated/shadow.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/Shadow/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/Shadow/key", - "filename": "tmp_key.pem" - }, - { - "name": "--thing_name", - "data": "CI_Shadow_Thing" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} From 52ed9e276b7e0e784e6875213e345943a5b2cdd3 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 13:29:29 -0700 Subject: [PATCH 06/40] more sample culling --- .github/workflows/ci.yml | 29 --- .../workflows/ci_run_cognito_connect_cfg.json | 24 --- .../ci_run_custom_authorizer_connect_cfg.json | 24 --- .../workflows/ci_run_pkcs11_connect_cfg.json | 43 ---- .../ci_run_websocket_connect_cfg.json | 20 -- .../workflows/ci_run_x509_connect_cfg.json | 42 ---- samples/cognito_connect.md | 81 -------- samples/cognito_connect.py | 72 ------- samples/custom_authorizer_connect.md | 54 ----- samples/custom_authorizer_connect.py | 57 ------ samples/pkcs11_connect.md | 109 ---------- samples/pkcs11_connect.py | 75 ------- samples/websocket_connect.md | 190 ------------------ samples/websocket_connect.py | 65 ------ samples/x509_connect.md | 59 ------ samples/x509_connect.py | 84 -------- 16 files changed, 1028 deletions(-) delete mode 100644 .github/workflows/ci_run_cognito_connect_cfg.json delete mode 100644 .github/workflows/ci_run_custom_authorizer_connect_cfg.json delete mode 100644 .github/workflows/ci_run_pkcs11_connect_cfg.json delete mode 100644 .github/workflows/ci_run_websocket_connect_cfg.json delete mode 100644 .github/workflows/ci_run_x509_connect_cfg.json delete mode 100644 samples/cognito_connect.md delete mode 100644 samples/cognito_connect.py delete mode 100644 samples/custom_authorizer_connect.md delete mode 100644 samples/custom_authorizer_connect.py delete mode 100644 samples/pkcs11_connect.md delete mode 100644 samples/pkcs11_connect.py delete mode 100644 samples/websocket_connect.md delete mode 100644 samples/websocket_connect.py delete mode 100644 samples/x509_connect.md delete mode 100644 samples/x509_connect.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad70cd89..c057fb50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -215,7 +215,6 @@ jobs: python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" chmod a+x builder ./builder build -p ${{ env.PACKAGE_NAME }} - - name: configure AWS credentials (service tests Fleet Provisioning) uses: aws-actions/configure-aws-credentials@v4 with: @@ -283,31 +282,11 @@ jobs: run: | export PYTHONPATH=${{ github.workspace }}/aws-iot-device-sdk-python-v2/utils:${{ github.workspace }}/aws-iot-device-sdk-python-v2/samples python3 ./test_cases/test_jobs_execution.py --config-file test_cases/mqtt5_jobs_cfg.json - - name: run Websocket Connect sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_websocket_connect_cfg.json - - name: run PKCS11 Connect sample - run: | - mkdir -p /tmp/tokens - export SOFTHSM2_CONF=/tmp/softhsm2.conf - echo "directories.tokendir = /tmp/tokens" > /tmp/softhsm2.conf - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_pkcs11_connect_cfg.json - name: configure AWS credentials (Cognito) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ env.CI_COGNITO_ROLE }} aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run Cognito Connect sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_cognito_connect_cfg.json - - name: configure AWS credentials (X509) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_X509_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run X509 sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_x509_connect_cfg.json - name: configure AWS credentials (MQTT5 samples) uses: aws-actions/configure-aws-credentials@v4 with: @@ -331,14 +310,6 @@ jobs: - name: run MQTT5 Shared Subscription sample run: | python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_shared_subscription_cfg.json - - name: configure AWS credentials (Custom Authorizer) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_CUSTOM_AUTHORIZER_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run CustomAuthorizerConnect sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_custom_authorizer_connect_cfg.json linux-greengrass-tests: runs-on: ubuntu-22.04 diff --git a/.github/workflows/ci_run_cognito_connect_cfg.json b/.github/workflows/ci_run_cognito_connect_cfg.json deleted file mode 100644 index 06294750..00000000 --- a/.github/workflows/ci_run_cognito_connect_cfg.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/cognito_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--signing_region", - "data": "us-east-1" - }, - { - "name": "--cognito_identity", - "secret": "ci/Cognito/identity_id" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_custom_authorizer_connect_cfg.json b/.github/workflows/ci_run_custom_authorizer_connect_cfg.json deleted file mode 100644 index 3921e89f..00000000 --- a/.github/workflows/ci_run_custom_authorizer_connect_cfg.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/custom_authorizer_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--custom_auth_authorizer_name", - "secret": "ci/CustomAuthorizer/name" - }, - { - "name": "--custom_auth_password", - "secret": "ci/CustomAuthorizer/password" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_pkcs11_connect_cfg.json b/.github/workflows/ci_run_pkcs11_connect_cfg.json deleted file mode 100644 index 4b1a2660..00000000 --- a/.github/workflows/ci_run_pkcs11_connect_cfg.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/pkcs11_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/PubSub/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/PubSub/keyp8", - "filename": "tmp_key.pem", - "pkcs11_key": "true" - }, - { - "name": "--pkcs11_lib", - "data": "/usr/lib/softhsm/libsofthsm2.so" - }, - { - "name": "--pin", - "data": "0000" - }, - { - "name": "--token_label", - "data": "my-token" - }, - { - "name": "--key_label", - "data": "my-key" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_websocket_connect_cfg.json b/.github/workflows/ci_run_websocket_connect_cfg.json deleted file mode 100644 index 378123f2..00000000 --- a/.github/workflows/ci_run_websocket_connect_cfg.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/websocket_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--signing_region", - "data": "us-east-1" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/.github/workflows/ci_run_x509_connect_cfg.json b/.github/workflows/ci_run_x509_connect_cfg.json deleted file mode 100644 index 24f43488..00000000 --- a/.github/workflows/ci_run_x509_connect_cfg.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/x509_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--x509_cert", - "secret": "ci/PubSub/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--x509_key", - "secret": "ci/PubSub/key", - "filename": "tmp_key.pem" - }, - { - "name": "--x509_endpoint", - "secret": "ci/X509/endpoint_credentials" - }, - { - "name": "--x509_role_alias", - "secret": "ci/X509/alias" - }, - { - "name": "--signing_region", - "data": "us-east-1" - }, - { - "name": "--x509_thing_name", - "data": "CI_PubSub_Thing" - }, - { - "name": "--is_ci", - "data": "true" - } - ] -} diff --git a/samples/cognito_connect.md b/samples/cognito_connect.md deleted file mode 100644 index 5224c38b..00000000 --- a/samples/cognito_connect.md +++ /dev/null @@ -1,81 +0,0 @@ -# Cognito Connect - -[**Return to main sample list**](./README.md) - -This sample is similar to the [Websocket Connect sample](./websocket_connect.md), but instead of sourcing the AWS credentials from the environment files or local files, it instead uses a [Cognito](https://aws.amazon.com/cognito/) identity to authorize the connection. This has the advantage of not requiring the needing to store AWS credentials on the device itself with permissions to perform the IoT actions your device requires, but instead just having AWS credentials for the [Cognito](https://aws.amazon.com/cognito/) identity instead. This provides a layer of security and indirection that gives you better security. - -On startup, the device connects to the server and then disconnects. This sample is for reference on connecting using Cognito. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run this sample, you need to have a Cognito identifier ID. You can get a Cognito identifier ID by creating a Cognito identity pool. For creating Cognito identity pools, please see the following page on the AWS documentation: [Tutorial: Creating an identity pool](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-identity-pool.html) -You should also add _iot:Connect_ permission to the role added to congnito or the default role created automatically when creating the new identity (or create a -
- (see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "cognito-identity:GetCredentialsForIdentity",
-        "iot:Connect"
-      ],
-      "Resource": [
-        "*"
-      ]
-    }
-  ]
-}
-
-
- -**Note:** This sample assumes using an identity pool with unauthenticated identity access for the sake of convenience. Please follow best practices in a real world application based on the needs of your application and the intended use case. - -Once you have a Cognito identity pool, you can run the following CLI command to get the Cognito identity pool ID: -```sh -aws cognito-identity get-id --identity-pool-id -# result from above command -{ - "IdentityId": "" -} -``` - -You can then use the returned ID in the `IdentityId` result as the input for the `--cognito_identity` argument. Please note that the Cognito identity pool ID is **not** the same as a Cognito identity ID and the sample will not work if you pass a Cognito pool id. - -To run the Cognito connect sample from the `samples` folder, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 cognito_connect.py --endpoint --signing_region --cognito_identity -``` diff --git a/samples/cognito_connect.py b/samples/cognito_connect.py deleted file mode 100644 index 5f212ef4..00000000 --- a/samples/cognito_connect.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import http, auth, io -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample shows how to create a MQTT connection using Cognito. -# This sample is intended to be used as a reference for making MQTT connections. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_cognito_connect() - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - -if __name__ == '__main__': - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create the cognito credentials provider - # Note: This sample and code assumes that you are using a Cognito identity - # in the same region as you pass to "--signing_region". - # If not, you may need to adjust the Cognito endpoint in the cmdUtils. - # See https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html - # for all Cognito endpoints. - cognito_endpoint = f"cognito-identity.{cmdData.input_signing_region}.amazonaws.com" - credentials_provider = auth.AwsCredentialsProvider.new_cognito( - endpoint=cognito_endpoint, - identity=cmdData.input_cognito_identity, - tls_ctx=io.ClientTlsContext(io.TlsContextOptions())) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.websockets_with_default_aws_signing( - endpoint=cmdData.input_endpoint, - region=cmdData.input_signing_region, - credentials_provider=credentials_provider, - http_proxy_options=proxy_options, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID...") - - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") diff --git a/samples/custom_authorizer_connect.md b/samples/custom_authorizer_connect.md deleted file mode 100644 index 823b21b3..00000000 --- a/samples/custom_authorizer_connect.md +++ /dev/null @@ -1,54 +0,0 @@ -# Custom Authorizer Connect - -[**Return to main sample list**](./README.md) - -This sample makes an MQTT connection and connects through a [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html). On startup, the device connects to the server and then disconnects. This sample is for reference on connecting using a Custom Authorizer. Using a Custom Authorizer allows you to perform your own authorization using an AWS Lambda function. See [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html) for more information. - -You will need to setup your Custom Authorizer so that the lambda function returns a policy document. See [this page on the documentation](https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html) for more details and example return result. You can customize this lambda function as needed for your application to provide your own security measures based on the needs of your application. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -# How to run - -**Note** The sample also allows passing arguments to specify additional data your custom authorizer may need. The snippet below assumes that the custom authorizer does not need these additional parameters, but in the general case, you will almost always need some of them depending on the authorizer's configuration and the associated Lambda function's internals. -* `--custom_auth_username` - opaque string value passed to the authorizer via an MQTT Connect packet. The authorizer's Lambda can check this value from the event JSON value it receives as input: `event.protocolData.mqtt.username` -* `--custom_auth_password` - opaque binary value passed to the authorizer via an MQTT Connect packet. The authorizer's Lambda can check this value from the event JSON value it receives as input: `event.protocolData.mqtt.password` -* `--custom_auth_token_key_name` - (Signed authorizers only) The query string parameter name that the token value should be bound to in the MQTT Connect packet. -* `--custom_auth_token_value` - (Signed authorizers only) An arbitrary value chosen by the user. The user must also submit a digital signature of this value using the private key associated with the authorizer. -* `--custom_auth_authorizer_signature` - (Signed authorizers only) a digital signature of the value of the `--custom_auth_token_value` parameter using the private key associated with the authorizer. The binary signature value must be base64 encoded and then URI encoded; the SDK will not do this for you. - -## MQTT over TCP with TLS - -To run the Custom Authorizer connect sample from the `samples` folder, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' -python3 custom_authorizer_connect.py --endpoint --custom_auth_authorizer_name -``` diff --git a/samples/custom_authorizer_connect.py b/samples/custom_authorizer_connect.py deleted file mode 100644 index 1e829bec..00000000 --- a/samples/custom_authorizer_connect.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample is similar to `samples/basic_connect.py` but it connects -# through a custom authorizer rather than using a key and certificate. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_custom_authorizer_connect() - - -def on_connection_interrupted(connection, error, **kwargs): - # Callback when connection is accidentally lost. - print("Connection interrupted. error: {}".format(error)) - - -def on_connection_resumed(connection, return_code, session_present, **kwargs): - # Callback when an interrupted connection is re-established. - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - -if __name__ == '__main__': - # Create MQTT connection with a custom authorizer - mqtt_connection = mqtt_connection_builder.direct_with_custom_authorizer( - endpoint=cmdData.input_endpoint, - auth_username=cmdData.input_custom_auth_username, - auth_authorizer_name=cmdData.input_custom_authorizer_name, - auth_authorizer_signature=cmdData.input_custom_authorizer_signature, - auth_password=cmdData.input_custom_auth_password, - auth_token_key_name=cmdData.input_custom_authorizer_token_key_name, - auth_token_value=cmdData.input_custom_authorizer_token_value, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") diff --git a/samples/pkcs11_connect.md b/samples/pkcs11_connect.md deleted file mode 100644 index fca00366..00000000 --- a/samples/pkcs11_connect.md +++ /dev/null @@ -1,109 +0,0 @@ -# PKCS#11 Connect - -[**Return to main sample list**](./README.md) - -This sample is similar to the [Basic Connect](./basic_connect.md) sample with how it connects, in that it connects via Mutual TLS (mTLS) using a certificate and key file. However, unlike Basic Connect where the certificate and private key file are stored on disk, this sample uses a PKCS#11 compatible smart card or Hardware Security Module (HSM) to store and access the private key file. This adds a layer of security because the private key file is not just sitting on the computer and instead is hidden securely away behind the PKCS#11 device. - -**WARNING: Unix (Linux) only**. Currently, TLS integration with PKCS#11 is only available on Unix devices. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -The PKCS11 connect sample can be run from the `samples` folder using the following command: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 pkcs11_connect.py --endpoint --cert --pkcs11_lib --pin --token_label --key_label -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 pkcs11_connect.py --endpoint --cert --pkcs11_lib --pin --token_label --key_label --ca_file -``` - -### Run sample with SoftHSM - -If you do not have a PKCS#11 device and/or want to use a software-based solution for testing, you can use [SoftHSM2](https://www.opendnssec.org/softhsm/) as the PKCS#11 device. This allows testing without the need to purchase and use separate hardware. - -The steps to use [SoftHSM2](https://www.opendnssec.org/softhsm/) as the PKCS#11 device with this sample are listed below: - -1. Create an AWS IoT Thing with a certificate and key if you haven't already. - -2. Convert the private key from the AWS IoT Thing into PKCS#8 format using the following command: - - ```sh - openssl pkcs8 -topk8 -in -out -nocrypt - ``` - -3. Install [SoftHSM2](https://www.opendnssec.org/softhsm/) using `apt`: - - ```sh - sudo apt install softhsm - ``` - - Note that if you are using a Linux distribution that does not include `apt`, you will need to - adjust the above command to get [SoftHSM2](https://www.opendnssec.org/softhsm/) from the package manager your distribution supports. - -4. Check that [SoftHSM2](https://www.opendnssec.org/softhsm/) is working as expected by running the following: - - ```sh - softhsm2-util --show-slots - ``` - - If this spits out an error message, create a config file: - * Default location: `~/.config/softhsm2/softhsm2.conf` - * This file must specify token dir, default value is: - ```sh - directories.tokendir = /usr/local/var/lib/softhsm/tokens/ - ``` - -5. Create a token and import the private key you converted in step 2: - - You can use any values for the labels, PINs, etc - - ```sh - softhsm2-util --init-token --free --label --pin --so-pin - ``` - - **Important**: Note which slot the token ended up in - - ```sh - softhsm2-util --import --slot --label --id --pin - ``` - -6. Now you can run the sample with the following: - - ```sh - # For Windows: replace 'python3' with 'python' and '/' with '\' - python3 pkcs11_connect.py --endpoint --ca_file --cert --pkcs11_lib --pin --token_label --key_label - ``` diff --git a/samples/pkcs11_connect.py b/samples/pkcs11_connect.py deleted file mode 100644 index c57a6e98..00000000 --- a/samples/pkcs11_connect.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import io -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample is similar to `samples/basic_connect.py` but the private key -# for mutual TLS is stored on a PKCS#11 compatible smart card or -# Hardware Security Module (HSM). -# -# See `samples/README.md` for instructions on setting up your PKCS#11 device -# to run this sample. -# -# WARNING: Unix only. Currently, TLS integration with PKCS#11 is only available on Unix devices. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_pkcs11_connect() - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - -if __name__ == '__main__': - - print(f"Loading PKCS#11 library '{cmdData.input_pkcs11_lib_path}' ...") - pkcs11_lib = io.Pkcs11Lib( - file=cmdData.input_pkcs11_lib_path, - behavior=io.Pkcs11Lib.InitializeFinalizeBehavior.STRICT) - print("Loaded!") - - pkcs11_slot_id = None - if (cmdData.input_pkcs11_slot_id): - pkcs11_slot_id = int(cmdData.input_pkcs11_slot_id) - - # Create MQTT connection - mqtt_connection = mqtt_connection_builder.mtls_with_pkcs11( - pkcs11_lib=pkcs11_lib, - user_pin=cmdData.input_pkcs11_user_pin, - slot_id=pkcs11_slot_id, - token_label=cmdData.input_pkcs11_token_label, - private_key_label=cmdData.input_pkcs11_key_label, - cert_filepath=cmdData.input_cert, - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - ca_filepath=cmdData.input_ca, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") diff --git a/samples/websocket_connect.md b/samples/websocket_connect.md deleted file mode 100644 index 8d249061..00000000 --- a/samples/websocket_connect.md +++ /dev/null @@ -1,190 +0,0 @@ -# Websocket Connect - -[**Return to main sample list**](./README.md) -If you want to use custom auth (or static creds, or basic auth, etc) instead, -then you will need to replace part of the sample (connection\_setup function) with a code snippet we provided in its corresponding readme. - -* [Websocket Connection Using Custom Authentication](#websocket-connection-using-custom-authentication) -* [Websocket Connection Using Static Credentials](#websocket-connection-using-custom-authentication) - -This sample makes an MQTT connection via Websockets and then disconnects. -On startup, the device connects to the server via Websockets and then disconnects right after. -This sample is for reference on connecting via Websockets. -This sample demonstrates the most straightforward way to connect via Websockets by querying the AWS credentials for the connection from the device's environment variables or local files. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. -Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. -Please follow best practices when working with AWS on production applications using the SDK. -Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -For this sample, using Websockets will attempt to fetch the AWS credentials to authorize the connection from your environment variables or local files. -See the [authorizing direct AWS](https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html) page for documentation on how to get the AWS credentials, which then you can set to the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` environment variables. - -
- -## How to run - -Optional parameters: -``` ---proxy_host ---proxy_port -``` -To run the websocket connect from the `samples` folder, use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 websocket_connect.py --endpoint --signing_region --proxy_host --proxy_port -``` - - -# Websocket Connection Using Custom Authentication - -This sample makes an MQTT connection and connects through a [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html). -On startup, the device connects to the server and then disconnects. -This sample is for reference on connecting using a Custom Authorizer. -Using a Custom Authorizer allows you to perform your own authorization using an AWS Lambda function. -See [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html) for more information. -You will need to setup your Custom Authorizer so that the lambda function returns a policy document. -See [this page on the documentation](https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html) for more details and example return result. -You can customize this lambda function as needed for your application to provide your own security measures based on the needs of your application. -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. -Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -If you want to use simple or custom auth (or static creds, or basic auth, etc) instead, -then you will need to replace part of the sample (connection\_setup function) with a code snippet we provided in its corresponding readme. - -
- (code snipet to replace the similar function) -
-
-def connection_setup():
-    # cmdData is the arguments/input from the command line placed into a single struct for
-    # use in this sample. This handles all of the command line parsing, validating, etc.
-    # See the Utils/CommandLineUtils for more information.
-    cmdData = CommandLineUtils.parse_sample_input_custom_authorizer_connect()
-    # Create the proxy options if the data is present in cmdData
-    proxy_options = None
-
-    if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0:
-        proxy_options = http.HttpProxyOptions(
-            host_name=cmdData.input_proxy_host,
-            port=cmdData.input_proxy_port)
-
-    # Create a default credentials provider and a MQTT connection from the command line data
-    credentials_provider = auth.AwsCredentialsProvider.new_default_chain()
-
-    mqtt_connection = mqtt_connection_builder.websockets_with_custom_authorizer(
-        endpoint=cmdData.input_endpoint,
-        credentials_provider=credentials_provider,
-        auth_username=cmdData.input_input_custom_auth_username,
-        auth_authorizer_name=cmdData.input_custom_authorizer_name,
-        auth_authorizer_signature=cmdData.input_custom_authorizer_signature,
-        auth_password=cmdData.input_custom_auth_password,
-        auth_token_key_name=cmdData.input_custom_authorizer_token_key_name,
-        auth_token_value=cmdData.input_custom_authorizer_token_value,
-        on_connection_interrupted=on_connection_interrupted,
-        on_connection_resumed=on_connection_resumed,
-        client_id=cmdData.input_clientId,
-        clean_session=False,
-        keep_alive_secs=30)
-
-    return mqtt_connection, cmdData
-
-
-
-
- -## How to run -Options for custom auth -``` ---custom_auth_username ---custom_auth_authorizer_name ---custom_auth_authorizer_signature ---custom_auth_password ---custom_auth_token_name ---custom_auth_token_value -``` - -To run the websocket connect from the `samples` folder, use the following command: -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 websocket_connect.py --endpoint --custom_auth_username --custom_auth_authorizer_name --custom_auth_authorizer_signature --custom_auth_password --custom_auth_token_name --custom_auth_token_value -``` - - -# Websocket Connection Using Static Credentials -This sample makes an MQTT connection via Websockets and then disconnects. -On startup, the device connects to the server via Websockets then disconnects right after. -This sample demonstrates connecting via static credentials. - -If you want to use simple or custom auth (or static creds, or basic auth, etc) instead, -then you will need to replace part of the sample (connection\_setup function) with a code snippet we provided in its corresponding readme. - -For this sample, using Websockets will attempt to fetch the AWS credentials to authorize the connection from static credentials. - -
- (code snipet to replace the similar function) -
-
-def connection_setup():
-    # cmdData is the arguments/input from the command line placed into a single struct for
-    # use in this sample. This handles all of the command line parsing, validating, etc.
-    # See the Utils/CommandLineUtils for more information.
-    cmdData = CommandLineUtils.parse_sample_input_static_credentials_connect()
-
-    cred_provider = AwsCredentialsProvider.new_static(
-        access_key_id=cmdData.input_access_key_id,
-        secret_access_key=cmdData.input_secret_access_key,
-        session_token=cmdData.input_session_token)
-
-    mqtt_connection = mqtt_connection_builder.websockets_with_default_aws_signing(
-        region=cmdData.input_signing_region,
-        credentials_provider=cred_provider,
-        endpoint=cmdData.input_endpoint,
-        client_id=cmdData.input_clientId)
-
-    return mqtt_connection, cmdData
-
-
-
- -## How to run - -Options for static credentials -``` ---access_key_id ---secret_access_key ---session_token -``` - -To run the websocket connect from the `samples` folder, use the following command: -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 websocket_connect.py --endpoint --signing_region --access_key_id --secret_access_key --session_token -``` - diff --git a/samples/websocket_connect.py b/samples/websocket_connect.py deleted file mode 100644 index 5db42cb8..00000000 --- a/samples/websocket_connect.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import http, auth -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample shows how to create a MQTT connection using websockets. -# This sample is intended to be used as a reference for making MQTT connections. - - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - -def connection_setup(): - # cmdData is the arguments/input from the command line placed into a single struct for - # use in this sample. This handles all of the command line parsing, validating, etc. - # See the Utils/CommandLineUtils for more information. - cmdData = CommandLineUtils.parse_sample_input_websocket_connect() - - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a default credentials provider and a MQTT connection from the command line data - credentials_provider = auth.AwsCredentialsProvider.new_default_chain() - mqtt_connection = mqtt_connection_builder.websockets_with_default_aws_signing( - endpoint=cmdData.input_endpoint, - region=cmdData.input_signing_region, - credentials_provider=credentials_provider, - http_proxy_options=proxy_options, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30) - return mqtt_connection, cmdData - -if __name__ == '__main__': - mqtt_connection, cmdData = connection_setup() - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID...") - - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") diff --git a/samples/x509_connect.md b/samples/x509_connect.md deleted file mode 100644 index c1a0a5c2..00000000 --- a/samples/x509_connect.md +++ /dev/null @@ -1,59 +0,0 @@ -# x509 Credentials Provider Connect - -[**Return to main sample list**](./README.md) - -This sample is similar to the [Basic Connect](./basic_connect.md), but the connection uses a X.509 certificate -to source the AWS credentials when connecting. - -See the [Authorizing direct calls to AWS services using AWS IoT Core credential provider](https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html) page for instructions on how to setup the IAM roles, the trust policy for the IAM roles, how to setup the IoT Core Role alias, and how to get the credential provider endpoint for your AWS account. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    },
-    {
-      "Effect":"Allow",
-      "Action":"iot:AssumeRoleWithCertificate",
-      "Resource":"arn:aws:iot:region:account:rolealias/role-alias"
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The X509 role alias you created and wish to connect using. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run the x509 Credentials Provider Connect sample use the following command: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 x509_connect.py --endpoint --signing_region --x509_cert --x509_endpoint --x509_key --x509_role_alias -x509_thing_name -``` - -You can also pass a Certificate Authority file (CA) if your X509 certificate and key combination requires it: - -``` sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 x509_connect.py --endpoint --signing_region --x509_cert --x509_endpoint --x509_key --x509_role_alias -x509_thing_name --x509_ca_file -``` diff --git a/samples/x509_connect.py b/samples/x509_connect.py deleted file mode 100644 index 85ddd3ae..00000000 --- a/samples/x509_connect.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import io, http, auth -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample shows how to create a MQTT connection using X509 files to connect. -# This sample is intended to be used as a reference for making MQTT connections via X509. - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_x509_connect() - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print(f"Connection interrupted. error: {error}") - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print(f"Connection resumed. return_code: {return_code} session_present: {session_present}") - - -if __name__ == '__main__': - - ############################################################ - # Set up and create the MQTT connection - ############################################################ - - # Set up the config needed to make a MQTT connection - - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - x509_tls_options = io.TlsContextOptions.create_client_with_mtls_from_path( - cmdData.input_x509_cert, cmdData.input_x509_key) - x509_tls_options.ca_dirpath = cmdData.input_x509_ca - x509_tls_context = io.ClientTlsContext(x509_tls_options) - - x509_provider = auth.AwsCredentialsProvider.new_x509( - endpoint=cmdData.input_x509_endpoint, - thing_name=cmdData.input_x509_thing_name, - role_alias=cmdData.input_x509_role, - tls_ctx=x509_tls_context, - http_proxy_options=proxy_options - ) - - # Create the MQTT connection from the configuration - mqtt_connection = mqtt_connection_builder.websockets_with_default_aws_signing( - endpoint=cmdData.input_endpoint, - region=cmdData.input_signing_region, - credentials_provider=x509_provider, - http_proxy_options=proxy_options, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30) - - ############################################################ - # Use the MQTT connection to connect and disconnect - ############################################################ - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - # Connect - connect_future = mqtt_connection.connect() - - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") From e6d375d13b9480e37f5590ea01be42089fd50964 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 13:34:08 -0700 Subject: [PATCH 07/40] remove more mqtt3 samples --- .github/workflows/ci.yml | 2 +- samples/basic_connect.md | 50 ----------------- samples/basic_connect.py | 62 --------------------- samples/basic_discovery.md | 9 --- samples/basic_discovery.py | 110 ------------------------------------- 5 files changed, 1 insertion(+), 232 deletions(-) delete mode 100644 samples/basic_connect.md delete mode 100644 samples/basic_connect.py delete mode 100644 samples/basic_discovery.md delete mode 100644 samples/basic_discovery.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c057fb50..460fd7a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,7 +193,7 @@ jobs: cd ./aws-iot-device-sdk-python-v2 python3 ./deviceadvisor/script/DATestRun.py - # Runs the samples and ensures that everything is working + # Runs the sampels and service tests and ensures that everything is working linux-smoke-tests: runs-on: ubuntu-22.04 permissions: diff --git a/samples/basic_connect.md b/samples/basic_connect.md deleted file mode 100644 index d6656531..00000000 --- a/samples/basic_connect.md +++ /dev/null @@ -1,50 +0,0 @@ -# Basic Connect - -[**Return to main sample list**](./README.md) - -This sample makes an MQTT connection using a certificate and key file using Mutual TLS (mTLS). On startup, the device connects to the server using the certificate and key files, and then disconnects. This sample is for reference on connecting via certificate and key files. Using a certificate and key file pair is the easiest and most straightforward way to authenticate a connection to AWS IoT Core. - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -To run the basic connect sample from the `samples` folder, use the following command: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 basic_connect.py --endpoint --cert --key -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -```sh -# For Windows: replace 'python3' with 'python' and '/' with '\' -python3 basic_connect.py --endpoint --cert --key --ca_file -``` diff --git a/samples/basic_connect.py b/samples/basic_connect.py deleted file mode 100644 index a38b3cac..00000000 --- a/samples/basic_connect.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -from awscrt import http -from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils - -# This sample shows how to create a MQTT connection using a certificate file and key file. -# This sample is intended to be used as a reference for making MQTT connections. - -# Callback when connection is accidentally lost. -def on_connection_interrupted(connection, error, **kwargs): - print("Connection interrupted. error: {}".format(error)) - -# Callback when an interrupted connection is re-established. -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present)) - - -if __name__ == '__main__': - - # cmdData is the arguments/input from the command line placed into a single struct for - # use in this sample. This handles all of the command line parsing, validating, etc. - # See the Utils/CommandLineUtils for more information. - cmdData = CommandLineUtils.parse_sample_input_basic_connect() - - # Create the proxy options if the data is present in cmdData - proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) - - # Create a MQTT connection from the command line data - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - on_connection_interrupted=on_connection_interrupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, - clean_session=False, - keep_alive_secs=30, - http_proxy_options=proxy_options) - - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") - - connect_future = mqtt_connection.connect() - # Future.result() waits until a result is available - connect_future.result() - print("Connected!") - - # Disconnect - print("Disconnecting...") - disconnect_future = mqtt_connection.disconnect() - disconnect_future.result() - print("Disconnected!") diff --git a/samples/basic_discovery.md b/samples/basic_discovery.md deleted file mode 100644 index d45d51ac..00000000 --- a/samples/basic_discovery.md +++ /dev/null @@ -1,9 +0,0 @@ -# Greengrass Discovery - -[**Return to main sample list**](./README.md) - -This sample is intended for use with the following tutorials in the AWS IoT Greengrass documentation: - -* [Connect and test client devices](https://docs.aws.amazon.com/greengrass/v2/developerguide/client-devices-tutorial.html) (Greengrass V2) -* [Test client device communications](https://docs.aws.amazon.com/greengrass/v2/developerguide/test-client-device-communications.html) (Greengrass V2) -* [Getting Started with AWS IoT Greengrass](https://docs.aws.amazon.com/greengrass/latest/developerguide/gg-gs.html) (Greengrass V1) diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py deleted file mode 100644 index 269f0ad5..00000000 --- a/samples/basic_discovery.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -import time -import json -from awscrt import io, http -from awscrt.mqtt import QoS -from awsiot.greengrass_discovery import DiscoveryClient -from awsiot import mqtt_connection_builder - -from utils.command_line_utils import CommandLineUtils - -allowed_actions = ['both', 'publish', 'subscribe'] - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_basic_discovery() - -tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(cmdData.input_cert, cmdData.input_key) -if (cmdData.input_ca is not None): - tls_options.override_default_trust_store_from_path(None, cmdData.input_ca) -tls_context = io.ClientTlsContext(tls_options) - -socket_options = io.SocketOptions() - -proxy_options = None -if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions(cmdData.input_proxy_host, cmdData.input_proxy_port) - -print('Performing greengrass discovery...') -discovery_client = DiscoveryClient( - io.ClientBootstrap.get_or_create_static_default(), - socket_options, - tls_context, - cmdData.input_signing_region, None, proxy_options) -resp_future = discovery_client.discover(cmdData.input_thing_name) -discover_response = resp_future.result() - -if (cmdData.input_is_ci): - print("Received a greengrass discovery result! Not showing result in CI for possible data sensitivity.") -else: - print(discover_response) - -if (cmdData.input_print_discovery_resp_only): - exit(0) - - -def on_connection_interupted(connection, error, **kwargs): - print('connection interrupted with error {}'.format(error)) - - -def on_connection_resumed(connection, return_code, session_present, **kwargs): - print('connection resumed with return code {}, session present {}'.format(return_code, session_present)) - - -# Try IoT endpoints until we find one that works -def try_iot_endpoints(): - for gg_group in discover_response.gg_groups: - for gg_core in gg_group.cores: - for connectivity_info in gg_core.connectivity: - try: - print( - f"Trying core {gg_core.thing_arn} at host {connectivity_info.host_address} port {connectivity_info.port}") - mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=connectivity_info.host_address, - port=connectivity_info.port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_bytes=gg_group.certificate_authorities[0].encode('utf-8'), - on_connection_interrupted=on_connection_interupted, - on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_thing_name, - clean_session=False, - keep_alive_secs=30) - - connect_future = mqtt_connection.connect() - connect_future.result() - print('Connected!') - return mqtt_connection - - except Exception as e: - print('Connection failed with exception {}'.format(e)) - continue - - exit('All connection attempts failed') - - -mqtt_connection = try_iot_endpoints() - -if cmdData.input_mode == 'both' or cmdData.input_mode == 'subscribe': - def on_publish(topic, payload, dup, qos, retain, **kwargs): - print('Publish received on topic {}'.format(topic)) - print(payload) - subscribe_future, _ = mqtt_connection.subscribe(cmdData.input_topic, QoS.AT_MOST_ONCE, on_publish) - subscribe_result = subscribe_future.result() - -loop_count = 0 -while loop_count < cmdData.input_max_pub_ops: - if cmdData.input_mode == 'both' or cmdData.input_mode == 'publish': - message = {} - message['message'] = cmdData.input_message - message['sequence'] = loop_count - messageJson = json.dumps(message) - pub_future, _ = mqtt_connection.publish(cmdData.input_topic, messageJson, QoS.AT_LEAST_ONCE) - publish_completion_data = pub_future.result() - print('Successfully published to topic {} with payload `{}`\n'.format(cmdData.input_topic, messageJson)) - - loop_count += 1 - time.sleep(1) From 72bf681c19fc176a036b4a2da2a43ef44864a324 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 13:41:17 -0700 Subject: [PATCH 08/40] remove unused roles --- .github/workflows/ci.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 460fd7a1..17c2c85d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,21 +20,12 @@ env: DA_SHADOW_VALUE_DEFAULT: OFF CI_UTILS_FOLDER: "./aws-iot-device-sdk-python-v2/utils" CI_SAMPLES_CFG_FOLDER: "./aws-iot-device-sdk-python-v2/.github/workflows" - CI_SAMPLES_FOLDER: "./aws-iot-device-sdk-python-v2/samples" - CI_PUBSUB_ROLE: arn:aws:iam::180635532705:role/CI_PubSub_Role - CI_COGNITO_ROLE: arn:aws:iam::180635532705:role/CI_Cognito_Role - CI_X509_ROLE: arn:aws:iam::180635532705:role/CI_X509_Role - CI_CUSTOM_AUTHORIZER_ROLE: arn:aws:iam::180635532705:role/CI_CustomAuthorizer_Role - CI_SHADOW_ROLE: arn:aws:iam::180635532705:role/CI_Shadow_Role - CI_JOBS_ROLE: arn:aws:iam::180635532705:role/CI_Jobs_Role CI_FLEET_PROVISIONING_ROLE: arn:aws:iam::180635532705:role/service-role/CI_FleetProvisioning_Role - CI_GREENGRASS_ROLE: arn:aws:iam::180635532705:role/CI_Greengrass_Role CI_GREENGRASS_INSTALLER_ROLE: arn:aws:iam::180635532705:role/CI_GreengrassInstaller_Role CI_DEVICE_ADVISOR: arn:aws:iam::180635532705:role/CI_DeviceAdvisor_Role CI_MQTT5_ROLE: arn:aws:iam::180635532705:role/CI_MQTT5_Role CI_BUILD_AND_TEST_ROLE: arn:aws:iam::180635532705:role/V2_SDK_Unit_Testing CI_JOBS_SERVICE_CLIENT_ROLE: arn:aws:iam::180635532705:role/CI_JobsServiceClient_Role - CI_SERVICE_ROLE_CFG_FOLDER: "./aws-iot-device-sdk-python-v2/servicetests/test_cases" CI_SHADOW_SERVICE_CLIENT_ROLE: arn:aws:iam::180635532705:role/CI_ShadowServiceClient_Role jobs: @@ -240,7 +231,6 @@ jobs: run: | export PYTHONPATH=${{ github.workspace }}/aws-iot-device-sdk-python-v2/utils:${{ github.workspace }}/aws-iot-device-sdk-python-v2/samples python3 ./test_cases/test_fleet_provisioning.py --config-file test_cases/mqtt5_fleet_provisioning_with_csr_cfg.json --thing-name-prefix Fleet_Thing_ - - name: configure AWS credentials (service tests Shadow) uses: aws-actions/configure-aws-credentials@v4 with: @@ -266,7 +256,6 @@ jobs: run: | export PYTHONPATH=${{ github.workspace }}/aws-iot-device-sdk-python-v2/utils:${{ github.workspace }}/aws-iot-device-sdk-python-v2/samples python3 ./test_cases/test_shadow_update.py --config-file test_cases/mqtt3_named_shadow_cfg.json - - name: configure AWS credentials (service tests Jobs) uses: aws-actions/configure-aws-credentials@v4 with: @@ -282,11 +271,6 @@ jobs: run: | export PYTHONPATH=${{ github.workspace }}/aws-iot-device-sdk-python-v2/utils:${{ github.workspace }}/aws-iot-device-sdk-python-v2/samples python3 ./test_cases/test_jobs_execution.py --config-file test_cases/mqtt5_jobs_cfg.json - - name: configure AWS credentials (Cognito) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_COGNITO_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: configure AWS credentials (MQTT5 samples) uses: aws-actions/configure-aws-credentials@v4 with: From 337355a4249d44a02b4781ad86b4c56a10654d26 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Fri, 15 Aug 2025 14:10:34 -0700 Subject: [PATCH 09/40] remove mqtt3 samples from codebuild smoketest --- codebuild/samples/connect-linux.sh | 18 ------------- codebuild/samples/custom-auth-linux.sh | 17 ------------- codebuild/samples/linux-smoke-tests.yml | 5 ---- codebuild/samples/pkcs11-connect-linux.sh | 31 ----------------------- codebuild/samples/pubsub-linux.sh | 15 ----------- codebuild/samples/shadow-linux.sh | 16 ------------ 6 files changed, 102 deletions(-) delete mode 100755 codebuild/samples/connect-linux.sh delete mode 100755 codebuild/samples/custom-auth-linux.sh delete mode 100755 codebuild/samples/pkcs11-connect-linux.sh delete mode 100755 codebuild/samples/pubsub-linux.sh delete mode 100755 codebuild/samples/shadow-linux.sh diff --git a/codebuild/samples/connect-linux.sh b/codebuild/samples/connect-linux.sh deleted file mode 100755 index 5cecd2b9..00000000 --- a/codebuild/samples/connect-linux.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -env - -pushd $CODEBUILD_SRC_DIR/samples/ - -ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - -echo "Basic Connect test" -python3 basic_connect.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem - -echo "Websocket Connect test" -python3 websocket_connect.py --endpoint $ENDPOINT --signing_region us-east-1 - -popd diff --git a/codebuild/samples/custom-auth-linux.sh b/codebuild/samples/custom-auth-linux.sh deleted file mode 100755 index 6fc7c2a2..00000000 --- a/codebuild/samples/custom-auth-linux.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -env - -pushd $CODEBUILD_SRC_DIR/samples/ - -ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') -AUTH_NAME=$(aws secretsmanager get-secret-value --secret-id "ci/CustomAuthorizer/name" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') -AUTH_PASSWORD=$(aws secretsmanager get-secret-value --secret-id "ci/CustomAuthorizer/password" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - -echo "Custom Authorizer test" -python3 custom_authorizer_connect.py --endpoint $ENDPOINT --custom_auth_authorizer_name $AUTH_NAME --custom_auth_password $AUTH_PASSWORD - -popd diff --git a/codebuild/samples/linux-smoke-tests.yml b/codebuild/samples/linux-smoke-tests.yml index e2faa151..e3711869 100644 --- a/codebuild/samples/linux-smoke-tests.yml +++ b/codebuild/samples/linux-smoke-tests.yml @@ -16,12 +16,7 @@ phases: commands: - echo Build started on `date` - $CODEBUILD_SRC_DIR/codebuild/samples/setup-linux.sh - - $CODEBUILD_SRC_DIR/codebuild/samples/connect-linux.sh - - $CODEBUILD_SRC_DIR/codebuild/samples/custom-auth-linux.sh - - $CODEBUILD_SRC_DIR/codebuild/samples/pkcs11-connect-linux.sh - $CODEBUILD_SRC_DIR/codebuild/samples/pubsub-mqtt5-linux.sh - - $CODEBUILD_SRC_DIR/codebuild/samples/pubsub-linux.sh - - $CODEBUILD_SRC_DIR/codebuild/samples/shadow-linux.sh post_build: commands: - echo Build completed on `date` diff --git a/codebuild/samples/pkcs11-connect-linux.sh b/codebuild/samples/pkcs11-connect-linux.sh deleted file mode 100755 index 48c2d0c9..00000000 --- a/codebuild/samples/pkcs11-connect-linux.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -pushd $CODEBUILD_SRC_DIR/samples/ - -ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - -# from hereon commands are echoed. don't leak secrets -set -x - -softhsm2-util --version - -# SoftHSM2's default tokendir path might be invalid on this machine -# so set up a conf file that specifies a known good tokendir path -mkdir -p /tmp/tokens -export SOFTHSM2_CONF=/tmp/softhsm2.conf -echo "directories.tokendir = /tmp/tokens" > /tmp/softhsm2.conf - -# create token -softhsm2-util --init-token --free --label my-token --pin 0000 --so-pin 0000 - -# add private key to token (must be in PKCS#8 format) -openssl pkcs8 -topk8 -in /tmp/privatekey.pem -out /tmp/privatekey.p8.pem -nocrypt -softhsm2-util --import /tmp/privatekey.p8.pem --token my-token --label my-key --id BEEFCAFE --pin 0000 - -# run sample -python3 pkcs11_connect.py --endpoint $ENDPOINT --cert /tmp/certificate.pem --pkcs11_lib /usr/lib/softhsm/libsofthsm2.so --pin 0000 --token_label my-token --key_label my-key - -popd diff --git a/codebuild/samples/pubsub-linux.sh b/codebuild/samples/pubsub-linux.sh deleted file mode 100755 index dc797e31..00000000 --- a/codebuild/samples/pubsub-linux.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -env - -pushd $CODEBUILD_SRC_DIR/samples/ - -ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - -echo "PubSub test" -python3 pubsub.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem --is_ci "true" - -popd diff --git a/codebuild/samples/shadow-linux.sh b/codebuild/samples/shadow-linux.sh deleted file mode 100755 index ffb34179..00000000 --- a/codebuild/samples/shadow-linux.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -env - -pushd $CODEBUILD_SRC_DIR/samples/ - -ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') - -echo "Shadow test" -python3 deprecated/shadow.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem --thing_name CI_CodeBuild_Thing --is_ci true -python3 deprecated/shadow_mqtt5.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem --thing_name CI_CodeBuild_Thing --is_ci true - -popd From 5b4bdf8e2d863ecfd07750ee827bfff7a523e6c1 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 09:16:22 -0700 Subject: [PATCH 10/40] point CD and other areas to mqtt5 pubsub. Reinstate basic_discovery --- .github/workflows/ci.yml | 1 - codebuild/cd/test-prod-pypi.yml | 2 +- codebuild/cd/test-test-pypi.yml | 2 +- samples/basic_discovery.py | 168 ++++++++++++++++++++++++++++++++ samples/mqtt5_pubsub.py | 59 +++++++++-- test/test_samples.py | 2 +- 6 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 samples/basic_discovery.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17c2c85d..26b23266 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -354,7 +354,6 @@ jobs: echo "=== software.amazon.awssdk.sdk-gg-ipc.log" cat testResults/gg*/software.amazon.awssdk.sdk-gg-ipc.log - # check that docs can still build check-docs: runs-on: ubuntu-22.04 # latest diff --git a/codebuild/cd/test-prod-pypi.yml b/codebuild/cd/test-prod-pypi.yml index 9777dc96..ccc9a56c 100644 --- a/codebuild/cd/test-prod-pypi.yml +++ b/codebuild/cd/test-prod-pypi.yml @@ -28,7 +28,7 @@ phases: - CURRENT_TAG_VERSION=$(cat $CODEBUILD_SRC_DIR/VERSION) - python3 codebuild/cd/pip-install-with-retry.py --no-cache-dir --user awsiotsdk==$CURRENT_TAG_VERSION # Run PubSub sample - - python3 samples/pubsub.py --endpoint ${ENDPOINT} --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --verbosity Trace + - python3 samples/mqtt5_pubsub.py --endpoint ${ENDPOINT} --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --verbosity Trace post_build: commands: diff --git a/codebuild/cd/test-test-pypi.yml b/codebuild/cd/test-test-pypi.yml index d202dcce..86cbd218 100644 --- a/codebuild/cd/test-test-pypi.yml +++ b/codebuild/cd/test-test-pypi.yml @@ -29,7 +29,7 @@ phases: - python3 -m pip install typing - python3 codebuild/cd/pip-install-with-retry.py -i https://testpypi.python.org/simple --user awsiotsdk==$CURRENT_TAG_VERSION # Run PubSub sample - - python3 samples/pubsub.py --endpoint ${ENDPOINT} --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --verbosity Trace + - python3 samples/mqtt5_pubsub.py --endpoint ${ENDPOINT} --cert /tmp/certificate.pem --key /tmp/privatekey.pem --ca_file /tmp/AmazonRootCA1.pem --verbosity Trace post_build: commands: diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py new file mode 100644 index 00000000..e069c2cd --- /dev/null +++ b/samples/basic_discovery.py @@ -0,0 +1,168 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid +from pathlib import Path + +def _existing_file(p: str) -> str: + if p and not Path(p).exists(): + raise argparse.ArgumentTypeError(f"file not found: {p}") + return p + +def _nonneg_int(s: str) -> int: + v = int(s) + if v < 0: + raise argparse.ArgumentTypeError("--count must be >= 0") + return v + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", type=_existing_file, help="Client cert (PEM)") + parser.add_argument("--key", required=True, dest="input_key", type=_existing_file, help="Client private key (PEM)") + parser.add_argument("--ca", dest="input_ca", type=_existing_file, help="Optional CA bundle (PEM)") + + # Messaging + parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") + parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") + parser.add_argument("--count", type=_nonneg_int, default=5, dest="input_count", + help="Messages to publish (0 = infinite)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") + parser.add_argument("--ci", action="store_true", dest="input_is_ci", help="CI mode (less verbose)") + + + parser.add_argument("--signing_region", required=True, dest="input_signing_region", + help="The signing region used for the websocket signer") + parser.add_argument("--thing_name", required=True, dest="input_thing_name", + help="The name assigned to your IoT Thing") + parser.add_argument("--mode", dest="input_mode", default='both', + help="The operation mode (optional, default='both').\nModes:both, publish, subscribe") + parser.add_argument("--region", required=True, dest="input_region", + help="The region to connect through.") + parser.add_argument("--max_pub_ops", dest="input_max_pub_ops", default=10, + help="The maximum number of publish operations (optional, default='10').") + parser.add_argument("--print_discover_resp_only", dest="input_print_discovery_resp_only", + help="(optional, default='False').", action="store_true", default=False) + + return parser.parse_args() + +cmdData = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + +import time, json +from awscrt import io, http +from awscrt.mqtt import QoS +from awsiot.greengrass_discovery import DiscoveryClient +from awsiot import mqtt_connection_builder + +# from utils.command_line_utils import CommandLineUtils + +allowed_actions = ['both', 'publish', 'subscribe'] + +# cmdData is the arguments/input from the command line placed into a single struct for +# use in this sample. This handles all of the command line parsing, validating, etc. +# See the Utils/CommandLineUtils for more information. +# cmdData = CommandLineUtils.parse_sample_input_basic_discovery() + +tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(cmdData.input_cert, cmdData.input_key) +if (cmdData.input_ca is not None): + tls_options.override_default_trust_store_from_path(None, cmdData.input_ca) +tls_context = io.ClientTlsContext(tls_options) + +socket_options = io.SocketOptions() + +proxy_options = None +if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: + proxy_options = http.HttpProxyOptions(cmdData.input_proxy_host, cmdData.input_proxy_port) + +print('Performing greengrass discovery...') +discovery_client = DiscoveryClient( + io.ClientBootstrap.get_or_create_static_default(), + socket_options, + tls_context, + cmdData.input_signing_region, None, proxy_options) +resp_future = discovery_client.discover(cmdData.input_thing_name) +discover_response = resp_future.result() + +print("Received a greengrass discovery result! Not showing result for possible data sensitivity.") + +if (cmdData.input_print_discovery_resp_only): + exit(0) + + +def on_connection_interupted(connection, error, **kwargs): + print('connection interrupted with error {}'.format(error)) + + +def on_connection_resumed(connection, return_code, session_present, **kwargs): + print('connection resumed with return code {}, session present {}'.format(return_code, session_present)) + + +# Try IoT endpoints until we find one that works +def try_iot_endpoints(): + for gg_group in discover_response.gg_groups: + for gg_core in gg_group.cores: + for connectivity_info in gg_core.connectivity: + try: + print( + f"Trying core {gg_core.thing_arn} at host {connectivity_info.host_address} port {connectivity_info.port}") + mqtt_connection = mqtt_connection_builder.mtls_from_path( + endpoint=connectivity_info.host_address, + port=connectivity_info.port, + cert_filepath=cmdData.input_cert, + pri_key_filepath=cmdData.input_key, + ca_bytes=gg_group.certificate_authorities[0].encode('utf-8'), + on_connection_interrupted=on_connection_interupted, + on_connection_resumed=on_connection_resumed, + client_id=cmdData.input_thing_name, + clean_session=False, + keep_alive_secs=30) + + connect_future = mqtt_connection.connect() + connect_future.result() + print('Connected!') + return mqtt_connection + + except Exception as e: + print('Connection failed with exception {}'.format(e)) + continue + + exit('All connection attempts failed') + + +mqtt_connection = try_iot_endpoints() + +if cmdData.input_mode == 'both' or cmdData.input_mode == 'subscribe': + def on_publish(topic, payload, dup, qos, retain, **kwargs): + print('Publish received on topic {}'.format(topic)) + print(payload) + subscribe_future, _ = mqtt_connection.subscribe(cmdData.input_topic, QoS.AT_MOST_ONCE, on_publish) + subscribe_result = subscribe_future.result() + +loop_count = 0 +while loop_count < cmdData.input_max_pub_ops: + if cmdData.input_mode == 'both' or cmdData.input_mode == 'publish': + message = {} + message['message'] = cmdData.input_message + message['sequence'] = loop_count + messageJson = json.dumps(message) + pub_future, _ = mqtt_connection.publish(cmdData.input_topic, messageJson, QoS.AT_LEAST_ONCE) + publish_completion_data = pub_future.result() + print('Successfully published to topic {} with payload `{}`\n'.format(cmdData.input_topic, messageJson)) + + loop_count += 1 + time.sleep(1) \ No newline at end of file diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index b5e03964..f38ce84d 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -1,22 +1,63 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid +from pathlib import Path + +def _existing_file(p: str) -> str: + if p and not Path(p).exists(): + raise argparse.ArgumentTypeError(f"file not found: {p}") + return p + +def _nonneg_int(s: str) -> int: + v = int(s) + if v < 0: + raise argparse.ArgumentTypeError("--count must be >= 0") + return v + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", type=_existing_file, help="Client cert (PEM)") + parser.add_argument("--key", required=True, dest="input_key", type=_existing_file, help="Client private key (PEM)") + parser.add_argument("--ca", dest="input_ca", type=_existing_file, help="Optional CA bundle (PEM)") + + # Messaging + parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") + parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") + parser.add_argument("--count", type=_nonneg_int, default=5, dest="input_count", + help="Messages to publish (0 = infinite)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") + parser.add_argument("--ci", action="store_true", dest="input_is_ci", help="CI mode (less verbose)") + + return parser.parse_args() + +cmdData = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + from awsiot import mqtt5_client_builder from awscrt import mqtt5, http -import threading +import threading, time, json from concurrent.futures import Future -import time -import json -from utils.command_line_utils import CommandLineUtils TIMEOUT = 100 topic_filter = "test/topic" -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_mqtt5_pubsub() - received_count = 0 received_all_event = threading.Event() future_stopped = Future() diff --git a/test/test_samples.py b/test/test_samples.py index 425406a6..9930d8ed 100644 --- a/test/test_samples.py +++ b/test/test_samples.py @@ -103,7 +103,7 @@ def test_pubsub(self): config = Config.get() args = [ sys.executable, - "samples/pubsub.py", + "samples/mqtt5_pubsub.py", "--endpoint", config.endpoint, "--cert", config.cert_filepath, "--key", config.key_filepath, From 8d380b846c2da6dad8791b4ae17ab72059dad392 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 09:31:29 -0700 Subject: [PATCH 11/40] remove --is_ci args from runner scripts --- .github/workflows/ci_run_greengrass_ipc_cfg.json | 4 ---- .github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json | 4 ---- .../ci_run_mqtt5_custom_authorizer_websockets_cfg.json | 4 ---- .github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json | 4 ---- .github/workflows/ci_run_mqtt5_pubsub_cfg.json | 4 ---- .github/workflows/ci_run_mqtt5_shared_subscription_cfg.json | 4 ---- codebuild/samples/pubsub-mqtt5-linux.sh | 2 +- utils/run_in_ci.py | 3 --- 8 files changed, 1 insertion(+), 28 deletions(-) diff --git a/.github/workflows/ci_run_greengrass_ipc_cfg.json b/.github/workflows/ci_run_greengrass_ipc_cfg.json index 767b98df..07918417 100644 --- a/.github/workflows/ci_run_greengrass_ipc_cfg.json +++ b/.github/workflows/ci_run_greengrass_ipc_cfg.json @@ -11,10 +11,6 @@ { "name": "--message", "data": "hello" - }, - { - "name": "--is_ci", - "data": "true" } ] } diff --git a/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json b/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json index 1325b5a6..f3608180 100644 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json +++ b/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json @@ -15,10 +15,6 @@ { "name": "--custom_auth_password", "secret": "ci/CustomAuthorizer/password" - }, - { - "name": "--is_ci", - "data": "true" } ] } diff --git a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json b/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json index 90bd08e8..c77cbc12 100644 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json +++ b/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json @@ -19,10 +19,6 @@ { "name": "--use_websockets", "data": "true" - }, - { - "name": "--is_ci", - "data": "true" } ] } diff --git a/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json b/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json index 4470facc..a8aaa3d9 100644 --- a/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json +++ b/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json @@ -34,10 +34,6 @@ { "name": "--key_label", "data": "my-key" - }, - { - "name": "--is_ci", - "data": "true" } ] } diff --git a/.github/workflows/ci_run_mqtt5_pubsub_cfg.json b/.github/workflows/ci_run_mqtt5_pubsub_cfg.json index 366f2da1..28410e29 100644 --- a/.github/workflows/ci_run_mqtt5_pubsub_cfg.json +++ b/.github/workflows/ci_run_mqtt5_pubsub_cfg.json @@ -17,10 +17,6 @@ "name": "--key", "secret": "ci/mqtt5/us/mqtt5_thing/key", "filename": "tmp_key.pem" - }, - { - "name": "--is_ci", - "data": "true" } ] } diff --git a/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json b/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json index b6234a7c..8c0866e5 100644 --- a/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json +++ b/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json @@ -17,10 +17,6 @@ "name": "--key", "secret": "ci/mqtt5/us/mqtt5_thing/key", "filename": "tmp_key.pem" - }, - { - "name": "--is_ci", - "data": "true" } ] } diff --git a/codebuild/samples/pubsub-mqtt5-linux.sh b/codebuild/samples/pubsub-mqtt5-linux.sh index 2b66fbf0..d37dacfc 100755 --- a/codebuild/samples/pubsub-mqtt5-linux.sh +++ b/codebuild/samples/pubsub-mqtt5-linux.sh @@ -10,6 +10,6 @@ pushd $CODEBUILD_SRC_DIR/samples/ ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "ci/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g') echo "MQTT5 PubSub test" -python3 mqtt5_pubsub.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem --is_ci "true" +python3 mqtt5_pubsub.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem popd diff --git a/utils/run_in_ci.py b/utils/run_in_ci.py index d8d284a6..462ce0e3 100644 --- a/utils/run_in_ci.py +++ b/utils/run_in_ci.py @@ -335,9 +335,6 @@ def launch_runnable(runnable_dir): elif (config_json['language'] == "Javascript"): os.chdir(config_json['runnable_file']) - config_json_arguments_list.append("--is_ci") - config_json_arguments_list.append("true") - runnable_return_one = None if not 'skip_install' in config_json: if sys.platform == "win32" or sys.platform == "cygwin": From 0a302fc681980a5f6e205ad80ab61b097983b685 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 10:07:37 -0700 Subject: [PATCH 12/40] remove ci from mqtt5 pubsub --- samples/mqtt5_pubsub.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index f38ce84d..3585f86e 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -42,7 +42,6 @@ def parse_sample_input(): # Misc parser.add_argument("--client-id", dest="input_clientId", default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") - parser.add_argument("--ci", action="store_true", dest="input_is_ci", help="CI mode (less verbose)") return parser.parse_args() @@ -122,18 +121,14 @@ def on_lifecycle_connection_failure(lifecycle_connection_failure: mqtt5.Lifecycl client_id=cmdData.input_clientId) print("MQTT5 Client Created") - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") + + print("Connecting to endpoint with client ID") client.start() lifecycle_connect_success_data = future_connection_success.result(TIMEOUT) connack_packet = lifecycle_connect_success_data.connack_packet negotiated_settings = lifecycle_connect_success_data.negotiated_settings - if not cmdData.input_is_ci: - print( - f"Connected to endpoint:'{cmdData.input_endpoint}' with Client ID:'{cmdData.input_clientId}' with reason_code:{repr(connack_packet.reason_code)}") + print(f"Connected to endpoint:'{cmdData.input_endpoint}' with Client ID:'{cmdData.input_clientId}' with reason_code:{repr(connack_packet.reason_code)}") # Subscribe From 5c230748549f743fd6d02a70f2b6239cc28e7df9 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 10:11:08 -0700 Subject: [PATCH 13/40] forgot utils --- utils/run_sample_ci.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/utils/run_sample_ci.py b/utils/run_sample_ci.py index 600cd076..fce6b150 100644 --- a/utils/run_sample_ci.py +++ b/utils/run_sample_ci.py @@ -293,9 +293,6 @@ def launch_sample(): exit_code = sample_return.returncode elif (config_json['language'] == "Python"): - config_json_arguments_list.append("--is_ci") - config_json_arguments_list.append("True") - sample_return = subprocess.run( args=[sys.executable, config_json['sample_file']] + config_json_arguments_list) exit_code = sample_return.returncode @@ -303,9 +300,6 @@ def launch_sample(): elif (config_json['language'] == "Javascript"): os.chdir(config_json['sample_file']) - config_json_arguments_list.append("--is_ci") - config_json_arguments_list.append("true") - sample_return_one = None if sys.platform == "win32" or sys.platform == "cygwin": sample_return_one = subprocess.run(args=["npm", "install"], shell=True) From ff8a81348ea84edecc1c280f0aae03380540d86b Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 10:29:52 -0700 Subject: [PATCH 14/40] restore old basic_discovery.py --- samples/basic_discovery.py | 74 +++++--------------------------------- 1 file changed, 8 insertions(+), 66 deletions(-) diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py index e069c2cd..be12152b 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -1,82 +1,21 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -# --------------------------------- ARGUMENT PARSING ----------------------------------------- -import argparse, uuid -from pathlib import Path - -def _existing_file(p: str) -> str: - if p and not Path(p).exists(): - raise argparse.ArgumentTypeError(f"file not found: {p}") - return p - -def _nonneg_int(s: str) -> int: - v = int(s) - if v < 0: - raise argparse.ArgumentTypeError("--count must be >= 0") - return v - -def parse_sample_input(): - parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - # Connection / TLS - parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") - parser.add_argument("--cert", required=True, dest="input_cert", type=_existing_file, help="Client cert (PEM)") - parser.add_argument("--key", required=True, dest="input_key", type=_existing_file, help="Client private key (PEM)") - parser.add_argument("--ca", dest="input_ca", type=_existing_file, help="Optional CA bundle (PEM)") - - # Messaging - parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") - parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") - parser.add_argument("--count", type=_nonneg_int, default=5, dest="input_count", - help="Messages to publish (0 = infinite)") - - # Proxy (optional) - parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") - parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") - - # Misc - parser.add_argument("--client-id", dest="input_clientId", - default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") - parser.add_argument("--ci", action="store_true", dest="input_is_ci", help="CI mode (less verbose)") - - - parser.add_argument("--signing_region", required=True, dest="input_signing_region", - help="The signing region used for the websocket signer") - parser.add_argument("--thing_name", required=True, dest="input_thing_name", - help="The name assigned to your IoT Thing") - parser.add_argument("--mode", dest="input_mode", default='both', - help="The operation mode (optional, default='both').\nModes:both, publish, subscribe") - parser.add_argument("--region", required=True, dest="input_region", - help="The region to connect through.") - parser.add_argument("--max_pub_ops", dest="input_max_pub_ops", default=10, - help="The maximum number of publish operations (optional, default='10').") - parser.add_argument("--print_discover_resp_only", dest="input_print_discovery_resp_only", - help="(optional, default='False').", action="store_true", default=False) - - return parser.parse_args() - -cmdData = parse_sample_input() - -# --------------------------------- ARGUMENT PARSING END ----------------------------------------- - -import time, json +import time +import json from awscrt import io, http from awscrt.mqtt import QoS from awsiot.greengrass_discovery import DiscoveryClient from awsiot import mqtt_connection_builder -# from utils.command_line_utils import CommandLineUtils +from utils.command_line_utils import CommandLineUtils allowed_actions = ['both', 'publish', 'subscribe'] # cmdData is the arguments/input from the command line placed into a single struct for # use in this sample. This handles all of the command line parsing, validating, etc. # See the Utils/CommandLineUtils for more information. -# cmdData = CommandLineUtils.parse_sample_input_basic_discovery() +cmdData = CommandLineUtils.parse_sample_input_basic_discovery() tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(cmdData.input_cert, cmdData.input_key) if (cmdData.input_ca is not None): @@ -98,7 +37,10 @@ def parse_sample_input(): resp_future = discovery_client.discover(cmdData.input_thing_name) discover_response = resp_future.result() -print("Received a greengrass discovery result! Not showing result for possible data sensitivity.") +if (cmdData.input_is_ci): + print("Received a greengrass discovery result! Not showing result in CI for possible data sensitivity.") +else: + print(discover_response) if (cmdData.input_print_discovery_resp_only): exit(0) From 029e88dcc35d0549ef9ddc00697333b353e5dae0 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 10:42:57 -0700 Subject: [PATCH 15/40] restore basic_discovery.md --- samples/basic_discovery.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 samples/basic_discovery.md diff --git a/samples/basic_discovery.md b/samples/basic_discovery.md new file mode 100644 index 00000000..503d79d6 --- /dev/null +++ b/samples/basic_discovery.md @@ -0,0 +1,10 @@ +@@ -1,9 +0,0 @@ +# Greengrass Discovery + +[**Return to main sample list**](./README.md) + +This sample is intended for use with the following tutorials in the AWS IoT Greengrass documentation: + +* [Connect and test client devices](https://docs.aws.amazon.com/greengrass/v2/developerguide/client-devices-tutorial.html) (Greengrass V2) +* [Test client device communications](https://docs.aws.amazon.com/greengrass/v2/developerguide/test-client-device-communications.html) (Greengrass V2) +* [Getting Started with AWS IoT Greengrass](https://docs.aws.amazon.com/greengrass/latest/developerguide/gg-gs.html) (Greengrass V1) \ No newline at end of file From 3cfbabf09ca57bd81d5db747cdf01693be2022d5 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 10:47:30 -0700 Subject: [PATCH 16/40] simplify arg parsing for pubsub --- samples/mqtt5_pubsub.py | 54 +++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index 3585f86e..9dce4411 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -3,18 +3,6 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid -from pathlib import Path - -def _existing_file(p: str) -> str: - if p and not Path(p).exists(): - raise argparse.ArgumentTypeError(f"file not found: {p}") - return p - -def _nonneg_int(s: str) -> int: - v = int(s) - if v < 0: - raise argparse.ArgumentTypeError("--count must be >= 0") - return v def parse_sample_input(): parser = argparse.ArgumentParser( @@ -25,14 +13,16 @@ def parse_sample_input(): # Connection / TLS parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") - parser.add_argument("--cert", required=True, dest="input_cert", type=_existing_file, help="Client cert (PEM)") - parser.add_argument("--key", required=True, dest="input_key", type=_existing_file, help="Client private key (PEM)") - parser.add_argument("--ca", dest="input_ca", type=_existing_file, help="Optional CA bundle (PEM)") + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") + parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") # Messaging parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") - parser.add_argument("--count", type=_nonneg_int, default=5, dest="input_count", + parser.add_argument("--count", default=5, dest="input_count", help="Messages to publish (0 = infinite)") # Proxy (optional) @@ -45,7 +35,7 @@ def parse_sample_input(): return parser.parse_args() -cmdData = parse_sample_input() +args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- @@ -69,7 +59,7 @@ def on_publish_received(publish_packet_data): print("Received message from topic'{}':{}".format(publish_packet.topic, publish_packet.payload)) global received_count received_count += 1 - if received_count == cmdData.input_count: + if received_count == args.input_count: received_all_event.set() @@ -95,30 +85,30 @@ def on_lifecycle_connection_failure(lifecycle_connection_failure: mqtt5.Lifecycl if __name__ == '__main__': print("\nStarting MQTT5 PubSub Sample\n") - message_count = cmdData.input_count - message_topic = cmdData.input_topic - message_string = cmdData.input_message + message_count = args.input_count + message_topic = args.input_topic + message_string = args.input_message - # Create the proxy options if the data is present in cmdData + # Create the proxy options if the data is present in args proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: + if args.input_proxy_host is not None and args.input_proxy_port != 0: proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) + host_name=args.input_proxy_host, + port=args.input_proxy_port) # Create MQTT5 client client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, http_proxy_options=proxy_options, on_publish_received=on_publish_received, on_lifecycle_stopped=on_lifecycle_stopped, on_lifecycle_connection_success=on_lifecycle_connection_success, on_lifecycle_connection_failure=on_lifecycle_connection_failure, - client_id=cmdData.input_clientId) + client_id=args.input_clientId) print("MQTT5 Client Created") @@ -128,7 +118,7 @@ def on_lifecycle_connection_failure(lifecycle_connection_failure: mqtt5.Lifecycl lifecycle_connect_success_data = future_connection_success.result(TIMEOUT) connack_packet = lifecycle_connect_success_data.connack_packet negotiated_settings = lifecycle_connect_success_data.negotiated_settings - print(f"Connected to endpoint:'{cmdData.input_endpoint}' with Client ID:'{cmdData.input_clientId}' with reason_code:{repr(connack_packet.reason_code)}") + print(f"Connected to endpoint:'{args.input_endpoint}' with Client ID:'{args.input_clientId}' with reason_code:{repr(connack_packet.reason_code)}") # Subscribe From 7561ef66d95f2d41dc292aae1500f9c51b210604 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:26:19 -0700 Subject: [PATCH 17/40] update custom auth sample --- samples/mqtt5_custom_authorizer_connect.py | 57 +++++++++++++++++++--- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 91000122..dbfce1eb 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -1,18 +1,63 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + + parser.add_argument("--custom_auth_username", dest="input_custom_auth_username" + required="", help="The name to send when connecting through the custom authorizer (optional)") + parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_auth_authorizer_name" + help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") + parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_auth_authorizer_signature", + help="The signature to send when connecting through a custom authorizer (optional)") + parser.add_argument("--custom_auth_password", dest="input_custom_auth_password", + help="The password to send when connecting through a custom authorizer (optional)") + parser.add_argument("--custom_auth_token_key_name", dest="input_custom_auth_token_key_name", + help="Key used to extract the custom authorizer token (optional)") + parser.add_argument("--custom_auth_token_value", dest="input_custom_auth_token_value", + help="The opaque token value for the custom authorizer (optional)") + + parser.add_argument("--use_websockets", dest="input_use_websockets", + action="store_const", const=True, default=None, + help="Use WebSockets instead of direct TLS") + parser.add_argument("--use_websockets", dest="input_use_websockets") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") + + args = parser.parse_args() + + # Validate custom-authorizer inputs: + # Either provide --custom-auth-username, OR provide signature + token key + token value. + has_username = bool(args.input_custom_auth_username) + has_token_triplet = all([ + args.input_custom_authorizer_signature, + args.input_custom_authorizer_token_key_name, + args.input_custom_authorizer_token_value, + ]) + + return args + +cmdData = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + from awsiot import mqtt5_client_builder from awscrt import mqtt5 from concurrent.futures import Future -from utils.command_line_utils import CommandLineUtils TIMEOUT = 100 -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_mqtt5_custom_authorizer_connect() - future_stopped = Future() future_connection_success = Future() From d5f5aa3846a88bbbb487434c8dcc1c5b9fa731ef Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:26:41 -0700 Subject: [PATCH 18/40] remove duplicate use_websockets --- samples/mqtt5_custom_authorizer_connect.py | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index dbfce1eb..529f1304 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -29,7 +29,6 @@ def parse_sample_input(): parser.add_argument("--use_websockets", dest="input_use_websockets", action="store_const", const=True, default=None, help="Use WebSockets instead of direct TLS") - parser.add_argument("--use_websockets", dest="input_use_websockets") # Misc parser.add_argument("--client-id", dest="input_clientId", From c8b1ed8af9bd4fee2991aaaf879114510e695144 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:27:18 -0700 Subject: [PATCH 19/40] missed comma --- samples/mqtt5_custom_authorizer_connect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 529f1304..d6c973fc 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -13,8 +13,8 @@ def parse_sample_input(): parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") - parser.add_argument("--custom_auth_username", dest="input_custom_auth_username" - required="", help="The name to send when connecting through the custom authorizer (optional)") + parser.add_argument("--custom_auth_username", dest="input_custom_auth_username", + help="The name to send when connecting through the custom authorizer (optional)") parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_auth_authorizer_name" help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_auth_authorizer_signature", From df3c19de2aab0ad0ca7e23ad838a5a3016ae4914 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:28:45 -0700 Subject: [PATCH 20/40] comma again --- samples/mqtt5_custom_authorizer_connect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index d6c973fc..28ac27c7 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -15,7 +15,7 @@ def parse_sample_input(): parser.add_argument("--custom_auth_username", dest="input_custom_auth_username", help="The name to send when connecting through the custom authorizer (optional)") - parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_auth_authorizer_name" + parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_auth_authorizer_name", help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_auth_authorizer_signature", help="The signature to send when connecting through a custom authorizer (optional)") From 2bb49a1fcf4d2389a951f5a08c3376f80492575d Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:34:07 -0700 Subject: [PATCH 21/40] rename args --- samples/mqtt5_custom_authorizer_connect.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 28ac27c7..0da1f60c 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -17,13 +17,13 @@ def parse_sample_input(): help="The name to send when connecting through the custom authorizer (optional)") parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_auth_authorizer_name", help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") - parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_auth_authorizer_signature", + parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_authorizer_signature", help="The signature to send when connecting through a custom authorizer (optional)") parser.add_argument("--custom_auth_password", dest="input_custom_auth_password", help="The password to send when connecting through a custom authorizer (optional)") - parser.add_argument("--custom_auth_token_key_name", dest="input_custom_auth_token_key_name", + parser.add_argument("--custom_auth_token_key_name", dest="input_custom_authorizer_token_key_name", help="Key used to extract the custom authorizer token (optional)") - parser.add_argument("--custom_auth_token_value", dest="input_custom_auth_token_value", + parser.add_argument("--custom_auth_token_value", dest="input_custom_authorizer_token_value", help="The opaque token value for the custom authorizer (optional)") parser.add_argument("--use_websockets", dest="input_use_websockets", From 4c54985599dcaf2fa2d3e43b8c7498229459ee28 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:48:58 -0700 Subject: [PATCH 22/40] input_custom_authorizer_name --- samples/mqtt5_custom_authorizer_connect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 0da1f60c..71e367f2 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -15,7 +15,7 @@ def parse_sample_input(): parser.add_argument("--custom_auth_username", dest="input_custom_auth_username", help="The name to send when connecting through the custom authorizer (optional)") - parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_auth_authorizer_name", + parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_authorizer_name", help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_authorizer_signature", help="The signature to send when connecting through a custom authorizer (optional)") From b696d7e17951c25cf1b159ae50509982900b8430 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 13:51:19 -0700 Subject: [PATCH 23/40] is_ci remove --- samples/mqtt5_custom_authorizer_connect.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 71e367f2..50b9d9d8 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -103,10 +103,7 @@ def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.Lifecy on_lifecycle_connection_success=on_lifecycle_connection_success, client_id=cmdData.input_clientId) - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") + print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") client.start() future_connection_success.result(TIMEOUT) From baa0c37912f0acbcd6504d415c759a6f14e22ee2 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 14:11:29 -0700 Subject: [PATCH 24/40] clientID --- samples/mqtt5_custom_authorizer_connect.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 50b9d9d8..25764c78 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -32,7 +32,7 @@ def parse_sample_input(): # Misc parser.add_argument("--client-id", dest="input_clientId", - default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") args = parser.parse_args() @@ -75,9 +75,8 @@ def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.Lifecy if __name__ == '__main__': - # Create MQTT5 Client with a custom authorizer - if cmdData.input_use_websockets is None: + if cmdData.input_use_websockets is None: client = mqtt5_client_builder.direct_with_custom_authorizer( endpoint=cmdData.input_endpoint, ca_filepath=cmdData.input_ca, From 228e40aa37f98a4e07b87c07d41f3c123ff3954c Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 14:14:31 -0700 Subject: [PATCH 25/40] use websockets is a toggle --- .../ci_run_mqtt5_custom_authorizer_websockets_cfg.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json b/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json index c77cbc12..55cbdac9 100644 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json +++ b/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json @@ -18,7 +18,7 @@ }, { "name": "--use_websockets", - "data": "true" + "data": "" } ] } From 3b696546abede7e87292b6d7ff7f19877cc47047 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 14:36:35 -0700 Subject: [PATCH 26/40] update samples --- samples/mqtt5_custom_authorizer_connect.py | 40 ++++++------ samples/mqtt5_pkcs11_connect.py | 76 ++++++++++++++++------ 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 25764c78..41bd584b 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -47,7 +47,7 @@ def parse_sample_input(): return args -cmdData = parse_sample_input() +args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- @@ -76,33 +76,33 @@ def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.Lifecy if __name__ == '__main__': # Create MQTT5 Client with a custom authorizer - if cmdData.input_use_websockets is None: + if args.input_use_websockets is None: client = mqtt5_client_builder.direct_with_custom_authorizer( - endpoint=cmdData.input_endpoint, - ca_filepath=cmdData.input_ca, - auth_username=cmdData.input_custom_auth_username, - auth_authorizer_name=cmdData.input_custom_authorizer_name, - auth_authorizer_signature=cmdData.input_custom_authorizer_signature, - auth_password=cmdData.input_custom_auth_password, - auth_token_key_name=cmdData.input_custom_authorizer_token_key_name, - auth_token_value=cmdData.input_custom_authorizer_token_value, + endpoint=args.input_endpoint, + ca_filepath=args.input_ca, + auth_username=args.input_custom_auth_username, + auth_authorizer_name=args.input_custom_authorizer_name, + auth_authorizer_signature=args.input_custom_authorizer_signature, + auth_password=args.input_custom_auth_password, + auth_token_key_name=args.input_custom_authorizer_token_key_name, + auth_token_value=args.input_custom_authorizer_token_value, on_lifecycle_stopped=on_lifecycle_stopped, on_lifecycle_connection_success=on_lifecycle_connection_success, - client_id=cmdData.input_clientId) + client_id=args.input_clientId) else: client = mqtt5_client_builder.websockets_with_custom_authorizer( - endpoint=cmdData.input_endpoint, - auth_username=cmdData.input_custom_auth_username, - auth_authorizer_name=cmdData.input_custom_authorizer_name, - auth_authorizer_signature=cmdData.input_custom_authorizer_signature, - auth_password=cmdData.input_custom_auth_password, - auth_token_key_name=cmdData.input_custom_authorizer_token_key_name, - auth_token_value=cmdData.input_custom_authorizer_token_value, + endpoint=args.input_endpoint, + auth_username=args.input_custom_auth_username, + auth_authorizer_name=args.input_custom_authorizer_name, + auth_authorizer_signature=args.input_custom_authorizer_signature, + auth_password=args.input_custom_auth_password, + auth_token_key_name=args.input_custom_authorizer_token_key_name, + auth_token_value=args.input_custom_authorizer_token_value, on_lifecycle_stopped=on_lifecycle_stopped, on_lifecycle_connection_success=on_lifecycle_connection_success, - client_id=cmdData.input_clientId) + client_id=args.input_clientId) - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}'...") client.start() future_connection_success.result(TIMEOUT) diff --git a/samples/mqtt5_pkcs11_connect.py b/samples/mqtt5_pkcs11_connect.py index 865edcfd..2f592bd0 100644 --- a/samples/mqtt5_pkcs11_connect.py +++ b/samples/mqtt5_pkcs11_connect.py @@ -1,18 +1,54 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # Messaging + parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") + parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") + parser.add_argument("--count", default=5, dest="input_count", + help="Messages to publish (0 = infinite)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") + + parser.add_argument("--pkcs11_lib", required=True, dest="input_pkcs11_lib_path", help="Path to PKCS#11 Library") + parser.add_argument("--pin", required=True, dest="input_pkcs11_user_pin", help="User PIN for logging into PKCS#11 token") + parser.add_argument("--token_label", dest="input_pkcs11_token_label", help="Label of the PKCS#11 token to use (optional).") + parser.add_argument("--slot_id", dest="input_pkcs11_slot_id", help="Slot ID containing the PKCS#11 token to use (optional).") + parser.add_argument("--key_label", dest="input_pkcs11_key_label", help="Label of private key on the PKCS#11 token (optional).") + + return parser.parse_args() + +args = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + from awscrt import mqtt5, io from awsiot import mqtt5_client_builder from concurrent.futures import Future -from utils.command_line_utils import CommandLineUtils TIMEOUT = 100 -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_mqtt5_pkcs11_connect() - future_stopped = Future() future_connection_success = Future() @@ -33,35 +69,35 @@ def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.Lifecy if __name__ == '__main__': print("\nStarting MQTT5 pkcs11 connect Sample\n") - print(f"Loading PKCS#11 library '{cmdData.input_pkcs11_lib_path}' ...") + print(f"Loading PKCS#11 library '{args.input_pkcs11_lib_path}' ...") pkcs11_lib = io.Pkcs11Lib( - file=cmdData.input_pkcs11_lib_path, + file=args.input_pkcs11_lib_path, behavior=io.Pkcs11Lib.InitializeFinalizeBehavior.STRICT) print("Loaded!") pkcs11_slot_id = None - if (cmdData.input_pkcs11_slot_id is not None): - pkcs11_slot_id = int(cmdData.input_pkcs11_slot_id) + if (args.input_pkcs11_slot_id is not None): + pkcs11_slot_id = int(args.input_pkcs11_slot_id) # Create MQTT5 client client = mqtt5_client_builder.mtls_with_pkcs11( pkcs11_lib=pkcs11_lib, - user_pin=cmdData.input_pkcs11_user_pin, + user_pin=args.input_pkcs11_user_pin, slot_id=pkcs11_slot_id, - token_label=cmdData.input_pkcs11_token_label, - private_key_label=cmdData.input_pkcs11_key_label, - cert_filepath=cmdData.input_cert, - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - ca_filepath=cmdData.input_ca, + token_label=args.input_pkcs11_token_label, + private_key_label=args.input_pkcs11_key_label, + cert_filepath=args.input_cert, + endpoint=args.input_endpoint, + port=args.input_port, + ca_filepath=args.input_ca, on_lifecycle_stopped=on_lifecycle_stopped, on_lifecycle_connection_success=on_lifecycle_connection_success, - client_id=cmdData.input_clientId) + client_id=args.input_clientId) print("MQTT5 Client Created") - if not cmdData.input_is_ci: - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}'...") + if not args.input_is_ci: + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}'...") else: print("Connecting to endpoint with client ID") From 81d83dc488c3ac56d4bd0370f79128715ace3f1d Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 14:37:11 -0700 Subject: [PATCH 27/40] remove is_ci --- samples/mqtt5_pkcs11_connect.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/samples/mqtt5_pkcs11_connect.py b/samples/mqtt5_pkcs11_connect.py index 2f592bd0..44c17c34 100644 --- a/samples/mqtt5_pkcs11_connect.py +++ b/samples/mqtt5_pkcs11_connect.py @@ -96,10 +96,7 @@ def on_lifecycle_connection_success(lifecycle_connect_success_data: mqtt5.Lifecy print("MQTT5 Client Created") - if not args.input_is_ci: - print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}'...") - else: - print("Connecting to endpoint with client ID") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}'...") client.start() future_connection_success.result(TIMEOUT) From 85bd3505724f70e8e3a6891973783c904c9f1117 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Mon, 18 Aug 2025 14:47:26 -0700 Subject: [PATCH 28/40] remove command line utils --- samples/mqtt5_shared_subscription.py | 78 ++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/samples/mqtt5_shared_subscription.py b/samples/mqtt5_shared_subscription.py index fe45d9db..7f511ec0 100644 --- a/samples/mqtt5_shared_subscription.py +++ b/samples/mqtt5_shared_subscription.py @@ -1,13 +1,53 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") + parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # Messaging + parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") + parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") + parser.add_argument("--count", default=5, dest="input_count", + help="Messages to publish (0 = infinite)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", default=f"test-{uuid.uuid4().hex[:8]}", + help="Client ID to use for MQTT5 connection (optional, default=None). Note that '1', '2', and '3' will be added for to the given clientIDs since this sample uses 3 clients.") + + parser.add_argument("--group_identifier", default="python-sample", dest="input_group_identifier", + help="The group identifier to use in the shared subscription (optional, default='python-sample').") + + return parser.parse_args() + +args = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + from awscrt import mqtt5 from awsiot import mqtt5_client_builder import threading from concurrent.futures import Future import time import json -from utils.command_line_utils import CommandLineUtils # For the purposes of this sample, we need to associate certain variables with a particular MQTT5 client # and to do so we use this class to hold all the data for a particular client used in the sample. @@ -89,27 +129,21 @@ def on_lifecycle_disconnection(self, disconnect_data: mqtt5.LifecycleDisconnectD # Stop the client, which will interrupt the subscription and stop the sample self.client.stop() - -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_mqtt5_shared_subscription() - # Construct the shared topic -input_shared_topic = f"$share/{cmdData.input_group_identifier}/{cmdData.input_topic}" +input_shared_topic = f"$share/{args.input_group_identifier}/{args.input_topic}" if __name__ == '__main__': try: # Create the MQTT5 clients: one publisher and two subscribers publisher = sample_mqtt5_client( - cmdData.input_endpoint, cmdData.input_cert, cmdData.input_key, cmdData.input_ca, - cmdData.input_clientId + "1", "Publisher") + args.input_endpoint, args.input_cert, args.input_key, args.input_ca, + args.input_clientId + "1", "Publisher") subscriber_one = sample_mqtt5_client( - cmdData.input_endpoint, cmdData.input_cert, cmdData.input_key, cmdData.input_ca, - cmdData.input_clientId + "2", "Subscriber One") + args.input_endpoint, args.input_cert, args.input_key, args.input_ca, + args.input_clientId + "2", "Subscriber One") subscriber_two = sample_mqtt5_client( - cmdData.input_endpoint, cmdData.input_cert, cmdData.input_key, cmdData.input_ca, - cmdData.input_clientId + "3", "Subscriber Two") + args.input_endpoint, args.input_cert, args.input_key, args.input_ca, + args.input_clientId + "3", "Subscriber Two") # Connect all the clients publisher.client.start() @@ -130,20 +164,20 @@ def on_lifecycle_disconnection(self, disconnect_data: mqtt5.LifecycleDisconnectD ) subscribe_one_future = subscriber_one.client.subscribe(subscribe_packet) suback_one = subscribe_one_future.result(60) - print(f"[{subscriber_one.name}]: Subscribed to topic '{cmdData.input_topic}' in shared subscription group '{cmdData.input_group_identifier}'.") + print(f"[{subscriber_one.name}]: Subscribed to topic '{args.input_topic}' in shared subscription group '{args.input_group_identifier}'.") print(f"[{subscriber_one.name}]: Full subscribed topic is: '{input_shared_topic}' with SubAck code: {suback_one.reason_codes}") subscribe_two_future = subscriber_two.client.subscribe(subscribe_packet) suback_two = subscribe_two_future.result(60) - print(f"[{subscriber_two.name}]: Subscribed to topic '{cmdData.input_topic}' in shared subscription group '{cmdData.input_group_identifier}'.") + print(f"[{subscriber_two.name}]: Subscribed to topic '{args.input_topic}' in shared subscription group '{args.input_group_identifier}'.") print(f"[{subscriber_two.name}]: Full subscribed topic is: '{input_shared_topic}' with SubAck code: {suback_two.reason_codes}") # Publish using the publisher client - if (cmdData.input_count > 0): + if (args.input_count > 0): publish_count = 1 - while (publish_count <= cmdData.input_count): - publish_message = f"{cmdData.input_message} [{publish_count}]" + while (publish_count <= args.input_count): + publish_message = f"{args.input_message} [{publish_count}]" publish_future = publisher.client.publish(mqtt5.PublishPacket( - topic=cmdData.input_topic, + topic=args.input_topic, payload=json.dumps(publish_message), qos=mqtt5.QoS.AT_LEAST_ONCE )) @@ -161,11 +195,11 @@ def on_lifecycle_disconnection(self, disconnect_data: mqtt5.LifecycleDisconnectD unsubscribe_packet = mqtt5.UnsubscribePacket(topic_filters=[input_shared_topic]) unsubscribe_one_future = subscriber_one.client.unsubscribe(unsubscribe_packet) unsuback_one = unsubscribe_one_future.result(60) - print(f"[{subscriber_one.name}]: Unsubscribed to topic '{cmdData.input_topic}' in shared subscription group '{cmdData.input_group_identifier}'.") + print(f"[{subscriber_one.name}]: Unsubscribed to topic '{args.input_topic}' in shared subscription group '{args.input_group_identifier}'.") print(f"[{subscriber_one.name}]: Full unsubscribed topic is: '{input_shared_topic}' with UnsubAck code: {unsuback_one.reason_codes}") unsubscribe_two_future = subscriber_two.client.unsubscribe(unsubscribe_packet) unsuback_two = unsubscribe_two_future.result(60) - print(f"[{subscriber_two.name}]: Unsubscribed to topic '{cmdData.input_topic}' in shared subscription group '{cmdData.input_group_identifier}'.") + print(f"[{subscriber_two.name}]: Unsubscribed to topic '{args.input_topic}' in shared subscription group '{args.input_group_identifier}'.") print(f"[{subscriber_two.name}]: Full unsubscribed topic is: '{input_shared_topic}' with UnsubAck code {unsuback_two.reason_codes}") # Disconnect all the clients From 45b4fcc1300f6bdcb70a3e469a7da8d6dfa85934 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 08:24:58 -0700 Subject: [PATCH 29/40] update fleet_provisioning test --- .../FleetProvisioning/fleet_provisioning.py | 95 +++++++++++++------ 1 file changed, 67 insertions(+), 28 deletions(-) diff --git a/servicetests/tests/FleetProvisioning/fleet_provisioning.py b/servicetests/tests/FleetProvisioning/fleet_provisioning.py index b08e0306..773d1207 100644 --- a/servicetests/tests/FleetProvisioning/fleet_provisioning.py +++ b/servicetests/tests/FleetProvisioning/fleet_provisioning.py @@ -10,7 +10,7 @@ import time import traceback import json -from utils.command_line_utils import CommandLineUtils +# from utils.command_line_utils import CommandLineUtils # - Overview - # This sample uses the AWS IoT Fleet Provisioning to provision device using either the keys @@ -28,7 +28,46 @@ # cmdData is the arguments/input from the command line placed into a single struct for # use in this sample. This handles all of the command line parsing, validating, etc. # See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_fleet_provisioning() +# cmdData = CommandLineUtils.parse_sample_input_fleet_provisioning() +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") + parser.add_argument("--mqtt_version", type=int, default=0, dest="input_mqtt_version", help="MQTT Version") + parser.add_argument("--csr", dest="input_csr_path", help="Path to CSR in Pem format (optional).") + parser.add_argument("--template_name", dest="input_template_name", help="The name of your provisioning template.") + parser.add_argument("--template_parameters", dest="input_template_parameters", help="Template parameters json.") + + return parser.parse_args() + +args = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + +# [--csr ] +# [--template_name ] +# [--template_parameters ] # MQTT5 specific mqtt5_client = None @@ -63,7 +102,7 @@ def exit(msg_or_exception): if not locked_data.disconnect_called: print("Disconnecting...") locked_data.disconnect_called = True - if cmdData.input_mqtt_version == 5: + if args.input_mqtt_version == 5: mqtt5_client.stop() else: future = mqtt_connection.disconnect() @@ -234,27 +273,27 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): if __name__ == '__main__': # Create the proxy options if the data is present in cmdData proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: + if args.input_proxy_host is not None and args.input_proxy_port != 0: proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) + host_name=args.input_proxy_host, + port=args.input_proxy_port) - if cmdData.input_mqtt_version == 5: + if args.input_mqtt_version == 5: mqtt_qos = mqtt5.QoS.AT_LEAST_ONCE # Create a mqtt5 connection from the command line data mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, + client_id=args.input_clientId, clean_session=False, keep_alive_secs=30, http_proxy_options=proxy_options, on_lifecycle_connection_success=on_lifecycle_connection_success, on_lifecycle_stopped=on_lifecycle_stopped) - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}' with MQTT5...") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}' with MQTT5...") mqtt5_client.start() @@ -267,22 +306,22 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): # fails or succeeds. future_connection_success.result() - elif cmdData.input_mqtt_version == 3: + elif args.input_mqtt_version == 3: mqtt_qos = mqtt.QoS.AT_LEAST_ONCE # Create a MQTT connection from the command line data mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, on_connection_interrupted=on_connection_interrupted, on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_clientId, + client_id=args.input_clientId, clean_session=False, keep_alive_secs=30, http_proxy_options=proxy_options) - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}' with MQTT5...") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}' with MQTT5...") connected_future = mqtt_connection.connect() @@ -306,7 +345,7 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): # to succeed before publishing the corresponding "request". # Keys workflow if csr is not provided - if cmdData.input_csr_path is None: + if args.input_csr_path is None: createkeysandcertificate_subscription_request = iotidentity.CreateKeysAndCertificateSubscriptionRequest() createkeysandcertificate_subscribed_accepted_future, _ = identity_client.subscribe_to_create_keys_and_certificate_accepted( @@ -344,7 +383,7 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): createcertificatefromcsr_subscribed_rejected_future.result() registerthing_subscription_request = iotidentity.RegisterThingSubscriptionRequest( - template_name=cmdData.input_template_name) + template_name=args.input_template_name) registerthing_subscribed_accepted_future, _ = identity_client.subscribe_to_register_thing_accepted( request=registerthing_subscription_request, @@ -361,9 +400,9 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): # Wait for subscription to succeed registerthing_subscribed_rejected_future.result() - fleet_template_name = cmdData.input_template_name - fleet_template_parameters = cmdData.input_template_parameters - if cmdData.input_csr_path is None: + fleet_template_name = args.input_template_name + fleet_template_parameters = args.input_template_parameters + if args.input_csr_path is None: publish_future = identity_client.publish_create_keys_and_certificate( request=iotidentity.CreateKeysAndCertificateRequest(), qos=mqtt_qos) publish_future.add_done_callback(on_publish_create_keys_and_certificate) @@ -378,7 +417,7 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): certificate_ownership_token=createKeysAndCertificateResponse.certificate_ownership_token, parameters=json.loads(fleet_template_parameters)) else: - csrPath = open(cmdData.input_csr_path, 'r').read() + csrPath = open(args.input_csr_path, 'r').read() publish_future = identity_client.publish_create_certificate_from_csr( request=iotidentity.CreateCertificateFromCsrRequest(certificate_signing_request=csrPath), qos=mqtt_qos) From 0750ba1d464ab859f14d1d8c4395d7b5ac2e1c01 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 08:39:00 -0700 Subject: [PATCH 30/40] remove utils dependency from remaining service tests --- .../FleetProvisioning/fleet_provisioning.py | 11 +- servicetests/tests/JobsExecution/jobs.py | 89 ++++++++++------ .../tests/ShadowUpdate/shadow_update.py | 100 ++++++++++++------ 3 files changed, 123 insertions(+), 77 deletions(-) diff --git a/servicetests/tests/FleetProvisioning/fleet_provisioning.py b/servicetests/tests/FleetProvisioning/fleet_provisioning.py index 773d1207..c5b33d90 100644 --- a/servicetests/tests/FleetProvisioning/fleet_provisioning.py +++ b/servicetests/tests/FleetProvisioning/fleet_provisioning.py @@ -5,12 +5,7 @@ from awsiot import iotidentity, mqtt_connection_builder from awsiot import mqtt5_client_builder from concurrent.futures import Future -import sys -import threading -import time -import traceback -import json -# from utils.command_line_utils import CommandLineUtils +import sys, threading, time, traceback, json # - Overview - # This sample uses the AWS IoT Fleet Provisioning to provision device using either the keys @@ -25,10 +20,6 @@ # On startup, the script subscribes to topics based on the request type of either CSR or Keys # publishes the request to corresponding topic and calls RegisterThing. -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -# cmdData = CommandLineUtils.parse_sample_input_fleet_provisioning() # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid diff --git a/servicetests/tests/JobsExecution/jobs.py b/servicetests/tests/JobsExecution/jobs.py index 5801922e..71b59a02 100644 --- a/servicetests/tests/JobsExecution/jobs.py +++ b/servicetests/tests/JobsExecution/jobs.py @@ -5,12 +5,7 @@ from awsiot import iotjobs, mqtt_connection_builder from awsiot import mqtt5_client_builder from concurrent.futures import Future -import sys -import threading -import time -import traceback -import time -from utils.command_line_utils import CommandLineUtils +import sys, threading, time, traceback, time # - Overview - # This sample uses the AWS IoT Jobs Service to get a list of pending jobs and @@ -38,14 +33,44 @@ # Using globals to simplify sample code is_sample_done = threading.Event() -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_jobs() +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") + parser.add_argument("--mqtt_version", type=int, default=0, dest="input_mqtt_version", help="MQTT Version") + parser.add_argument("--thing_name", required=True, dest="input_thing_name", help="The name assigned to your IoT Thing.") + parser.add_argument("--job_time", type=int, default=5, dest="input_job_time", help="Emulate working on a job by sleeping this many seconds (optional, default='5')") + + return parser.parse_args() + +args = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- mqtt_connection = None jobs_client = None -jobs_thing_name = cmdData.input_thing_name +jobs_thing_name = args.input_thing_name mqtt_qos = None # MQTT5 specific @@ -75,7 +100,7 @@ def exit(msg_or_exception): if not locked_data.disconnect_called: print("Disconnecting...") locked_data.disconnect_called = True - if cmdData.input_mqtt_version == 5: + if args.input_mqtt_version == 5: mqtt5_client.stop() else: future = mqtt_connection.disconnect() @@ -213,7 +238,7 @@ def on_start_next_pending_job_execution_rejected(rejected): def job_thread_fn(job_id, job_document): try: print("Starting local work on job...") - time.sleep(cmdData.input_job_time) + time.sleep(args.input_job_time) print("Done working on job.") print("Publishing request to update job status to SUCCEEDED...") @@ -272,27 +297,27 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): # Create the proxy options if the data is present in cmdData proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: + if args.input_proxy_host is not None and args.input_proxy_port != 0: proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) + host_name=args.input_proxy_host, + port=args.input_proxy_port) - if cmdData.input_mqtt_version == 5: + if args.input_mqtt_version == 5: mqtt_qos = mqtt5.QoS.AT_LEAST_ONCE # Create a mqtt5 connection from the command line data mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, + client_id=args.input_clientId, clean_session=False, keep_alive_secs=30, http_proxy_options=proxy_options, on_lifecycle_connection_success=on_lifecycle_connection_success, on_lifecycle_stopped=on_lifecycle_stopped) - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}' with MQTT5...") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}' with MQTT5...") mqtt5_client.start() @@ -304,21 +329,21 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): # mqtt5_client before its fully connected will simply be queued. # But this sample waits here so it's obvious when a connection # fails or succeeds. - elif cmdData.input_mqtt_version == 3: + elif args.input_mqtt_version == 3: mqtt_qos = mqtt.QoS.AT_LEAST_ONCE # Create a MQTT connection from the command line data mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, + client_id=args.input_clientId, clean_session=False, keep_alive_secs=30, http_proxy_options=proxy_options) - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}' with MQTT3...") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}' with MQTT3...") connected_future = mqtt_connection.connect() diff --git a/servicetests/tests/ShadowUpdate/shadow_update.py b/servicetests/tests/ShadowUpdate/shadow_update.py index 8c89cb2d..16bc79a8 100644 --- a/servicetests/tests/ShadowUpdate/shadow_update.py +++ b/servicetests/tests/ShadowUpdate/shadow_update.py @@ -5,11 +5,8 @@ from awscrt import mqtt, mqtt5, http from awsiot import iotshadow, mqtt_connection_builder, mqtt5_client_builder from concurrent.futures import Future -import sys -import threading -import traceback +import sys, threading, traceback from uuid import uuid4 -from utils.command_line_utils import CommandLineUtils # - Overview - # This sample uses the AWS IoT Device Shadow Service to keep a property in @@ -27,16 +24,49 @@ # initial state. The Test subscribes to modified events from the server, # which are sent when a property's value changes -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_shadow() +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + # Connection / TLS + parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") + parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") + parser.add_argument("--mqtt_version", type=int, default=0, dest="input_mqtt_version", help="MQTT Version") + parser.add_argument("--thing_name", required=True, dest="input_thing_name", help="The name assigned to your IoT Thing.") + parser.add_argument("--shadow_property", dest="input_shadow_property", default="", + help="The name of the shadow property you want to change (optional, default=''") + parser.add_argument("--shadow_value", dest="input_shadow_value", help="The desired value of the shadow property you want to set (optional)") + parser.add_argument("--shadow_name", dest="input_shadow_name", default="", help="Shadow name (optional, default='')") + + return parser.parse_args() + +args = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- # Using globals to simplify sample code is_sample_done = threading.Event() mqtt_connection = None -shadow_thing_name = cmdData.input_thing_name -shadow_property = cmdData.input_shadow_property +shadow_thing_name = args.input_thing_name +shadow_property = args.input_shadow_property mqtt_qos = None # MQTT5 specific @@ -67,7 +97,7 @@ def exit(msg_or_exception): with locked_data.lock: if not locked_data.disconnect_called: locked_data.disconnect_called = True - if cmdData.input_mqtt_version == 5: + if args.input_mqtt_version == 5: print("Stop the client...") mqtt5_client.stop() else: @@ -211,7 +241,7 @@ def on_lifecycle_stopped(lifecycle_stopped_data: mqtt5.LifecycleStoppedData): def update_named_shadow(): print("Updating named shadow") # named shadow here - named_shadow = cmdData.input_shadow_name + named_shadow = args.input_shadow_name try: # Subscribe to necessary topics. # Note that is **is** important to wait for "accepted/rejected" subscriptions @@ -272,8 +302,8 @@ def update_named_shadow(): subscribe_future.result() state=iotshadow.ShadowState( - reported={shadow_property: cmdData.input_shadow_value}, - desired={shadow_property: cmdData.input_shadow_value}, + reported={shadow_property: args.input_shadow_value}, + desired={shadow_property: args.input_shadow_value}, token=token) update_thing_update_future = shadow_client.publish_update_named_shadow(request = iotshadow.UpdateNamedShadowRequest @@ -347,8 +377,8 @@ def update_shadow(): subscribe_future.result() state=iotshadow.ShadowState( - reported={shadow_property: cmdData.input_shadow_value}, - desired={shadow_property: cmdData.input_shadow_value}, + reported={shadow_property: args.input_shadow_value}, + desired={shadow_property: args.input_shadow_value}, token=token) update_thing_update_future = shadow_client.publish_update_shadow(request = iotshadow.UpdateShadowRequest @@ -362,27 +392,27 @@ def update_shadow(): if __name__ == '__main__': # Create the proxy options if the data is present in cmdData proxy_options = None - if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: + if args.input_proxy_host is not None and args.input_proxy_port != 0: proxy_options = http.HttpProxyOptions( - host_name=cmdData.input_proxy_host, - port=cmdData.input_proxy_port) + host_name=args.input_proxy_host, + port=args.input_proxy_port) - if cmdData.input_mqtt_version == 5: + if args.input_mqtt_version == 5: mqtt_qos = mqtt5.QoS.AT_LEAST_ONCE # Create a mqtt5 connection from the command line data mqtt5_client = mqtt5_client_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, + client_id=args.input_clientId, clean_session=False, keep_alive_secs=30, http_proxy_options=proxy_options, on_lifecycle_connection_success=on_lifecycle_connection_success, on_lifecycle_stopped=on_lifecycle_stopped) - print(f"Connecting to {cmdData.input_endpoint} with client ID '{cmdData.input_clientId}' with MQTT5...") + print(f"Connecting to {args.input_endpoint} with client ID '{args.input_clientId}' with MQTT5...") mqtt5_client.start() @@ -394,16 +424,16 @@ def update_shadow(): # mqtt5_client before its fully connected will simply be queued. # But this sample waits here so it's obvious when a connection # fails or succeeds. - elif cmdData.input_mqtt_version == 3: + elif args.input_mqtt_version == 3: mqtt_qos = mqtt.QoS.AT_LEAST_ONCE # Create a MQTT connection from the command line data mqtt_connection = mqtt_connection_builder.mtls_from_path( - endpoint=cmdData.input_endpoint, - port=cmdData.input_port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, - ca_filepath=cmdData.input_ca, - client_id=cmdData.input_clientId, + endpoint=args.input_endpoint, + port=args.input_port, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, + ca_filepath=args.input_ca, + client_id=args.input_clientId, clean_session=False, keep_alive_secs=30, http_proxy_options=proxy_options) @@ -424,7 +454,7 @@ def update_shadow(): print("Connected!") - if not cmdData.input_shadow_name: + if not args.input_shadow_name: update_shadow() else: update_named_shadow() From ac730221acd9a41daecfc4b90415fc3e555970b7 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 09:15:39 -0700 Subject: [PATCH 31/40] remove utils from basic_discovery --- samples/basic_discovery.py | 90 +++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py index be12152b..0c2aa44b 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -8,41 +8,81 @@ from awsiot.greengrass_discovery import DiscoveryClient from awsiot import mqtt_connection_builder -from utils.command_line_utils import CommandLineUtils +# from utils.command_line_utils import CommandLineUtils allowed_actions = ['both', 'publish', 'subscribe'] # cmdData is the arguments/input from the command line placed into a single struct for # use in this sample. This handles all of the command line parsing, validating, etc. # See the Utils/CommandLineUtils for more information. -cmdData = CommandLineUtils.parse_sample_input_basic_discovery() - -tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(cmdData.input_cert, cmdData.input_key) -if (cmdData.input_ca is not None): - tls_options.override_default_trust_store_from_path(None, cmdData.input_ca) +# cmdData = CommandLineUtils.parse_sample_input_basic_discovery() + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="MQTT5 pub/sub sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + + parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") + parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # Messaging + parser.add_argument("--topic", default=f"test/topic/{uuid.uuid4().hex[:8]}", dest="input_topic", help="Topic") + parser.add_argument("--message", default="Hello World!", dest="input_message", help="Message payload") + parser.add_argument("--thing_name", required=True, dest="input_thing_name", help="The name assigned to your IoT Thing.") + parser.add_argument("--region", required=True, dest="input_signing_region", help="The region to connect through.") + parser.add_argument("--max_pub_ops", type=int, default=10, dest="input_max_pub_ops", + help="The maximum number of publish operations (optional, default='10').") + parser.add_argument("--print_discover_resp_only", type=bool, default=False, dest="input_print_discovery_resp_only", + help="(optional, default='False').") + parser.add_argument("--mode", default='both', dest="input_mode", + help=f"The operation mode (optional, default='both').\nModes:{allowed_actions}") + + # Proxy (optional) + parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") + parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") + + # Misc + parser.add_argument("--client-id", dest="input_clientId", + default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") + + return parser.parse_args() + +args = parse_sample_input() + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + +# [--mode ] + +tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(args.input_cert, args.input_key) +if (args.input_ca is not None): + tls_options.override_default_trust_store_from_path(None, args.input_ca) tls_context = io.ClientTlsContext(tls_options) socket_options = io.SocketOptions() proxy_options = None -if cmdData.input_proxy_host is not None and cmdData.input_proxy_port != 0: - proxy_options = http.HttpProxyOptions(cmdData.input_proxy_host, cmdData.input_proxy_port) +if args.input_proxy_host is not None and args.input_proxy_port != 0: + proxy_options = http.HttpProxyOptions(args.input_proxy_host, args.input_proxy_port) print('Performing greengrass discovery...') discovery_client = DiscoveryClient( io.ClientBootstrap.get_or_create_static_default(), socket_options, tls_context, - cmdData.input_signing_region, None, proxy_options) -resp_future = discovery_client.discover(cmdData.input_thing_name) + args.input_signing_region, None, proxy_options) +resp_future = discovery_client.discover(args.input_thing_name) discover_response = resp_future.result() -if (cmdData.input_is_ci): - print("Received a greengrass discovery result! Not showing result in CI for possible data sensitivity.") -else: - print(discover_response) +print("Received a greengrass discovery result! Not showing result for possible data sensitivity.") -if (cmdData.input_print_discovery_resp_only): +if (args.input_print_discovery_resp_only): exit(0) @@ -65,12 +105,12 @@ def try_iot_endpoints(): mqtt_connection = mqtt_connection_builder.mtls_from_path( endpoint=connectivity_info.host_address, port=connectivity_info.port, - cert_filepath=cmdData.input_cert, - pri_key_filepath=cmdData.input_key, + cert_filepath=args.input_cert, + pri_key_filepath=args.input_key, ca_bytes=gg_group.certificate_authorities[0].encode('utf-8'), on_connection_interrupted=on_connection_interupted, on_connection_resumed=on_connection_resumed, - client_id=cmdData.input_thing_name, + client_id=args.input_thing_name, clean_session=False, keep_alive_secs=30) @@ -88,23 +128,23 @@ def try_iot_endpoints(): mqtt_connection = try_iot_endpoints() -if cmdData.input_mode == 'both' or cmdData.input_mode == 'subscribe': +if args.input_mode == 'both' or args.input_mode == 'subscribe': def on_publish(topic, payload, dup, qos, retain, **kwargs): print('Publish received on topic {}'.format(topic)) print(payload) - subscribe_future, _ = mqtt_connection.subscribe(cmdData.input_topic, QoS.AT_MOST_ONCE, on_publish) + subscribe_future, _ = mqtt_connection.subscribe(args.input_topic, QoS.AT_MOST_ONCE, on_publish) subscribe_result = subscribe_future.result() loop_count = 0 -while loop_count < cmdData.input_max_pub_ops: - if cmdData.input_mode == 'both' or cmdData.input_mode == 'publish': +while loop_count < args.input_max_pub_ops: + if args.input_mode == 'both' or args.input_mode == 'publish': message = {} - message['message'] = cmdData.input_message + message['message'] = args.input_message message['sequence'] = loop_count messageJson = json.dumps(message) - pub_future, _ = mqtt_connection.publish(cmdData.input_topic, messageJson, QoS.AT_LEAST_ONCE) + pub_future, _ = mqtt_connection.publish(args.input_topic, messageJson, QoS.AT_LEAST_ONCE) publish_completion_data = pub_future.result() - print('Successfully published to topic {} with payload `{}`\n'.format(cmdData.input_topic, messageJson)) + print('Successfully published to topic {} with payload `{}`\n'.format(args.input_topic, messageJson)) loop_count += 1 time.sleep(1) \ No newline at end of file From bb3b98aff67a1edbf9a70cb963e0ee28d66b4187 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 09:21:45 -0700 Subject: [PATCH 32/40] remove command_line_utils.py --- samples/basic_discovery.py | 14 +- samples/utils/command_line_utils.py | 922 ---------------------------- 2 files changed, 2 insertions(+), 934 deletions(-) delete mode 100644 samples/utils/command_line_utils.py diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py index 0c2aa44b..f9bca36e 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -1,28 +1,20 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -import time -import json +import time, json from awscrt import io, http from awscrt.mqtt import QoS from awsiot.greengrass_discovery import DiscoveryClient from awsiot import mqtt_connection_builder -# from utils.command_line_utils import CommandLineUtils - allowed_actions = ['both', 'publish', 'subscribe'] -# cmdData is the arguments/input from the command line placed into a single struct for -# use in this sample. This handles all of the command line parsing, validating, etc. -# See the Utils/CommandLineUtils for more information. -# cmdData = CommandLineUtils.parse_sample_input_basic_discovery() - # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="Greengrass basic discovery", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) @@ -58,8 +50,6 @@ def parse_sample_input(): # --------------------------------- ARGUMENT PARSING END ----------------------------------------- -# [--mode ] - tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(args.input_cert, args.input_key) if (args.input_ca is not None): tls_options.override_default_trust_store_from_path(None, args.input_ca) diff --git a/samples/utils/command_line_utils.py b/samples/utils/command_line_utils.py deleted file mode 100644 index 81f9925e..00000000 --- a/samples/utils/command_line_utils.py +++ /dev/null @@ -1,922 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -import argparse -from awscrt import io -from uuid import uuid4 - -class CommandLineUtils: - def __init__(self, description) -> None: - self.parser = argparse.ArgumentParser(description="Send and receive messages through and MQTT connection.") - self.commands = {} - self.parsed_commands = None - - def register_command(self, command_name, example_input, help_output, required=False, type=None, default=None, choices=None, action=None): - self.commands[command_name] = { - "name":command_name, - "example_input":example_input, - "help_output":help_output, - "required": required, - "type": type, - "default": default, - "choices": choices, - "action": action - } - - def remove_command(self, command_name): - if command_name in self.commands.keys(): - self.commands.pop(command_name) - - """ - Returns the command if it exists and has been passed to the console, otherwise it will print the help for the sample and exit the application. - """ - def get_command_required(self, command_name, command_name_alt = None): - if(command_name_alt != None): - if hasattr(self.parsed_commands, command_name_alt): - if(getattr(self.parsed_commands, command_name_alt) != None): - return getattr(self.parsed_commands, command_name_alt) - - if hasattr(self.parsed_commands, command_name): - if(getattr(self.parsed_commands, command_name) != None): - return getattr(self.parsed_commands, command_name) - - self.parser.print_help() - print("Command --" + command_name + " required.") - exit() - - """ - Returns the command if it exists, has been passed to the console, and is not None. Otherwise it returns whatever is passed as the default. - """ - def get_command(self, command_name, default=None): - if hasattr(self.parsed_commands, command_name): - result = getattr(self.parsed_commands, command_name) - if (result != None): - return result - return default - - def get_args(self): - # if we have already parsed, then return the cached parsed commands - if self.parsed_commands is not None: - return self.parsed_commands - - # add all the commands - for command in self.commands.values(): - if not command["action"] is None: - self.parser.add_argument("--" + command["name"], action=command["action"], help=command["help_output"], - required=command["required"], default=command["default"]) - else: - self.parser.add_argument("--" + command["name"], metavar=command["example_input"], help=command["help_output"], - required=command["required"], type=command["type"], default=command["default"], choices=command["choices"]) - - self.parsed_commands = self.parser.parse_args() - # Automatically start logging if it is set - if self.parsed_commands.verbosity: - io.init_logging(getattr(io.LogLevel, self.parsed_commands.verbosity), 'stderr') - - return self.parsed_commands - - def update_command(self, command_name, new_example_input=None, new_help_output=None, new_required=None, new_type=None, new_default=None, new_action=None): - if command_name in self.commands.keys(): - if new_example_input: - self.commands[command_name]["example_input"] = new_example_input - if new_help_output: - self.commands[command_name]["help_output"] = new_help_output - if new_required: - self.commands[command_name]["required"] = new_required - if new_type: - self.commands[command_name]["type"] = new_type - if new_default: - self.commands[command_name]["default"] = new_default - if new_action: - self.commands[command_name]["action"] = new_action - - def add_common_mqtt_commands(self): - self.register_command( - CommandLineUtils.m_cmd_endpoint, - "", - "The endpoint of the mqtt server not including a port.", - True, - str) - self.register_command( - CommandLineUtils.m_cmd_ca_file, - "", - "Path to AmazonRootCA1.pem (optional, system trust store used by default)", - False, - str) - self.register_command( - CommandLineUtils.m_cmd_is_ci, - "", - "If present the sample will run in CI mode (optional, default='None')", - False, - str) - - def add_common_mqtt5_commands(self): - self.register_command( - CommandLineUtils.m_cmd_endpoint, - "", - "The endpoint of the mqtt server not including a port.", - True, - str) - self.register_command( - CommandLineUtils.m_cmd_ca_file, - "", - "Path to AmazonRootCA1.pem (optional, system trust store used by default)", - False, - str) - self.register_command( - CommandLineUtils.m_cmd_is_ci, - "", - "If present the sample will run in CI mode (optional, default='None')", - False, - str) - - def add_common_proxy_commands(self): - self.register_command( - CommandLineUtils.m_cmd_proxy_host, - "", - "Host name of the proxy server to connect through (optional)", - False, - str) - self.register_command( - CommandLineUtils.m_cmd_proxy_port, - "", - "Port of the http proxy to use (optional, default='8080')", - type=int, - default=8080) - - def add_common_topic_message_commands(self): - self.register_command( - CommandLineUtils.m_cmd_topic, - "", - "Topic to publish, subscribe to (optional, default='test/topic').", - default="test/topic") - self.register_command( - CommandLineUtils.m_cmd_message, - "", - "The message to send in the payload (optional, default='Hello World!').", - default="Hello World! ") - - def add_common_logging_commands(self): - self.register_command( - CommandLineUtils.m_cmd_verbosity, - "", - "Logging level.", - default=io.LogLevel.NoLogs.name, - choices=[ - x.name for x in io.LogLevel]) - - def add_common_key_cert_commands(self): - self.register_command(CommandLineUtils.m_cmd_key_file, "", "Path to your key in PEM format.", True, str) - self.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to your client certificate in PEM format.", True, str) - - def add_common_custom_authorizer_commands(self): - self.register_command( - CommandLineUtils.m_cmd_custom_auth_username, - "", - "The name to send when connecting through the custom authorizer (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_authorizer_name, - "", - "The name of the custom authorizer to connect to (optional but required for everything but custom domains)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_authorizer_signature, - "", - "The signature to send when connecting through a custom authorizer (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_password, - "", - "The password to send when connecting through a custom authorizer (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_token_key_name, - "", - "Key used to extract the custom authorizer token (optional)") - self.register_command( - CommandLineUtils.m_cmd_custom_auth_token_value, - "", - "The opaque token value for the custom authorizer (optional)") - - def add_common_x509_commands(self): - self.register_command( - CommandLineUtils.m_cmd_x509_endpoint, - "", - "The credentials endpoint to fetch x509 credentials from", - ) - self.register_command( - CommandLineUtils.m_cmd_x509_thing_name, - "", - "Thing name to fetch x509 credentials on behalf of" - ) - self.register_command( - CommandLineUtils.m_cmd_x509_role_alias, - "", - "Role alias to use with the x509 credentials provider" - ) - self.register_command( - CommandLineUtils.m_cmd_x509_key, - "", - "Path to the IoT thing private key used in fetching x509 credentials" - ) - self.register_command( - CommandLineUtils.m_cmd_x509_cert, - "", - "Path to the IoT thing certificate used in fetching x509 credentials" - ) - - self.register_command( - CommandLineUtils.m_cmd_x509_ca, - "", - "Path to the root certificate used in fetching x509 credentials" - ) - - ######################################################################## - # cmdData utils/functions - ######################################################################## - - class CmdData: - # General use - input_endpoint : str - input_cert : str - input_key : str - input_ca : str - input_clientId : str - input_port : int - input_is_ci : bool - input_use_websockets : bool - # Proxy - input_proxy_host : str - input_proxy_port : int - # PubSub - input_topic : str - input_message : str - input_count : int - # Websockets - input_signing_region : str - # Cognito - input_cognito_identity : str - # Custom auth - input_custom_auth_username : str - input_custom_authorizer_name : str - input_custom_authorizer_signature : str - input_custom_auth_password : str - input_custom_authorizer_token_key_name : str - input_custom_authorizer_token_value : str - # Fleet provisioning - input_template_name : str - input_template_parameters : str - input_csr_path : str - # Services (Shadow, Jobs, Greengrass, etc) - input_thing_name : str - input_mode : str - # Shared Subscription - input_group_identifier : str - # PKCS#11 - input_pkcs11_lib_path : str - input_pkcs11_user_pin : str - input_pkcs11_token_label : str - input_pkcs11_slot_id : int - input_pkcs11_key_label : str - # X509 - input_x509_endpoint : str - input_x509_role : str - input_x509_thing_name : str - input_x509_cert : str - input_x509_key : str - input_x509_ca : str - # Basic discovery - input_max_pub_ops : int - input_print_discovery_resp_only : bool - # Jobs - input_job_time : int - # Shadow - input_shadow_property : str - input_shadow_value : str - input_shadow_name : str - # PKCS12 - input_pkcs12_file : str - input_pkcs12_password : str - # Static credentials - input_session_token : str - input_access_key_id : str - input_secret_access_key : str - - def __init__(self) -> None: - pass - - def parse_input_topic(self, cmdUtils): - self.input_topic = cmdUtils.get_command(CommandLineUtils.m_cmd_topic, "test/topic") - if (cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci) != None): - self.input_topic += "/" + str(uuid4()) - - def parse_sample_input_basic_connect(): - # Parse arguments - cmdUtils = CommandLineUtils("Basic Connect - Make a MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", - "Connection port for direct connection. " + - "AWS IoT supports 443 and 8883 (optional, default=8883).", - False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - # Needs to be called so the command utils parse the commands - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_basic_discovery(): - allowed_actions = ['both', 'publish', 'subscribe'] - - cmdUtils = CommandLineUtils("Basic Discovery - Greengrass discovery example.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.remove_command(CommandLineUtils.m_cmd_endpoint) - cmdUtils.register_command(CommandLineUtils.m_cmd_thing_name, "", "The name assigned to your IoT Thing", required=True) - cmdUtils.register_command( - CommandLineUtils.m_cmd_mode, "", - f"The operation mode (optional, default='both').\nModes:{allowed_actions}", default='both') - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", "The region to connect through.", required=True) - cmdUtils.register_command( - CommandLineUtils.m_cmd_max_pub_ops, "", - "The maximum number of publish operations (optional, default='10').", - default=10, type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_print_discovery_resp_only, "", "(optional, default='False').", - default=False, type=bool, action="store_true") - cmdUtils.add_common_proxy_commands() - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.parse_input_topic(cmdUtils) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_thing_name) - cmdData.input_mode = cmdUtils.get_command(CommandLineUtils.m_cmd_mode, "both") - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_region, CommandLineUtils.m_cmd_signing_region) - cmdData.input_max_pub_ops = int(cmdUtils.get_command(CommandLineUtils.m_cmd_max_pub_ops, 10)) - cmdData.input_print_discovery_resp_only = bool(cmdUtils.get_command(CommandLineUtils.m_cmd_print_discovery_resp_only, False)) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_cognito_connect(): - cmdUtils = CommandLineUtils("Cognito Connect - Make a Cognito MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_signing_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_cognito_identity, "", - "The Cognito identity ID to use to connect via Cognito", - True, str) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_signing_region, CommandLineUtils.m_cmd_region) - cmdData.input_cognito_identity = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cognito_identity) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_custom_authorizer_connect(): - cmdUtils = CommandLineUtils( - "Custom Authorizer Connect - Make a MQTT connection using a custom authorizer.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_custom_authorizer_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_custom_authorizer_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_name) - cmdData.input_custom_authorizer_signature = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_signature) - cmdData.input_custom_auth_password = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_password) - cmdData.input_custom_auth_username = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_username) - cmdData.input_custom_authorizer_token_key_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_key_name) - cmdData.input_custom_authorizer_token_value = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_value) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_static_credentials_connect(): - cmdUtils = CommandLineUtils( - "Static Credentials Connect - Make a MQTT connection using Static Credentials.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_session_token, "", "", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_access_key_id, "", "", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_secret_access_key, "", "") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_session_token = cmdUtils.get_command(CommandLineUtils.m_cmd_session_token) - cmdData.input_access_key_id = cmdUtils.get_command(CommandLineUtils.m_cmd_access_key_id) - cmdData.input_secret_access_key = cmdUtils.get_command(CommandLineUtils.m_secret_access_key) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_fleet_provisioning(): - cmdUtils = CommandLineUtils("Fleet Provisioning - Provision device using either the keys or CSR.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_csr, "", "Path to CSR in Pem format (optional).") - cmdUtils.register_command(CommandLineUtils.m_cmd_template_name, "", "The name of your provisioning template.") - cmdUtils.register_command(CommandLineUtils.m_cmd_template_parameters, "", "Template parameters json.") - cmdUtils.register_command(CommandLineUtils.m_cmd_mqtt_version, "", "MQTT Version") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_csr_path = cmdUtils.get_command(CommandLineUtils.m_cmd_csr, None) - cmdData.input_template_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_template_name) - cmdData.input_template_parameters = cmdUtils.get_command_required(CommandLineUtils.m_cmd_template_parameters) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - cmdData.input_mqtt_version = int(cmdUtils.get_command(CommandLineUtils.m_cmd_mqtt_version, 5)) - return cmdData - - def parse_sample_input_jobs(): - cmdUtils = CommandLineUtils("Jobs - Receive and execute operations on the device.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_thing_name, "", "The name assigned to your IoT Thing", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_job_time, "", "Emulate working on a job by sleeping this many seconds (optional, default='5')", default=5, type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_mqtt_version, "", "mqtt version (optional, default='5')", default=5, type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_thing_name) - cmdData.input_job_time = int(cmdUtils.get_command(CommandLineUtils.m_cmd_job_time, 5)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - cmdData.input_mqtt_version = int(cmdUtils.get_command(CommandLineUtils.m_cmd_mqtt_version, 5)) - return cmdData - - def parse_sample_input_mqtt5_custom_authorizer_connect(): - cmdUtils = CommandLineUtils( - "Custom Authorizer Connect - Make a MQTT5 Client connection using a custom authorizer.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_custom_authorizer_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_use_websockets, "", "If set, websockets will be used (optional, do not set to use direct MQTT)") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_custom_authorizer_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_name) - cmdData.input_custom_authorizer_signature = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_authorizer_signature) - cmdData.input_custom_auth_password = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_password) - cmdData.input_custom_auth_username = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_username) - cmdData.input_custom_authorizer_token_key_name = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_key_name) - cmdData.input_custom_authorizer_token_value = cmdUtils.get_command(CommandLineUtils.m_cmd_custom_auth_token_value) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_use_websockets = bool(cmdUtils.get_command(CommandLineUtils.m_cmd_use_websockets, False)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_mqtt5_pkcs11_connect(): - cmdUtils = CommandLineUtils("MQTT5 PKCS11 Connect - Make a MQTT5 Client connection using PKCS11.") - cmdUtils.add_common_mqtt5_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to your client certificate in PEM format.", True, str) - cmdUtils.register_command( - CommandLineUtils.m_cmd_port, - "", - "Connection port. AWS IoT supports 433 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_client_id, - "", - "Client ID to use for MQTT5 connection (optional, default=None).", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_lib, "", "Path to PKCS#11 Library", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_pin, "", "User PIN for logging into PKCS#11 token.", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_token, "", "Label of the PKCS#11 token to use (optional).") - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_slot, "", "Slot ID containing the PKCS#11 token to use (optional).", False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_key, "", "Label of private key on the PKCS#11 token (optional).") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_pkcs11_lib_path = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_lib) - cmdData.input_pkcs11_user_pin = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_pin) - cmdData.input_pkcs11_token_label = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_token) - cmdData.input_pkcs11_slot_id = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_slot, None) - cmdData.input_pkcs11_key_label = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_key, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_mqtt5_pubsub(): - cmdUtils = CommandLineUtils("PubSub - Send and receive messages through an MQTT5 connection.") - cmdUtils.add_common_mqtt5_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command( - CommandLineUtils.m_cmd_port, - "", - "Connection port. AWS IoT supports 433 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_client_id, - "", - "Client ID to use for MQTT5 connection (optional, default=None).", - default="test-" + str(uuid4())) - cmdUtils.register_command( - CommandLineUtils.m_cmd_count, - "", - "The number of messages to send (optional, default='10').", - default=10, - type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.parse_input_topic(cmdUtils) - cmdData.input_count = int(cmdUtils.get_command(CommandLineUtils.m_cmd_count, 10)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_mqtt5_shared_subscription(): - cmdUtils = CommandLineUtils("SharedSubscription - Send and receive messages through a MQTT5 shared subscription") - cmdUtils.add_common_mqtt5_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command( - CommandLineUtils.m_cmd_port, - "", - "Connection port. AWS IoT supports 433 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_client_id, - "", - "Client ID to use for MQTT5 connection (optional, default=None)." - "Note that '1', '2', and '3' will be added for to the given clientIDs since this sample uses 3 clients.", - default="test-" + str(uuid4())) - cmdUtils.register_command( - CommandLineUtils.m_cmd_count, - "", - "The number of messages to send (optional, default='10').", - default=10, - type=int) - cmdUtils.register_command( - CommandLineUtils.m_cmd_group_identifier, - "", - "The group identifier to use in the shared subscription (optional, default='python-sample')", - default="python-sample", - type=str) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.parse_input_topic(cmdUtils) - cmdData.input_count = cmdUtils.get_command(CommandLineUtils.m_cmd_count, 10) - cmdData.input_group_identifier = cmdUtils.get_command(CommandLineUtils.m_cmd_group_identifier, "python-sample") - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_pkcs11_connect(): - cmdUtils = CommandLineUtils("PKCS11 Connect - Make a MQTT connection using PKCS11.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to your client certificate in PEM format.", True, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", - "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", - type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_lib, "", "Path to PKCS#11 Library", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_pin, "", "User PIN for logging into PKCS#11 token.", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_token, "", "Label of the PKCS#11 token to use (optional).") - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_slot, "", "Slot ID containing the PKCS#11 token to use (optional).", False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs11_key, "", "Label of private key on the PKCS#11 token (optional).") - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_pkcs11_lib_path = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_lib) - cmdData.input_pkcs11_user_pin = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_pin) - cmdData.input_pkcs11_token_label = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs11_token) - cmdData.input_pkcs11_slot_id = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_slot, None) - cmdData.input_pkcs11_key_label = cmdUtils.get_command(CommandLineUtils.m_cmd_pkcs11_key, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_pubsub(): - cmdUtils = CommandLineUtils("PubSub - Send and receive messages through an MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_topic_message_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_count, "", "The number of messages to send (optional, default='10').", default=10, type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_message = cmdUtils.get_command(CommandLineUtils.m_cmd_message, "Hello World! ") - cmdData.parse_input_topic(cmdUtils) - cmdData.input_count = int(cmdUtils.get_command(CommandLineUtils.m_cmd_count, 10)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_shadow(): - cmdUtils = CommandLineUtils("Shadow - Keep a property in sync between device and server.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_key_cert_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=8883).", type=int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", "Client ID to use for MQTT connection (optional, default='test-*').", default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_thing_name, "", "The name assigned to your IoT Thing", required=True) - cmdUtils.register_command(CommandLineUtils.m_cmd_shadow_property, "", "The name of the shadow property you want to change (optional, default=''", default="") - cmdUtils.register_command(CommandLineUtils.m_cmd_shadow_value, "", "The desired value of the shadow property you want to set (optional)") - cmdUtils.register_command(CommandLineUtils.m_cmd_shadow_name, "", "Shadow name (optional, default='')", type=str) - cmdUtils.register_command(CommandLineUtils.m_cmd_mqtt_version, "", "mqtt version (optional, default='5')", default=5, type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_key_file) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_thing_name) - cmdData.input_shadow_property = cmdUtils.get_command_required(CommandLineUtils.m_cmd_shadow_property) - cmdData.input_shadow_value = cmdUtils.get_command(CommandLineUtils.m_cmd_shadow_value, None) - cmdData.input_shadow_name = cmdUtils.get_command(CommandLineUtils.m_cmd_shadow_name, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - cmdData.input_mqtt_version = int(cmdUtils.get_command(CommandLineUtils.m_cmd_mqtt_version, 5)) - return cmdData - - def parse_sample_input_websocket_connect(): - cmdUtils = CommandLineUtils("Websocket Connect - Make a websocket MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_signing_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_signing_region, CommandLineUtils.m_cmd_region) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_windows_cert_connect(): - cmdUtils = CommandLineUtils("Windows Cert Connect - Make a MQTT connection using Windows Store Certificates.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.register_command(CommandLineUtils.m_cmd_cert_file, "", "Path to certificate in Windows cert store. " - "e.g. \"CurrentUser\\MY\\6ac133ac58f0a88b83e9c794eba156a98da39b4c\"", True, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", "Connection port. AWS IoT supports 443 and 8883 (optional, default=auto).", type=int) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_cert_file) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_x509_connect(): - cmdUtils = CommandLineUtils("X509 Connect - Make a MQTT connection using X509.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.add_common_x509_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_signing_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_region, "", - "The signing region used for the websocket signer", - False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_signing_region = cmdUtils.get_command_required(CommandLineUtils.m_cmd_signing_region, CommandLineUtils.m_cmd_region) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_x509_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_endpoint) - cmdData.input_x509_thing_name = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_thing_name) - cmdData.input_x509_role = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_role_alias) - cmdData.input_x509_cert = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_cert) - cmdData.input_x509_key = cmdUtils.get_command_required(CommandLineUtils.m_cmd_x509_key) - cmdData.input_x509_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_x509_ca, None) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - def parse_sample_input_pkcs12_connect(): - # Parse arguments - cmdUtils = CommandLineUtils("PKCS12 Connect - Make a MQTT connection.") - cmdUtils.add_common_mqtt_commands() - cmdUtils.add_common_proxy_commands() - cmdUtils.add_common_logging_commands() - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs12_file, "", - "Path to the PKCS12 file to use.", True, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_pkcs12_password, "", - "The password for the PKCS12 file.", False, str) - cmdUtils.register_command(CommandLineUtils.m_cmd_port, "", - "Connection port for direct connection. " + - "AWS IoT supports 443 and 8883 (optional, default=8883).", - False, int) - cmdUtils.register_command(CommandLineUtils.m_cmd_client_id, "", - "Client ID to use for MQTT connection (optional, default='test-*').", - default="test-" + str(uuid4())) - # Needs to be called so the command utils parse the commands - cmdUtils.get_args() - - cmdData = CommandLineUtils.CmdData() - cmdData.input_endpoint = cmdUtils.get_command_required(CommandLineUtils.m_cmd_endpoint) - cmdData.input_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_port, 8883)) - cmdData.input_pkcs12_file = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs12_file) - cmdData.input_pkcs12_password = cmdUtils.get_command_required(CommandLineUtils.m_cmd_pkcs12_password) - cmdData.input_ca = cmdUtils.get_command(CommandLineUtils.m_cmd_ca_file, None) - cmdData.input_clientId = cmdUtils.get_command(CommandLineUtils.m_cmd_client_id, "test-" + str(uuid4())) - cmdData.input_proxy_host = cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_host) - cmdData.input_proxy_port = int(cmdUtils.get_command(CommandLineUtils.m_cmd_proxy_port)) - cmdData.input_is_ci = cmdUtils.get_command(CommandLineUtils.m_cmd_is_ci, None) != None - return cmdData - - - # Constants for commonly used/needed commands - m_cmd_endpoint = "endpoint" - m_cmd_ca_file = "ca_file" - m_cmd_cert_file = "cert" - m_cmd_key_file = "key" - m_cmd_proxy_host = "proxy_host" - m_cmd_proxy_port = "proxy_port" - m_cmd_signing_region = "signing_region" - m_cmd_pkcs11_lib = "pkcs11_lib" - m_cmd_pkcs11_cert = "cert" - m_cmd_pkcs11_pin = "pin" - m_cmd_pkcs11_token = "token_label" - m_cmd_pkcs11_slot = "slot_id" - m_cmd_pkcs11_key = "key_label" - m_cmd_message = "message" - m_cmd_topic = "topic" - m_cmd_verbosity = "verbosity" - m_cmd_custom_auth_username = "custom_auth_username" - m_cmd_custom_auth_authorizer_name = "custom_auth_authorizer_name" - m_cmd_custom_auth_authorizer_signature = "custom_auth_authorizer_signature" - m_cmd_custom_auth_password = "custom_auth_password" - m_cmd_custom_auth_token_key_name = "custom_auth_token_key_name" - m_cmd_custom_auth_token_value = "custom_auth_token_value" - m_cmd_cognito_identity = "cognito_identity" - m_cmd_x509_endpoint = "x509_endpoint" - m_cmd_x509_thing_name = "x509_thing_name" - m_cmd_x509_role_alias = "x509_role_alias" - m_cmd_x509_cert = "x509_cert" - m_cmd_x509_key = "x509_key" - m_cmd_x509_ca = "x509_ca_file" - m_cmd_port = "port" - m_cmd_client_id = "client_id" - m_cmd_is_ci = "is_ci" - m_cmd_thing_name = "thing_name" - m_cmd_mode = "mode" - m_cmd_max_pub_ops = "max_pub_ops" - m_cmd_print_discovery_resp_only = "print_discover_resp_only" - m_cmd_csr = "csr" - m_cmd_template_name = "template_name" - m_cmd_template_parameters = "template_parameters" - m_cmd_job_time = "job_time" - m_cmd_use_websockets = "use_websockets" - m_cmd_count = "count" - m_cmd_group_identifier = "group_identifier" - m_cmd_shadow_property = "shadow_property" - m_cmd_shadow_value = "shadow_value" - m_cmd_shadow_name = "shadow_name" - m_cmd_pkcs12_file = "pkcs12_file" - m_cmd_pkcs12_password = "pkcs12_password" - m_cmd_region = "region" - m_cmd_mqtt_version = "mqtt_version" - m_cmd_session_token = "session_token" - m_cmd_secret_access_key = "secret_access_key" - m_cmd_access_key_id = "access_key_id" From 5805cd7a47b0e554158e4a0028aa6d83b04ea2e1 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 09:53:16 -0700 Subject: [PATCH 33/40] samples-wide factoring start --- samples/basic_discovery.py | 13 ++++++----- samples/fleet_provisioning_basic.py | 9 +++++--- samples/fleet_provisioning_csr.py | 9 +++++--- samples/ipc_greengrass.py | 5 +---- samples/jobs.py | 9 +++++--- samples/mqtt5_custom_authorizer_connect.py | 21 ++++++++++-------- samples/mqtt5_pkcs11_connect.py | 25 ++++++++++++---------- samples/mqtt5_pubsub.py | 16 ++++++++------ samples/mqtt5_shared_subscription.py | 21 +++++++++--------- samples/shadow.py | 10 +++++---- 10 files changed, 78 insertions(+), 60 deletions(-) diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py index f9bca36e..466e6c0e 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -1,11 +1,11 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -import time, json -from awscrt import io, http -from awscrt.mqtt import QoS from awsiot.greengrass_discovery import DiscoveryClient from awsiot import mqtt_connection_builder +from awscrt import io, http +from awscrt.mqtt import QoS +import time, json allowed_actions = ['both', 'publish', 'subscribe'] @@ -14,10 +14,11 @@ def parse_sample_input(): parser = argparse.ArgumentParser( - description="Greengrass basic discovery", + description="Greengrass Basic Discovery", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) + # Connection / TLS parser.add_argument("--cert", required=True, dest="input_cert", help="Path to the certificate file to use during mTLS connection establishment") parser.add_argument("--key", required=True, dest="input_key", @@ -36,7 +37,7 @@ def parse_sample_input(): parser.add_argument("--mode", default='both', dest="input_mode", help=f"The operation mode (optional, default='both').\nModes:{allowed_actions}") - # Proxy (optional) + # Proxy parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") @@ -46,10 +47,12 @@ def parse_sample_input(): return parser.parse_args() +# args contains all the parsed commandline arguments used by the sample args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- + tls_options = io.TlsContextOptions.create_client_with_mtls_from_path(args.input_cert, args.input_key) if (args.input_ca is not None): tls_options.override_default_trust_store_from_path(None, args.input_ca) diff --git a/samples/fleet_provisioning_basic.py b/samples/fleet_provisioning_basic.py index 9f6b5583..ba240dc5 100644 --- a/samples/fleet_provisioning_basic.py +++ b/samples/fleet_provisioning_basic.py @@ -1,12 +1,15 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -from awscrt import mqtt5, mqtt_request_response from awsiot import iotidentity, mqtt5_client_builder +from awscrt import mqtt5, mqtt_request_response from concurrent.futures import Future +import json, uuid + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse -import json -import uuid + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- if __name__ == '__main__': diff --git a/samples/fleet_provisioning_csr.py b/samples/fleet_provisioning_csr.py index 6c1e98e9..a4d61a75 100644 --- a/samples/fleet_provisioning_csr.py +++ b/samples/fleet_provisioning_csr.py @@ -1,12 +1,15 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -from awscrt import mqtt5, mqtt_request_response from awsiot import iotidentity, mqtt5_client_builder +from awscrt import mqtt5, mqtt_request_response from concurrent.futures import Future +import json, uuid + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse -import json -import uuid + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- if __name__ == '__main__': diff --git a/samples/ipc_greengrass.py b/samples/ipc_greengrass.py index 92db3bd0..679a907f 100644 --- a/samples/ipc_greengrass.py +++ b/samples/ipc_greengrass.py @@ -19,10 +19,7 @@ """ -import json -import time -import os -import sys +import json, time, os, sys import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.model as model diff --git a/samples/jobs.py b/samples/jobs.py index 0516a5e9..935778a2 100644 --- a/samples/jobs.py +++ b/samples/jobs.py @@ -1,15 +1,18 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -from awscrt import mqtt5, mqtt_request_response from awsiot import iotjobs, mqtt5_client_builder +from awscrt import mqtt5, mqtt_request_response import boto3 from concurrent.futures import Future from dataclasses import dataclass from typing import Optional -import awsiot +import awsiot, sys + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse -import sys + +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- @dataclass diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 41bd584b..9d313a62 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -1,18 +1,27 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +from awsiot import mqtt5_client_builder +from awscrt import mqtt5 +from concurrent.futures import Future + # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="MQTT5 Custom Authorizer Sample.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) + # Connection parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") - parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") + parser.add_argument("--use_websockets", dest="input_use_websockets", + action="store_const", const=True, default=None, + help="Use WebSockets instead of direct TLS") + # Custom Auth parser.add_argument("--custom_auth_username", dest="input_custom_auth_username", help="The name to send when connecting through the custom authorizer (optional)") parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_authorizer_name", @@ -25,10 +34,6 @@ def parse_sample_input(): help="Key used to extract the custom authorizer token (optional)") parser.add_argument("--custom_auth_token_value", dest="input_custom_authorizer_token_value", help="The opaque token value for the custom authorizer (optional)") - - parser.add_argument("--use_websockets", dest="input_use_websockets", - action="store_const", const=True, default=None, - help="Use WebSockets instead of direct TLS") # Misc parser.add_argument("--client-id", dest="input_clientId", @@ -47,13 +52,11 @@ def parse_sample_input(): return args +# args contains all the parsed commandline arguments used by the sample args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- -from awsiot import mqtt5_client_builder -from awscrt import mqtt5 -from concurrent.futures import Future TIMEOUT = 100 diff --git a/samples/mqtt5_pkcs11_connect.py b/samples/mqtt5_pkcs11_connect.py index 44c17c34..a388fd3e 100644 --- a/samples/mqtt5_pkcs11_connect.py +++ b/samples/mqtt5_pkcs11_connect.py @@ -1,12 +1,16 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +from awsiot import mqtt5_client_builder +from awscrt import mqtt5, io +from concurrent.futures import Future + # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="MQTT5 PKCS11 Sample.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) @@ -15,7 +19,14 @@ def parse_sample_input(): parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") parser.add_argument("--cert", required=True, dest="input_cert", help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") + + # PKCS11 + parser.add_argument("--pkcs11_lib", required=True, dest="input_pkcs11_lib_path", help="Path to PKCS#11 Library") + parser.add_argument("--pin", required=True, dest="input_pkcs11_user_pin", help="User PIN for logging into PKCS#11 token") + parser.add_argument("--token_label", dest="input_pkcs11_token_label", help="Label of the PKCS#11 token to use (optional).") + parser.add_argument("--slot_id", dest="input_pkcs11_slot_id", help="Slot ID containing the PKCS#11 token to use (optional).") + parser.add_argument("--key_label", dest="input_pkcs11_key_label", help="Label of private key on the PKCS#11 token (optional).") # Messaging parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") @@ -30,22 +41,14 @@ def parse_sample_input(): # Misc parser.add_argument("--client-id", dest="input_clientId", default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") - - parser.add_argument("--pkcs11_lib", required=True, dest="input_pkcs11_lib_path", help="Path to PKCS#11 Library") - parser.add_argument("--pin", required=True, dest="input_pkcs11_user_pin", help="User PIN for logging into PKCS#11 token") - parser.add_argument("--token_label", dest="input_pkcs11_token_label", help="Label of the PKCS#11 token to use (optional).") - parser.add_argument("--slot_id", dest="input_pkcs11_slot_id", help="Slot ID containing the PKCS#11 token to use (optional).") - parser.add_argument("--key_label", dest="input_pkcs11_key_label", help="Label of private key on the PKCS#11 token (optional).") return parser.parse_args() +# args contains all the parsed commandline arguments used by the sample args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- -from awscrt import mqtt5, io -from awsiot import mqtt5_client_builder -from concurrent.futures import Future TIMEOUT = 100 diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index 9dce4411..fd6582a4 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -1,12 +1,17 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +from awsiot import mqtt5_client_builder +from awscrt import mqtt5, http +import threading, time, json +from concurrent.futures import Future + # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="MQTT5 pub/sub Sample (mTLS).", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) @@ -17,7 +22,7 @@ def parse_sample_input(): help="Path to the certificate file to use during mTLS connection establishment") parser.add_argument("--key", required=True, dest="input_key", help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") # Messaging parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") @@ -25,7 +30,7 @@ def parse_sample_input(): parser.add_argument("--count", default=5, dest="input_count", help="Messages to publish (0 = infinite)") - # Proxy (optional) + # Proxy parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") @@ -35,14 +40,11 @@ def parse_sample_input(): return parser.parse_args() +# args contains all the parsed commandline arguments used by the sample args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- -from awsiot import mqtt5_client_builder -from awscrt import mqtt5, http -import threading, time, json -from concurrent.futures import Future TIMEOUT = 100 topic_filter = "test/topic" diff --git a/samples/mqtt5_shared_subscription.py b/samples/mqtt5_shared_subscription.py index 7f511ec0..6c37e989 100644 --- a/samples/mqtt5_shared_subscription.py +++ b/samples/mqtt5_shared_subscription.py @@ -1,12 +1,17 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. +from awsiot import mqtt5_client_builder +from awscrt import mqtt5 +from concurrent.futures import Future +import time, json + # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="MQTT5 Shared Subscription Sample.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) @@ -17,13 +22,15 @@ def parse_sample_input(): help="Path to the certificate file to use during mTLS connection establishment") parser.add_argument("--key", required=True, dest="input_key", help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument("--ca", dest="input_ca", help="Path to optional CA bundle (PEM)") + parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") # Messaging parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") parser.add_argument("--count", default=5, dest="input_count", help="Messages to publish (0 = infinite)") + parser.add_argument("--group_identifier", default="python-sample", dest="input_group_identifier", + help="The group identifier to use in the shared subscription (optional, default='python-sample').") # Proxy (optional) parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") @@ -32,22 +39,14 @@ def parse_sample_input(): # Misc parser.add_argument("--client-id", dest="input_clientId", default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID to use for MQTT5 connection (optional, default=None). Note that '1', '2', and '3' will be added for to the given clientIDs since this sample uses 3 clients.") - - parser.add_argument("--group_identifier", default="python-sample", dest="input_group_identifier", - help="The group identifier to use in the shared subscription (optional, default='python-sample').") return parser.parse_args() +# args contains all the parsed commandline arguments used by the sample args = parse_sample_input() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- -from awscrt import mqtt5 -from awsiot import mqtt5_client_builder -import threading -from concurrent.futures import Future -import time -import json # For the purposes of this sample, we need to associate certain variables with a particular MQTT5 client # and to do so we use this class to hold all the data for a particular client used in the sample. diff --git a/samples/shadow.py b/samples/shadow.py index dfeb89ac..1f507c12 100644 --- a/samples/shadow.py +++ b/samples/shadow.py @@ -1,15 +1,17 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -from awscrt import mqtt5, mqtt_request_response, io from awsiot import iotshadow, mqtt5_client_builder +from awscrt import mqtt5, mqtt_request_response from concurrent.futures import Future from dataclasses import dataclass from typing import Optional -import awsiot +import awsiot, json, sys + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse -import json -import sys +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + @dataclass From f75b65e531e97cd03b53430174f494a43431999a Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 10:09:26 -0700 Subject: [PATCH 34/40] simplify parser --- samples/basic_discovery.py | 64 +++++++++---------- samples/mqtt5_custom_authorizer_connect.py | 72 +++++++++------------- samples/mqtt5_pkcs11_connect.py | 64 +++++++++---------- samples/mqtt5_pubsub.py | 55 ++++++++--------- samples/mqtt5_shared_subscription.py | 59 ++++++++---------- 5 files changed, 135 insertions(+), 179 deletions(-) diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py index 466e6c0e..636de973 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -12,43 +12,37 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid -def parse_sample_input(): - parser = argparse.ArgumentParser( - description="Greengrass Basic Discovery", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - # Connection / TLS - parser.add_argument("--cert", required=True, dest="input_cert", - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument("--key", required=True, dest="input_key", - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") - - # Messaging - parser.add_argument("--topic", default=f"test/topic/{uuid.uuid4().hex[:8]}", dest="input_topic", help="Topic") - parser.add_argument("--message", default="Hello World!", dest="input_message", help="Message payload") - parser.add_argument("--thing_name", required=True, dest="input_thing_name", help="The name assigned to your IoT Thing.") - parser.add_argument("--region", required=True, dest="input_signing_region", help="The region to connect through.") - parser.add_argument("--max_pub_ops", type=int, default=10, dest="input_max_pub_ops", - help="The maximum number of publish operations (optional, default='10').") - parser.add_argument("--print_discover_resp_only", type=bool, default=False, dest="input_print_discovery_resp_only", - help="(optional, default='False').") - parser.add_argument("--mode", default='both', dest="input_mode", - help=f"The operation mode (optional, default='both').\nModes:{allowed_actions}") - - # Proxy - parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") - parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") - - # Misc - parser.add_argument("--client-id", dest="input_clientId", - default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") - - return parser.parse_args() +parser = argparse.ArgumentParser( + description="Greengrass Basic Discovery", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) + +# Connection / TLS +parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") +# Messaging +parser.add_argument("--topic", default=f"test/topic/{uuid.uuid4().hex[:8]}", dest="input_topic", help="Topic") +parser.add_argument("--message", default="Hello World!", dest="input_message", help="Message payload") +parser.add_argument("--thing_name", required=True, dest="input_thing_name", help="The name assigned to your IoT Thing.") +parser.add_argument("--region", required=True, dest="input_signing_region", help="The region to connect through.") +parser.add_argument("--max_pub_ops", type=int, default=10, dest="input_max_pub_ops", + help="The maximum number of publish operations (optional, default='10').") +parser.add_argument("--print_discover_resp_only", type=bool, default=False, dest="input_print_discovery_resp_only", + help="(optional, default='False').") +parser.add_argument("--mode", default='both', dest="input_mode", + help=f"The operation mode (optional, default='both').\nModes:{allowed_actions}") +# Proxy +parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") +parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") +# Misc +parser.add_argument("--client-id", dest="input_clientId", + default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") # args contains all the parsed commandline arguments used by the sample -args = parse_sample_input() +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index 9d313a62..d0251b87 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -8,52 +8,36 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid -def parse_sample_input(): - parser = argparse.ArgumentParser( - description="MQTT5 Custom Authorizer Sample.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - # Connection - parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") - parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") - parser.add_argument("--use_websockets", dest="input_use_websockets", - action="store_const", const=True, default=None, - help="Use WebSockets instead of direct TLS") - - # Custom Auth - parser.add_argument("--custom_auth_username", dest="input_custom_auth_username", - help="The name to send when connecting through the custom authorizer (optional)") - parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_authorizer_name", - help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") - parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_authorizer_signature", - help="The signature to send when connecting through a custom authorizer (optional)") - parser.add_argument("--custom_auth_password", dest="input_custom_auth_password", - help="The password to send when connecting through a custom authorizer (optional)") - parser.add_argument("--custom_auth_token_key_name", dest="input_custom_authorizer_token_key_name", - help="Key used to extract the custom authorizer token (optional)") - parser.add_argument("--custom_auth_token_value", dest="input_custom_authorizer_token_value", - help="The opaque token value for the custom authorizer (optional)") - - # Misc - parser.add_argument("--client-id", dest="input_clientId", - default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") - - args = parser.parse_args() - - # Validate custom-authorizer inputs: - # Either provide --custom-auth-username, OR provide signature + token key + token value. - has_username = bool(args.input_custom_auth_username) - has_token_triplet = all([ - args.input_custom_authorizer_signature, - args.input_custom_authorizer_token_key_name, - args.input_custom_authorizer_token_value, - ]) - - return args + +parser = argparse.ArgumentParser( + description="MQTT5 Custom Authorizer Sample.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) +# Connection +parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") +parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") +parser.add_argument("--use_websockets", dest="input_use_websockets", + action="store_const", const=True, default=None, + help="Use WebSockets instead of direct TLS") +# Custom Auth +parser.add_argument("--custom_auth_username", dest="input_custom_auth_username", + help="The name to send when connecting through the custom authorizer (optional)") +parser.add_argument("--custom_auth_authorizer_name", dest="input_custom_authorizer_name", + help="The name of the custom authorizer to connect to (optional but required for everything but custom domains)") +parser.add_argument("--custom_auth_authorizer_signature", dest="input_custom_authorizer_signature", + help="The signature to send when connecting through a custom authorizer (optional)") +parser.add_argument("--custom_auth_password", dest="input_custom_auth_password", + help="The password to send when connecting through a custom authorizer (optional)") +parser.add_argument("--custom_auth_token_key_name", dest="input_custom_authorizer_token_key_name", + help="Key used to extract the custom authorizer token (optional)") +parser.add_argument("--custom_auth_token_value", dest="input_custom_authorizer_token_value", + help="The opaque token value for the custom authorizer (optional)") +# Misc +parser.add_argument("--client-id", dest="input_clientId", + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") # args contains all the parsed commandline arguments used by the sample -args = parse_sample_input() +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_pkcs11_connect.py b/samples/mqtt5_pkcs11_connect.py index a388fd3e..9acd4583 100644 --- a/samples/mqtt5_pkcs11_connect.py +++ b/samples/mqtt5_pkcs11_connect.py @@ -8,44 +8,36 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid -def parse_sample_input(): - parser = argparse.ArgumentParser( - description="MQTT5 PKCS11 Sample.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - # Connection / TLS - parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") - parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") - parser.add_argument("--cert", required=True, dest="input_cert", - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") - - # PKCS11 - parser.add_argument("--pkcs11_lib", required=True, dest="input_pkcs11_lib_path", help="Path to PKCS#11 Library") - parser.add_argument("--pin", required=True, dest="input_pkcs11_user_pin", help="User PIN for logging into PKCS#11 token") - parser.add_argument("--token_label", dest="input_pkcs11_token_label", help="Label of the PKCS#11 token to use (optional).") - parser.add_argument("--slot_id", dest="input_pkcs11_slot_id", help="Slot ID containing the PKCS#11 token to use (optional).") - parser.add_argument("--key_label", dest="input_pkcs11_key_label", help="Label of private key on the PKCS#11 token (optional).") - - # Messaging - parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") - parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") - parser.add_argument("--count", default=5, dest="input_count", - help="Messages to publish (0 = infinite)") - - # Proxy (optional) - parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") - parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") - - # Misc - parser.add_argument("--client-id", dest="input_clientId", - default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") - - return parser.parse_args() +parser = argparse.ArgumentParser( + description="MQTT5 PKCS11 Sample.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) +# Connection / TLS +parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") +parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") +parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") +# PKCS11 +parser.add_argument("--pkcs11_lib", required=True, dest="input_pkcs11_lib_path", help="Path to PKCS#11 Library") +parser.add_argument("--pin", required=True, dest="input_pkcs11_user_pin", help="User PIN for logging into PKCS#11 token") +parser.add_argument("--token_label", dest="input_pkcs11_token_label", help="Label of the PKCS#11 token to use (optional).") +parser.add_argument("--slot_id", dest="input_pkcs11_slot_id", help="Slot ID containing the PKCS#11 token to use (optional).") +parser.add_argument("--key_label", dest="input_pkcs11_key_label", help="Label of private key on the PKCS#11 token (optional).") +# Messaging +parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") +parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") +parser.add_argument("--count", default=5, dest="input_count", + help="Messages to publish (0 = infinite)") +# Proxy (optional) +parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") +parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") +# Misc +parser.add_argument("--client-id", dest="input_clientId", + default=f"test-{uuid.uuid4().hex[:8]}", help="Client ID") # args contains all the parsed commandline arguments used by the sample -args = parse_sample_input() +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index fd6582a4..b055e20f 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -9,39 +9,32 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid -def parse_sample_input(): - parser = argparse.ArgumentParser( - description="MQTT5 pub/sub Sample (mTLS).", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - # Connection / TLS - parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") - parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") - parser.add_argument("--cert", required=True, dest="input_cert", - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument("--key", required=True, dest="input_key", - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") - - # Messaging - parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") - parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") - parser.add_argument("--count", default=5, dest="input_count", - help="Messages to publish (0 = infinite)") - - # Proxy - parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") - parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") - - # Misc - parser.add_argument("--client-id", dest="input_clientId", - default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") - - return parser.parse_args() +parser = argparse.ArgumentParser( + description="MQTT5 pub/sub Sample (mTLS).", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) +# Connection / TLS +parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") +parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") +parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") +# Messaging +parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") +parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") +parser.add_argument("--count", default=5, dest="input_count", + help="Messages to publish (0 = infinite)") +# Proxy +parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") +parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") +# Misc +parser.add_argument("--client-id", dest="input_clientId", + default=f"mqtt5-sample-{uuid.uuid4().hex[:8]}", help="Client ID") # args contains all the parsed commandline arguments used by the sample -args = parse_sample_input() +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_shared_subscription.py b/samples/mqtt5_shared_subscription.py index 6c37e989..7343141e 100644 --- a/samples/mqtt5_shared_subscription.py +++ b/samples/mqtt5_shared_subscription.py @@ -9,41 +9,34 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid -def parse_sample_input(): - parser = argparse.ArgumentParser( - description="MQTT5 Shared Subscription Sample.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - - # Connection / TLS - parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") - parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") - parser.add_argument("--cert", required=True, dest="input_cert", - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument("--key", required=True, dest="input_key", - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") - - # Messaging - parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") - parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") - parser.add_argument("--count", default=5, dest="input_count", - help="Messages to publish (0 = infinite)") - parser.add_argument("--group_identifier", default="python-sample", dest="input_group_identifier", - help="The group identifier to use in the shared subscription (optional, default='python-sample').") - - # Proxy (optional) - parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") - parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") - - # Misc - parser.add_argument("--client-id", dest="input_clientId", default=f"test-{uuid.uuid4().hex[:8]}", - help="Client ID to use for MQTT5 connection (optional, default=None). Note that '1', '2', and '3' will be added for to the given clientIDs since this sample uses 3 clients.") - - return parser.parse_args() +parser = argparse.ArgumentParser( + description="MQTT5 Shared Subscription Sample.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, +) +# Connection / TLS +parser.add_argument("--endpoint", required=True, dest="input_endpoint", help="IoT endpoint hostname") +parser.add_argument("--port", type=int, default=8883, dest="input_port", help="Port (8883 mTLS, 443 ALPN)") +parser.add_argument("--cert", required=True, dest="input_cert", + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument("--key", required=True, dest="input_key", + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument("--ca_file", dest="input_ca", help="Path to optional CA bundle (PEM)") +# Messaging +parser.add_argument("--topic", default="test/topic", dest="input_topic", help="Topic") +parser.add_argument("--message", default="Hello from mqtt5 sample", dest="input_message", help="Message payload") +parser.add_argument("--count", default=5, dest="input_count", + help="Messages to publish (0 = infinite)") +parser.add_argument("--group_identifier", default="python-sample", dest="input_group_identifier", + help="The group identifier to use in the shared subscription (optional, default='python-sample').") +# Proxy (optional) +parser.add_argument("--proxy-host", dest="input_proxy_host", help="HTTP proxy host") +parser.add_argument("--proxy-port", type=int, default=0, dest="input_proxy_port", help="HTTP proxy port") +# Misc +parser.add_argument("--client-id", dest="input_clientId", default=f"test-{uuid.uuid4().hex[:8]}", + help="Client ID to use for MQTT5 connection (optional, default=None). Note that '1', '2', and '3' will be added for to the given clientIDs since this sample uses 3 clients.") # args contains all the parsed commandline arguments used by the sample -args = parse_sample_input() +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- From 13724e803e30bcf2224d21726bc7621a5544fb6a Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Tue, 19 Aug 2025 10:21:39 -0700 Subject: [PATCH 35/40] further formatting --- samples/basic_discovery.py | 2 -- samples/fleet_provisioning_basic.py | 28 ++++++++++---------- samples/fleet_provisioning_csr.py | 30 ++++++++++------------ samples/jobs.py | 26 +++++++++---------- samples/mqtt5_custom_authorizer_connect.py | 2 -- samples/mqtt5_pkcs11_connect.py | 1 - samples/mqtt5_pubsub.py | 1 - samples/mqtt5_shared_subscription.py | 1 - samples/shadow.py | 24 ++++++++--------- 9 files changed, 51 insertions(+), 64 deletions(-) diff --git a/samples/basic_discovery.py b/samples/basic_discovery.py index 636de973..e38918c9 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -16,7 +16,6 @@ description="Greengrass Basic Discovery", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) - # Connection / TLS parser.add_argument("--cert", required=True, dest="input_cert", help="Path to the certificate file to use during mTLS connection establishment") @@ -43,7 +42,6 @@ # args contains all the parsed commandline arguments used by the sample args = parser.parse_args() - # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/fleet_provisioning_basic.py b/samples/fleet_provisioning_basic.py index ba240dc5..3b777735 100644 --- a/samples/fleet_provisioning_basic.py +++ b/samples/fleet_provisioning_basic.py @@ -9,24 +9,24 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse +parser = argparse.ArgumentParser( + description="AWS IoT Basic Fleet Provisioning sample application") +parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") +parser.add_argument('--cert', required=True, + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument('--key', required=True, + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument('--template_name', required=True, + help="Name of the provisioning template to use") +parser.add_argument('--template_parameters', required=False, + help="JSON map of substitution parameters for the provisioning template") + +# args contains all the parsed commandline arguments used by the sample +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- if __name__ == '__main__': - parser = argparse.ArgumentParser( - description="AWS IoT Basic Fleet Provisioning sample application") - parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") - parser.add_argument('--cert', required=True, - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument('--key', required=True, - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument('--template_name', required=True, - help="Name of the provisioning template to use") - parser.add_argument('--template_parameters', required=False, - help="JSON map of substitution parameters for the provisioning template") - - args = parser.parse_args() - initial_connection_success = Future() def on_lifecycle_connection_success(event: mqtt5.LifecycleConnectSuccessData): initial_connection_success.set_result(True) diff --git a/samples/fleet_provisioning_csr.py b/samples/fleet_provisioning_csr.py index a4d61a75..2402de6b 100644 --- a/samples/fleet_provisioning_csr.py +++ b/samples/fleet_provisioning_csr.py @@ -9,26 +9,24 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse +parser = argparse.ArgumentParser( + description="AWS IoT CSR Fleet Provisioning sample application") +parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") +parser.add_argument('--cert', required=True, + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument('--key', required=True, + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument('--template_name', required=True, + help="Name of the provisioning template to use") +parser.add_argument('--csr_file', required=True, + help="Path to a CSR file in PEM format") +parser.add_argument('--template_parameters', required=False, + help="JSON map of substitution parameters for the provisioning template") +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- if __name__ == '__main__': - parser = argparse.ArgumentParser( - description="AWS IoT CSR Fleet Provisioning sample application") - parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") - parser.add_argument('--cert', required=True, - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument('--key', required=True, - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument('--template_name', required=True, - help="Name of the provisioning template to use") - parser.add_argument('--csr_file', required=True, - help="Path to a CSR file in PEM format") - parser.add_argument('--template_parameters', required=False, - help="JSON map of substitution parameters for the provisioning template") - - args = parser.parse_args() - with open(args.csr_file, "r") as csr_file: csr_data = csr_file.read() diff --git a/samples/jobs.py b/samples/jobs.py index 935778a2..bbbc1382 100644 --- a/samples/jobs.py +++ b/samples/jobs.py @@ -12,6 +12,18 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse +parser = argparse.ArgumentParser( + description="AWS IoT Jobs sandbox application") +parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") +parser.add_argument('--cert', required=True, + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument('--key', required=True, + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument('--thing', required=True, + help="Name of the IoT thing to interact with") +parser.add_argument('--region', required=True, + help="AWS region to use. Must match the endpoint region.") +args = parser.parse_args() # --------------------------------- ARGUMENT PARSING END ----------------------------------------- @@ -113,20 +125,6 @@ def create_thing_if_needed(context: SampleContext): print(f"Thing {context.thing} successfully created with arn {context.thing_arn}") if __name__ == '__main__': - parser = argparse.ArgumentParser( - description="AWS IoT Jobs sandbox application") - parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") - parser.add_argument('--cert', required=True, - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument('--key', required=True, - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument('--thing', required=True, - help="Name of the IoT thing to interact with") - parser.add_argument('--region', required=True, - help="AWS region to use. Must match the endpoint region.") - - args = parser.parse_args() - initial_connection_success = Future() def on_lifecycle_connection_success(event: mqtt5.LifecycleConnectSuccessData): initial_connection_success.set_result(True) diff --git a/samples/mqtt5_custom_authorizer_connect.py b/samples/mqtt5_custom_authorizer_connect.py index d0251b87..f07742d3 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -8,7 +8,6 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse, uuid - parser = argparse.ArgumentParser( description="MQTT5 Custom Authorizer Sample.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, @@ -38,7 +37,6 @@ # args contains all the parsed commandline arguments used by the sample args = parser.parse_args() - # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_pkcs11_connect.py b/samples/mqtt5_pkcs11_connect.py index 9acd4583..6f714b71 100644 --- a/samples/mqtt5_pkcs11_connect.py +++ b/samples/mqtt5_pkcs11_connect.py @@ -38,7 +38,6 @@ # args contains all the parsed commandline arguments used by the sample args = parser.parse_args() - # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index b055e20f..f0e6df8b 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -35,7 +35,6 @@ # args contains all the parsed commandline arguments used by the sample args = parser.parse_args() - # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/mqtt5_shared_subscription.py b/samples/mqtt5_shared_subscription.py index 7343141e..c89bda5c 100644 --- a/samples/mqtt5_shared_subscription.py +++ b/samples/mqtt5_shared_subscription.py @@ -37,7 +37,6 @@ # args contains all the parsed commandline arguments used by the sample args = parser.parse_args() - # --------------------------------- ARGUMENT PARSING END ----------------------------------------- diff --git a/samples/shadow.py b/samples/shadow.py index 1f507c12..a6d7c9b9 100644 --- a/samples/shadow.py +++ b/samples/shadow.py @@ -10,8 +10,18 @@ # --------------------------------- ARGUMENT PARSING ----------------------------------------- import argparse -# --------------------------------- ARGUMENT PARSING END ----------------------------------------- +parser = argparse.ArgumentParser( + description="AWS IoT Shadow sandbox application") +parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") +parser.add_argument('--cert', required=True, + help="Path to the certificate file to use during mTLS connection establishment") +parser.add_argument('--key', required=True, + help="Path to the private key file to use during mTLS connection establishment") +parser.add_argument('--thing', required=True, + help="Name of the IoT thing to interact with") +args = parser.parse_args() +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- @dataclass @@ -76,18 +86,6 @@ def handle_input(context : SampleContext, line: str): return False if __name__ == '__main__': - parser = argparse.ArgumentParser( - description="AWS IoT Shadow sandbox application") - parser.add_argument('--endpoint', required=True, help="AWS IoT endpoint to connect to") - parser.add_argument('--cert', required=True, - help="Path to the certificate file to use during mTLS connection establishment") - parser.add_argument('--key', required=True, - help="Path to the private key file to use during mTLS connection establishment") - parser.add_argument('--thing', required=True, - help="Name of the IoT thing to interact with") - - args = parser.parse_args() - initial_connection_success = Future() def on_lifecycle_connection_success(event: mqtt5.LifecycleConnectSuccessData): initial_connection_success.set_result(True) From 575774c0ec43a4ccdb58586b035359346a49786b Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Wed, 27 Aug 2025 09:25:17 -0700 Subject: [PATCH 36/40] update README and FAQ --- .github/workflows/ci.yml | 2 +- documents/FAQ.md | 4 ++++ samples/README.md | 10 ---------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77da4384..cdc43a5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,7 +190,7 @@ jobs: permissions: id-token: write # This is required for requesting the JWT steps: - - name: Running samples in CI setup + - name: CI setup run: | python3 -m pip install boto3 sudo apt-get update -y diff --git a/documents/FAQ.md b/documents/FAQ.md index 94bbcf27..9886ef21 100644 --- a/documents/FAQ.md +++ b/documents/FAQ.md @@ -8,6 +8,7 @@ * [I am experiencing deadlocks](#i-am-experiencing-deadlocks) * [How do debug in VSCode?](#how-do-debug-in-vscode) * [What certificates do I need?](#what-certificates-do-i-need) +* [Where can I find MQTT 311 Samples?](#where-can-i-find-mqtt-311-samples) * [I still have more questions about this sdk?](#i-still-have-more-questions-about-this-sdk) ### Where should I start? @@ -126,6 +127,9 @@ Here is an example launch.json file to run the pubsub sample * You should have generated/downloaded private and public keys that will be used to verify that communications are coming from you * When using samples you only need the private key and it will look like this: `--key abcde12345-private.pem.key` +### Where can I find MQTT 311 Samples? +The MQTT 311 Samples can be found in the v1.24.0 samples folder [here](https://github.com/aws/aws-iot-device-sdk-python-v2/tree/v1.24.0/samples) + ### I still have more questions about this sdk? * [Here](https://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html) are the AWS IoT Core docs for more details about IoT Core diff --git a/samples/README.md b/samples/README.md index 4758b875..d7c63b55 100644 --- a/samples/README.md +++ b/samples/README.md @@ -9,16 +9,6 @@ * [MQTT5 Shared Subscription](./mqtt5_shared_subscription.md) * [MQTT5 PKCS#11 Connect](./mqtt5_pkcs11_connect.md) * [MQTT5 Custom Authorizer Connect](./mqtt5_custom_authorizer_connect.md) -## MQTT311 Samples -* [PubSub](./pubsub.md) -* [Basic Connect](./basic_connect.md) -* [Websocket Connect](./websocket_connect.md) -* [PKCS#11 Connect](./pkcs11_connect.md) -* [PKCS#12 Connect](./pkcs12_connect.md) -* [Windows Certificate Connect](./windows_cert_connect/README.md) -* [Custom Authorizer Connect](./custom_authorizer_connect.md) -* [Cognito Connect](./cognito_connect.md) -* [X509 Connect](./x509_connect.md) ## Other * [Basic Fleet Provisioning](./fleet_provisioning_basic.md) * [CSR Fleet Provisioning](./fleet_provisioning_csr.md) From edf254e2f23d24491d6f30e790554c945dba55e5 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Wed, 27 Aug 2025 13:30:46 -0700 Subject: [PATCH 37/40] PR fixes --- .github/workflows/ci.yml | 2 +- samples/basic_discovery.md | 6 +++--- servicetests/tests/FleetProvisioning/fleet_provisioning.py | 6 +----- servicetests/tests/JobsExecution/jobs.py | 2 +- servicetests/tests/ShadowUpdate/shadow_update.py | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cdc43a5c..44fac85d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -184,7 +184,7 @@ jobs: cd ./aws-iot-device-sdk-python-v2 python3 ./deviceadvisor/script/DATestRun.py - # Runs the sampels and service tests and ensures that everything is working + # Runs the samples and service tests and ensures that everything is working linux-smoke-tests: runs-on: ubuntu-22.04 permissions: diff --git a/samples/basic_discovery.md b/samples/basic_discovery.md index 503d79d6..e8363ee7 100644 --- a/samples/basic_discovery.md +++ b/samples/basic_discovery.md @@ -5,6 +5,6 @@ This sample is intended for use with the following tutorials in the AWS IoT Greengrass documentation: -* [Connect and test client devices](https://docs.aws.amazon.com/greengrass/v2/developerguide/client-devices-tutorial.html) (Greengrass V2) -* [Test client device communications](https://docs.aws.amazon.com/greengrass/v2/developerguide/test-client-device-communications.html) (Greengrass V2) -* [Getting Started with AWS IoT Greengrass](https://docs.aws.amazon.com/greengrass/latest/developerguide/gg-gs.html) (Greengrass V1) \ No newline at end of file +* [Connect and test client devices](https://docs.aws.amazon.com/greengrass/v2/developerguide/client-devices-tutorial.html) +* [Test client device communications](https://docs.aws.amazon.com/greengrass/v2/developerguide/test-client-device-communications.html) +* [Getting Started with AWS IoT Greengrass](https://docs.aws.amazon.com/greengrass/latest/developerguide/gg-gs.html) \ No newline at end of file diff --git a/servicetests/tests/FleetProvisioning/fleet_provisioning.py b/servicetests/tests/FleetProvisioning/fleet_provisioning.py index c5b33d90..045b022e 100644 --- a/servicetests/tests/FleetProvisioning/fleet_provisioning.py +++ b/servicetests/tests/FleetProvisioning/fleet_provisioning.py @@ -25,7 +25,7 @@ def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="Fleet Provisioning - Provision device using either the keys or CSR.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) @@ -56,10 +56,6 @@ def parse_sample_input(): # --------------------------------- ARGUMENT PARSING END ----------------------------------------- -# [--csr ] -# [--template_name ] -# [--template_parameters ] - # MQTT5 specific mqtt5_client = None future_connection_success = Future() diff --git a/servicetests/tests/JobsExecution/jobs.py b/servicetests/tests/JobsExecution/jobs.py index 71b59a02..8f0f2a8a 100644 --- a/servicetests/tests/JobsExecution/jobs.py +++ b/servicetests/tests/JobsExecution/jobs.py @@ -38,7 +38,7 @@ def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="Jobs - Receive and execute operations on the device.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) diff --git a/servicetests/tests/ShadowUpdate/shadow_update.py b/servicetests/tests/ShadowUpdate/shadow_update.py index 16bc79a8..af079ccc 100644 --- a/servicetests/tests/ShadowUpdate/shadow_update.py +++ b/servicetests/tests/ShadowUpdate/shadow_update.py @@ -29,7 +29,7 @@ def parse_sample_input(): parser = argparse.ArgumentParser( - description="MQTT5 pub/sub sample (mTLS).", + description="Shadow - Keep a property in sync between device and server.", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) From 353908a04aac757cf0d3c1b2e992e3003fb1bb0b Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Wed, 27 Aug 2025 13:32:00 -0700 Subject: [PATCH 38/40] try removing ci_run_greengrass_discovery_cfg to check if it's running --- .../ci_run_greengrass_discovery_cfg.json | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 .github/workflows/ci_run_greengrass_discovery_cfg.json diff --git a/.github/workflows/ci_run_greengrass_discovery_cfg.json b/.github/workflows/ci_run_greengrass_discovery_cfg.json deleted file mode 100644 index 34c389ce..00000000 --- a/.github/workflows/ci_run_greengrass_discovery_cfg.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "language": "Python", - "runnable_file": "basic_discovery.py", - "runnable_region": "us-east-1", - "runnable_main_class": "", - "arguments": [ - { - "name": "--cert", - "secret": "ci/GreengrassDiscovery/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/GreengrassDiscovery/key", - "filename": "tmp_key.pem" - }, - { - "name": "--thing_name", - "data": "CI_Greengrass_Discovery_Thing" - }, - { - "name": "--region", - "data": "us-east-1" - }, - { - "name": "--topic", - "data": "clients/CI_Greengrass_Discovery_Thing/hello/world/$INPUT_UUID" - }, - { - "name": "--mode", - "data": "publish" - } - ] -} From 1d0fa5b5df141bf59fbe8354e0e1c993043e342f Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Wed, 27 Aug 2025 13:44:09 -0700 Subject: [PATCH 39/40] restore ci_run_greengrass_ipc_cfg --- .../ci_run_greengrass_discovery_cfg.json | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/ci_run_greengrass_discovery_cfg.json diff --git a/.github/workflows/ci_run_greengrass_discovery_cfg.json b/.github/workflows/ci_run_greengrass_discovery_cfg.json new file mode 100644 index 00000000..34c389ce --- /dev/null +++ b/.github/workflows/ci_run_greengrass_discovery_cfg.json @@ -0,0 +1,34 @@ +{ + "language": "Python", + "runnable_file": "basic_discovery.py", + "runnable_region": "us-east-1", + "runnable_main_class": "", + "arguments": [ + { + "name": "--cert", + "secret": "ci/GreengrassDiscovery/cert", + "filename": "tmp_certificate.pem" + }, + { + "name": "--key", + "secret": "ci/GreengrassDiscovery/key", + "filename": "tmp_key.pem" + }, + { + "name": "--thing_name", + "data": "CI_Greengrass_Discovery_Thing" + }, + { + "name": "--region", + "data": "us-east-1" + }, + { + "name": "--topic", + "data": "clients/CI_Greengrass_Discovery_Thing/hello/world/$INPUT_UUID" + }, + { + "name": "--mode", + "data": "publish" + } + ] +} From ea9e2d9b7c2d55a0018b305ce715463b82239ad4 Mon Sep 17 00:00:00 2001 From: Steve Kim Date: Thu, 28 Aug 2025 09:51:50 -0700 Subject: [PATCH 40/40] be holistic and also remove mqtt5 samples from ci --- .github/workflows/ci.yml | 33 ---------------- .../ci_run_mqtt5_custom_authorizer_cfg.json | 20 ---------- ...qtt5_custom_authorizer_websockets_cfg.json | 24 ------------ .../ci_run_mqtt5_pkcs11_connect_cfg.json | 39 ------------------- .../workflows/ci_run_mqtt5_pubsub_cfg.json | 22 ----------- .../ci_run_mqtt5_shared_subscription_cfg.json | 22 ----------- 6 files changed, 160 deletions(-) delete mode 100644 .github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_pubsub_cfg.json delete mode 100644 .github/workflows/ci_run_mqtt5_shared_subscription_cfg.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44fac85d..eb188a03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,9 +63,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: run MQTT5 PubSub sample - run: | - python ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pubsub_cfg.json - name: configure AWS credentials (Device Advisor) uses: aws-actions/configure-aws-credentials@v4 with: @@ -122,10 +119,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: run MQTT5 PubSub sample - run: | - source .venv/bin/activate - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pubsub_cfg.json - name: configure AWS credentials (Device Advisor) uses: aws-actions/configure-aws-credentials@v4 with: @@ -171,9 +164,6 @@ jobs: python3 -m unittest test.test_identity source utils/test_cleanup.sh cd .. - - name: run MQTT5 PubSub sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pubsub_cfg.json - name: configure AWS credentials (Device Advisor) uses: aws-actions/configure-aws-credentials@v4 with: @@ -271,29 +261,6 @@ jobs: run: | export PYTHONPATH=${{ github.workspace }}/aws-iot-device-sdk-python-v2/utils:${{ github.workspace }}/aws-iot-device-sdk-python-v2/samples python3 ./test_cases/test_jobs_execution.py --config-file test_cases/mqtt5_jobs_cfg.json - - name: configure AWS credentials (MQTT5 samples) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ env.CI_MQTT5_ROLE }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: run MQTT5 PubSub sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pubsub_cfg.json - - name: run MQTT5 PKCS11 Connect sample - run: | - mkdir -p /tmp/mqtt5/tokens - export SOFTHSM2_CONF=/tmp/softhsm2.conf - echo "directories.tokendir = /tmp/mqtt5/tokens" > /tmp/softhsm2.conf - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_pkcs11_connect_cfg.json - - name: run MQTT5 CustomAuthorizerConnect sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_custom_authorizer_cfg.json - - name: run MQTT5 CustomAuthorizerConnect sample (websockets) - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_custom_authorizer_websockets_cfg.json - - name: run MQTT5 Shared Subscription sample - run: | - python3 ${{ env.CI_UTILS_FOLDER }}/run_sample_ci.py --file ${{ env.CI_SAMPLES_CFG_FOLDER }}/ci_run_mqtt5_shared_subscription_cfg.json linux-greengrass-tests: runs-on: ubuntu-22.04 diff --git a/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json b/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json deleted file mode 100644 index f3608180..00000000 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/mqtt5_custom_authorizer_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--custom_auth_authorizer_name", - "secret": "ci/CustomAuthorizer/name" - }, - { - "name": "--custom_auth_password", - "secret": "ci/CustomAuthorizer/password" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json b/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json deleted file mode 100644 index 55cbdac9..00000000 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/mqtt5_custom_authorizer_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--custom_auth_authorizer_name", - "secret": "ci/CustomAuthorizer/name" - }, - { - "name": "--custom_auth_password", - "secret": "ci/CustomAuthorizer/password" - }, - { - "name": "--use_websockets", - "data": "" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json b/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json deleted file mode 100644 index a8aaa3d9..00000000 --- a/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/mqtt5_pkcs11_connect.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/PubSub/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/PubSub/keyp8", - "filename": "tmp_key.pem", - "pkcs11_key": "true" - }, - { - "name": "--pkcs11_lib", - "data": "/usr/lib/softhsm/libsofthsm2.so" - }, - { - "name": "--pin", - "data": "0000" - }, - { - "name": "--token_label", - "data": "my-token" - }, - { - "name": "--key_label", - "data": "my-key" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_pubsub_cfg.json b/.github/workflows/ci_run_mqtt5_pubsub_cfg.json deleted file mode 100644 index 28410e29..00000000 --- a/.github/workflows/ci_run_mqtt5_pubsub_cfg.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/mqtt5_pubsub.py", - "sample_region": "us-east-1", - "sample_main_class": "mqtt5.pubsub.PubSub", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/mqtt5/us/mqtt5_thing/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/mqtt5/us/mqtt5_thing/key", - "filename": "tmp_key.pem" - } - ] -} diff --git a/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json b/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json deleted file mode 100644 index 8c0866e5..00000000 --- a/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "language": "Python", - "sample_file": "./aws-iot-device-sdk-python-v2/samples/mqtt5_shared_subscription.py", - "sample_region": "us-east-1", - "sample_main_class": "", - "arguments": [ - { - "name": "--endpoint", - "secret": "ci/endpoint" - }, - { - "name": "--cert", - "secret": "ci/mqtt5/us/mqtt5_thing/cert", - "filename": "tmp_certificate.pem" - }, - { - "name": "--key", - "secret": "ci/mqtt5/us/mqtt5_thing/key", - "filename": "tmp_key.pem" - } - ] -}