Skip to content

Commit 19b51e4

Browse files
Split the PubSub sample down into smaller samples (#231)
Splits the pub-sub sample into smaller connect samples and simplifies the sample where possible. Commit log: * Split pub-sub sample into smaller connect samples, simplified samples where possible * Fixed codebuild tests * Fixed websocket region using incorrect name, fixed issue with websocket code build test * Fixed minor grammar mistake in README
1 parent a88da19 commit 19b51e4

File tree

21 files changed

+705
-1931
lines changed

21 files changed

+705
-1931
lines changed

codebuild/samples/pubsub-linux.shrenamed to codebuild/samples/connect-linux.sh

+10-4
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,22 @@ set -e
44

55
env
66

7-
pushd$CODEBUILD_SRC_DIR/samples/node/pub_sub
7+
pushd$CODEBUILD_SRC_DIR/samples/node/basic_connect
88

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

1111
npm install --unsafe-perm
1212

13-
echo"Mqtt Direct test"
13+
echo"Connect Basic (Direct) test"
1414
node dist/index.js --endpoint $ENDPOINT --key /tmp/privatekey.pem --cert /tmp/certificate.pem
1515

16-
echo"Websocket test"
17-
node dist/index.js --endpoint $ENDPOINT --use_websocket --signing_region us-east-1
16+
popd
17+
18+
pushd$CODEBUILD_SRC_DIR/samples/node/websocket_connect
19+
20+
npm install --unsafe-perm
21+
22+
echo"Connect Websocket test"
23+
node dist/index.js --endpoint $ENDPOINT --signing_region us-east-1
1824

1925
popd

codebuild/samples/linux-smoke-tests.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ phases:
88
commands:
99
- echo Build started on `date`
1010
- $CODEBUILD_SRC_DIR/codebuild/samples/setup-linux.sh
11-
- $CODEBUILD_SRC_DIR/codebuild/samples/pubsub-linux.sh
11+
- $CODEBUILD_SRC_DIR/codebuild/samples/connect-linux.sh
1212
post_build:
1313
commands:
14-
- echo Build completed on `date`
14+
- echo Build completed on `date`

samples/README.md

+111-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
*[pub_sub](#nodepub_sub)
44
*[pub_sub_js](#nodepub_sub_js)
5-
*[pub_sub_pkcs11](#nodepub_sub_pkcs11)
5+
*[basic_connect](#basic_connect)
6+
*[websocket_connect](#websocket_connect)
7+
*[pkcs11_connect](#websocket_pkcs11)
68
*[shadow](#nodeshadow)
79
*[fleet provisioning](#fleet-provisioning)
810
*[basic discovery](#nodebasic_discovery)
@@ -99,14 +101,93 @@ npm install
99101
node index.js --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
100102
```
101103

102-
## Node/pub_sub_pkcs11
104+
## Node/Basic_Connect
103105

104-
This sample is similar to [pub_sub](#nodepub_sub),
105-
but the private key for mutual TLS is stored on a PKCS#11 compatible smart card or hardware security module (HSM)
106+
This sample creates a basic MQTT connection using a certificate and key file.
107+
On startup, the device connects and then disconnects from the AWS server. This
108+
sample is for reference on connecting via certificate and key files.
109+
110+
Source: `samples/node/basic_connect`
111+
112+
Run the sample like this:
113+
```sh
114+
npm install
115+
node dist/index.js --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
116+
```
117+
118+
Your Thing's
119+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
120+
must provide privileges for this sample to connect, subscribe, publish,
121+
and receive.
122+
<details>
123+
<summary>(see sample policy)</summary>
124+
<pre>
125+
{
126+
"Version": "2012-10-17",
127+
"Statement": [
128+
{
129+
"Effect": "Allow",
130+
"Action": [
131+
"iot:Connect"
132+
],
133+
"Resource": [
134+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
135+
]
136+
}
137+
]
138+
}
139+
</pre>
140+
</details>
141+
142+
## Node/Websocket_Connect
143+
144+
This sample creates a basic MQTT connection using websockets.
145+
On startup, the device connects and then disconnects from the AWS server. This
146+
sample is for reference on connecting via websockets.
147+
148+
Source: `samples/node/websocket_connect`
149+
150+
Run the sample like this:
151+
```sh
152+
npm install
153+
node dist/index.js --endpoint <endpoint> --ca_file <file> --signing_region <signing region>
154+
```
155+
156+
Your Thing's
157+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
158+
must provide privileges for this sample to connect, subscribe, publish,
159+
and receive.
160+
<details>
161+
<summary>(see sample policy)</summary>
162+
<pre>
163+
{
164+
"Version": "2012-10-17",
165+
"Statement": [
166+
{
167+
"Effect": "Allow",
168+
"Action": [
169+
"iot:Connect"
170+
],
171+
"Resource": [
172+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
173+
]
174+
}
175+
]
176+
}
177+
</pre>
178+
</details>
179+
180+
## Node/Pkcs11_Connect
181+
182+
This sample is similar to the basic connect sample, but the private key for mutual TLS is stored on
183+
a PKCS#11 compatible smart card or hardware security module (HSM).
184+
185+
On startup, the device connects and then disconnects from the AWS server. This
186+
sample is for reference on connecting via websockets.
106187

107188
WARNING: Unix only. Node only. Currently, TLS integration with PKCS#11 is only available on Unix devices.
108189

109-
Source: `samples/node/pub_sub_pkcs11`
190+
Source: `samples/node/pkcs11_connect`
110191

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

@@ -163,8 +244,31 @@ To run this sample using [SoftHSM2](https://www.opendnssec.org/softhsm/) as the
163244
5) Now you can run the sample:
164245
```sh
165246
npm install
166-
node dist/index.js --endpoint <xxxx-ats.iot.xxxx.amazonaws.com> --root-ca <AmazonRootCA1.pem> --cert <certificate.pem.crt> --pkcs11_lib <libsofthsm2.so> --pin <user-pin> --token_label <token-label> --key_label <key-label>
167-
```
247+
node dist/index.js --endpoint <endpoint> --ca_file <AmazonRootCA1.pem> --cert <certificate.pem.crt> --pkcs11_lib <libsofthsm2.so> --pin <user-pin> --token_label <token-label> --key_label <key-label>
248+
249+
Your Thing's
250+
[Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html)
251+
must provide privileges for this sample to connect, subscribe, publish,
252+
and receive.
253+
<details>
254+
<summary>(see sample policy)</summary>
255+
<pre>
256+
{
257+
"Version": "2012-10-17",
258+
"Statement": [
259+
{
260+
"Effect": "Allow",
261+
"Action": [
262+
"iot:Connect"
263+
],
264+
"Resource": [
265+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
266+
]
267+
}
268+
]
269+
}
270+
</pre>
271+
</details>
168272
169273
## Node/shadow
170274

samples/node/basic_connect/index.ts

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
import{mqtt}from'aws-iot-device-sdk-v2';
7+
import{iot}from'aws-iot-device-sdk-v2';
8+
import{http}from'aws-iot-device-sdk-v2';
9+
10+
typeArgs={[index: string]: any};
11+
12+
constyargs=require('yargs');
13+
14+
// The relative path is '../../util/cli_args' from here, but the compiled javascript file gets put one level
15+
// deeper inside the 'dist' folder
16+
constcommon_args=require('../../../util/cli_args');
17+
18+
yargs.command('*',false,(yargs: any)=>{
19+
yargs.usage("Connect using certificate and private key files.");
20+
common_args.add_universal_arguments(yargs);
21+
common_args.add_common_mqtt_arguments(yargs);
22+
common_args.add_direct_tls_connect_arguments(yargs,true);
23+
common_args.add_proxy_arguments(yargs);
24+
},main).parse();
25+
26+
// Creates and returns a MQTT connection using a certificate file and key file
27+
functionbuild_connection(argv: Args): mqtt.MqttClientConnection{
28+
letconfig_builder=iot.AwsIotMqttConnectionConfigBuilder.new_mtls_builder_from_path(argv.cert,argv.key);
29+
30+
if(argv.proxy_host){
31+
config_builder.with_http_proxy_options(newhttp.HttpProxyOptions(argv.proxy_host,argv.proxy_port));
32+
}
33+
if(argv.ca_file!=null){
34+
config_builder.with_certificate_authority_from_path(undefined,argv.ca_file);
35+
}
36+
37+
config_builder.with_clean_session(false);
38+
config_builder.with_client_id(argv.client_id||"test-"+Math.floor(Math.random()*100000000));
39+
config_builder.with_endpoint(argv.endpoint);
40+
constconfig=config_builder.build();
41+
42+
constclient=newmqtt.MqttClient();
43+
returnclient.new_connection(config);
44+
}
45+
46+
asyncfunctionmain(argv: Args){
47+
common_args.apply_sample_arguments(argv);
48+
constconnection=build_connection(argv);
49+
50+
// force node to wait 20 seconds before killing itself, promises do not keep node alive
51+
// ToDo: we can get rid of this but it requires a refactor of the native connection binding that includes
52+
// pinning the libuv event loop while the connection is active or potentially active.
53+
consttimer=setInterval(()=>{},20*1000);
54+
55+
console.log("Connecting...");
56+
awaitconnection.connect()
57+
console.log("Connection completed.");
58+
console.log("Disconnecting...");
59+
awaitconnection.disconnect()
60+
console.log("Disconnect completed.");
61+
62+
// Allow node to die if the promise above resolved
63+
clearTimeout(timer);
64+
}

samples/node/pub_sub_pkcs11/package.jsonrenamed to samples/node/basic_connect/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"name": "pub-sub-pkcs11",
2+
"name": "basic-connect",
33
"version": "1.0.0",
4-
"description": "NodeJS IoT SDK v2 Pub Sub with PKCS#11 Sample",
4+
"description": "NodeJS IoT SDK v2 Basic Connect Sample",
55
"homepage": "https://github.com/aws/aws-iot-device-sdk-js-v2",
66
"repository": {
77
"type": "git",

samples/node/basic_discovery/index.ts

+13-33
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@ import { TextDecoder } from 'util';
88

99
typeArgs={[index: string]: any};
1010

11+
// The relative path is '../../util/cli_args' from here, but the compiled javascript file gets put one level
12+
// deeper inside the 'dist' folder
13+
constcommon_args=require('../../../util/cli_args');
14+
1115
constyargs=require('yargs');
1216
yargs.command('*',false,(yargs: any)=>{
13-
yargs.option('ca_file',{
17+
common_args.add_universal_arguments(yargs);
18+
common_args.add_topic_message_arguments(yargs);
19+
20+
yargs
21+
.option('ca_file',{
1422
alias: 'r',
1523
description: '<path>: path to a Root CA certificate file in PEM format (optional, system trust store used by default).',
1624
type: 'string',
@@ -34,50 +42,22 @@ yargs.command('*', false, (yargs: any) => {
3442
type: 'string',
3543
required: true
3644
})
37-
.option('topic',{
38-
alias: 't',
39-
description: 'Targeted topic (optional).',
40-
type: 'string',
41-
default: 'test/topic'
42-
})
4345
.option('mode',{
4446
alias: 'm',
4547
description: 'Mode options: [publish, subscribe, both] (optional).',
4648
type: 'string',
4749
default: 'both',
4850
choices: ['publish','subscribe','both']
4951
})
50-
.option('message',{
51-
alias: 'M',
52-
description: 'Message to publish (optional).',
53-
type: 'string',
54-
default: 'Hello world!'
55-
})
5652
.option('region',{
57-
description: 'AWS Region (optional).',
58-
type: 'string',
59-
default: 'us-east-1'
60-
})
61-
.option('count',{
62-
description: 'Maximum number of publishes to send (optional).',
63-
type: 'number',
64-
default: 10
53+
description: 'AWS Region.',
54+
type: 'string'
6555
})
6656
.option('print_discover_resp_only',{
6757
description: 'Only print the response from Greengrass discovery (optional).',
6858
type: 'boolean',
6959
default: false
7060
})
71-
.option('verbose',{
72-
alias: 'v',
73-
description: 'Verbose output (optional).',
74-
type: 'string',
75-
default: 'none',
76-
choices: ['fatal','error','warn','info','debug','trace','none']
77-
})
78-
.help()
79-
.alias('help','h')
80-
.showHelpOnFail(false)
8161
},main).parse();
8262

8363
functionfirstResolved<T>(promises: Promise<T>[]){
@@ -181,7 +161,7 @@ async function execute_session(connection: mqtt.MqttClientConnection, argv: Args
181161

182162
asyncfunctionmain(argv: Args){
183163
if(argv.verbose!='none'){
184-
constlevel: io.LogLevel=parseInt(io.LogLevel[argv.verbose.toUpperCase()]);
164+
constlevel: io.LogLevel=parseInt(io.LogLevel[argv.verbose.toUpperCase()]);
185165
io.enable_logging(level);
186166
}
187167

@@ -198,7 +178,7 @@ async function main(argv: Args) {
198178
constdiscovery=newgreengrass.DiscoveryClient(client_bootstrap,socket_options,tls_ctx,argv.region);
199179

200180
// force node to wait 60 seconds before killing itself, promises do not keep node alive
201-
consttimer=setTimeout(()=>{},60*1000);
181+
consttimer=setTimeout(()=>{},60*1000);
202182

203183
awaitdiscovery.discover(argv.thing_name)
204184
.then(async(discovery_response: greengrass.model.DiscoverResponse)=>{

0 commit comments

Comments
 (0)
close