mirror of https://github.com/astral-sh/uv
Use the root index URL when retrieving credentials from the native store (#15873)
Part of https://github.com/astral-sh/uv/issues/15818 We use the root when we store the credentials, so we need to use the root when we retrieve them!
This commit is contained in:
parent
daff98988b
commit
31f46cd6a6
|
|
@ -95,9 +95,9 @@ impl Indexes {
|
||||||
index_urls
|
index_urls
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the index URL prefix for a URL if one exists.
|
/// Get the index for a URL if one exists.
|
||||||
pub fn index_url_for(&self, url: &Url) -> Option<&DisplaySafeUrl> {
|
pub fn index_for(&self, url: &Url) -> Option<&Index> {
|
||||||
self.find_prefix_index(url).map(|index| &index.url)
|
self.find_prefix_index(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the [`AuthPolicy`] for a URL.
|
/// Get the [`AuthPolicy`] for a URL.
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
realm::Realm,
|
realm::Realm,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{TextCredentialStore, TomlCredentialError};
|
use crate::{Index, TextCredentialStore, TomlCredentialError};
|
||||||
|
|
||||||
/// Strategy for loading netrc files.
|
/// Strategy for loading netrc files.
|
||||||
enum NetrcMode {
|
enum NetrcMode {
|
||||||
|
|
@ -297,7 +297,7 @@ impl Middleware for AuthMiddleware {
|
||||||
// In the middleware, existing credentials are already moved from the URL
|
// In the middleware, existing credentials are already moved from the URL
|
||||||
// to the headers so for display purposes we restore some information
|
// to the headers so for display purposes we restore some information
|
||||||
let url = tracing_url(&request, request_credentials.as_ref());
|
let url = tracing_url(&request, request_credentials.as_ref());
|
||||||
let maybe_index_url = self.indexes.index_url_for(request.url());
|
let index = self.indexes.index_for(request.url());
|
||||||
let auth_policy = self.indexes.auth_policy_for(request.url());
|
let auth_policy = self.indexes.auth_policy_for(request.url());
|
||||||
trace!("Handling request for {url} with authentication policy {auth_policy}");
|
trace!("Handling request for {url} with authentication policy {auth_policy}");
|
||||||
|
|
||||||
|
|
@ -312,7 +312,7 @@ impl Middleware for AuthMiddleware {
|
||||||
extensions,
|
extensions,
|
||||||
next,
|
next,
|
||||||
&url,
|
&url,
|
||||||
maybe_index_url,
|
index,
|
||||||
auth_policy,
|
auth_policy,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -406,8 +406,8 @@ impl Middleware for AuthMiddleware {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|credentials| credentials.to_username())
|
.map(|credentials| credentials.to_username())
|
||||||
.unwrap_or(Username::none());
|
.unwrap_or(Username::none());
|
||||||
let credentials = if let Some(index_url) = maybe_index_url {
|
let credentials = if let Some(index) = index {
|
||||||
self.cache().get_url(index_url, &username).or_else(|| {
|
self.cache().get_url(&index.url, &username).or_else(|| {
|
||||||
self.cache()
|
self.cache()
|
||||||
.get_realm(Realm::from(&**retry_request_url), username)
|
.get_realm(Realm::from(&**retry_request_url), username)
|
||||||
})
|
})
|
||||||
|
|
@ -435,7 +435,7 @@ impl Middleware for AuthMiddleware {
|
||||||
.fetch_credentials(
|
.fetch_credentials(
|
||||||
credentials.as_deref(),
|
credentials.as_deref(),
|
||||||
retry_request_url,
|
retry_request_url,
|
||||||
maybe_index_url,
|
index,
|
||||||
auth_policy,
|
auth_policy,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
@ -529,7 +529,7 @@ impl AuthMiddleware {
|
||||||
extensions: &mut Extensions,
|
extensions: &mut Extensions,
|
||||||
next: Next<'_>,
|
next: Next<'_>,
|
||||||
url: &DisplaySafeUrl,
|
url: &DisplaySafeUrl,
|
||||||
index_url: Option<&DisplaySafeUrl>,
|
index: Option<&Index>,
|
||||||
auth_policy: AuthPolicy,
|
auth_policy: AuthPolicy,
|
||||||
) -> reqwest_middleware::Result<Response> {
|
) -> reqwest_middleware::Result<Response> {
|
||||||
let credentials = Arc::new(credentials);
|
let credentials = Arc::new(credentials);
|
||||||
|
|
@ -545,11 +545,15 @@ impl AuthMiddleware {
|
||||||
trace!("Request for {url} is missing a password, looking for credentials");
|
trace!("Request for {url} is missing a password, looking for credentials");
|
||||||
|
|
||||||
// There's just a username, try to find a password.
|
// There's just a username, try to find a password.
|
||||||
// If we have an index URL, check the cache for that URL. Otherwise,
|
// If we have an index, check the cache for that URL. Otherwise,
|
||||||
// check for the realm.
|
// check for the realm.
|
||||||
let maybe_cached_credentials = if let Some(index_url) = index_url {
|
let maybe_cached_credentials = if let Some(index) = index {
|
||||||
self.cache()
|
self.cache()
|
||||||
.get_url(index_url, credentials.as_username().as_ref())
|
.get_url(&index.url, credentials.as_username().as_ref())
|
||||||
|
.or_else(|| {
|
||||||
|
self.cache()
|
||||||
|
.get_url(&index.root_url, credentials.as_username().as_ref())
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
self.cache()
|
self.cache()
|
||||||
.get_realm(Realm::from(request.url()), credentials.to_username())
|
.get_realm(Realm::from(request.url()), credentials.to_username())
|
||||||
|
|
@ -574,14 +578,14 @@ impl AuthMiddleware {
|
||||||
.fetch_credentials(
|
.fetch_credentials(
|
||||||
Some(&credentials),
|
Some(&credentials),
|
||||||
DisplaySafeUrl::ref_cast(request.url()),
|
DisplaySafeUrl::ref_cast(request.url()),
|
||||||
index_url,
|
index,
|
||||||
auth_policy,
|
auth_policy,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
request = credentials.authenticate(request);
|
request = credentials.authenticate(request);
|
||||||
Some(credentials)
|
Some(credentials)
|
||||||
} else if index_url.is_some() {
|
} else if index.is_some() {
|
||||||
// If this is a known index, we fall back to checking for the realm.
|
// If this is a known index, we fall back to checking for the realm.
|
||||||
if let Some(credentials) = self
|
if let Some(credentials) = self
|
||||||
.cache()
|
.cache()
|
||||||
|
|
@ -608,7 +612,7 @@ impl AuthMiddleware {
|
||||||
&self,
|
&self,
|
||||||
credentials: Option<&Credentials>,
|
credentials: Option<&Credentials>,
|
||||||
url: &DisplaySafeUrl,
|
url: &DisplaySafeUrl,
|
||||||
maybe_index_url: Option<&DisplaySafeUrl>,
|
index: Option<&Index>,
|
||||||
auth_policy: AuthPolicy,
|
auth_policy: AuthPolicy,
|
||||||
) -> Option<Arc<Credentials>> {
|
) -> Option<Arc<Credentials>> {
|
||||||
let username = Username::from(
|
let username = Username::from(
|
||||||
|
|
@ -617,8 +621,8 @@ impl AuthMiddleware {
|
||||||
|
|
||||||
// Fetches can be expensive, so we will only run them _once_ per realm or index URL and username combination
|
// Fetches can be expensive, so we will only run them _once_ per realm or index URL and username combination
|
||||||
// All other requests for the same realm or index URL will wait until the first one completes
|
// All other requests for the same realm or index URL will wait until the first one completes
|
||||||
let key = if let Some(index_url) = maybe_index_url {
|
let key = if let Some(index) = index {
|
||||||
(FetchUrl::Index(index_url.clone()), username)
|
(FetchUrl::Index(index.url.clone()), username)
|
||||||
} else {
|
} else {
|
||||||
(FetchUrl::Realm(Realm::from(&**url)), username)
|
(FetchUrl::Realm(Realm::from(&**url)), username)
|
||||||
};
|
};
|
||||||
|
|
@ -719,13 +723,16 @@ impl AuthMiddleware {
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
if let Some(index_url) = maybe_index_url {
|
if let Some(index) = index {
|
||||||
debug!("Checking native store for credentials for index URL {}{}", display_username, index_url);
|
// N.B. The native store performs an exact look up right now, so we use the root
|
||||||
native_store.fetch(DisplaySafeUrl::ref_cast(index_url), username).await
|
// URL of the index instead of relying on prefix-matching.
|
||||||
|
debug!("Checking native store for credentials for index URL {}{}", display_username, index.root_url);
|
||||||
|
native_store.fetch(&index.root_url, username).await
|
||||||
} else {
|
} else {
|
||||||
debug!("Checking native store for credentials for URL {}{}", display_username, url);
|
debug!("Checking native store for credentials for URL {}{}", display_username, url);
|
||||||
native_store.fetch(url, username).await
|
native_store.fetch(url, username).await
|
||||||
}
|
}
|
||||||
|
// TODO(zanieb): We should have a realm fallback here too
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -742,19 +749,20 @@ impl AuthMiddleware {
|
||||||
// URLs; instead, we fetch if there's a username or if the user has requested to
|
// URLs; instead, we fetch if there's a username or if the user has requested to
|
||||||
// always authenticate.
|
// always authenticate.
|
||||||
if let Some(username) = credentials.and_then(|credentials| credentials.username()) {
|
if let Some(username) = credentials.and_then(|credentials| credentials.username()) {
|
||||||
if let Some(index_url) = maybe_index_url {
|
if let Some(index) = index {
|
||||||
debug!("Checking keyring for credentials for index URL {}@{}", username, index_url);
|
debug!("Checking keyring for credentials for index URL {}@{}", username, index.url);
|
||||||
keyring.fetch(DisplaySafeUrl::ref_cast(index_url), Some(username)).await
|
keyring.fetch(DisplaySafeUrl::ref_cast(&index.url), Some(username)).await
|
||||||
} else {
|
} else {
|
||||||
debug!("Checking keyring for credentials for full URL {}@{}", username, url);
|
debug!("Checking keyring for credentials for full URL {}@{}", username, url);
|
||||||
keyring.fetch(url, Some(username)).await
|
keyring.fetch(url, Some(username)).await
|
||||||
}
|
}
|
||||||
} else if matches!(auth_policy, AuthPolicy::Always) {
|
} else if matches!(auth_policy, AuthPolicy::Always) {
|
||||||
if let Some(index_url) = maybe_index_url {
|
if let Some(index) = index {
|
||||||
debug!(
|
debug!(
|
||||||
"Checking keyring for credentials for index URL {index_url} without username due to `authenticate = always`"
|
"Checking keyring for credentials for index URL {} without username due to `authenticate = always`",
|
||||||
|
index.url
|
||||||
);
|
);
|
||||||
keyring.fetch(DisplaySafeUrl::ref_cast(index_url), None).await
|
keyring.fetch(DisplaySafeUrl::ref_cast(&index.url), None).await
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,16 +176,17 @@ fn add_package_native_auth() -> Result<()> {
|
||||||
// credentials storied in the system keyring.
|
// credentials storied in the system keyring.
|
||||||
uv_snapshot!(context.add().arg("anyio").arg("--default-index").arg("https://public@pypi-proxy.fly.dev/basic-auth/simple")
|
uv_snapshot!(context.add().arg("anyio").arg("--default-index").arg("https://public@pypi-proxy.fly.dev/basic-auth/simple")
|
||||||
.env(EnvVars::UV_PREVIEW_FEATURES, "native-auth"), @r"
|
.env(EnvVars::UV_PREVIEW_FEATURES, "native-auth"), @r"
|
||||||
success: false
|
success: true
|
||||||
exit_code: 1
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
× No solution found when resolving dependencies:
|
Resolved 4 packages in [TIME]
|
||||||
╰─▶ Because anyio was not found in the package registry and your project depends on anyio, we can conclude that your project's requirements are unsatisfiable.
|
Prepared 3 packages in [TIME]
|
||||||
|
Installed 3 packages in [TIME]
|
||||||
hint: An index URL (https://pypi-proxy.fly.dev/basic-auth/simple) could not be queried due to a lack of valid authentication credentials (401 Unauthorized).
|
+ anyio==4.3.0
|
||||||
help: If you want to add the package regardless of the failed resolution, provide the `--frozen` flag to skip locking and syncing.
|
+ idna==3.6
|
||||||
|
+ sniffio==1.3.1
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue