Skip to content

Commit

Permalink
feat: Support OS truststore for the TLS certificate verification
Browse files Browse the repository at this point in the history
This commit add support for loading the OS truststore root certificates in addition to the "legacy" certifi bundle. It will come in handy for every user behind a company proxy or just using a private PyPI warehouse.

Close #9249
  • Loading branch information
Ousret committed Sep 12, 2024
1 parent 3183126 commit 7fece0d
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 6 deletions.
4 changes: 4 additions & 0 deletions docs/repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,10 @@ poetry config -- http-basic.pypi myUsername -myPasswordStartingWithDash

## Certificates

### OS Truststore

Poetry access the system truststore by default and retrieve the root certificates appropriately on Linux, Windows, and MacOS.

### Custom certificate authority and mutual TLS authentication

Poetry supports repositories that are secured by a custom certificate authority as well as those that require
Expand Down
95 changes: 91 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ tomlkit = ">=0.11.4,<1.0.0"
trove-classifiers = ">=2022.5.19"
virtualenv = "^20.23.0"
xattr = { version = "^1.0.0", markers = "sys_platform == 'darwin'" }
wassima = "^1.1.2"

[tool.poetry.group.dev.dependencies]
pre-commit = ">=2.10"
Expand Down
4 changes: 2 additions & 2 deletions src/poetry/utils/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import requests.auth
import requests.exceptions

from cachecontrol import CacheControlAdapter
from cachecontrol.caches import FileCache
from requests_toolbelt import user_agent

Expand All @@ -28,6 +27,7 @@
from poetry.utils.constants import STATUS_FORCELIST
from poetry.utils.password_manager import HTTPAuthCredential
from poetry.utils.password_manager import PasswordManager
from poetry.utils.truststore import WithTrustStoreAdapter


if TYPE_CHECKING:
Expand Down Expand Up @@ -137,7 +137,7 @@ def create_session(self) -> requests.Session:
if self._cache_control is None:
return session

adapter = CacheControlAdapter(
adapter = WithTrustStoreAdapter(
cache=self._cache_control,
pool_maxsize=self._pool_size,
)
Expand Down
26 changes: 26 additions & 0 deletions src/poetry/utils/truststore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import annotations

from cachecontrol import CacheControlAdapter
from wassima import RUSTLS_LOADED
from wassima import generate_ca_bundle


DEFAULT_CA_BUNDLE = generate_ca_bundle()


class WithTrustStoreAdapter(CacheControlAdapter):
"""
Inject the OS truststore in Requests.
Certifi is still loaded in addition to the OS truststore for backward compatibility purposes.
See https://github.com/jawah/wassima for more details.
"""

def cert_verify(self, conn, url, verify, cert):
#: only apply truststore cert if "verify" is set with default value "True".
#: RUSTLS_LOADED means that "wassima" is not the py3 none wheel and does not fallback on "certifi"
#: if "RUSTLS_LOADED" is False then "wassima" just return "certifi" bundle instead.
if RUSTLS_LOADED and url.lower().startswith("https") and verify is True:
conn.ca_cert_data = DEFAULT_CA_BUNDLE

# still apply upstream logic as before
super().cert_verify(conn, url, verify, cert)

0 comments on commit 7fece0d

Please sign in to comment.