From 52f0e0a74dd8997091984c6635016e53d9cc5d10 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Fri, 11 Dec 2020 17:35:02 -0800 Subject: [PATCH 01/16] Issue #3483 Add cert retrieval for requests The authenticator.py code already retrieves credentials from the config for every request based on url matching. This change makes the authenticator also retrieve certs from the config for each request based on url matching. Also includes unit tests. --- src/poetry/utils/authenticator.py | 49 ++++++++++++++++++++++++++++-- tests/utils/test_authenticator.py | 50 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 85f7dadc955..478d306b088 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -1,4 +1,5 @@ import logging +import pathlib import time import urllib.parse @@ -7,6 +8,8 @@ from typing import Dict from typing import Optional from typing import Tuple +from typing import Dict +from typing import Generator import requests import requests.auth @@ -14,6 +17,7 @@ from poetry.exceptions import PoetryException from poetry.utils.password_manager import PasswordManager +from poetry.utils.helpers import get_cert, get_client_cert if TYPE_CHECKING: @@ -31,6 +35,7 @@ def __init__(self, config: "Config", io: Optional["IO"] = None) -> None: self._io = io self._session = None self._credentials = {} + self._certs = {} self._password_manager = PasswordManager(self._config) def _log(self, message: str, level: str = "debug") -> None: @@ -62,8 +67,10 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response: proxies = kwargs.get("proxies", {}) stream = kwargs.get("stream") - verify = kwargs.get("verify") - cert = kwargs.get("cert") + + certs = self.get_certs_for_url(url) + verify = kwargs.get("verify", certs.get("verify")) + cert = kwargs.get("cert", certs.get("cert")) settings = session.merge_environment_settings( prepared_request.url, proxies, stream, verify, cert @@ -168,6 +175,31 @@ def _get_credentials_for_netloc( ) -> Tuple[Optional[str], Optional[str]]: credentials = (None, None) + for (repository_name, repository_netloc) in self._get_repository_netlocs(): + if netloc == repository_netloc: + auth = self._password_manager.get_http_auth(repository_name) + + if auth is None: + continue + + credentials = (auth["username"], auth["password"]) + break + + return credentials + + def get_certs_for_url( + self, url: str + ) -> Dict[str, pathlib.PosixPath]: + parsed_url = urllib.parse.urlsplit(url) + + netloc = parsed_url.netloc + + return self._certs.setdefault( + netloc, + self._get_certs_for_netloc_from_config(netloc), + ) + + def _get_repository_netlocs(self) -> Generator[[str, str], None, None]: for repository_name in self._config.get("repositories", []): auth = self._get_http_auth(repository_name, netloc) @@ -204,3 +236,16 @@ def _get_credentials_for_netloc_from_keyring( } return None + + def _get_certs_for_netloc_from_config( + self, netloc: str + ) -> Dict[str, pathlib.PosixPath]: + certs = dict(cert=None, verify=None) + + for (repository_name, repository_netloc) in self._get_repository_netlocs(): + if netloc == repository_netloc: + certs['cert'] = get_client_cert(self._config, repository_name) + certs['verify'] = get_cert(self._config, repository_name) + break + + return certs diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 9c36f9d49c8..18007328801 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -1,3 +1,4 @@ +import pathlib import re import uuid @@ -308,3 +309,52 @@ def test_authenticator_uses_env_provided_credentials( request = http.last_request() assert request.headers["Authorization"] == "Basic YmFyOmJheg==" + + +def test_authenticator_uses_certs_from_config_if_not_provided( + config, mock_remote, http, mocker +): + config.merge( + { + "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, + "http-basic": {"foo": {"username": "bar", "password": "baz"}}, + "certificates": {"foo": { + "cert": "/path/to/cert", + "client-cert": "/path/to/client-cert", + }}, + } + ) + + authenticator = Authenticator(config, NullIO()) + session_send = mocker.patch.object(authenticator.session, "send") + authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") + call_args = session_send.call_args + call_args.kwargs["verify"] == pathlib.Path("/path/to/cert") + call_args.kwargs["cert"] == pathlib.Path("/path/to/client-cert") + + +def test_authenticator_uses_provided_certs_instead_of_config_certs( + config, mock_remote, http, mocker +): + config.merge( + { + "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, + "http-basic": {"foo": {"username": "bar", "password": "baz"}}, + "certificates": {"foo": { + "cert": "/path/to/cert", + "client-cert": "/path/to/client-cert", + }}, + } + ) + + authenticator = Authenticator(config, NullIO()) + session_send = mocker.patch.object(authenticator.session, "send") + authenticator.request( + "get", + "https://foo.bar/files/foo-0.1.0.tar.gz", + verify="/path/to/provided/cert", + cert="/path/to/provided/client-cert", + ) + call_args = session_send.call_args + call_args.kwargs["verify"] == pathlib.Path("/path/to/provided/cert") + call_args.kwargs["cert"] == pathlib.Path("/path/to/provided/client-cert") From 4ee7cf8fdd4d4e8451c96abd21ce7eea93291b26 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Mon, 14 Dec 2020 08:56:32 -0800 Subject: [PATCH 02/16] Issue #3483 Fixed style issues with black --- src/poetry/utils/authenticator.py | 14 ++++++-------- tests/utils/test_authenticator.py | 14 ++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 478d306b088..ce7eace93ac 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -16,8 +16,9 @@ import requests.exceptions from poetry.exceptions import PoetryException +from poetry.utils.helpers import get_cert +from poetry.utils.helpers import get_client_cert from poetry.utils.password_manager import PasswordManager -from poetry.utils.helpers import get_cert, get_client_cert if TYPE_CHECKING: @@ -187,16 +188,13 @@ def _get_credentials_for_netloc( return credentials - def get_certs_for_url( - self, url: str - ) -> Dict[str, pathlib.PosixPath]: + def get_certs_for_url(self, url: str) -> Dict[str, pathlib.PosixPath]: parsed_url = urllib.parse.urlsplit(url) netloc = parsed_url.netloc return self._certs.setdefault( - netloc, - self._get_certs_for_netloc_from_config(netloc), + netloc, self._get_certs_for_netloc_from_config(netloc), ) def _get_repository_netlocs(self) -> Generator[[str, str], None, None]: @@ -244,8 +242,8 @@ def _get_certs_for_netloc_from_config( for (repository_name, repository_netloc) in self._get_repository_netlocs(): if netloc == repository_netloc: - certs['cert'] = get_client_cert(self._config, repository_name) - certs['verify'] = get_cert(self._config, repository_name) + certs["cert"] = get_client_cert(self._config, repository_name) + certs["verify"] = get_cert(self._config, repository_name) break return certs diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 18007328801..48635a9b62f 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -318,10 +318,9 @@ def test_authenticator_uses_certs_from_config_if_not_provided( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, "http-basic": {"foo": {"username": "bar", "password": "baz"}}, - "certificates": {"foo": { - "cert": "/path/to/cert", - "client-cert": "/path/to/client-cert", - }}, + "certificates": { + "foo": {"cert": "/path/to/cert", "client-cert": "/path/to/client-cert"} + }, } ) @@ -340,10 +339,9 @@ def test_authenticator_uses_provided_certs_instead_of_config_certs( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, "http-basic": {"foo": {"username": "bar", "password": "baz"}}, - "certificates": {"foo": { - "cert": "/path/to/cert", - "client-cert": "/path/to/client-cert", - }}, + "certificates": { + "foo": {"cert": "/path/to/cert", "client-cert": "/path/to/client-cert"} + }, } ) From 9e72dc449d6753b802d04af77ff65fcf5e64befc Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Mon, 14 Dec 2020 09:08:35 -0800 Subject: [PATCH 03/16] Issue #3483 Fixed broken unit test --- tests/utils/test_authenticator.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 48635a9b62f..2983d97262a 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -1,4 +1,3 @@ -import pathlib import re import uuid @@ -327,9 +326,9 @@ def test_authenticator_uses_certs_from_config_if_not_provided( authenticator = Authenticator(config, NullIO()) session_send = mocker.patch.object(authenticator.session, "send") authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") - call_args = session_send.call_args - call_args.kwargs["verify"] == pathlib.Path("/path/to/cert") - call_args.kwargs["cert"] == pathlib.Path("/path/to/client-cert") + kwargs = session_send.call_args[1] + assert str(kwargs["verify"]) == "/path/to/cert" + assert str(kwargs["cert"]) == "/path/to/client-cert" def test_authenticator_uses_provided_certs_instead_of_config_certs( @@ -353,6 +352,6 @@ def test_authenticator_uses_provided_certs_instead_of_config_certs( verify="/path/to/provided/cert", cert="/path/to/provided/client-cert", ) - call_args = session_send.call_args - call_args.kwargs["verify"] == pathlib.Path("/path/to/provided/cert") - call_args.kwargs["cert"] == pathlib.Path("/path/to/provided/client-cert") + kwargs = session_send.call_args[1] + assert str(kwargs["verify"]) == "/path/to/provided/cert" + assert str(kwargs["cert"]) == "/path/to/provided/client-cert" From 9d51dd0e4e5000025acb67f9aa2d34fedda2fdbf Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Mon, 14 Dec 2020 09:16:04 -0800 Subject: [PATCH 04/16] Issue #3483 Fixed broken unit test for windows --- tests/utils/test_authenticator.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 2983d97262a..754dbbc3c11 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -1,3 +1,4 @@ +import pathlib import re import uuid @@ -327,8 +328,8 @@ def test_authenticator_uses_certs_from_config_if_not_provided( session_send = mocker.patch.object(authenticator.session, "send") authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") kwargs = session_send.call_args[1] - assert str(kwargs["verify"]) == "/path/to/cert" - assert str(kwargs["cert"]) == "/path/to/client-cert" + assert str(kwargs["verify"]) == str(pathlib.Path("/path/to/cert")) + assert str(kwargs["cert"]) == str(pathlib.Path("/path/to/client-cert")) def test_authenticator_uses_provided_certs_instead_of_config_certs( @@ -353,5 +354,5 @@ def test_authenticator_uses_provided_certs_instead_of_config_certs( cert="/path/to/provided/client-cert", ) kwargs = session_send.call_args[1] - assert str(kwargs["verify"]) == "/path/to/provided/cert" - assert str(kwargs["cert"]) == "/path/to/provided/client-cert" + assert str(kwargs["verify"]) == str(pathlib.Path("/path/to/provided/cert")) + assert str(kwargs["cert"]) == str(pathlib.Path("/path/to/provided/client-cert")) From 2b78bded1c88decd74c3976ba70f73a63aaf939e Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Mon, 14 Dec 2020 09:21:57 -0800 Subject: [PATCH 05/16] Issue #3483 Fixing path issue in unit tests for windows --- tests/utils/test_authenticator.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 754dbbc3c11..709a7992e59 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -328,8 +328,8 @@ def test_authenticator_uses_certs_from_config_if_not_provided( session_send = mocker.patch.object(authenticator.session, "send") authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") kwargs = session_send.call_args[1] - assert str(kwargs["verify"]) == str(pathlib.Path("/path/to/cert")) - assert str(kwargs["cert"]) == str(pathlib.Path("/path/to/client-cert")) + assert pathlib.Path(kwargs["verify"]) == pathlib.Path("/path/to/cert") + assert pathlib.Path(kwargs["cert"]) == pathlib.Path("/path/to/client-cert") def test_authenticator_uses_provided_certs_instead_of_config_certs( @@ -354,5 +354,5 @@ def test_authenticator_uses_provided_certs_instead_of_config_certs( cert="/path/to/provided/client-cert", ) kwargs = session_send.call_args[1] - assert str(kwargs["verify"]) == str(pathlib.Path("/path/to/provided/cert")) - assert str(kwargs["cert"]) == str(pathlib.Path("/path/to/provided/client-cert")) + assert pathlib.Path(kwargs["verify"]) == pathlib.Path("/path/to/provided/cert") + assert pathlib.Path(kwargs["cert"]) == pathlib.Path("/path/to/provided/client-cert") From 7dcb682a009883042eecdf5c053febc611dccfd0 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Wed, 3 Feb 2021 17:49:59 -0800 Subject: [PATCH 06/16] Issue #3483: Fixed cert handling for pathlib paths --- src/poetry/utils/authenticator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index ce7eace93ac..8c0c68face2 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -73,6 +73,12 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response: verify = kwargs.get("verify", certs.get("verify")) cert = kwargs.get("cert", certs.get("cert")) + if isinstance(cert, pathlib.PurePath): + cert = str(cert) + + if isinstance(verify, pathlib.PurePath): + verify = str(verify) + settings = session.merge_environment_settings( prepared_request.url, proxies, stream, verify, cert ) From fddf76bceeef07e8645b969fbe2e610e12911ff9 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Wed, 3 Feb 2021 17:56:41 -0800 Subject: [PATCH 07/16] Issue #3483: Style change to make the linter happy --- src/poetry/utils/authenticator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 8c0c68face2..408e572d3f7 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -200,7 +200,8 @@ def get_certs_for_url(self, url: str) -> Dict[str, pathlib.PosixPath]: netloc = parsed_url.netloc return self._certs.setdefault( - netloc, self._get_certs_for_netloc_from_config(netloc), + netloc, + self._get_certs_for_netloc_from_config(netloc), ) def _get_repository_netlocs(self) -> Generator[[str, str], None, None]: From d5bb81a8d0ec68c99111f55b06edad82a6c14bbb Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Tue, 13 Apr 2021 15:27:32 -0700 Subject: [PATCH 08/16] Issue #3483: Rebased and fixed type hint --- src/poetry/utils/authenticator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 408e572d3f7..d6c0dbe92ef 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -204,7 +204,7 @@ def get_certs_for_url(self, url: str) -> Dict[str, pathlib.PosixPath]: self._get_certs_for_netloc_from_config(netloc), ) - def _get_repository_netlocs(self) -> Generator[[str, str], None, None]: + def _get_repository_netlocs(self) -> Generator[Tuple[str, str], None, None]: for repository_name in self._config.get("repositories", []): auth = self._get_http_auth(repository_name, netloc) From 038ed312e8ddbfe79127ab0e9c4aa362174034c9 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Tue, 13 Apr 2021 15:30:45 -0700 Subject: [PATCH 09/16] Issue #3483: Fixed a style issue --- src/poetry/utils/authenticator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index d6c0dbe92ef..4d27b3beb5b 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -6,10 +6,9 @@ from typing import TYPE_CHECKING from typing import Any from typing import Dict +from typing import Generator from typing import Optional from typing import Tuple -from typing import Dict -from typing import Generator import requests import requests.auth From 6fc640c5734359a31a15328c250fe460983232fb Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Wed, 28 Apr 2021 15:49:49 -0700 Subject: [PATCH 10/16] Issue #3483: Applied updates from code review --- src/poetry/utils/authenticator.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 4d27b3beb5b..9d8b7985e77 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -72,7 +72,7 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response: verify = kwargs.get("verify", certs.get("verify")) cert = kwargs.get("cert", certs.get("cert")) - if isinstance(cert, pathlib.PurePath): + if cert is not None: cert = str(cert) if isinstance(verify, pathlib.PurePath): @@ -241,9 +241,7 @@ def _get_credentials_for_netloc_from_keyring( return None - def _get_certs_for_netloc_from_config( - self, netloc: str - ) -> Dict[str, pathlib.PosixPath]: + def _get_certs_for_netloc_from_config(self, netloc: str) -> Dict[str, pathlib.Path]: certs = dict(cert=None, verify=None) for (repository_name, repository_netloc) in self._get_repository_netlocs(): From 864d6770f1c1173df28d639fa01c94e375d230f2 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Tue, 4 May 2021 10:35:35 -0700 Subject: [PATCH 11/16] Issue #3483: more revisions based on code review feedback --- src/poetry/utils/authenticator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 9d8b7985e77..9ac1f3c75e2 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -75,7 +75,7 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response: if cert is not None: cert = str(cert) - if isinstance(verify, pathlib.PurePath): + if verify is not None: verify = str(verify) settings = session.merge_environment_settings( @@ -193,7 +193,7 @@ def _get_credentials_for_netloc( return credentials - def get_certs_for_url(self, url: str) -> Dict[str, pathlib.PosixPath]: + def get_certs_for_url(self, url: str) -> Dict[str, pathlib.Path]: parsed_url = urllib.parse.urlsplit(url) netloc = parsed_url.netloc From 7de523a306ca8a9869c7face65a5e0795004d13f Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Thu, 6 May 2021 11:17:22 -0700 Subject: [PATCH 12/16] Issue #3483: Some revisions based on code review --- src/poetry/utils/authenticator.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 9ac1f3c75e2..fb5c29becde 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -69,8 +69,8 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response: stream = kwargs.get("stream") certs = self.get_certs_for_url(url) - verify = kwargs.get("verify", certs.get("verify")) - cert = kwargs.get("cert", certs.get("cert")) + verify = kwargs.get("verify") or certs.get("verify") + cert = kwargs.get("cert") or certs.get("cert") if cert is not None: cert = str(cert) @@ -179,19 +179,14 @@ def _get_http_auth( def _get_credentials_for_netloc( self, netloc: str ) -> Tuple[Optional[str], Optional[str]]: - credentials = (None, None) - for (repository_name, repository_netloc) in self._get_repository_netlocs(): if netloc == repository_netloc: auth = self._password_manager.get_http_auth(repository_name) if auth is None: - continue - - credentials = (auth["username"], auth["password"]) - break + return (auth["username"], auth["password"]) - return credentials + return (None, None) def get_certs_for_url(self, url: str) -> Dict[str, pathlib.Path]: parsed_url = urllib.parse.urlsplit(url) From 4a6bf9b312d23563474b23cb94f97a5534849516 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Mon, 24 May 2021 09:45:20 -0700 Subject: [PATCH 13/16] Issue #3483: Applied code review suggestions and fixed unit tests --- src/poetry/utils/authenticator.py | 8 +++--- tests/utils/test_authenticator.py | 45 ++++++++++++------------------- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index fb5c29becde..2691e407754 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -1,8 +1,8 @@ import logging -import pathlib import time import urllib.parse +from pathlib import Path from typing import TYPE_CHECKING from typing import Any from typing import Dict @@ -183,12 +183,12 @@ def _get_credentials_for_netloc( if netloc == repository_netloc: auth = self._password_manager.get_http_auth(repository_name) - if auth is None: + if auth is not None: return (auth["username"], auth["password"]) return (None, None) - def get_certs_for_url(self, url: str) -> Dict[str, pathlib.Path]: + def get_certs_for_url(self, url: str) -> Dict[str, Path]: parsed_url = urllib.parse.urlsplit(url) netloc = parsed_url.netloc @@ -236,7 +236,7 @@ def _get_credentials_for_netloc_from_keyring( return None - def _get_certs_for_netloc_from_config(self, netloc: str) -> Dict[str, pathlib.Path]: + def _get_certs_for_netloc_from_config(self, netloc: str) -> Dict[str, Path]: certs = dict(cert=None, verify=None) for (repository_name, repository_netloc) in self._get_repository_netlocs(): diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 709a7992e59..609212c8a64 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -1,4 +1,3 @@ -import pathlib import re import uuid @@ -8,6 +7,7 @@ from typing import List from typing import Type from typing import Union +from pathlib import Path import httpretty import pytest @@ -311,36 +311,24 @@ def test_authenticator_uses_env_provided_credentials( assert request.headers["Authorization"] == "Basic YmFyOmJheg==" +@pytest.mark.parametrize( + "cert,client_cert", + [ + (None, None), + ("/path/to/provided/cert", "path/to/provided/client-cert"), + ], +) def test_authenticator_uses_certs_from_config_if_not_provided( - config, mock_remote, http, mocker + config, mock_remote, http, mocker, cert, client_cert ): + configured_cert = "/path/to/cert" + configured_client_cert = "/path/to/client-cert" config.merge( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, "http-basic": {"foo": {"username": "bar", "password": "baz"}}, "certificates": { - "foo": {"cert": "/path/to/cert", "client-cert": "/path/to/client-cert"} - }, - } - ) - - authenticator = Authenticator(config, NullIO()) - session_send = mocker.patch.object(authenticator.session, "send") - authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") - kwargs = session_send.call_args[1] - assert pathlib.Path(kwargs["verify"]) == pathlib.Path("/path/to/cert") - assert pathlib.Path(kwargs["cert"]) == pathlib.Path("/path/to/client-cert") - - -def test_authenticator_uses_provided_certs_instead_of_config_certs( - config, mock_remote, http, mocker -): - config.merge( - { - "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, - "http-basic": {"foo": {"username": "bar", "password": "baz"}}, - "certificates": { - "foo": {"cert": "/path/to/cert", "client-cert": "/path/to/client-cert"} + "foo": {"cert": configured_cert, "client-cert": configured_client_cert} }, } ) @@ -350,9 +338,10 @@ def test_authenticator_uses_provided_certs_instead_of_config_certs( authenticator.request( "get", "https://foo.bar/files/foo-0.1.0.tar.gz", - verify="/path/to/provided/cert", - cert="/path/to/provided/client-cert", + verify=cert, + cert=client_cert, ) kwargs = session_send.call_args[1] - assert pathlib.Path(kwargs["verify"]) == pathlib.Path("/path/to/provided/cert") - assert pathlib.Path(kwargs["cert"]) == pathlib.Path("/path/to/provided/client-cert") + + assert Path(kwargs["verify"]) == Path(cert or configured_cert) + assert Path(kwargs["cert"]) == Path(client_cert or configured_client_cert) From 451568ce2e7f35aa259cd0baa22bfb8b70f86d3c Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Thu, 14 Oct 2021 05:53:26 -0700 Subject: [PATCH 14/16] Issue #3483 Fixed broken code from rebase --- src/poetry/utils/authenticator.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index 2691e407754..f7ab6709d54 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -179,14 +179,17 @@ def _get_http_auth( def _get_credentials_for_netloc( self, netloc: str ) -> Tuple[Optional[str], Optional[str]]: + credentials = (None, None) + for (repository_name, repository_netloc) in self._get_repository_netlocs(): - if netloc == repository_netloc: - auth = self._password_manager.get_http_auth(repository_name) + auth = self._get_http_auth(repository_name, netloc) + + if auth is None: + continue - if auth is not None: - return (auth["username"], auth["password"]) + return auth["username"], auth["password"] - return (None, None) + return credentials def get_certs_for_url(self, url: str) -> Dict[str, Path]: parsed_url = urllib.parse.urlsplit(url) @@ -200,14 +203,12 @@ def get_certs_for_url(self, url: str) -> Dict[str, Path]: def _get_repository_netlocs(self) -> Generator[Tuple[str, str], None, None]: for repository_name in self._config.get("repositories", []): - auth = self._get_http_auth(repository_name, netloc) - - if auth is None: - continue - - return auth["username"], auth["password"] - - return credentials + url = self._config.get(f"repositories.{repository_name}.url") + parsed_url = urllib.parse.urlsplit(url) + yield ( + repository_name, + parsed_url.netloc, + ) def _get_credentials_for_netloc_from_keyring( self, url: str, netloc: str, username: Optional[str] From 1d9132c4a250a551a53a5afc714b5b20e86ffaa8 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Tue, 2 Nov 2021 02:46:18 -0700 Subject: [PATCH 15/16] Issue #3483: Applied fix for linting issue and improved test coverage --- src/poetry/utils/authenticator.py | 2 +- tests/utils/test_authenticator.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index f7ab6709d54..e96d78d445f 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -181,7 +181,7 @@ def _get_credentials_for_netloc( ) -> Tuple[Optional[str], Optional[str]]: credentials = (None, None) - for (repository_name, repository_netloc) in self._get_repository_netlocs(): + for (repository_name, _) in self._get_repository_netlocs(): auth = self._get_http_auth(repository_name, netloc) if auth is None: diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index 609212c8a64..c40d26a3ed2 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -315,6 +315,8 @@ def test_authenticator_uses_env_provided_credentials( "cert,client_cert", [ (None, None), + (None, "path/to/provided/client-cert"), + ("/path/to/provided/cert", None), ("/path/to/provided/cert", "path/to/provided/client-cert"), ], ) From 45bb9d12947ab7f2b6afd50b145b5851935ee200 Mon Sep 17 00:00:00 2001 From: Tucker Beck Date: Tue, 14 Dec 2021 15:00:09 -0800 Subject: [PATCH 16/16] Issue #3483 Fixed issues with linting and type-checking --- src/poetry/utils/authenticator.py | 9 +++++---- tests/utils/test_authenticator.py | 9 +++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/poetry/utils/authenticator.py b/src/poetry/utils/authenticator.py index e96d78d445f..b83858f0812 100644 --- a/src/poetry/utils/authenticator.py +++ b/src/poetry/utils/authenticator.py @@ -2,7 +2,6 @@ import time import urllib.parse -from pathlib import Path from typing import TYPE_CHECKING from typing import Any from typing import Dict @@ -21,6 +20,8 @@ if TYPE_CHECKING: + from pathlib import Path + from cleo.io.io import IO from poetry.config.config import Config @@ -191,7 +192,7 @@ def _get_credentials_for_netloc( return credentials - def get_certs_for_url(self, url: str) -> Dict[str, Path]: + def get_certs_for_url(self, url: str) -> Dict[str, "Path"]: parsed_url = urllib.parse.urlsplit(url) netloc = parsed_url.netloc @@ -237,8 +238,8 @@ def _get_credentials_for_netloc_from_keyring( return None - def _get_certs_for_netloc_from_config(self, netloc: str) -> Dict[str, Path]: - certs = dict(cert=None, verify=None) + def _get_certs_for_netloc_from_config(self, netloc: str) -> Dict[str, "Path"]: + certs = {"cert": None, "verify": None} for (repository_name, repository_netloc) in self._get_repository_netlocs(): if netloc == repository_netloc: diff --git a/tests/utils/test_authenticator.py b/tests/utils/test_authenticator.py index c40d26a3ed2..6c643b9163d 100644 --- a/tests/utils/test_authenticator.py +++ b/tests/utils/test_authenticator.py @@ -1,13 +1,13 @@ import re import uuid +from pathlib import Path from typing import TYPE_CHECKING from typing import Any from typing import Dict from typing import List from typing import Type from typing import Union -from pathlib import Path import httpretty import pytest @@ -321,7 +321,12 @@ def test_authenticator_uses_env_provided_credentials( ], ) def test_authenticator_uses_certs_from_config_if_not_provided( - config, mock_remote, http, mocker, cert, client_cert + config: "Config", + mock_remote: Type[httpretty.httpretty], + http: Type[httpretty.httpretty], + mocker: "MockerFixture", + cert: Union[str, None], + client_cert: Union[str, None], ): configured_cert = "/path/to/cert" configured_client_cert = "/path/to/client-cert"