Skip to content

Commit 03db033

Browse files
authored
Support PKCS#11 for mutual TLS on Unix platforms (#220)
- Update to latest `aws-crt-nodejs`, which exposes PKCS#11 functionality (see awslabs/aws-crt-nodejs#295) - Add `pub_sub_pkcs11` sample, demonstrating an MQTT connection where the private key is stored in PKCS#11 token. - Add docs for sample
1 parent fb10852 commit 03db033

File tree

12 files changed

+1980
-39
lines changed

12 files changed

+1980
-39
lines changed

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,13 @@ build/
191191

192192
# config files
193193
config.ts
194+
195+
# Mac
196+
.DS_Store
197+
198+
# VSCode
199+
.vscode/
200+
.devcontainer/
201+
202+
# Git
203+
*.orig

package-lock.json

+23-20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@
3131
"typescript": "^3.9.7"
3232
},
3333
"dependencies": {
34-
"aws-crt": "1.10.6"
34+
"aws-crt": "1.11.0"
3535
}
3636
}

samples/README.md

+83-14
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@
22

33
* [pub_sub](#nodepub_sub)
44
* [pub_sub_js](#nodepub_sub_js)
5+
* [pub_sub_pkcs11](#nodepub_sub_pkcs11)
56
* [fleet provisioning](#fleet-provisioning)
67
* [basic discovery](#nodebasic_discovery)
78

89
## Note
910

1011
If you are installing via npm instead of building from source, please make the following change to the package.json under each sample.
1112

12-
``` json
1313
From:
14+
``` json
1415
"dependencies": {
15-
"aws-iot-device-sdk-v2": "../../../",
16+
"aws-iot-device-sdk-v2": "file:../../..",
1617
"yargs": "^14.0.0"
1718
}
18-
19+
```
1920
To:
21+
``` json
2022
"dependencies": {
2123
"aws-iot-device-sdk-v2": "<latest released version eg: ^1.3.0>",
2224
"yargs": "^14.0.0"
@@ -96,6 +98,73 @@ npm install
9698
node index.js --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
9799
```
98100

101+
## Node/pub_sub_pkcs11
102+
103+
This sample is similar to [pub_sub](#nodepub_sub),
104+
but the private key for mutual TLS is stored on a PKCS#11 compatible smart card or hardware security module (HSM)
105+
106+
WARNING: Unix only. Node only. Currently, TLS integration with PKCS#11 is only available on Unix devices.
107+
108+
Source: `samples/node/pub_sub_pkcs11`
109+
110+
To run this sample using [SoftHSM2](https://www.opendnssec.org/softhsm/) as the PKCS#11 device:
111+
112+
1) Create an IoT Thing with a certificate and key if you haven't already.
113+
114+
2) Convert the private key into PKCS#8 format
115+
```sh
116+
openssl pkcs8 -topk8 -in <private.pem.key> -out <private.p8.key> -nocrypt
117+
```
118+
119+
3) Install [SoftHSM2](https://www.opendnssec.org/softhsm/):
120+
```sh
121+
sudo apt install softhsm
122+
```
123+
124+
Check that it's working:
125+
```sh
126+
softhsm2-util --show-slots
127+
```
128+
129+
If this works, continue to step 4.
130+
131+
But if it spits out an error message, it's likely that SoftHM2's default token
132+
directory doesn't exist, or you don't have read/write access to it.
133+
134+
Either create the directory with user permissions:
135+
```sh
136+
mkdir -p /usr/local/var/lib/softhsm/tokens
137+
```
138+
139+
Or if that doesn't work, create a directory wherever you like and tell SoftHSM2 where to find it:
140+
* Create the token directory
141+
* Create a config file at this location: `~/.config/softhsm2/softhsm2.conf`
142+
* The config file should look something like:
143+
```
144+
directories.tokendir = <my-token-dir>
145+
```
146+
147+
4) Create token and import private key.
148+
149+
You can use any values for the labels, PINs, etc.
150+
```sh
151+
softhsm2-util --init-token --free --label <token-label> --pin <user-pin> --so-pin <security-officer-pin>
152+
```
153+
154+
Note which slot the token ended up in, and use that for `<slot-with-token>`.
155+
156+
For `<hex-chars>` enter hex characters like "0123BEEF"
157+
158+
```sh
159+
softhsm2-util --import <private.p8.key> --slot <slot-with-token> --label <key-label> --id <hex-chars> --pin <user-pin>
160+
```
161+
162+
5) Now you can run the sample:
163+
```sh
164+
npm install
165+
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>
166+
```
167+
99168
## Fleet Provisioning
100169

101170
This sample uses the AWS IoT
@@ -177,7 +246,7 @@ get the sample up and running. These steps assume you have the AWS CLI installed
177246
sufficient permission to perform all of the listed operations. You will also need python3 to be able to run parse_cert_set_result.py. These steps are based on provisioning setup steps
178247
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).
179248
180-
First, create the IAM role that will be needed by the fleet provisioning template. Replace `RoleName` with a name of the role you want to create.
249+
First, create the IAM role that will be needed by the fleet provisioning template. Replace `RoleName` with a name of the role you want to create.
181250
``` sh
182251
aws iam create-role \
183252
--role-name [RoleName] \
@@ -189,17 +258,17 @@ aws iam attach-role-policy \
189258
--role-name [RoleName] \
190259
--policy-arn arn:aws:iam::aws:policy/service-role/AWSIoTThingsRegistration
191260
```
192-
Finally, create the template resource which will be used for provisioning by the demo application. This needs to be done only
193-
once. To create a template, the following AWS CLI command may be used. Replace `TemplateName` with the name of the fleet
194-
provisioning template you want to create. Replace `RoleName` with the name of the role you created previously. Replace
195-
`TemplateJSON` with the template body as a JSON string (containing escape characters). Replace `account` with your AWS
196-
account number.
261+
Finally, create the template resource which will be used for provisioning by the demo application. This needs to be done only
262+
once. To create a template, the following AWS CLI command may be used. Replace `TemplateName` with the name of the fleet
263+
provisioning template you want to create. Replace `RoleName` with the name of the role you created previously. Replace
264+
`TemplateJSON` with the template body as a JSON string (containing escape characters). Replace `account` with your AWS
265+
account number.
197266
``` sh
198267
aws iot create-provisioning-template \
199268
--template-name [TemplateName] \
200269
--provisioning-role-arn arn:aws:iam::[account]:role/[RoleName] \
201270
--template-body "[TemplateJSON]" \
202-
--enabled
271+
--enabled
203272
```
204273
The rest of the instructions assume you have used the following for the template body:
205274
``` sh
@@ -209,13 +278,13 @@ If you use a different body, you may need to pass in different template paramete
209278
210279
#### Running the sample and provisioning using a certificate-key set from a provisioning claim
211280
212-
To run the provisioning sample, you'll need a certificate and key set with sufficient permissions. Provisioning certificates are normally
281+
To run the provisioning sample, you'll need a certificate and key set with sufficient permissions. Provisioning certificates are normally
213282
created ahead of time and placed on your device, but for this sample, we will just create them on the fly. You can also
214283
use any certificate set you've already created if it has sufficient IoT permissions and in doing so, you can skip the step
215284
that calls `create-provisioning-claim`.
216285
217286
We've included a script in the utils folder that creates certificate and key files from the response of calling
218-
`create-provisioning-claim`. These dynamically sourced certificates are only valid for five minutes. When running the command,
287+
`create-provisioning-claim`. These dynamically sourced certificates are only valid for five minutes. When running the command,
219288
you'll need to substitute the name of the template you previously created, and on Windows, replace the paths with something appropriate.
220289
221290
(Optional) Create a temporary provisioning claim certificate set:
@@ -228,7 +297,7 @@ aws iot create-provisioning-claim \
228297
```
229298
230299
The provisioning claim's cert and key set have been written to `/tmp/provision*`. Now you can use these temporary keys
231-
to perform the actual provisioning. If you are not using the temporary provisioning certificate, replace the paths for `--cert`
300+
to perform the actual provisioning. If you are not using the temporary provisioning certificate, replace the paths for `--cert`
232301
and `--key` appropriately:
233302

234303
``` sh
@@ -278,7 +347,7 @@ node dist/index.js \
278347
--key /tmp/provision.private.key \
279348
--template_name [TemplateName] \
280349
--template_parameters "{\"SerialNumber\":\"1\",\"DeviceLocation\":\"Seattle\"}" \
281-
--csr_file /tmp/deviceCert.csr
350+
--csr_file /tmp/deviceCert.csr
282351
```
283352
284353
## Greengrass Discovery (Basic Discovery)

samples/node/basic_discovery/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"typescript": "^3.7.3"
2222
},
2323
"dependencies": {
24-
"aws-iot-device-sdk-v2": "../../../",
24+
"aws-iot-device-sdk-v2": "file:../../..",
2525
"yargs": "^16.2.0"
2626
}
2727
}

samples/node/fleet_provisioning/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"typescript": "^3.9.7"
2222
},
2323
"dependencies": {
24-
"aws-iot-device-sdk-v2": "../../../",
24+
"aws-iot-device-sdk-v2": "file:../../..",
2525
"yargs": "^16.2.0"
2626
}
2727
}

samples/node/pub_sub/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"typescript": "^3.9.7"
2222
},
2323
"dependencies": {
24-
"aws-iot-device-sdk-v2": "../../../",
24+
"aws-iot-device-sdk-v2": "file:../../..",
2525
"yargs": "^16.2.0"
2626
}
2727
}

samples/node/pub_sub_js/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"license": "Apache-2.0",
1414
"main": "./index.js",
1515
"dependencies": {
16-
"aws-iot-device-sdk-v2": "../../../",
16+
"aws-iot-device-sdk-v2": "file:../../..",
1717
"yargs": "^16.2.0"
1818
}
1919
}

0 commit comments

Comments
 (0)