Skip to content

Commit bdf98bc

Browse files
committed
add pkcs11 sample
1 parent b7d0397 commit bdf98bc

4 files changed

Lines changed: 681 additions & 1 deletion

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ jobs:
240240
run: |
241241
cd ${{ env.CI_FOLDER }}
242242
echo "Starting to run AppVerifier with mqtt5 pub-sub sample"
243-
python ${{ env.CI_UTILS_FOLDER }}/appverifier_launch_sample.py --sample_file ".\aws-iot-device-sdk-cpp-v2\build\samples\mqtt5\mqtt5_pubsub\RelWithDebInfo\mqtt5_x509.exe" --sample_secret_endpoint 'ci/endpoint' --sample_secret_certificate 'ci/mqtt5/us/mqtt5_thing/cert' --sample_secret_private_key 'ci/mqtt5/us/mqtt5_thing/key'
243+
python ${{ env.CI_UTILS_FOLDER }}/appverifier_launch_sample.py --sample_file ".\aws-iot-device-sdk-cpp-v2\build\samples\mqtt\mqtt5_x509\RelWithDebInfo\mqtt5_x509.exe" --sample_secret_endpoint 'ci/endpoint' --sample_secret_certificate 'ci/mqtt5/us/mqtt5_thing/cert' --sample_secret_private_key 'ci/mqtt5/us/mqtt5_thing/key'
244244
245245
windows-shared-lib:
246246
runs-on: windows-latest
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required(VERSION 3.9...3.31)
2+
# note: cxx-17 requires cmake 3.8, cxx-20 requires cmake 3.12
3+
project(mqtt5_pkcs11 CXX)
4+
5+
file(GLOB SRC_FILES
6+
"*.cpp"
7+
)
8+
9+
add_executable(${PROJECT_NAME} ${SRC_FILES})
10+
11+
set_target_properties(${PROJECT_NAME} PROPERTIES
12+
CXX_STANDARD 14)
13+
14+
#set warnings
15+
if (MSVC)
16+
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX /wd4068)
17+
else ()
18+
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror)
19+
endif ()
20+
21+
find_package(aws-crt-cpp REQUIRED)
22+
23+
include(AwsSanitizers)
24+
enable_language(C)
25+
aws_add_sanitizers(${PROJECT_NAME})
26+
27+
target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-crt-cpp)
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# MQTT5 PKCS#11 PubSub
2+
3+
[**Return to main sample list**](../../README.md)
4+
5+
*__Jump To:__*
6+
* [Introduction](#introduction)
7+
* [Requirements](#requirements)
8+
* [How To Build](#how-to-build)
9+
* [How To Run](#how-to-run)
10+
* [Run Sample with Soft HSM](#run-sample-with-softhsm)
11+
* [Additional Information](#additional-information)
12+
13+
## Introduction
14+
This sample is similar to the [MQTT5 X509](../mqtt5_x509/) sample in that it connects via Mutual TLS (mTLS) using a certificate and key file. However, unlike the x509 sample 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 openly on the computer but instead is hidden securely away behind the PKCS#11 device.
15+
16+
You can read more about MQTT5 for the CPP IoT Device SDK V2 in the [MQTT5 user guide](../../../documents/MQTT5_Userguide.md).
17+
18+
## Requirements
19+
20+
**WARNING: Unix (Linux) only**. Currently, TLS integration with PKCS#11 is only available on Unix devices.
21+
22+
This sample assumes you have the required AWS IoT resources available. Information about AWS IoT can be found [HERE](https://docs.aws.amazon.com/iot/latest/developerguide/what-is-aws-iot.html) and instructions on creating AWS IoT resources (AWS IoT Policy, Device Certificate, Private Key) can be found [HERE](https://docs.aws.amazon.com/iot/latest/developerguide/create-iot-resources.html).
23+
24+
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.
25+
26+
<details>
27+
<summary>(see sample policy)</summary>
28+
<pre>
29+
{
30+
"Version": "2012-10-17",
31+
"Statement": [
32+
{
33+
"Effect": "Allow",
34+
"Action": [
35+
"iot:Publish",
36+
"iot:Receive"
37+
],
38+
"Resource": [
39+
"arn:aws:iot:<b>region</b>:<b>account</b>:topic/test/topic"
40+
]
41+
},
42+
{
43+
"Effect": "Allow",
44+
"Action": [
45+
"iot:Subscribe"
46+
],
47+
"Resource": [
48+
"arn:aws:iot:<b>region</b>:<b>account</b>:topicfilter/test/topic"
49+
]
50+
},
51+
{
52+
"Effect": "Allow",
53+
"Action": [
54+
"iot:Connect"
55+
],
56+
"Resource": [
57+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/mqtt5-sample-*"
58+
]
59+
}
60+
]
61+
}
62+
</pre>
63+
64+
Replace with the following with the data from your AWS account:
65+
* `<region>`: 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`.
66+
* `<account>`: 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.
67+
68+
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 `mqtt5-sample-*` to connect or use `--client_id <client ID here>` to send the client ID your policy supports.
69+
70+
</details>
71+
72+
## How to build
73+
74+
To build the sample, change directory into the samples, and run the cmake commands
75+
```sh
76+
cd samples/mqtt/mqtt5_pkcs11/
77+
# If you followed the SDK build instruction, you would use the path to `sdk-workspace` folder for `CMAKE_PREFIX_PATH` here
78+
cmake -B build -S . -DCMAKE_PREFIX_PATH="<absolute path sdk-workspace dir>" -DCMAKE_BUILD_TYPE="Debug" .
79+
cmake --build build --config "Debug"
80+
```
81+
82+
## How to run
83+
84+
To Run this sample from the `samples/mqtt/mqtt5_pkcs11` folder, use the following command:
85+
86+
```sh
87+
./mqtt5_pkcs11 \
88+
--endpoint <AWS IoT endpoint> \
89+
--cert <path to certificate file> \
90+
--pkcs11_lib <Path to PKCS#11 Library> \
91+
--pin <User PIN for logging into PKCS#11 token> \
92+
--token_label <Label of the PKCS#11 token to use (optional)> \
93+
--key_label <Label of private key on the PKCS#11 token (optional)>
94+
```
95+
96+
If you would like to see what optional arguments are available, use the `--help` argument:
97+
```sh
98+
./mqtt5_pkcs11 --help
99+
```
100+
101+
will result in the following output:
102+
```
103+
MQTT5 PKCS11 Sample.
104+
105+
options:
106+
-h, --help show this help message and exit
107+
108+
required arguments:
109+
--endpoint IoT endpoint hostname (default: None)
110+
--cert Path to the certificate file to use during mTLS connection establishment (default: None)
111+
--pkcs11_lib Path to PKCS#11 Library (default: None)
112+
--pin User PIN for logging into PKCS#11 token (default: None)
113+
114+
optional arguments:
115+
--port Port (8883 mTLS, 443 ALPN) (default: 8883)
116+
--token_label Label of the PKCS#11 token to use (optional). (default: None)
117+
--slot_id Slot ID containing the PKCS#11 token to use (optional). (default: None)
118+
--key_label Label of private key on the PKCS#11 token (optional). (default: None)
119+
--ca_file Path to optional CA bundle (PEM) (default: None)
120+
--topic Topic (default: test/topic)
121+
--message Message payload (default: Hello from mqtt5 sample)
122+
--count Messages to publish (0 = infinite) (default: 5)
123+
--proxy_host HTTP proxy host (default: None)
124+
--proxy_port HTTP proxy port (default: 0)
125+
--client_id Client ID (default: test-548e4344)
126+
```
127+
128+
### Run sample with SoftHSM
129+
130+
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.
131+
132+
The steps to use [SoftHSM2](https://www.opendnssec.org/softhsm/) as the PKCS#11 device with this sample are listed below:
133+
134+
1. Create an AWS IoT Thing with a certificate and key if you haven't already.
135+
136+
2. Convert the private key from the AWS IoT Thing into PKCS#8 format using the following command:
137+
138+
```sh
139+
openssl pkcs8 -topk8 -in <private.pem.key> -out <private.p8.key> -nocrypt
140+
```
141+
142+
3. Install [SoftHSM2](https://www.opendnssec.org/softhsm/) using `apt`:
143+
144+
```sh
145+
sudo apt install softhsm
146+
```
147+
148+
Note that if you are using a Linux distribution that does not include `apt`, you will need to
149+
adjust the above command to get [SoftHSM2](https://www.opendnssec.org/softhsm/) from the package manager your distribution supports.
150+
151+
4. Check that [SoftHSM2](https://www.opendnssec.org/softhsm/) is working as expected by running the following:
152+
153+
```sh
154+
softhsm2-util --show-slots
155+
```
156+
157+
If this spits out an error message, create a config file:
158+
* Default location: `~/.config/softhsm2/softhsm2.conf`
159+
* This file must specify token dir, default value is:
160+
```sh
161+
directories.tokendir = /usr/local/var/lib/softhsm/tokens/
162+
```
163+
164+
5. Create a token and import the private key you converted in step 2:
165+
166+
You can use any values for the labels, PINs, etc
167+
168+
```sh
169+
softhsm2-util --init-token --free --label <token-label> --pin <user-pin> --so-pin <so-pin>
170+
```
171+
172+
**Important**: Note which slot the token ended up in
173+
174+
```sh
175+
softhsm2-util --import <private.p8.key> --slot <slot-with-token> --label <key-label> --id <hex-chars> --pin <user-pin>
176+
```
177+
178+
6. Now you can run the sample with the following:
179+
180+
```sh
181+
# For Windows: replace 'python3' with 'python' and '/' with '\'
182+
python3 mqtt5_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>
183+
```
184+
185+
## Additional Information
186+
Additional help with the MQTT5 Client can be found in the [MQTT5 Userguide](../../../documents/MQTT5_Userguide.md). This guide will provide more details on MQTT5 [operations](../../../documents/MQTT5_Userguide.md#client-operations), [lifecycle events](../../documents/MQTT5_Userguide.md#client-lifecycle-management), [connection methods](../../../documents/MQTT5_Userguide.md#connecting-to-aws-iot-core), and other useful information.

0 commit comments

Comments
 (0)