Skip to content

Commit 813bc8f

Browse files
committed
Use truststore by default, add '--use-deprecated=legacy-certs' to disable
1 parent 18c0a7f commit 813bc8f

File tree

11 files changed

+369
-138
lines changed

11 files changed

+369
-138
lines changed

docs/html/topics/https-certificates.md

+13-41
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
By default, pip will perform SSL certificate verification for network
1010
connections it makes over HTTPS. These serve to prevent man-in-the-middle
11-
attacks against package downloads. This does not use the system certificate
12-
store but, instead, uses a bundled CA certificate store from {pypi}`certifi`.
11+
attacks against package downloads. Pip by default uses a bundled CA certificate
12+
store from {pypi}`certifi`.
1313

1414
## Using a specific certificate store
1515

@@ -20,52 +20,24 @@ variables.
2020

2121
## Using system certificate stores
2222

23-
```{versionadded} 22.2
24-
Experimental support, behind `--use-feature=truststore`.
25-
```
26-
27-
It is possible to use the system trust store, instead of the bundled certifi
28-
certificates for verifying HTTPS certificates. This approach will typically
29-
support corporate proxy certificates without additional configuration.
30-
31-
In order to use system trust stores, you need to:
32-
33-
- Use Python 3.10 or newer.
34-
- Install the {pypi}`truststore` package, in the Python environment you're
35-
running pip in.
36-
37-
This is typically done by installing this package using a system package
38-
manager or by using pip in {ref}`Hash-checking mode` for this package and
39-
trusting the network using the `--trusted-host` flag.
40-
41-
```{pip-cli}
42-
$ python -m pip install truststore
43-
[...]
44-
$ python -m pip install SomePackage --use-feature=truststore
45-
[...]
46-
Successfully installed SomePackage
47-
```
23+
```{versionadded} 23.1
4824
49-
### When to use
50-
51-
You should try using system trust stores when there is a custom certificate
52-
chain configured for your system that pip isn't aware of. Typically, this
53-
situation will manifest with an `SSLCertVerificationError` with the message
54-
"certificate verify failed: unable to get local issuer certificate":
55-
56-
```{pip-cli}
57-
$ pip install -U SomePackage
58-
[...]
59-
SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (\_ssl.c:997)'))) - skipping
6025
```
6126

62-
This error means that OpenSSL wasn't able to find a trust anchor to verify the
63-
chain against. Using system trust stores instead of certifi will likely solve
64-
this issue.
27+
If Python 3.10 or later is being used then by default
28+
system certificates are used in addition to certifi to verify HTTPS connections.
29+
This functionality is provided through the {pypi}`truststore` package.
6530

6631
If you encounter a TLS/SSL error when using the `truststore` feature you should
6732
open an issue on the [truststore GitHub issue tracker] instead of pip's issue
6833
tracker. The maintainers of truststore will help diagnose and fix the issue.
6934

35+
To opt-out of using system certificates you can pass the `--use-deprecated=legacy-certs`
36+
flag to pip.
37+
38+
```{warning}
39+
If Python 3.9 or earlier is in use then only certifi is used to verify HTTPS connections.
40+
```
41+
7042
[truststore github issue tracker]:
7143
https://github.com/sethmlarson/truststore/issues

src/pip/_internal/cli/cmdoptions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,6 @@ def check_list_path_option(options: Values) -> None:
982982
default=[],
983983
choices=[
984984
"fast-deps",
985-
"truststore",
986985
"no-binary-enable-wheel-cache",
987986
],
988987
help="Enable new functionality, that may be backward incompatible.",
@@ -997,6 +996,7 @@ def check_list_path_option(options: Values) -> None:
997996
default=[],
998997
choices=[
999998
"legacy-resolver",
999+
"legacy-certs",
10001000
],
10011001
help=("Enable deprecated functionality, that will be removed in the future."),
10021002
)

src/pip/_internal/cli/req_command.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from optparse import Values
1313
from typing import TYPE_CHECKING, Any, List, Optional, Tuple
1414

15+
from pip._vendor import certifi
16+
1517
from pip._internal.cache import WheelCache
1618
from pip._internal.cli import cmdoptions
1719
from pip._internal.cli.base_command import Command
@@ -57,15 +59,18 @@ def _create_truststore_ssl_context() -> Optional["SSLContext"]:
5759
logger.warning("Disabling truststore since ssl support is missing")
5860
return None
5961

62+
# Since truststore is developed with only Python 3.10+ in mind
63+
# we delay the import until we know we're running pip with Python 3.10+.
6064
try:
61-
import truststore
62-
except ImportError:
63-
raise CommandError(
64-
"To use the truststore feature, 'truststore' must be installed into "
65-
"pip's current environment."
66-
)
65+
from pip._vendor import truststore
66+
# Truststore doesn't work on macOS versions earlier than 10.8
67+
except OSError:
68+
logger.warning("Disabling truststore since OS version isn't supported")
69+
return None
6770

68-
return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
71+
ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
72+
ctx.load_verify_locations(cafile=certifi.where())
73+
return ctx
6974

7075

7176
class SessionCommandMixin(CommandContextMixIn):
@@ -112,7 +117,7 @@ def _build_session(
112117
cache_dir = options.cache_dir
113118
assert not cache_dir or os.path.isabs(cache_dir)
114119

115-
if "truststore" in options.features_enabled:
120+
if "legacy-certs" not in options.deprecated_features_enabled:
116121
try:
117122
ssl_context = _create_truststore_ssl_context()
118123
except Exception:
+9-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
"""Verify certificates using OS trust stores"""
1+
"""Verify certificates using OS trust stores. This is useful when your system contains
2+
custom certificate authorities such as when using a corporate proxy or using test certificates.
3+
Supports macOS, Windows, and Linux (with OpenSSL).
4+
"""
25

36
import sys as _sys
47

58
if _sys.version_info < (3, 10):
69
raise ImportError("truststore requires Python 3.10 or later")
7-
del _sys
810

9-
from ._api import SSLContext # noqa: E402
11+
from ._api import SSLContext, extract_from_ssl, inject_into_ssl # noqa: E402
1012

11-
__all__ = ["SSLContext"]
12-
__version__ = "0.5.0"
13+
del _api, _sys # type: ignore[name-defined] # noqa: F821
14+
15+
__all__ = ["SSLContext", "inject_into_ssl", "extract_from_ssl"]
16+
__version__ = "0.6.0"

0 commit comments

Comments
 (0)