Skip to content

Commit b3b1d99

Browse files
authored
Support mutual TLS using a certificate from a Windows cert store (#292)
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_pubsub.py` sample to show this in action.
1 parent 0face13 commit b3b1d99

15 files changed

+492
-761
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
docs/.buildinfo
22
docs/.doctrees/
33
__pycache__/
4+
*.egg-info

awsiot/mqtt_connection_builder.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ def mtls_with_pkcs11(*,
267267
This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT,
268268
using a PKCS#11 library for private key operations.
269269
270+
NOTE: Unix only
271+
270272
This function takes all :mod:`common arguments<awsiot.mqtt_connection_builder>`
271273
described at the top of this doc, as well as...
272274
@@ -309,6 +311,30 @@ def mtls_with_pkcs11(*,
309311
return _builder(tls_ctx_options, **kwargs)
310312

311313

314+
def mtls_with_windows_cert_store_path(*,
315+
cert_store_path: str,
316+
**kwargs) -> awscrt.mqtt.Connection:
317+
"""
318+
This builder creates an :class:`awscrt.mqtt.Connection`, configured for an mTLS MQTT connection to AWS IoT,
319+
using a client certificate in a Windows certificate store.
320+
321+
NOTE: Windows only
322+
323+
This function takes all :mod:`common arguments<awsiot.mqtt_connection_builder>`
324+
described at the top of this doc, as well as...
325+
326+
Args:
327+
cert_store_path: Path to certificate in a Windows certificate store.
328+
The path must use backslashes and end with the certificate's thumbprint.
329+
Example: ``CurrentUser\\MY\\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6``
330+
"""
331+
_check_required_kwargs(**kwargs)
332+
333+
tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_windows_cert_store_path(cert_store_path)
334+
335+
return _builder(tls_ctx_options, **kwargs)
336+
337+
312338
def websockets_with_default_aws_signing(
313339
region,
314340
credentials_provider,

docs/awsiot/eventstreamrpc.html

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,13 @@ <h3>Navigation</h3>
196196
</dl>
197197
<dl class="py attribute">
198198
<dt class="sig sig-object py" id="awsiot.eventstreamrpc.MessageAmendment.headers">
199-
<span class="sig-name descname"><span class="pre">headers</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Sequence</span><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://awslabs.github.io/aws-crt-python/api/eventstream.html#awscrt.eventstream.Header" title="(in awscrt)"><span class="pre">awscrt.eventstream.Header</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></em><a class="headerlink" href="#awsiot.eventstreamrpc.MessageAmendment.headers" title="Permalink to this definition"></a></dt>
199+
<span class="sig-name descname"><span class="pre">headers</span></span><a class="headerlink" href="#awsiot.eventstreamrpc.MessageAmendment.headers" title="Permalink to this definition"></a></dt>
200200
<dd><p>Headers to add</p>
201201
</dd></dl>
202202

203203
<dl class="py attribute">
204204
<dt class="sig sig-object py" id="awsiot.eventstreamrpc.MessageAmendment.payload">
205-
<span class="sig-name descname"><span class="pre">payload</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#bytes" title="(in Python v3.10)"><span class="pre">bytes</span></a><span class="p"><span class="pre">]</span></span></em><a class="headerlink" href="#awsiot.eventstreamrpc.MessageAmendment.payload" title="Permalink to this definition"></a></dt>
205+
<span class="sig-name descname"><span class="pre">payload</span></span><a class="headerlink" href="#awsiot.eventstreamrpc.MessageAmendment.payload" title="Permalink to this definition"></a></dt>
206206
<dd><p>Binary payload data</p>
207207
</dd></dl>
208208

@@ -221,7 +221,7 @@ <h3>Navigation</h3>
221221
<cite>connect_message_amender</cite> init arg.</p>
222222
</dd>
223223
<dt class="field-odd">Return type</dt>
224-
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Callable" title="(in Python v3.10)"><em>Callable</em></a>[[], <a class="reference internal" href="#awsiot.eventstreamrpc.MessageAmendment" title="awsiot.eventstreamrpc.MessageAmendment">awsiot.eventstreamrpc.MessageAmendment</a>]</p>
224+
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Callable" title="(in Python v3.10)"><em>Callable</em></a>[<a class="reference internal" href="#awsiot.eventstreamrpc.MessageAmendment" title="awsiot.eventstreamrpc.MessageAmendment">awsiot.eventstreamrpc.MessageAmendment</a>]</p>
225225
</dd>
226226
</dl>
227227
</dd></dl>
@@ -250,7 +250,7 @@ <h3>Navigation</h3>
250250
<li><p><strong>tls_connection_options</strong> (<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Optional" title="(in Python v3.10)"><em>Optional</em></a><em>[</em><a class="reference external" href="https://awslabs.github.io/aws-crt-python/api/io.html#awscrt.io.TlsConnectionOptions" title="(in awscrt)"><em>awscrt.io.TlsConnectionOptions</em></a><em>]</em>) – Optional TLS connection options.
251251
If None is provided, then the connection will be attempted over
252252
plain-text.</p></li>
253-
<li><p><strong>connect_message_amender</strong> (<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Optional" title="(in Python v3.10)"><em>Optional</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Callable" title="(in Python v3.10)"><em>Callable</em></a><em>[</em><em>[</em><em>]</em><em>, </em><a class="reference internal" href="#awsiot.eventstreamrpc.MessageAmendment" title="awsiot.eventstreamrpc.MessageAmendment"><em>awsiot.eventstreamrpc.MessageAmendment</em></a><em>]</em><em>]</em>) – Optional callable that should return a
253+
<li><p><strong>connect_message_amender</strong> (<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Optional" title="(in Python v3.10)"><em>Optional</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Callable" title="(in Python v3.10)"><em>Callable</em></a><em>[</em><a class="reference internal" href="#awsiot.eventstreamrpc.MessageAmendment" title="awsiot.eventstreamrpc.MessageAmendment"><em>awsiot.eventstreamrpc.MessageAmendment</em></a><em>]</em><em>]</em>) – Optional callable that should return a
254254
<a class="reference internal" href="#awsiot.eventstreamrpc.MessageAmendment" title="awsiot.eventstreamrpc.MessageAmendment"><code class="xref py py-class docutils literal notranslate"><span class="pre">MessageAmendment</span></code></a> for the
255255
<a class="reference external" href="https://awslabs.github.io/aws-crt-python/api/eventstream.html#awscrt.eventstream.rpc.MessageType.CONNECT" title="(in awscrt)"><code class="xref py py-attr docutils literal notranslate"><span class="pre">CONNECT</span></code></a> message.
256256
This callable will be invoked whenever a network connection is
@@ -398,6 +398,30 @@ <h3>Navigation</h3>
398398
</ul>
399399
</dd>
400400
</dl>
401+
<dl class="py method">
402+
<dt class="sig sig-object py" id="awsiot.eventstreamrpc.Client.close">
403+
<span class="sig-name descname"><span class="pre">close</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">reason</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#awsiot.eventstreamrpc.Client.close" title="Permalink to this definition"></a></dt>
404+
<dd><p>Close the connection.</p>
405+
<p>Shutdown is asynchronous. This call has no effect if the connection
406+
is already closed or closing.</p>
407+
<dl class="field-list simple">
408+
<dt class="field-odd">Parameters</dt>
409+
<dd class="field-odd"><p><strong>reason</strong> (<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Optional" title="(in Python v3.10)"><em>Optional</em></a><em>[</em><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#Exception" title="(in Python v3.10)"><em>Exception</em></a><em>]</em>) – If set, the connection will
410+
close with this error as the reason (unless
411+
it was already closing for another reason).</p>
412+
</dd>
413+
<dt class="field-even">Returns</dt>
414+
<dd class="field-even"><p>The future which will complete
415+
when the shutdown process is done. The future will have an
416+
exception if shutdown was caused by an error, or a result
417+
of None if the shutdown was clean and user-initiated.</p>
418+
</dd>
419+
<dt class="field-odd">Return type</dt>
420+
<dd class="field-odd"><p>concurrent.futures._base.Future</p>
421+
</dd>
422+
</dl>
423+
</dd></dl>
424+
401425
</dd></dl>
402426

403427
</section>

docs/awsiot/greengrass_discovery.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ <h3>Navigation</h3>
104104
</dl>
105105
<dl class="py attribute">
106106
<dt class="sig sig-object py" id="awsiot.greengrass_discovery.DiscoveryException.http_response_code">
107-
<span class="sig-name descname"><span class="pre">http_response_code</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.10)"><span class="pre">int</span></a></em><a class="headerlink" href="#awsiot.greengrass_discovery.DiscoveryException.http_response_code" title="Permalink to this definition"></a></dt>
107+
<span class="sig-name descname"><span class="pre">http_response_code</span></span><a class="headerlink" href="#awsiot.greengrass_discovery.DiscoveryException.http_response_code" title="Permalink to this definition"></a></dt>
108108
<dd><p>HTTP response code</p>
109109
</dd></dl>
110110

111111
<dl class="py attribute">
112112
<dt class="sig sig-object py" id="awsiot.greengrass_discovery.DiscoveryException.message">
113-
<span class="sig-name descname"><span class="pre">message</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><span class="pre">str</span></a></em><a class="headerlink" href="#awsiot.greengrass_discovery.DiscoveryException.message" title="Permalink to this definition"></a></dt>
113+
<span class="sig-name descname"><span class="pre">message</span></span><a class="headerlink" href="#awsiot.greengrass_discovery.DiscoveryException.message" title="Permalink to this definition"></a></dt>
114114
<dd><p>Message</p>
115115
</dd></dl>
116116

@@ -198,7 +198,7 @@ <h3>Navigation</h3>
198198
<p>Discovery response</p>
199199
<dl class="py attribute">
200200
<dt class="sig sig-object py" id="awsiot.greengrass_discovery.DiscoverResponse.gg_groups">
201-
<span class="sig-name descname"><span class="pre">gg_groups</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">List</span><span class="p"><span class="pre">[</span></span><a class="reference internal" href="#awsiot.greengrass_discovery.GGGroup" title="awsiot.greengrass_discovery.GGGroup"><span class="pre">awsiot.greengrass_discovery.GGGroup</span></a><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></em><a class="headerlink" href="#awsiot.greengrass_discovery.DiscoverResponse.gg_groups" title="Permalink to this definition"></a></dt>
201+
<span class="sig-name descname"><span class="pre">gg_groups</span></span><a class="headerlink" href="#awsiot.greengrass_discovery.DiscoverResponse.gg_groups" title="Permalink to this definition"></a></dt>
202202
<dd><p>List of <a class="reference internal" href="#awsiot.greengrass_discovery.GGGroup" title="awsiot.greengrass_discovery.GGGroup"><code class="xref py py-class docutils literal notranslate"><span class="pre">GGGroup</span></code></a></p>
203203
</dd></dl>
204204

0 commit comments

Comments
 (0)