Skip to content

Commit 3c1f39f

Browse files
committed
fix: Remove hard-code and implement real behavior
1 parent 310cebf commit 3c1f39f

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/anaconda_auth/_conda/auth_handler.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
55
"""
66

7+
from fnmatch import fnmatch
78
from functools import lru_cache
89
from typing import Any
910
from typing import NamedTuple
@@ -12,6 +13,7 @@
1213
from urllib.parse import urlparse
1314

1415
from conda import CondaError
16+
from conda.base.context import context as conda_context
1517
from conda.plugins.types import ChannelAuthBase
1618
from requests import PreparedRequest
1719
from requests import Response
@@ -41,7 +43,47 @@ class AnacondaAuthError(CondaError):
4143

4244

4345
def _load_channel_settings(channel_name: str) -> dict[str, Any]:
44-
return {"auth_domain": "auth.some-domain.com"}
46+
"""Find the correct channel settings from conda's configuration."""
47+
# TODO(mattkram): Open conda issue to see if we can pass this into the AuthHandler
48+
# as part of the plugin protocol.
49+
50+
# Since the conda logic uses a url, we derive a url from the channel name
51+
# this will not work for multi_channels like "defaults", but we restrict the
52+
# extra fields we need to URL-based channel_settings, which should be sufficient.
53+
url = channel_name
54+
if not url.endswith("/"):
55+
url += "/"
56+
57+
parsed_url = urlparse(url)
58+
if not parsed_url.scheme or not parsed_url.netloc:
59+
return {}
60+
61+
# The following implementation has mostly been copied from conda, with one noted exception.
62+
# Ideally, we can receive the settings in the plugin instantiation.
63+
# See: https://github.com/conda/conda/blob/2af8e0f7255e1d06ea0bfcb6076c7427d101feee/conda/gateways/connection/session.py#L91-L112
64+
65+
# We ensure here if there are duplicates defined, we choose the last one
66+
channel_settings = {}
67+
for settings in conda_context.channel_settings:
68+
channel = settings.get("channel", "")
69+
if channel == channel_name:
70+
# First we check for exact match
71+
channel_settings = settings
72+
continue
73+
74+
parsed_setting = urlparse(channel)
75+
76+
# We require that the schemes must be identical to prevent downgrade attacks.
77+
# This includes the case of a scheme-less pattern like "*", which is not allowed.
78+
if parsed_setting.scheme != parsed_url.scheme:
79+
continue
80+
81+
url_without_schema = parsed_url.netloc + parsed_url.path
82+
pattern = parsed_setting.netloc + parsed_setting.path
83+
if fnmatch(url_without_schema, pattern):
84+
channel_settings = settings
85+
86+
return channel_settings
4587

4688

4789
class AnacondaAuthHandler(ChannelAuthBase):

src/anaconda_auth/_conda/condarc.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ def update_channel_settings(
5656
"""
5757
Update the condarc file's "channel_settings" section
5858
"""
59-
if username is None:
60-
updated_settings = {"channel": channel, "auth": auth_type}
61-
else:
62-
updated_settings = {
63-
"channel": channel,
64-
"auth": auth_type,
65-
"username": username,
66-
}
59+
updated_settings = {
60+
"channel": channel,
61+
"auth": auth_type,
62+
"username": username,
63+
"auth_domain": auth_domain,
64+
}
65+
66+
# Filter out any None values
67+
updated_settings = {
68+
key: value for key, value in updated_settings.items() if value is not None
69+
}
6770

6871
channel_settings = self._loaded_yaml.get("channel_settings", []) or []
6972

0 commit comments

Comments
 (0)