Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vendor truststore #12107

Merged
merged 6 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 1 addition & 11 deletions docs/html/topics/https-certificates.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,9 @@ It is possible to use the system trust store, instead of the bundled certifi
certificates for verifying HTTPS certificates. This approach will typically
support corporate proxy certificates without additional configuration.

In order to use system trust stores, you need to:

- Use Python 3.10 or newer.
- Install the {pypi}`truststore` package, in the Python environment you're
running pip in.

This is typically done by installing this package using a system package
manager or by using pip in {ref}`Hash-checking mode` for this package and
trusting the network using the `--trusted-host` flag.
In order to use system trust stores, you need to use Python 3.10 or newer.

```{pip-cli}
$ python -m pip install truststore
[...]
$ python -m pip install SomePackage --use-feature=truststore
[...]
Successfully installed SomePackage
Expand Down
1 change: 1 addition & 0 deletions news/truststore.vendor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add truststore 0.8.0
6 changes: 6 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ def lint(session: nox.Session) -> None:
# git reset --hard origin/main
@nox.session
def vendoring(session: nox.Session) -> None:
# Ensure that the session Python is running 3.10+
# so that truststore can be installed correctly.
session.run(
"python", "-c", "import sys; sys.exit(1 if sys.version_info < (3, 10) else 0)"
)

session.install("vendoring~=1.2.0")

parser = argparse.ArgumentParser(prog="nox -s vendoring")
Expand Down
9 changes: 3 additions & 6 deletions src/pip/_internal/cli/req_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@ def _create_truststore_ssl_context() -> Optional["SSLContext"]:
return None

try:
import truststore
except ImportError:
raise CommandError(
"To use the truststore feature, 'truststore' must be installed into "
"pip's current environment."
)
from pip._vendor import truststore
except ImportError as e:
raise CommandError(f"The truststore feature is unavailable: {e}")

return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

Expand Down
15 changes: 11 additions & 4 deletions src/pip/_internal/commands/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,29 @@ def create_vendor_txt_map() -> Dict[str, str]:
return dict(line.split("==", 1) for line in lines)


def get_module_from_module_name(module_name: str) -> ModuleType:
def get_module_from_module_name(module_name: str) -> Optional[ModuleType]:
# Module name can be uppercase in vendor.txt for some reason...
module_name = module_name.lower().replace("-", "_")
# PATCH: setuptools is actually only pkg_resources.
if module_name == "setuptools":
module_name = "pkg_resources"

__import__(f"pip._vendor.{module_name}", globals(), locals(), level=0)
return getattr(pip._vendor, module_name)
try:
__import__(f"pip._vendor.{module_name}", globals(), locals(), level=0)
return getattr(pip._vendor, module_name)
except ImportError:
# We allow 'truststore' to fail to import due
# to being unavailable on Python 3.9 and earlier.
if module_name == "truststore" and sys.version_info < (3, 10):
return None
raise


def get_vendor_version_from_module(module_name: str) -> Optional[str]:
module = get_module_from_module_name(module_name)
version = getattr(module, "__version__", None)

if not version:
if module and not version:
# Try to find version in debundled module info.
assert module.__file__ is not None
env = get_environment([os.path.dirname(module.__file__)])
Expand Down
1 change: 1 addition & 0 deletions src/pip/_vendor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,5 @@ def vendored(modulename):
vendored("rich.traceback")
vendored("tenacity")
vendored("tomli")
vendored("truststore")
vendored("urllib3")
21 changes: 21 additions & 0 deletions src/pip/_vendor/truststore/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2022 Seth Michael Larson

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
13 changes: 13 additions & 0 deletions src/pip/_vendor/truststore/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Verify certificates using native system trust stores"""

import sys as _sys

if _sys.version_info < (3, 10):
raise ImportError("truststore requires Python 3.10 or later")

from ._api import SSLContext, extract_from_ssl, inject_into_ssl # noqa: E402

del _api, _sys # type: ignore[name-defined] # noqa: F821

__all__ = ["SSLContext", "inject_into_ssl", "extract_from_ssl"]
__version__ = "0.8.0"