Skip to content

Commit

Permalink
ensure git repository authn uses exact urls
Browse files Browse the repository at this point in the history
Since git repository authentication is a special case of repository
configuration, the existing assumptions around path matching do not
apply. In order to prevent unexpected behaviour due to similar path
matching, git authentication will use exact url matching.
  • Loading branch information
abn committed May 9, 2022
1 parent c9debec commit 5ff1e35
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
20 changes: 17 additions & 3 deletions src/poetry/utils/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,10 @@ def _get_credentials_for_repository(

return self._credentials[key]

def _get_credentials_for_url(self, url: str) -> HTTPAuthCredential:
repository = self.get_repository_config_for_url(url)
def _get_credentials_for_url(
self, url: str, exact_match: bool = False
) -> HTTPAuthCredential:
repository = self.get_repository_config_for_url(url, exact_match)

credential = (
self._get_credentials_for_repository(repository=repository)
Expand All @@ -267,6 +269,14 @@ def _get_credentials_for_url(self, url: str) -> HTTPAuthCredential:

return credential

def get_credentials_for_git_url(self, url: str) -> HTTPAuthCredential:
key = f"git+{url}"

if key not in self._credentials:
self._credentials[key] = self._get_credentials_for_url(url, True)

return self._credentials[key]

def get_credentials_for_url(self, url: str) -> HTTPAuthCredential:
parsed_url = urllib.parse.urlsplit(url)
netloc = parsed_url.netloc
Expand Down Expand Up @@ -338,13 +348,17 @@ def get_certs_for_url(self, url: str) -> dict[str, Path | None]:

@functools.lru_cache(maxsize=None)
def get_repository_config_for_url(
self, url: str
self, url: str, exact_match: bool = False
) -> AuthenticatorRepositoryConfig | None:
parsed_url = urllib.parse.urlsplit(url)
candidates_netloc_only = []
candidates_path_match = []

for repository in self.configured_repositories.values():
if exact_match:
if parsed_url.path == repository.path:
return repository
continue

if repository.netloc == parsed_url.netloc:
if parsed_url.path.startswith(repository.path) or commonprefix(
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/vcs/git/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def _fetch_remote_refs(cls, url: str, local: Repo) -> FetchPackResult:
client: GitClient
path: str

credentials = get_default_authenticator().get_credentials_for_url(url=url)
credentials = get_default_authenticator().get_credentials_for_git_url(url=url)
client, path = get_transport_and_path( # type: ignore[no-untyped-call]
url, username=credentials.username, password=credentials.password
)
Expand Down
35 changes: 35 additions & 0 deletions tests/utils/test_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,38 @@ def test_authenticator_add_repository(

basic_auth = base64.b64encode(b"foo:bar").decode()
assert request.headers["Authorization"] == f"Basic {basic_auth}"


def test_authenticator_git_repositories(
config: Config,
mock_remote: None,
http: type[httpretty.httpretty],
with_simple_keyring: None,
dummy_keyring: DummyBackend,
):
config.merge(
{
"repositories": {
"one": {"url": "https://foo.bar/org/one.git"},
"two": {"url": "https://foo.bar/org/two.git"},
},
"http-basic": {
"one": {"username": "foo", "password": "bar"},
"two": {"username": "baz", "password": "qux"},
},
}
)

authenticator = Authenticator(config, NullIO())

one = authenticator.get_credentials_for_git_url("https://foo.bar/org/one.git")
assert one.username == "foo"
assert one.password == "bar"

two = authenticator.get_credentials_for_git_url("https://foo.bar/org/two.git")
assert two.username == "baz"
assert two.password == "qux"

three = authenticator.get_credentials_for_git_url("https://foo.bar/org/three.git")
assert not three.username
assert not three.password

0 comments on commit 5ff1e35

Please sign in to comment.