Skip to content

Commit 2b53e07

Browse files
authored
Support mutual TLS using a certificate from a Windows cert store (#232)
Add the ability to use a client certificate located in a Windows certificate store. Previously, the client certificate and private key had to be passed by filepath or file contents. With this change, certificates and keys stored on TPM devices can be used. Add new `windows_cert_connect` sample to show this in action.
1 parent 19b51e4 commit 2b53e07

File tree

11 files changed

+3473
-16
lines changed

11 files changed

+3473
-16
lines changed

docs/assets/js/search.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/classes/aws_iot.awsiotmqttconnectionconfigbuilder.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ <h3>Methods</h3>
106106
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_mtls_builder" class="tsd-kind-icon">new_<wbr>mtls_<wbr>builder</a></li>
107107
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_mtls_builder_from_path" class="tsd-kind-icon">new_<wbr>mtls_<wbr>builder_<wbr>from_<wbr>path</a></li>
108108
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_mtls_pkcs11_builder" class="tsd-kind-icon">new_<wbr>mtls_<wbr>pkcs11_<wbr>builder</a></li>
109+
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_mtls_windows_cert_store_path_builder" class="tsd-kind-icon">new_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path_<wbr>builder</a></li>
109110
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_websocket_builder" class="tsd-kind-icon">new_<wbr>websocket_<wbr>builder</a></li>
110111
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_with_websockets" class="tsd-kind-icon">new_<wbr>with_<wbr>websockets</a></li>
111112
</ul>
@@ -654,6 +655,37 @@ <h4 class="tsd-returns-title">Returns <a href="aws_iot.awsiotmqttconnectionconfi
654655
</li>
655656
</ul>
656657
</section>
658+
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-static">
659+
<a name="new_mtls_windows_cert_store_path_builder" class="tsd-anchor"></a>
660+
<h3><span class="tsd-flag ts-flagStatic">Static</span> new_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path_<wbr>builder</h3>
661+
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class tsd-is-static">
662+
<li class="tsd-signature tsd-kind-icon">new_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path_<wbr>builder<span class="tsd-signature-symbol">(</span>certificate_path<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="aws_iot.awsiotmqttconnectionconfigbuilder.html" class="tsd-signature-type">AwsIotMqttConnectionConfigBuilder</a></li>
663+
</ul>
664+
<ul class="tsd-descriptions">
665+
<li class="tsd-description">
666+
<aside class="tsd-sources">
667+
</aside>
668+
<div class="tsd-comment tsd-typography">
669+
<div class="lead">
670+
<p>Create a new builder with mTLS using a certificate in a Windows certificate store.</p>
671+
</div>
672+
<p>NOTE: This configuration only works on Windows devices.</p>
673+
</div>
674+
<h4 class="tsd-parameters-title">Parameters</h4>
675+
<ul class="tsd-parameters">
676+
<li>
677+
<h5>certificate_path: <span class="tsd-signature-type">string</span></h5>
678+
<div class="tsd-comment tsd-typography">
679+
<p>Path to certificate in a Windows certificate store.
680+
The path must use backslashes and end with the certificate&#39;s thumbprint.
681+
Example: <code>CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6</code></p>
682+
</div>
683+
</li>
684+
</ul>
685+
<h4 class="tsd-returns-title">Returns <a href="aws_iot.awsiotmqttconnectionconfigbuilder.html" class="tsd-signature-type">AwsIotMqttConnectionConfigBuilder</a></h4>
686+
</li>
687+
</ul>
688+
</section>
657689
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-static">
658690
<a name="new_websocket_builder" class="tsd-anchor"></a>
659691
<h3><span class="tsd-flag ts-flagStatic">Static</span> new_<wbr>websocket_<wbr>builder</h3>
@@ -794,6 +826,9 @@ <h4 class="tsd-returns-title">Returns <a href="aws_iot.awsiotmqttconnectionconfi
794826
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
795827
<a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_mtls_pkcs11_builder" class="tsd-kind-icon">new_<wbr>mtls_<wbr>pkcs11_<wbr>builder</a>
796828
</li>
829+
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
830+
<a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_mtls_windows_cert_store_path_builder" class="tsd-kind-icon">new_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path_<wbr>builder</a>
831+
</li>
797832
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
798833
<a href="aws_iot.awsiotmqttconnectionconfigbuilder.html#new_websocket_builder" class="tsd-kind-icon">new_<wbr>websocket_<wbr>builder</a>
799834
</li>

docs/classes/io.tlscontextoptions.html

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ <h3>Properties</h3>
107107
<li class="tsd-kind-property tsd-parent-kind-class"><a href="io.tlscontextoptions.html#private_key" class="tsd-kind-icon">private_<wbr>key</a></li>
108108
<li class="tsd-kind-property tsd-parent-kind-class"><a href="io.tlscontextoptions.html#private_key_filepath" class="tsd-kind-icon">private_<wbr>key_<wbr>filepath</a></li>
109109
<li class="tsd-kind-property tsd-parent-kind-class"><a href="io.tlscontextoptions.html#verify_peer" class="tsd-kind-icon">verify_<wbr>peer</a></li>
110+
<li class="tsd-kind-property tsd-parent-kind-class"><a href="io.tlscontextoptions.html#windows_cert_store_path" class="tsd-kind-icon">windows_<wbr>cert_<wbr>store_<wbr>path</a></li>
110111
</ul>
111112
</section>
112113
<section class="tsd-index-section ">
@@ -119,6 +120,7 @@ <h3>Methods</h3>
119120
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="io.tlscontextoptions.html#create_client_with_mtls_pkcs11" class="tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>pkcs11</a></li>
120121
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="io.tlscontextoptions.html#create_client_with_mtls_pkcs12_from_path" class="tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>pkcs12_<wbr>from_<wbr>path</a></li>
121122
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="io.tlscontextoptions.html#create_client_with_mtls_pkcs_from_path" class="tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>pkcs_<wbr>from_<wbr>path</a></li>
123+
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="io.tlscontextoptions.html#create_client_with_mtls_windows_cert_store_path" class="tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path</a></li>
122124
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="io.tlscontextoptions.html#create_server_with_mtls_from_path" class="tsd-kind-icon">create_<wbr>server_<wbr>with_<wbr>mtls_<wbr>from_<wbr>path</a></li>
123125
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="io.tlscontextoptions.html#create_server_with_mtls_pkcs_from_path" class="tsd-kind-icon">create_<wbr>server_<wbr>with_<wbr>mtls_<wbr>pkcs_<wbr>from_<wbr>path</a></li>
124126
</ul>
@@ -381,6 +383,18 @@ <h3>verify_<wbr>peer</h3>
381383
set this to true.</p>
382384
</div>
383385
</section>
386+
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-class">
387+
<a name="windows_cert_store_path" class="tsd-anchor"></a>
388+
<h3><span class="tsd-flag ts-flagOptional">Optional</span> windows_<wbr>cert_<wbr>store_<wbr>path</h3>
389+
<div class="tsd-signature tsd-kind-icon">windows_<wbr>cert_<wbr>store_<wbr>path<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">string</span></div>
390+
<aside class="tsd-sources">
391+
</aside>
392+
<div class="tsd-comment tsd-typography">
393+
<div class="lead">
394+
<p>Path to certificate in a Windows cert store. Windows only.</p>
395+
</div>
396+
</div>
397+
</section>
384398
</section>
385399
<section class="tsd-panel-group tsd-member-group ">
386400
<h2>Methods</h2>
@@ -616,6 +630,38 @@ <h4 class="tsd-returns-title">Returns <a href="io.tlscontextoptions.html" class=
616630
</li>
617631
</ul>
618632
</section>
633+
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-static">
634+
<a name="create_client_with_mtls_windows_cert_store_path" class="tsd-anchor"></a>
635+
<h3><span class="tsd-flag ts-flagStatic">Static</span> create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path</h3>
636+
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class tsd-is-static">
637+
<li class="tsd-signature tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path<span class="tsd-signature-symbol">(</span>certificate_path<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="io.tlscontextoptions.html" class="tsd-signature-type">TlsContextOptions</a></li>
638+
</ul>
639+
<ul class="tsd-descriptions">
640+
<li class="tsd-description">
641+
<aside class="tsd-sources">
642+
</aside>
643+
<div class="tsd-comment tsd-typography">
644+
<div class="lead">
645+
<p>Create options configured for mutual TLS in client mode,
646+
using a certificate in a Windows certificate store.</p>
647+
</div>
648+
<p>NOTE: Windows only.</p>
649+
</div>
650+
<h4 class="tsd-parameters-title">Parameters</h4>
651+
<ul class="tsd-parameters">
652+
<li>
653+
<h5>certificate_path: <span class="tsd-signature-type">string</span></h5>
654+
<div class="tsd-comment tsd-typography">
655+
<p>Path to certificate in a Windows certificate store.
656+
The path must use backslashes and end with the certificate&#39;s thumbprint.
657+
Example: <code>CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6</code></p>
658+
</div>
659+
</li>
660+
</ul>
661+
<h4 class="tsd-returns-title">Returns <a href="io.tlscontextoptions.html" class="tsd-signature-type">TlsContextOptions</a></h4>
662+
</li>
663+
</ul>
664+
</section>
619665
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-static">
620666
<a name="create_server_with_mtls_from_path" class="tsd-anchor"></a>
621667
<h3><span class="tsd-flag ts-flagStatic">Static</span> create_<wbr>server_<wbr>with_<wbr>mtls_<wbr>from_<wbr>path</h3>
@@ -806,6 +852,9 @@ <h4 class="tsd-returns-title">Returns <a href="io.tlscontextoptions.html" class=
806852
<li class=" tsd-kind-property tsd-parent-kind-class">
807853
<a href="io.tlscontextoptions.html#verify_peer" class="tsd-kind-icon">verify_<wbr>peer</a>
808854
</li>
855+
<li class=" tsd-kind-property tsd-parent-kind-class">
856+
<a href="io.tlscontextoptions.html#windows_cert_store_path" class="tsd-kind-icon">windows_<wbr>cert_<wbr>store_<wbr>path</a>
857+
</li>
809858
<li class=" tsd-kind-method tsd-parent-kind-class">
810859
<a href="io.tlscontextoptions.html#override_default_trust_store" class="tsd-kind-icon">override_<wbr>default_<wbr>trust_<wbr>store</a>
811860
</li>
@@ -827,6 +876,9 @@ <h4 class="tsd-returns-title">Returns <a href="io.tlscontextoptions.html" class=
827876
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
828877
<a href="io.tlscontextoptions.html#create_client_with_mtls_pkcs_from_path" class="tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>pkcs_<wbr>from_<wbr>path</a>
829878
</li>
879+
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
880+
<a href="io.tlscontextoptions.html#create_client_with_mtls_windows_cert_store_path" class="tsd-kind-icon">create_<wbr>client_<wbr>with_<wbr>mtls_<wbr>windows_<wbr>cert_<wbr>store_<wbr>path</a>
881+
</li>
830882
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
831883
<a href="io.tlscontextoptions.html#create_server_with_mtls_from_path" class="tsd-kind-icon">create_<wbr>server_<wbr>with_<wbr>mtls_<wbr>from_<wbr>path</a>
832884
</li>

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@
3131
"typescript": "^3.9.7"
3232
},
3333
"dependencies": {
34-
"aws-crt": "1.11.3"
34+
"aws-crt": "1.12.0"
3535
}
3636
}

