Skip to content

Commit e56d3e8

Browse files
Pub sub sample split (#296)
Splits the PubSub sample down into smaller connect samples that show how just how to make a connection. * Simplified command line parsing * Fixed tests not working correctly after simplified command line parsing * Added action support to command line parser * Added additional command groups * Split PubSub sample into smaller connect samples * Fixed codebuild tests to work with sample split * Adjusted code based on code review: * Added PubSub sample back to codebuild tests * Simplified connection samples by using utility functions in command_line_utils * Removed PKCS11 PubSub sample (since it's replaced by PKCS11 connect sample) * Added PKCS11 connection builder function to command_line_utils * Converted Windows Cert PubSub to Windows Cert Connect * Adjusted README to use consistent command format * Fixed diff being included in fleet provision sample
1 parent d5480f1 commit e56d3e8

17 files changed

+661
-539
lines changed

codebuild/.DS_Store

6 KB
Binary file not shown.

codebuild/samples/connect-linux.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
env
6+
7+
pushd $CODEBUILD_SRC_DIR/samples/
8+
9+
ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
10+
11+
echo "Mqtt Direct test"
12+
python3 basic_connect.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem
13+
14+
echo "Websocket test"
15+
python3 websocket_connect.py --endpoint $ENDPOINT --signing_region us-east-1
16+
17+
popd

codebuild/samples/linux-smoke-tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ phases:
99
commands:
1010
- echo Build started on `date`
1111
- $CODEBUILD_SRC_DIR/codebuild/samples/setup-linux.sh
12+
- $CODEBUILD_SRC_DIR/codebuild/samples/connect-linux.sh
1213
- $CODEBUILD_SRC_DIR/codebuild/samples/pubsub-linux.sh
1314
post_build:
1415
commands:
15-
- echo Build completed on `date`
16+
- echo Build completed on `date`

codebuild/samples/pubsub-linux.sh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ pushd $CODEBUILD_SRC_DIR/samples/
88

99
ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
1010

11-
echo "Mqtt Direct test"
11+
echo "PubSub test"
1212
python3 pubsub.py --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem
1313

14-
echo "Websocket test"
15-
python3 pubsub.py --endpoint $ENDPOINT --use_websocket --signing_region us-east-1
16-
1714
popd

samples/README.md

Lines changed: 165 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
# Sample apps for the AWS IoT Device SDK v2 for Python
22

33
* [PubSub](#pubsub)
4-
* [PKCS#11 PubSub](#pkcs11-pubsub)
5-
* [Windows Certificate PubSub](#windows-certificate-pubsub)
4+
* [Basic Connect](#basic-connect)
5+
* [Websocket Connect](#websocket-connect)
6+
* [PKCS#11 Connect](#pkcs11-connect)
7+
* [Windows Certificate Connect](#windows-certificate-connect)
68
* [Shadow](#shadow)
79
* [Jobs](#jobs)
810
* [Fleet Provisioning](#fleet-provisioning)
911
* [Greengrass Discovery](#greengrass-discovery)
1012

13+
## Build instructions
14+
15+
First, install the aws-iot-devices-sdk-python-v2 with following the instructions from [Installation](../README.md#Installation).
16+
17+
Then change into the samples directory to run the Python commands to execute the samples. You can view the commands of a sample like this:
18+
19+
``` sh
20+
python3 pubsub.py --help
21+
```
22+
1123
## PubSub
1224

1325
This sample uses the
@@ -21,11 +33,6 @@ Status updates are continually printed to the console.
2133

2234
Source: `samples/pubsub.py`
2335

24-
Run the sample like this:
25-
``` sh
26-
python3 pubsub.py --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
27-
```
28-
2936
Your Thing's
3037
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
3138
must provide privileges for this sample to connect, subscribe, publish,
@@ -70,14 +77,120 @@ and receive.
7077
</pre>
7178
</details>
7279

73-
## PKCS#11 PubSub
80+
Run the sample like this:
81+
``` sh
82+
python3 pubsub.py --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
83+
```
84+
85+
## Basic Connect
86+
87+
This sample makes an MQTT connection using a certificate and key file. On startup, the device connects to the server using the certificate and key files, and then disconnects.
88+
This sample is for reference on connecting via certificate and key files.
7489

75-
This sample is similar to the basic [PubSub](#pubsub),
90+
Source: `samples/basic_connect.py`
91+
92+
Your Thing's
93+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
94+
must provide privileges for this sample to connect, subscribe, publish,
95+
and receive.
96+
97+
<details>
98+
<summary>(see sample policy)</summary>
99+
<pre>
100+
{
101+
"Version": "2012-10-17",
102+
"Statement": [
103+
{
104+
"Effect": "Allow",
105+
"Action": [
106+
"iot:Connect"
107+
],
108+
"Resource": [
109+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
110+
]
111+
}
112+
]
113+
}
114+
</pre>
115+
</details>
116+
117+
Run the sample like this:
118+
``` sh
119+
python3 basic_connect.py --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
120+
```
121+
122+
## Websocket Connect
123+
124+
This sample makes an MQTT connection via websockets and then disconnects. On startup, the device connects to the server via websockets and then disconnects.
125+
This sample is for reference on connecting via websockets.
126+
127+
Source: `samples/websocket_connect.py`
128+
129+
Your Thing's
130+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
131+
must provide privileges for this sample to connect, subscribe, publish,
132+
and receive.
133+
134+
<details>
135+
<summary>(see sample policy)</summary>
136+
<pre>
137+
{
138+
"Version": "2012-10-17",
139+
"Statement": [
140+
{
141+
"Effect": "Allow",
142+
"Action": [
143+
"iot:Connect"
144+
],
145+
"Resource": [
146+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
147+
]
148+
}
149+
]
150+
}
151+
</pre>
152+
</details>
153+
154+
Run the sample like this:
155+
``` sh
156+
python3 websocket_connect.py --endpoint <endpoint> --ca_file <file> --signing_region <signing region>
157+
```
158+
159+
Note that using Websockets will attempt to fetch the AWS credentials from your enviornment 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`, and `AWS_SESSION_TOKEN` environment variables.
160+
161+
## PKCS#11 Connect
162+
163+
This sample is similar to the [Basic Connect](#basic-connect),
76164
but the private key for mutual TLS is stored on a PKCS#11 compatible smart card or Hardware Security Module (HSM)
77165

78166
WARNING: Unix only. Currently, TLS integration with PKCS#11 is only available on Unix devices.
79167

80-
source: `samples/pkcs11_pubsub.py`
168+
source: `samples/pkcs11_connect.py`
169+
170+
Your Thing's
171+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
172+
must provide privileges for this sample to connect, subscribe, publish,
173+
and receive.
174+
175+
<details>
176+
<summary>(see sample policy)</summary>
177+
<pre>
178+
{
179+
"Version": "2012-10-17",
180+
"Statement": [
181+
{
182+
"Effect": "Allow",
183+
"Action": [
184+
"iot:Connect"
185+
],
186+
"Resource": [
187+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
188+
]
189+
}
190+
]
191+
}
192+
</pre>
193+
</details>
81194

82195
To run this sample using [SoftHSM2](https://www.opendnssec.org/softhsm/) as the PKCS#11 device:
83196

@@ -120,14 +233,14 @@ To run this sample using [SoftHSM2](https://www.opendnssec.org/softhsm/) as the
120233
121234
5) Now you can run the sample:
122235
```sh
123-
python3 pkcs11_pubsub.py --endpoint <xxxx-ats.iot.xxxx.amazonaws.com> --ca_file <AmazonRootCA1.pem> --cert <certificate.pem.crt> --pkcs11_lib <libsofthsm2.so> --pin <user-pin> --token_label <token-label> --key_label <key-label>
124-
236+
python3 pkcs11_connect.py --endpoint <endpoint> --ca_file <path to root CA> --cert <path to certificate> --pkcs11_lib <path to PKCS11 lib> --pin <user-pin> --token_label <token-label> --key_label <key-label>
237+
```
125238
126-
## Windows Certificate PubSub
239+
## Windows Certificate Connect
127240
128241
WARNING: Windows only
129242
130-
This sample is similar to the basic [PubSub](#pubsub),
243+
This sample is similar to the basic [Connect](#basic-connect),
131244
but your certificate and private key are in a
132245
[Windows certificate store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores),
133246
rather than simply being files on disk.
@@ -141,7 +254,32 @@ If your certificate and private key are in a
141254
[TPM](https://docs.microsoft.com/en-us/windows/security/information-protection/tpm/trusted-platform-module-overview),,
142255
you would use them by passing their certificate store path.
143256

144-
source: `samples/windows_cert_pubsub.py`
257+
source: `samples/windows_cert_connect.py`
258+
259+
Your Thing's
260+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
261+
must provide privileges for this sample to connect, subscribe, publish,
262+
and receive.
263+
264+
<details>
265+
<summary>(see sample policy)</summary>
266+
<pre>
267+
{
268+
"Version": "2012-10-17",
269+
"Statement": [
270+
{
271+
"Effect": "Allow",
272+
"Action": [
273+
"iot:Connect"
274+
],
275+
"Resource": [
276+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
277+
]
278+
}
279+
]
280+
}
281+
</pre>
282+
</details>
145283
146284
To run this sample with a basic certificate from AWS IoT Core:
147285
@@ -183,7 +321,7 @@ To run this sample with a basic certificate from AWS IoT Core:
183321
4) Now you can run the sample:
184322
185323
```sh
186-
python3 windows_cert_pubsub.py --endpoint xxxx-ats.iot.xxxx.amazonaws.com --root-ca AmazonRootCA.pem --cert CurrentUser\My\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6
324+
python3 windows_cert_connect.py --endpoint <endpoint> --ca_file <path to root CA> --cert <path to certificate>
187325
```
188326
189327
## Shadow
@@ -488,11 +626,11 @@ and `--key` appropriately:
488626
489627
``` sh
490628
python3 fleetprovisioning.py \
491-
--endpoint [your endpoint]-ats.iot.[region].amazonaws.com \
492-
--ca_file [pathToRootCA] \
493-
--cert /tmp/provision.cert.pem \
494-
--key /tmp/provision.private.key \
495-
--template_name [TemplateName] \
629+
--endpoint <endpoint> \
630+
--ca_file <path to root CA> \
631+
--cert <path to certificate> \
632+
--key <path to private key> \
633+
--template_name <template name> \
496634
--template_parameters "{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}"
497635
```
498636
@@ -528,13 +666,13 @@ using a permanent certificate set, replace the paths specified in the `--cert` a
528666

529667
``` sh
530668
python3 fleetprovisioning.py \
531-
--endpoint [your endpoint]-ats.iot.[region].amazonaws.com \
532-
--ca_file [pathToRootCA] \
533-
--cert /tmp/provision.cert.pem \
534-
--key /tmp/provision.private.key \
535-
--template_name [TemplateName] \
669+
--endpoint <endpoint> \
670+
--ca_file <path to root CA> \
671+
--cert <path to certificate> \
672+
--key <path to key> \
673+
--template_name <template name> \
536674
--template_parameters "{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}" \
537-
--csr /tmp/deviceCert.csr
675+
--csr <path to csr file>
538676
```
539677

540678
## Greengrass Discovery

samples/basic_connect.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0.
3+
4+
from uuid import uuid4
5+
6+
# This sample shows how to create a MQTT connection using a certificate file and key file.
7+
# This sample is intended to be used as a reference for making MQTT connections.
8+
9+
# Parse arguments
10+
import command_line_utils
11+
cmdUtils = command_line_utils.CommandLineUtils("Basic Connect - Make a MQTT connection.")
12+
cmdUtils.add_common_mqtt_commands()
13+
cmdUtils.add_common_proxy_commands()
14+
cmdUtils.add_common_logging_commands()
15+
cmdUtils.register_command("key", "<path>", "Path to your key in PEM format.", True, str)
16+
cmdUtils.register_command("cert", "<path>", "Path to your client certificate in PEM format.", True, str)
17+
cmdUtils.register_command("port", "<int>",
18+
"Connection port for direct connection. " +
19+
"AWS IoT supports 433 and 8883 (optional, default=8883).",
20+
False, int)
21+
cmdUtils.register_command("client_id", "<str>",
22+
"Client ID to use for MQTT connection (optional, default='test-*').",
23+
default="test-" + str(uuid4()))
24+
# Needs to be called so the command utils parse the commands
25+
cmdUtils.get_args()
26+
27+
# Callback when connection is accidentally lost.
28+
def on_connection_interrupted(connection, error, **kwargs):
29+
print("Connection interrupted. error: {}".format(error))
30+
31+
# Callback when an interrupted connection is re-established.
32+
def on_connection_resumed(connection, return_code, session_present, **kwargs):
33+
print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present))
34+
35+
36+
if __name__ == '__main__':
37+
# Create a connection using a certificate and key.
38+
# Note: The data for the connection is gotten from cmdUtils.
39+
# (see build_direct_mqtt_connection for implementation)
40+
mqtt_connection = cmdUtils.build_direct_mqtt_connection(on_connection_interrupted, on_connection_resumed)
41+
42+
print("Connecting to {} with client ID '{}'...".format(
43+
cmdUtils.get_command(cmdUtils.m_cmd_endpoint), cmdUtils.get_command("client_id")))
44+
45+
connect_future = mqtt_connection.connect()
46+
47+
# Future.result() waits until a result is available
48+
connect_future.result()
49+
print("Connected!")
50+
51+
# Disconnect
52+
print("Disconnecting...")
53+
disconnect_future = mqtt_connection.disconnect()
54+
disconnect_future.result()
55+
print("Disconnected!")

0 commit comments

Comments
 (0)