File: index.md

package info (click to toggle)
python-truststore 0.10.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 236 kB
  • sloc: python: 1,835; makefile: 13; sh: 6
file content (185 lines) | stat: -rw-r--r-- 6,482 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# Truststore

```{toctree}
:maxdepth: 2
:caption: Contents
```

Truststore is a library which exposes native system certificate stores (ie "trust stores")
through an `ssl.SSLContext`-like API. This means that Python applications no longer need to
rely on certifi as a root certificate store. Native system certificate stores
have many helpful features compared to a static certificate bundle like certifi:

- Automatically update certificates as new CAs are created and removed
- Fetch missing intermediate certificates
- Check certificates against certificate revocation lists (CRLs) to avoid monster-in-the-middle (MITM) attacks
- Managed per-system rather than per-application by a operations/IT team
- PyPI is no longer a CA distribution channel 🥳

Right now truststore is a stand-alone library that can be installed globally in your
application to immediately take advantage of the benefits in Python 3.10+. Truststore
has also been integrated into pip as an opt-in method for verifying HTTPS certificates
with truststore instead of certifi.

Long-term the hope is to make truststore the default way to verify HTTPS certificates in pip
and to add this functionality into Python itself. Wish us luck!

## Installation

Truststore can be installed from [PyPI](https://pypi.org/project/truststore) with pip:

```{code-block} shell
$ python -m pip install truststore
```

Truststore **requires Python 3.10 or later** and supports the following platforms:
- macOS 10.8+ via [Security framework](https://developer.apple.com/documentation/security)
- Windows via [CryptoAPI](https://docs.microsoft.com/en-us/windows/win32/seccrypto/cryptography-functions#certificate-verification-functions)
- Linux via OpenSSL

## User Guide

```{warning}
**PLEASE READ:** `inject_into_ssl()` **must not be used by libraries or packages** as it will cause issues on import time when integrated with other libraries.
Libraries and packages should instead use `truststore.SSLContext` directly which is detailed below. 
The `inject_into_ssl()` function is intended only for use in applications and scripts.
```

You can inject `truststore` into the standard library `ssl` module so the functionality is used
by every library by default. To do so use the `truststore.inject_into_ssl()` function.

The call to `truststore.inject_into_ssl()` should be called as early as possible in
your program as modules that have already imported `ssl.SSLContext` won't be affected.

```python
import truststore
truststore.inject_into_ssl()

# Automatically works with urllib3, requests, aiohttp, and more:
import urllib3
http = urllib3.PoolManager()
resp = http.request("GET", "https://example.com")

import aiohttp
http = aiohttp.ClientSession()
resp = await http.request("GET", "https://example.com")

import requests
resp = requests.get("https://example.com")
```

If you'd like finer-grained control you can create your own `truststore.SSLContext` instance
and use it anywhere you'd use an `ssl.SSLContext`:

```python
import ssl
import truststore

ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

import urllib3
http = urllib3.PoolManager(ssl_context=ctx)
resp = http.request("GET", "https://example.com")
```

If Truststore can't work for a given platform due to APIs not being available then
at import time the exception `ImportError` will be raised with an informative message:

```python
# On Python 3.9 and earlier:
import truststore  # Raises 'ImportError'

# On macOS 10.7 and earlier:
import truststore  # Raises 'ImportError'
```

### Using truststore with pip

[Pip v22.2](https://discuss.python.org/t/announcement-pip-22-2-release/17543) includes experimental support for verifying certificates with system trust stores using `truststore`. To enable the feature, use the flag `--use-feature=truststore` when installing a package like so:

```{code-block} bash
# Install Django using system trust stores
$ python -m pip install --use-feature=truststore Django
```

This requires `truststore` to be installed in the same environment as the one running pip and to be running Python 3.10 or later. For more information you can [read the pip documentation about the feature](https://pip.pypa.io/en/stable/user_guide/#using-system-trust-stores-for-verifying-https).

### Using truststore with urllib3

```{code-block} python
import urllib3
import truststore

truststore.inject_into_ssl()

http = urllib3.PoolManager()
resp = http.request("GET", "https://example.com")
```

If you'd like to use the `truststore.SSLContext` directly you can pass
the instance via the `ssl_context` parameter:

```{code-block} python
import ssl
import urllib3
import truststore

ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

http = urllib3.PoolManager(ssl_context=ctx)
resp = http.request("GET", "https://example.com")
```

### Using truststore with aiohttp

Truststore supports wrapping either {py:class}`socket.socket` or {py:class}`ssl.MemoryBIO` which means both synchronous and asynchronous I/O can be used:

```{code-block} python
import aiohttp
import truststore

truststore.inject_into_ssl()

async with aiohttp.ClientSession() as http_client:
    async with http_client.get("https://example.com") as http_response:
        ...
```

If you'd like to use the `truststore.SSLContext` directly you can pass
the instance via the `ssl` parameter:

```{code-block} python
import ssl
import aiohttp
import truststore

ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

async with aiohttp.ClientSession(ssl=ctx) as http_client:
    async with http_client.get("https://example.com") as http_response:
        ...
```

### Using truststore with Requests

Just like with `urllib3` using `truststore.inject_into_ssl()` is the easiest method for using Truststore with Requests:

```{code-block} python
import requests
import truststore

truststore.inject_into_ssl()

resp = requests.request("GET", "https://example.com")
```

## Prior art

* [pip v22.2 with support for `--use-feature=truststore`](https://discuss.python.org/t/announcement-pip-22-2-release/17543)
* [The future of trust stores in Python (PyCon US 2022 lightning talk)](https://youtu.be/1IiL31tUEVk?t=698) ([slides](https://speakerdeck.com/sethmlarson/the-future-of-trust-stores-in-python))
* [Experimental APIs in Python 3.10 and the future of trust stores](https://sethmlarson.dev/blog/2021-11-27/experimental-python-3.10-apis-and-trust-stores)
* [PEP 543: A Unified TLS API for Python](https://www.python.org/dev/peps/pep-0543)

## License

MIT