samples/README.md

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
* [pub_sub](#nodepub_sub)
44
* [pub_sub_js](#nodepub_sub_js)
5-
* [basic_connect](#basic_connect)
6-
* [websocket_connect](#websocket_connect)
7-
* [pkcs11_connect](#websocket_pkcs11)
5+
* [basic_connect](#nodebasic_connect)
6+
* [websocket_connect](#nodewebsocket_connect)
7+
* [pkcs11_connect](#nodepkcs11_connect)
8+
* [windows_cert_connect](#nodewindows_cert_connect)
89
* [shadow](#nodeshadow)
910
* [fleet provisioning](#fleet-provisioning)
10-
* [basic discovery](#nodebasic_discovery)
11+
* [basic discovery](#greengrass-discovery-basic-discovery)
1112

1213
## Note
1314

@@ -28,7 +29,7 @@ To:
2829
}
2930
```
3031

31-
## Node/Pub_sub
32+
## Node/pub_sub
3233

3334
This sample uses the
3435
[Message Broker](https://docs.aws.amazon.com/iot/latest/developerguide/iot-message-broker.html)
@@ -101,7 +102,7 @@ npm install
101102
node index.js --endpoint <endpoint> --ca_file <file> --cert <file> --key <file>
102103
```
103104

104-
## Node/Basic_Connect
105+
## Node/basic_connect
105106

106107
This sample creates a basic MQTT connection using a certificate and key file.
107108
On startup, the device connects and then disconnects from the AWS server. This
@@ -139,7 +140,7 @@ and receive.
139140
</pre>
140141
</details>
141142

142-
## Node/Websocket_Connect
143+
## Node/websocket_connect
143144

144145
This sample creates a basic MQTT connection using websockets.
145146
On startup, the device connects and then disconnects from the AWS server. This
@@ -177,7 +178,7 @@ and receive.
177178
</pre>
178179
</details>
179180

180-
## Node/Pkcs11_Connect
181+
## Node/pkcs11_connect
181182

182183
This sample is similar to the basic connect sample, but the private key for mutual TLS is stored on
183184
a PKCS#11 compatible smart card or hardware security module (HSM).
@@ -270,6 +271,70 @@ and receive.
270271
</pre>
271272
</details>
272273
274+
## Node/windows_cert_connect
275+
276+
WARNING: Windows only
277+
278+
This sample is similar to the basic connect sample, but your certificate and private key are in a
279+
[Windows certificate store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores),
280+
rather than simply being files on disk.
281+
282+
To run this sample you need the path to your certificate in the store,
283+
which will look something like:
284+
"CurrentUser\My\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6"
285+
(where "CurrentUser\My" is the store and "A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6" is the certificate's thumbprint)
286+
287+
If your certificate and private key are in a
288+
[TPM](https://docs.microsoft.com/en-us/windows/security/information-protection/tpm/trusted-platform-module-overview),
289+
you would use them by passing their certificate store path.
290+
291+
source: `samples/node/windows_cert_connect`
292+
293+
To run this sample with a basic certificate from AWS IoT Core:
294+
295+
1) Create an IoT Thing with a certificate and key if you haven't already.
296+
297+
2) Combine the certificate and private key into a single .pfx file.
298+
299+
You will be prompted for a password while creating this file. Remember it for the next step.
300+
301+
If you have OpenSSL installed:
302+
```powershell
303+
openssl pkcs12 -in certificate.pem.crt -inkey private.pem.key -out certificate.pfx
304+
```
305+
306+
Otherwise use [CertUtil](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/certutil).
307+
```powershell
308+
certutil -mergePFX certificate.pem.crt,private.pem.key certificate.pfx
309+
```
310+
311+
3) Add the .pfx file to a Windows certificate store using PowerShell's
312+
[Import-PfxCertificate](https://docs.microsoft.com/en-us/powershell/module/pki/import-pfxcertificate)
313+
314+
In this example we're adding it to "CurrentUser\My"
315+
316+
```powershell
317+
$mypwd = Get-Credential -UserName 'Enter password below' -Message 'Enter password below'
318+
Import-PfxCertificate -FilePath certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password $mypwd.Password
319+
```
320+
321+
Note the certificate thumbprint that is printed out:
322+
```
323+
Thumbprint Subject
324+
---------- -------
325+
A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6 CN=AWS IoT Certificate
326+
```
327+
328+
So this certificate's path would be: "CurrentUser\My\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6"
329+
330+
4) Now you can run the sample:
331+
332+
```
333+
npm install
334+
node dist\index.js --endpoint xxxx-ats.iot.xxxx.amazonaws.com --ca_file AmazonRootCA1.pem --cert CurrentUser\My\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6
335+
```
336+
337+
273338
## Node/shadow
274339
275340
This sample uses the AWS IoT

0 commit comments

Comments
 (0)