diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c1060e1..eb188a03 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: @@ -57,7 +48,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,25 +63,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 - name: configure AWS credentials (Device Advisor) uses: aws-actions/configure-aws-credentials@v4 with: @@ -113,8 +85,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 @@ -147,32 +119,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: | - 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 - 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 - 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: @@ -218,22 +164,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: - 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: configure AWS credentials (Device Advisor) uses: aws-actions/configure-aws-credentials@v4 with: @@ -244,13 +174,13 @@ jobs: cd ./aws-iot-device-sdk-python-v2 python3 ./deviceadvisor/script/DATestRun.py - # Runs the samples 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: 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 @@ -266,7 +196,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: @@ -292,7 +221,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: @@ -318,7 +246,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: @@ -335,113 +262,6 @@ jobs: 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 - - 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 - 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: - 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 - - 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 - - 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 permissions: @@ -501,7 +321,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/.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_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_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_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_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_custom_authorizer_cfg.json b/.github/workflows/ci_run_mqtt5_custom_authorizer_cfg.json deleted file mode 100644 index 1325b5a6..00000000 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_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": "--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 deleted file mode 100644 index 90bd08e8..00000000 --- a/.github/workflows/ci_run_mqtt5_custom_authorizer_websockets_cfg.json +++ /dev/null @@ -1,28 +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": "true" - }, - { - "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_pkcs11_connect_cfg.json b/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json deleted file mode 100644 index 4470facc..00000000 --- a/.github/workflows/ci_run_mqtt5_pkcs11_connect_cfg.json +++ /dev/null @@ -1,43 +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" - }, - { - "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 deleted file mode 100644 index 366f2da1..00000000 --- a/.github/workflows/ci_run_mqtt5_pubsub_cfg.json +++ /dev/null @@ -1,26 +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" - }, - { - "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_mqtt5_shared_subscription_cfg.json b/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json deleted file mode 100644 index b6234a7c..00000000 --- a/.github/workflows/ci_run_mqtt5_shared_subscription_cfg.json +++ /dev/null @@ -1,26 +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" - }, - { - "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_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/.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_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" - } - ] -} 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_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/.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/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/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/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/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 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) 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 index d45d51ac..e8363ee7 100644 --- a/samples/basic_discovery.md +++ b/samples/basic_discovery.md @@ -1,9 +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) +* [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/samples/basic_discovery.py b/samples/basic_discovery.py index 269f0ad5..e38918c9 100644 --- a/samples/basic_discovery.py +++ b/samples/basic_discovery.py @@ -1,48 +1,73 @@ # 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 +from awscrt import io, http +from awscrt.mqtt import QoS +import time, json 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) +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +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 = parser.parse_args() +# --------------------------------- 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) 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 +90,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 +113,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) + time.sleep(1) \ No newline at end of file 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/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" diff --git a/samples/fleet_provisioning_basic.py b/samples/fleet_provisioning_basic.py index 9f6b5583..3b777735 100644 --- a/samples/fleet_provisioning_basic.py +++ b/samples/fleet_provisioning_basic.py @@ -1,29 +1,32 @@ # 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 +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() +if __name__ == '__main__': 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 6c1e98e9..2402de6b 100644 --- a/samples/fleet_provisioning_csr.py +++ b/samples/fleet_provisioning_csr.py @@ -1,31 +1,32 @@ # 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 +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() +if __name__ == '__main__': with open(args.csr_file, "r") as csr_file: csr_data = csr_file.read() 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..bbbc1382 100644 --- a/samples/jobs.py +++ b/samples/jobs.py @@ -1,15 +1,30 @@ # 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 + +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 ----------------------------------------- @dataclass @@ -110,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 91000122..f07742d3 100644 --- a/samples/mqtt5_custom_authorizer_connect.py +++ b/samples/mqtt5_custom_authorizer_connect.py @@ -4,14 +4,43 @@ from awsiot import mqtt5_client_builder from awscrt import mqtt5 from concurrent.futures import Future -from utils.command_line_utils import CommandLineUtils -TIMEOUT = 100 +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +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") -# 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() +# args contains all the parsed commandline arguments used by the sample +args = parser.parse_args() +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + + +TIMEOUT = 100 future_stopped = Future() future_connection_success = Future() @@ -31,38 +60,34 @@ 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) - 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 {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..6f714b71 100644 --- a/samples/mqtt5_pkcs11_connect.py +++ b/samples/mqtt5_pkcs11_connect.py @@ -1,17 +1,47 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -from awscrt import mqtt5, io from awsiot import mqtt5_client_builder +from awscrt import mqtt5, io from concurrent.futures import Future -from utils.command_line_utils import CommandLineUtils -TIMEOUT = 100 +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +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 = parser.parse_args() +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- -# 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() + +TIMEOUT = 100 future_stopped = Future() future_connection_success = Future() @@ -33,37 +63,34 @@ 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}'...") - 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) diff --git a/samples/mqtt5_pubsub.py b/samples/mqtt5_pubsub.py index b5e03964..f0e6df8b 100644 --- a/samples/mqtt5_pubsub.py +++ b/samples/mqtt5_pubsub.py @@ -3,20 +3,44 @@ 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 + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +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 = parser.parse_args() +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + 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() @@ -29,7 +53,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() @@ -55,44 +79,40 @@ 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") - 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:'{args.input_endpoint}' with Client ID:'{args.input_clientId}' with reason_code:{repr(connack_packet.reason_code)}") # Subscribe diff --git a/samples/mqtt5_shared_subscription.py b/samples/mqtt5_shared_subscription.py index fe45d9db..c89bda5c 100644 --- a/samples/mqtt5_shared_subscription.py +++ b/samples/mqtt5_shared_subscription.py @@ -1,13 +1,44 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -from awscrt import mqtt5 from awsiot import mqtt5_client_builder -import threading +from awscrt import mqtt5 from concurrent.futures import Future -import time -import json -from utils.command_line_utils import CommandLineUtils +import time, json + +# --------------------------------- ARGUMENT PARSING ----------------------------------------- +import argparse, uuid + +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 = parser.parse_args() +# --------------------------------- ARGUMENT PARSING END ----------------------------------------- + # 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 +120,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 +155,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 +186,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 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/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!") 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/shadow.py b/samples/shadow.py index dfeb89ac..a6d7c9b9 100644 --- a/samples/shadow.py +++ b/samples/shadow.py @@ -1,15 +1,27 @@ # 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 + +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 @@ -74,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) 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" 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/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!") 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!") diff --git a/servicetests/tests/FleetProvisioning/fleet_provisioning.py b/servicetests/tests/FleetProvisioning/fleet_provisioning.py index b08e0306..045b022e 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,41 @@ # 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 + +def parse_sample_input(): + parser = argparse.ArgumentParser( + description="Fleet Provisioning - Provision device using either the keys or CSR.", + 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 ----------------------------------------- # MQTT5 specific mqtt5_client = None @@ -63,7 +89,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 +260,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 +293,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 +332,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 +370,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 +387,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 +404,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) diff --git a/servicetests/tests/JobsExecution/jobs.py b/servicetests/tests/JobsExecution/jobs.py index 5801922e..8f0f2a8a 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="Jobs - Receive and execute operations on the device.", + 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..af079ccc 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="Shadow - Keep a property in sync between device and server.", + 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() 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, 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": 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)