mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Add support for --trusted-host
(#6591)
## Summary This PR revives https://github.com/astral-sh/uv/pull/4944, which I think was a good start towards adding `--trusted-host`. Last night, I tried to add `--trusted-host` with a custom verifier, but we had to vendor a lot of `reqwest` code and I eventually hit some private APIs. I'm not confident that I can implement it correctly with that mechanism, and since this is security, correctness is the priority. So, instead, we now use two clients and multiplex between them. Closes https://github.com/astral-sh/uv/issues/1339. ## Test Plan Created self-signed certificate, and ran `python3 -m http.server --bind 127.0.0.1 4443 --directory . --certfile cert.pem --keyfile key.pem` from the packse index directory. Verified that `cargo run pip install transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url https://127.0.0.1:8443/simple-html` failed with: ``` error: Request failed after 3 retries Caused by: error sending request for url (https://127.0.0.1:8443/simple-html/transitive-yanked-and-unyanked-dependency-a-0abad3b6/) Caused by: client error (Connect) Caused by: invalid peer certificate: Other(OtherError(CaUsedAsEndEntity)) ``` Verified that `cargo run pip install transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url 'https://127.0.0.1:8443/simple-html' --trusted-host '127.0.0.1:8443'` failed with the expected error (invalid resolution) and made valid requests. Verified that `cargo run pip install transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url 'https://127.0.0.1:8443/simple-html' --trusted-host '127.0.0.2' -n` also failed.
This commit is contained in:
parent
ce749591de
commit
d86075fc1e
31 changed files with 808 additions and 125 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4774,7 +4774,9 @@ dependencies = [
|
|||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"url",
|
||||
"uv-auth",
|
||||
"uv-cache",
|
||||
"uv-normalize",
|
||||
|
|
|
@ -39,9 +39,6 @@ pub struct PipCompileCompatArgs {
|
|||
#[clap(long, hide = true)]
|
||||
client_cert: Option<String>,
|
||||
|
||||
#[clap(long, hide = true)]
|
||||
trusted_host: Option<String>,
|
||||
|
||||
#[clap(long, hide = true)]
|
||||
emit_trusted_host: bool,
|
||||
|
||||
|
@ -118,15 +115,9 @@ impl CompatArgs for PipCompileCompatArgs {
|
|||
));
|
||||
}
|
||||
|
||||
if self.trusted_host.is_some() {
|
||||
return Err(anyhow!(
|
||||
"pip-compile's `--trusted-host` is unsupported (uv always requires HTTPS)"
|
||||
));
|
||||
}
|
||||
|
||||
if self.emit_trusted_host {
|
||||
return Err(anyhow!(
|
||||
"pip-compile's `--emit-trusted-host` is unsupported (uv always requires HTTPS)"
|
||||
"pip-compile's `--emit-trusted-host` is unsupported"
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -209,9 +200,6 @@ pub struct PipSyncCompatArgs {
|
|||
#[clap(short, long, hide = true)]
|
||||
ask: bool,
|
||||
|
||||
#[clap(long, hide = true)]
|
||||
trusted_host: Option<String>,
|
||||
|
||||
#[clap(long, hide = true)]
|
||||
python_executable: Option<String>,
|
||||
|
||||
|
@ -265,12 +253,6 @@ impl CompatArgs for PipSyncCompatArgs {
|
|||
));
|
||||
}
|
||||
|
||||
if self.trusted_host.is_some() {
|
||||
return Err(anyhow!(
|
||||
"pip-sync's `--trusted-host` is unsupported (uv always requires HTTPS)"
|
||||
));
|
||||
}
|
||||
|
||||
if self.config.is_some() {
|
||||
return Err(anyhow!(
|
||||
"pip-sync's `--config` is unsupported (uv does not use a configuration file)"
|
||||
|
|
|
@ -6,13 +6,13 @@ use std::str::FromStr;
|
|||
use anyhow::{anyhow, Result};
|
||||
use clap::builder::styling::Style;
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
use distribution_types::{FlatIndexLocation, IndexUrl};
|
||||
use pep508_rs::Requirement;
|
||||
use pypi_types::VerbatimParsedUrl;
|
||||
use uv_cache::CacheArgs;
|
||||
use uv_configuration::{
|
||||
ConfigSettingEntry, IndexStrategy, KeyringProviderType, PackageNameSpecifier, TargetTriple,
|
||||
TrustedHost,
|
||||
};
|
||||
use uv_normalize::{ExtraName, PackageName};
|
||||
use uv_python::{PythonDownloads, PythonPreference, PythonVersion};
|
||||
|
@ -678,6 +678,18 @@ fn parse_index_url(input: &str) -> Result<Maybe<IndexUrl>, String> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a string into an [`Url`], mapping the empty string to `None`.
|
||||
fn parse_insecure_host(input: &str) -> Result<Maybe<TrustedHost>, String> {
|
||||
if input.is_empty() {
|
||||
Ok(Maybe::None)
|
||||
} else {
|
||||
match TrustedHost::from_str(input) {
|
||||
Ok(host) => Ok(Maybe::Some(host)),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a string into a [`PathBuf`]. The string can represent a file, either as a path or a
|
||||
/// `file://` URL.
|
||||
fn parse_file_path(input: &str) -> Result<PathBuf, String> {
|
||||
|
@ -1559,6 +1571,25 @@ pub struct PipUninstallArgs {
|
|||
#[arg(long, value_enum, env = "UV_KEYRING_PROVIDER")]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
|
||||
/// Allow insecure connections to a host.
|
||||
///
|
||||
/// Can be provided multiple times.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "trusted-host",
|
||||
env = "UV_INSECURE_HOST",
|
||||
value_delimiter = ' ',
|
||||
value_parser = parse_insecure_host,
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
|
||||
|
||||
/// Use the system Python to uninstall packages.
|
||||
///
|
||||
/// By default, uv uninstalls from the virtual environment in the current working directory or
|
||||
|
@ -1985,6 +2016,25 @@ pub struct VenvArgs {
|
|||
#[arg(long, value_enum, env = "UV_KEYRING_PROVIDER")]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
|
||||
/// Allow insecure connections to a host.
|
||||
///
|
||||
/// Can be provided multiple times.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "trusted-host",
|
||||
env = "UV_INSECURE_HOST",
|
||||
value_delimiter = ' ',
|
||||
value_parser = parse_insecure_host,
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
|
||||
|
||||
/// Limit candidate packages to those that were uploaded prior to the given date.
|
||||
///
|
||||
/// Accepts both RFC 3339 timestamps (e.g., `2006-12-02T02:07:43Z`) and local dates in the same
|
||||
|
@ -3321,6 +3371,26 @@ pub struct InstallerArgs {
|
|||
)]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
|
||||
/// Allow insecure connections to a host.
|
||||
///
|
||||
/// Can be provided multiple times.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "trusted-host",
|
||||
env = "UV_INSECURE_HOST",
|
||||
value_delimiter = ' ',
|
||||
value_parser = parse_insecure_host,
|
||||
help_heading = "Index options"
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
|
||||
|
||||
/// Settings to pass to the PEP 517 build backend, specified as `KEY=VALUE` pairs.
|
||||
#[arg(
|
||||
long,
|
||||
|
@ -3463,6 +3533,26 @@ pub struct ResolverArgs {
|
|||
)]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
|
||||
/// Allow insecure connections to a host.
|
||||
///
|
||||
/// Can be provided multiple times.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "trusted-host",
|
||||
env = "UV_INSECURE_HOST",
|
||||
value_delimiter = ' ',
|
||||
value_parser = parse_insecure_host,
|
||||
help_heading = "Index options"
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
|
||||
|
||||
/// The strategy to use when selecting between the different compatible versions for a given
|
||||
/// package requirement.
|
||||
///
|
||||
|
@ -3635,6 +3725,26 @@ pub struct ResolverInstallerArgs {
|
|||
)]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
|
||||
/// Allow insecure connections to a host.
|
||||
///
|
||||
/// Can be provided multiple times.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[arg(
|
||||
long,
|
||||
alias = "trusted-host",
|
||||
env = "UV_INSECURE_HOST",
|
||||
value_delimiter = ' ',
|
||||
value_parser = parse_insecure_host,
|
||||
help_heading = "Index options"
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
|
||||
|
||||
/// The strategy to use when selecting between the different compatible versions for a given
|
||||
/// package requirement.
|
||||
///
|
||||
|
|
|
@ -38,6 +38,7 @@ impl From<ResolverArgs> for PipOptions {
|
|||
upgrade_package,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
pre,
|
||||
|
@ -55,6 +56,12 @@ impl From<ResolverArgs> for PipOptions {
|
|||
upgrade_package: Some(upgrade_package),
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
resolution,
|
||||
prerelease: if pre {
|
||||
Some(PrereleaseMode::Allow)
|
||||
|
@ -82,6 +89,7 @@ impl From<InstallerArgs> for PipOptions {
|
|||
reinstall_package,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
config_setting,
|
||||
no_build_isolation,
|
||||
build_isolation,
|
||||
|
@ -97,6 +105,12 @@ impl From<InstallerArgs> for PipOptions {
|
|||
reinstall_package: Some(reinstall_package),
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
config_settings: config_setting
|
||||
.map(|config_settings| config_settings.into_iter().collect::<ConfigSettings>()),
|
||||
no_build_isolation: flag(no_build_isolation, build_isolation),
|
||||
|
@ -121,6 +135,7 @@ impl From<ResolverInstallerArgs> for PipOptions {
|
|||
reinstall_package,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
pre,
|
||||
|
@ -142,6 +157,12 @@ impl From<ResolverInstallerArgs> for PipOptions {
|
|||
reinstall_package: Some(reinstall_package),
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
resolution,
|
||||
prerelease: if pre {
|
||||
Some(PrereleaseMode::Allow)
|
||||
|
@ -194,6 +215,7 @@ pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> R
|
|||
upgrade_package,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
pre,
|
||||
|
@ -233,6 +255,12 @@ pub fn resolver_options(resolver_args: ResolverArgs, build_args: BuildArgs) -> R
|
|||
upgrade_package: Some(upgrade_package),
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
resolution,
|
||||
prerelease: if pre {
|
||||
Some(PrereleaseMode::Allow)
|
||||
|
@ -268,6 +296,7 @@ pub fn resolver_installer_options(
|
|||
reinstall_package,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
pre,
|
||||
|
@ -319,6 +348,12 @@ pub fn resolver_installer_options(
|
|||
},
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
resolution,
|
||||
prerelease: if pre {
|
||||
Some(PrereleaseMode::Allow)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::error::Error;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
use std::{env, iter};
|
||||
|
||||
use itertools::Itertools;
|
||||
use pep508_rs::MarkerEnvironment;
|
||||
use platform_tags::Platform;
|
||||
use reqwest::{Client, ClientBuilder, Response};
|
||||
use reqwest_middleware::ClientWithMiddleware;
|
||||
use reqwest_retry::policies::ExponentialBackoff;
|
||||
|
@ -12,11 +13,9 @@ use reqwest_retry::{
|
|||
DefaultRetryableStrategy, RetryTransientMiddleware, Retryable, RetryableStrategy,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
use pep508_rs::MarkerEnvironment;
|
||||
use platform_tags::Platform;
|
||||
use url::Url;
|
||||
use uv_auth::AuthMiddleware;
|
||||
use uv_configuration::KeyringProviderType;
|
||||
use uv_configuration::{KeyringProviderType, TrustedHost};
|
||||
use uv_fs::Simplified;
|
||||
use uv_version::version;
|
||||
use uv_warnings::warn_user_once;
|
||||
|
@ -30,6 +29,7 @@ use crate::Connectivity;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct BaseClientBuilder<'a> {
|
||||
keyring: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
native_tls: bool,
|
||||
retries: u32,
|
||||
pub connectivity: Connectivity,
|
||||
|
@ -48,6 +48,7 @@ impl BaseClientBuilder<'_> {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
keyring: KeyringProviderType::default(),
|
||||
allow_insecure_host: vec![],
|
||||
native_tls: false,
|
||||
connectivity: Connectivity::Online,
|
||||
retries: 3,
|
||||
|
@ -65,6 +66,12 @@ impl<'a> BaseClientBuilder<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn allow_insecure_host(mut self, allow_insecure_host: Vec<TrustedHost>) -> Self {
|
||||
self.allow_insecure_host = allow_insecure_host;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn connectivity(mut self, connectivity: Connectivity) -> Self {
|
||||
self.connectivity = connectivity;
|
||||
|
@ -117,6 +124,18 @@ impl<'a> BaseClientBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// Check for the presence of an `SSL_CERT_FILE`.
|
||||
let ssl_cert_file_exists = env::var_os("SSL_CERT_FILE").is_some_and(|path| {
|
||||
let path_exists = Path::new(&path).exists();
|
||||
if !path_exists {
|
||||
warn_user_once!(
|
||||
"Ignoring invalid `SSL_CERT_FILE`. File does not exist: {}.",
|
||||
path.simplified_display().cyan()
|
||||
);
|
||||
}
|
||||
path_exists
|
||||
});
|
||||
|
||||
// Timeout options, matching https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout
|
||||
// `UV_REQUEST_TIMEOUT` is provided for backwards compatibility with v0.1.6
|
||||
let default_timeout = 30;
|
||||
|
@ -134,54 +153,83 @@ impl<'a> BaseClientBuilder<'a> {
|
|||
.unwrap_or(default_timeout);
|
||||
debug!("Using request timeout of {timeout}s");
|
||||
|
||||
// Initialize the base client.
|
||||
let client = self.client.clone().unwrap_or_else(|| {
|
||||
// Check for the presence of an `SSL_CERT_FILE`.
|
||||
let ssl_cert_file_exists = env::var_os("SSL_CERT_FILE").is_some_and(|path| {
|
||||
let path_exists = Path::new(&path).exists();
|
||||
if !path_exists {
|
||||
warn_user_once!(
|
||||
"Ignoring invalid `SSL_CERT_FILE`. File does not exist: {}.",
|
||||
path.simplified_display().cyan()
|
||||
);
|
||||
// Create a secure client that validates certificates.
|
||||
let client = self.create_client(
|
||||
&user_agent_string,
|
||||
timeout,
|
||||
ssl_cert_file_exists,
|
||||
Security::Secure,
|
||||
);
|
||||
|
||||
// Create an insecure client that accepts invalid certificates.
|
||||
let dangerous_client = self.create_client(
|
||||
&user_agent_string,
|
||||
timeout,
|
||||
ssl_cert_file_exists,
|
||||
Security::Insecure,
|
||||
);
|
||||
|
||||
// Wrap in any relevant middleware and handle connectivity.
|
||||
let client = self.apply_middleware(client);
|
||||
let dangerous_client = self.apply_middleware(dangerous_client);
|
||||
|
||||
BaseClient {
|
||||
connectivity: self.connectivity,
|
||||
allow_insecure_host: self.allow_insecure_host.clone(),
|
||||
client,
|
||||
dangerous_client,
|
||||
timeout,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_client(
|
||||
&self,
|
||||
user_agent: &str,
|
||||
timeout: u64,
|
||||
ssl_cert_file_exists: bool,
|
||||
security: Security,
|
||||
) -> Client {
|
||||
// Configure the builder.
|
||||
let client_builder = ClientBuilder::new()
|
||||
.user_agent(user_agent)
|
||||
.pool_max_idle_per_host(20)
|
||||
.read_timeout(std::time::Duration::from_secs(timeout))
|
||||
.tls_built_in_root_certs(false);
|
||||
|
||||
// If necessary, accept invalid certificates.
|
||||
let client_builder = match security {
|
||||
Security::Secure => client_builder,
|
||||
Security::Insecure => client_builder.danger_accept_invalid_certs(true),
|
||||
};
|
||||
|
||||
let client_builder = if self.native_tls || ssl_cert_file_exists {
|
||||
client_builder.tls_built_in_native_certs(true)
|
||||
} else {
|
||||
client_builder.tls_built_in_webpki_certs(true)
|
||||
};
|
||||
|
||||
// Configure mTLS.
|
||||
let client_builder = if let Some(ssl_client_cert) = env::var_os("SSL_CLIENT_CERT") {
|
||||
match read_identity(&ssl_client_cert) {
|
||||
Ok(identity) => client_builder.identity(identity),
|
||||
Err(err) => {
|
||||
warn_user_once!("Ignoring invalid `SSL_CLIENT_CERT`: {err}");
|
||||
client_builder
|
||||
}
|
||||
path_exists
|
||||
});
|
||||
}
|
||||
} else {
|
||||
client_builder
|
||||
};
|
||||
|
||||
// Configure the builder.
|
||||
let client_core = ClientBuilder::new()
|
||||
.user_agent(user_agent_string)
|
||||
.pool_max_idle_per_host(20)
|
||||
.read_timeout(std::time::Duration::from_secs(timeout))
|
||||
.tls_built_in_root_certs(false);
|
||||
client_builder
|
||||
.build()
|
||||
.expect("Failed to build HTTP client.")
|
||||
}
|
||||
|
||||
// Configure TLS.
|
||||
let client_core = if self.native_tls || ssl_cert_file_exists {
|
||||
client_core.tls_built_in_native_certs(true)
|
||||
} else {
|
||||
client_core.tls_built_in_webpki_certs(true)
|
||||
};
|
||||
|
||||
// Configure mTLS.
|
||||
let client_core = if let Some(ssl_client_cert) = env::var_os("SSL_CLIENT_CERT") {
|
||||
match read_identity(&ssl_client_cert) {
|
||||
Ok(identity) => client_core.identity(identity),
|
||||
Err(err) => {
|
||||
warn_user_once!("Ignoring invalid `SSL_CLIENT_CERT`: {err}");
|
||||
client_core
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client_core
|
||||
};
|
||||
|
||||
client_core.build().expect("Failed to build HTTP client")
|
||||
});
|
||||
|
||||
// Wrap in any relevant middleware.
|
||||
let client = match self.connectivity {
|
||||
fn apply_middleware(&self, client: Client) -> ClientWithMiddleware {
|
||||
match self.connectivity {
|
||||
Connectivity::Online => {
|
||||
let client = reqwest_middleware::ClientBuilder::new(client.clone());
|
||||
let client = reqwest_middleware::ClientBuilder::new(client);
|
||||
|
||||
// Initialize the retry strategy.
|
||||
let retry_policy =
|
||||
|
@ -198,15 +246,9 @@ impl<'a> BaseClientBuilder<'a> {
|
|||
|
||||
client.build()
|
||||
}
|
||||
Connectivity::Offline => reqwest_middleware::ClientBuilder::new(client.clone())
|
||||
Connectivity::Offline => reqwest_middleware::ClientBuilder::new(client)
|
||||
.with(OfflineMiddleware)
|
||||
.build(),
|
||||
};
|
||||
|
||||
BaseClient {
|
||||
connectivity: self.connectivity,
|
||||
client,
|
||||
timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,20 +256,45 @@ impl<'a> BaseClientBuilder<'a> {
|
|||
/// A base client for HTTP requests
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BaseClient {
|
||||
/// The underlying HTTP client.
|
||||
/// The underlying HTTP client that enforces valid certificates.
|
||||
client: ClientWithMiddleware,
|
||||
/// The underlying HTTP client that accepts invalid certificates.
|
||||
dangerous_client: ClientWithMiddleware,
|
||||
/// The connectivity mode to use.
|
||||
connectivity: Connectivity,
|
||||
/// Configured client timeout, in seconds.
|
||||
timeout: u64,
|
||||
/// Hosts that are trusted to use the insecure client.
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Security {
|
||||
/// The client should use secure settings, i.e., valid certificates.
|
||||
Secure,
|
||||
/// The client should use insecure settings, i.e., skip certificate validation.
|
||||
Insecure,
|
||||
}
|
||||
|
||||
impl BaseClient {
|
||||
/// The underlying [`ClientWithMiddleware`].
|
||||
/// The underlying [`ClientWithMiddleware`] for secure requests.
|
||||
pub fn client(&self) -> ClientWithMiddleware {
|
||||
self.client.clone()
|
||||
}
|
||||
|
||||
/// Selects the appropriate client based on the host's trustworthiness.
|
||||
pub fn for_host(&self, url: &Url) -> &ClientWithMiddleware {
|
||||
if self
|
||||
.allow_insecure_host
|
||||
.iter()
|
||||
.any(|allow_insecure_host| allow_insecure_host.matches(url))
|
||||
{
|
||||
&self.dangerous_client
|
||||
} else {
|
||||
&self.client
|
||||
}
|
||||
}
|
||||
|
||||
/// The configured client timeout, in seconds.
|
||||
pub fn timeout(&self) -> u64 {
|
||||
self.timeout
|
||||
|
@ -239,16 +306,6 @@ impl BaseClient {
|
|||
}
|
||||
}
|
||||
|
||||
// To avoid excessively verbose call chains, as the [`BaseClient`] is often nested within other client types.
|
||||
impl Deref for BaseClient {
|
||||
type Target = ClientWithMiddleware;
|
||||
|
||||
/// Deference to the underlying [`ClientWithMiddleware`].
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.client
|
||||
}
|
||||
}
|
||||
|
||||
/// Extends [`DefaultRetryableStrategy`], to log transient request failures and additional retry cases.
|
||||
struct UvRetryableStrategy;
|
||||
|
||||
|
|
|
@ -165,9 +165,9 @@ impl CachedClient {
|
|||
Self(client)
|
||||
}
|
||||
|
||||
/// The base client
|
||||
pub fn uncached(&self) -> BaseClient {
|
||||
self.0.clone()
|
||||
/// The underlying [`BaseClient`] without caching.
|
||||
pub fn uncached(&self) -> &BaseClient {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Make a cached request with a custom response transformation
|
||||
|
@ -460,6 +460,7 @@ impl CachedClient {
|
|||
debug!("Sending revalidation request for: {url}");
|
||||
let response = self
|
||||
.0
|
||||
.for_host(req.url())
|
||||
.execute(req)
|
||||
.instrument(info_span!("revalidation_request", url = url.as_str()))
|
||||
.await
|
||||
|
@ -499,6 +500,7 @@ impl CachedClient {
|
|||
let cache_policy_builder = CachePolicyBuilder::new(&req);
|
||||
let response = self
|
||||
.0
|
||||
.for_host(req.url())
|
||||
.execute(req)
|
||||
.await
|
||||
.map_err(ErrorKind::from)?
|
||||
|
|
|
@ -154,7 +154,7 @@ impl<'a> FlatIndexClient<'a> {
|
|||
|
||||
let flat_index_request = self
|
||||
.client
|
||||
.uncached_client()
|
||||
.uncached_client(url)
|
||||
.get(url.clone())
|
||||
.header("Accept-Encoding", "gzip")
|
||||
.header("Accept", "text/html")
|
||||
|
|
|
@ -7,6 +7,7 @@ use async_http_range_reader::AsyncHttpRangeReader;
|
|||
use futures::{FutureExt, TryStreamExt};
|
||||
use http::HeaderMap;
|
||||
use reqwest::{Client, Response, StatusCode};
|
||||
use reqwest_middleware::ClientWithMiddleware;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
|
||||
|
@ -21,11 +22,11 @@ use pep508_rs::MarkerEnvironment;
|
|||
use platform_tags::Platform;
|
||||
use pypi_types::{Metadata23, SimpleJson};
|
||||
use uv_cache::{Cache, CacheBucket, CacheEntry, WheelCache};
|
||||
use uv_configuration::IndexStrategy;
|
||||
use uv_configuration::KeyringProviderType;
|
||||
use uv_configuration::{IndexStrategy, TrustedHost};
|
||||
use uv_normalize::PackageName;
|
||||
|
||||
use crate::base_client::{BaseClient, BaseClientBuilder};
|
||||
use crate::base_client::BaseClientBuilder;
|
||||
use crate::cached_client::CacheControl;
|
||||
use crate::html::SimpleHtml;
|
||||
use crate::remote_metadata::wheel_metadata_from_remote_zip;
|
||||
|
@ -71,6 +72,14 @@ impl<'a> RegistryClientBuilder<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn allow_insecure_host(mut self, allow_insecure_host: Vec<TrustedHost>) -> Self {
|
||||
self.base_client_builder = self
|
||||
.base_client_builder
|
||||
.allow_insecure_host(allow_insecure_host);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn connectivity(mut self, connectivity: Connectivity) -> Self {
|
||||
self.base_client_builder = self.base_client_builder.connectivity(connectivity);
|
||||
|
@ -171,8 +180,8 @@ impl RegistryClient {
|
|||
}
|
||||
|
||||
/// Return the [`BaseClient`] used by this client.
|
||||
pub fn uncached_client(&self) -> BaseClient {
|
||||
self.client.uncached()
|
||||
pub fn uncached_client(&self, url: &Url) -> &ClientWithMiddleware {
|
||||
self.client.uncached().for_host(url)
|
||||
}
|
||||
|
||||
/// Return the [`Connectivity`] mode used by this client.
|
||||
|
@ -298,7 +307,7 @@ impl RegistryClient {
|
|||
cache_control: CacheControl,
|
||||
) -> Result<OwnedArchive<SimpleMetadata>, Error> {
|
||||
let simple_request = self
|
||||
.uncached_client()
|
||||
.uncached_client(url)
|
||||
.get(url.clone())
|
||||
.header("Accept-Encoding", "gzip")
|
||||
.header("Accept", MediaType::accepts())
|
||||
|
@ -512,7 +521,7 @@ impl RegistryClient {
|
|||
})
|
||||
};
|
||||
let req = self
|
||||
.uncached_client()
|
||||
.uncached_client(&url)
|
||||
.get(url.clone())
|
||||
.build()
|
||||
.map_err(ErrorKind::from)?;
|
||||
|
@ -551,7 +560,7 @@ impl RegistryClient {
|
|||
};
|
||||
|
||||
let req = self
|
||||
.uncached_client()
|
||||
.uncached_client(url)
|
||||
.head(url.clone())
|
||||
.header(
|
||||
"accept-encoding",
|
||||
|
@ -571,7 +580,7 @@ impl RegistryClient {
|
|||
let read_metadata_range_request = |response: Response| {
|
||||
async {
|
||||
let mut reader = AsyncHttpRangeReader::from_head_response(
|
||||
self.uncached_client().client(),
|
||||
self.uncached_client(url).clone(),
|
||||
response,
|
||||
url.clone(),
|
||||
headers,
|
||||
|
@ -619,7 +628,7 @@ impl RegistryClient {
|
|||
|
||||
// Create a request to stream the file.
|
||||
let req = self
|
||||
.uncached_client()
|
||||
.uncached_client(url)
|
||||
.get(url.clone())
|
||||
.header(
|
||||
// `reqwest` defaults to accepting compressed responses.
|
||||
|
|
|
@ -56,6 +56,7 @@ async fn test_user_agent_has_version() -> Result<()> {
|
|||
let res = client
|
||||
.cached_client()
|
||||
.uncached()
|
||||
.client()
|
||||
.get(format!("http://{addr}"))
|
||||
.send()
|
||||
.await?;
|
||||
|
@ -151,6 +152,7 @@ async fn test_user_agent_has_linehaul() -> Result<()> {
|
|||
let res = client
|
||||
.cached_client()
|
||||
.uncached()
|
||||
.client()
|
||||
.get(format!("http://{addr}"))
|
||||
.send()
|
||||
.await?;
|
||||
|
|
|
@ -28,7 +28,9 @@ rustc-hash = { workspace = true }
|
|||
schemars = { workspace = true, optional = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
url = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
@ -12,6 +12,7 @@ pub use package_options::*;
|
|||
pub use preview::*;
|
||||
pub use sources::*;
|
||||
pub use target_triple::*;
|
||||
pub use trusted_host::*;
|
||||
|
||||
mod authentication;
|
||||
mod build_options;
|
||||
|
@ -27,3 +28,4 @@ mod package_options;
|
|||
mod preview;
|
||||
mod sources;
|
||||
mod target_triple;
|
||||
mod trusted_host;
|
||||
|
|
137
crates/uv-configuration/src/trusted_host.rs
Normal file
137
crates/uv-configuration/src/trusted_host.rs
Normal file
|
@ -0,0 +1,137 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
/// A trusted host, which could be a host or a host-port pair.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TrustedHost {
|
||||
scheme: Option<String>,
|
||||
host: String,
|
||||
port: Option<u16>,
|
||||
}
|
||||
|
||||
impl TrustedHost {
|
||||
/// Returns `true` if the [`Url`] matches this trusted host.
|
||||
pub fn matches(&self, url: &Url) -> bool {
|
||||
if self
|
||||
.scheme
|
||||
.as_ref()
|
||||
.is_some_and(|scheme| scheme != url.scheme())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.port.is_some_and(|port| url.port() != Some(port)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if Some(self.host.as_ref()) != url.host_str() {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TrustedHostError {
|
||||
#[error("missing host for `--trusted-host`: `{0}`")]
|
||||
MissingHost(String),
|
||||
#[error("invalid port for `--trusted-host`: `{0}`")]
|
||||
InvalidPort(String),
|
||||
}
|
||||
|
||||
impl std::str::FromStr for TrustedHost {
|
||||
type Err = TrustedHostError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// Detect scheme.
|
||||
let (scheme, s) = if let Some(s) = s.strip_prefix("https://") {
|
||||
(Some("https".to_string()), s)
|
||||
} else if let Some(s) = s.strip_prefix("http://") {
|
||||
(Some("http".to_string()), s)
|
||||
} else {
|
||||
(None, s)
|
||||
};
|
||||
|
||||
let mut parts = s.splitn(2, ':');
|
||||
|
||||
// Detect host.
|
||||
let host = parts
|
||||
.next()
|
||||
.and_then(|host| host.split('/').next())
|
||||
.map(ToString::to_string)
|
||||
.ok_or_else(|| TrustedHostError::MissingHost(s.to_string()))?;
|
||||
|
||||
// Detect port.
|
||||
let port = parts
|
||||
.next()
|
||||
.map(str::parse)
|
||||
.transpose()
|
||||
.map_err(|_| TrustedHostError::InvalidPort(s.to_string()))?;
|
||||
|
||||
Ok(Self { scheme, host, port })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "schemars")]
|
||||
impl schemars::JsonSchema for TrustedHost {
|
||||
fn schema_name() -> String {
|
||||
"TrustedHost".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
schemars::schema::SchemaObject {
|
||||
instance_type: Some(schemars::schema::InstanceType::String.into()),
|
||||
metadata: Some(Box::new(schemars::schema::Metadata {
|
||||
description: Some("A host or host-port pair.".to_string()),
|
||||
..schemars::schema::Metadata::default()
|
||||
})),
|
||||
..schemars::schema::SchemaObject::default()
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn parse() {
|
||||
assert_eq!(
|
||||
"example.com".parse::<super::TrustedHost>().unwrap(),
|
||||
super::TrustedHost {
|
||||
scheme: None,
|
||||
host: "example.com".to_string(),
|
||||
port: None
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
"example.com:8080".parse::<super::TrustedHost>().unwrap(),
|
||||
super::TrustedHost {
|
||||
scheme: None,
|
||||
host: "example.com".to_string(),
|
||||
port: Some(8080)
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
"https://example.com".parse::<super::TrustedHost>().unwrap(),
|
||||
super::TrustedHost {
|
||||
scheme: Some("https".to_string()),
|
||||
host: "example.com".to_string(),
|
||||
port: None
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
"https://example.com/hello/world"
|
||||
.parse::<super::TrustedHost>()
|
||||
.unwrap(),
|
||||
super::TrustedHost {
|
||||
scheme: Some("https".to_string()),
|
||||
host: "example.com".to_string(),
|
||||
port: None
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -834,7 +834,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
|
|||
fn request(&self, url: Url) -> Result<reqwest::Request, reqwest::Error> {
|
||||
self.client
|
||||
.unmanaged
|
||||
.uncached_client()
|
||||
.uncached_client(&url)
|
||||
.get(url)
|
||||
.header(
|
||||
// `reqwest` defaults to accepting compressed responses.
|
||||
|
|
|
@ -1118,7 +1118,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.git()
|
||||
.fetch(
|
||||
resource.git,
|
||||
client.unmanaged.uncached_client().client(),
|
||||
client.unmanaged.uncached_client(resource.url).clone(),
|
||||
self.build_context.cache().bucket(CacheBucket::Git),
|
||||
self.reporter.clone().map(Facade::from),
|
||||
)
|
||||
|
@ -1188,7 +1188,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.git()
|
||||
.fetch(
|
||||
resource.git,
|
||||
client.unmanaged.uncached_client().client(),
|
||||
client.unmanaged.uncached_client(resource.url).clone(),
|
||||
self.build_context.cache().bucket(CacheBucket::Git),
|
||||
self.reporter.clone().map(Facade::from),
|
||||
)
|
||||
|
@ -1589,7 +1589,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
/// Returns a GET [`reqwest::Request`] for the given URL.
|
||||
fn request(url: Url, client: &RegistryClient) -> Result<reqwest::Request, reqwest::Error> {
|
||||
client
|
||||
.uncached_client()
|
||||
.uncached_client(&url)
|
||||
.get(url)
|
||||
.header(
|
||||
// `reqwest` defaults to accepting compressed responses.
|
||||
|
|
|
@ -432,7 +432,7 @@ impl ManagedPythonDownload {
|
|||
let filename = url.path_segments().unwrap().last().unwrap();
|
||||
let ext = SourceDistExtension::from_path(filename)
|
||||
.map_err(|err| Error::MissingExtension(url.to_string(), err))?;
|
||||
let response = client.get(url.clone()).send().await?;
|
||||
let response = client.client().get(url.clone()).send().await?;
|
||||
|
||||
// Ensure the request was successful.
|
||||
response.error_for_status_ref()?;
|
||||
|
|
|
@ -8,6 +8,7 @@ use pep508_rs::Requirement;
|
|||
use pypi_types::{SupportedEnvironments, VerbatimParsedUrl};
|
||||
use uv_configuration::{
|
||||
ConfigSettings, IndexStrategy, KeyringProviderType, PackageNameSpecifier, TargetTriple,
|
||||
TrustedHost,
|
||||
};
|
||||
use uv_macros::{CombineOptions, OptionsMetadata};
|
||||
use uv_normalize::{ExtraName, PackageName};
|
||||
|
@ -213,6 +214,7 @@ pub struct InstallerOptions {
|
|||
pub find_links: Option<Vec<FlatIndexLocation>>,
|
||||
pub index_strategy: Option<IndexStrategy>,
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
pub allow_insecure_host: Option<Vec<TrustedHost>>,
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
pub exclude_newer: Option<ExcludeNewer>,
|
||||
pub link_mode: Option<LinkMode>,
|
||||
|
@ -239,6 +241,7 @@ pub struct ResolverOptions {
|
|||
pub find_links: Option<Vec<FlatIndexLocation>>,
|
||||
pub index_strategy: Option<IndexStrategy>,
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
pub allow_insecure_host: Option<Vec<TrustedHost>>,
|
||||
pub resolution: Option<ResolutionMode>,
|
||||
pub prerelease: Option<PrereleaseMode>,
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
|
@ -350,6 +353,22 @@ pub struct ResolverInstallerOptions {
|
|||
"#
|
||||
)]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
/// Allow insecure connections to host.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[option(
|
||||
default = "[]",
|
||||
value_type = "list[str]",
|
||||
example = r#"
|
||||
allow-insecure-host = ["localhost:8080"]
|
||||
"#
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<TrustedHost>>,
|
||||
/// The strategy to use when selecting between the different compatible versions for a given
|
||||
/// package requirement.
|
||||
///
|
||||
|
@ -721,6 +740,22 @@ pub struct PipOptions {
|
|||
"#
|
||||
)]
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
/// Allow insecure connections to host.
|
||||
///
|
||||
/// Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
/// `localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
///
|
||||
/// WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
/// store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
/// bypasses SSL verification and could expose you to MITM attacks.
|
||||
#[option(
|
||||
default = "[]",
|
||||
value_type = "list[str]",
|
||||
example = r#"
|
||||
allow-insecure-host = ["localhost:8080"]
|
||||
"#
|
||||
)]
|
||||
pub allow_insecure_host: Option<Vec<TrustedHost>>,
|
||||
/// Don't build source distributions.
|
||||
///
|
||||
/// When enabled, resolving will not run arbitrary Python code. The cached wheels of
|
||||
|
@ -1208,6 +1243,7 @@ impl From<ResolverInstallerOptions> for ResolverOptions {
|
|||
find_links: value.find_links,
|
||||
index_strategy: value.index_strategy,
|
||||
keyring_provider: value.keyring_provider,
|
||||
allow_insecure_host: value.allow_insecure_host,
|
||||
resolution: value.resolution,
|
||||
prerelease: value.prerelease,
|
||||
config_settings: value.config_settings,
|
||||
|
@ -1235,6 +1271,7 @@ impl From<ResolverInstallerOptions> for InstallerOptions {
|
|||
find_links: value.find_links,
|
||||
index_strategy: value.index_strategy,
|
||||
keyring_provider: value.keyring_provider,
|
||||
allow_insecure_host: value.allow_insecure_host,
|
||||
config_settings: value.config_settings,
|
||||
exclude_newer: value.exclude_newer,
|
||||
link_mode: value.link_mode,
|
||||
|
@ -1267,6 +1304,7 @@ pub struct ToolOptions {
|
|||
pub find_links: Option<Vec<FlatIndexLocation>>,
|
||||
pub index_strategy: Option<IndexStrategy>,
|
||||
pub keyring_provider: Option<KeyringProviderType>,
|
||||
pub allow_insecure_host: Option<Vec<TrustedHost>>,
|
||||
pub resolution: Option<ResolutionMode>,
|
||||
pub prerelease: Option<PrereleaseMode>,
|
||||
pub config_settings: Option<ConfigSettings>,
|
||||
|
@ -1291,6 +1329,7 @@ impl From<ResolverInstallerOptions> for ToolOptions {
|
|||
find_links: value.find_links,
|
||||
index_strategy: value.index_strategy,
|
||||
keyring_provider: value.keyring_provider,
|
||||
allow_insecure_host: value.allow_insecure_host,
|
||||
resolution: value.resolution,
|
||||
prerelease: value.prerelease,
|
||||
config_settings: value.config_settings,
|
||||
|
@ -1317,6 +1356,7 @@ impl From<ToolOptions> for ResolverInstallerOptions {
|
|||
find_links: value.find_links,
|
||||
index_strategy: value.index_strategy,
|
||||
keyring_provider: value.keyring_provider,
|
||||
allow_insecure_host: value.allow_insecure_host,
|
||||
resolution: value.resolution,
|
||||
prerelease: value.prerelease,
|
||||
config_settings: value.config_settings,
|
||||
|
|
|
@ -17,7 +17,7 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, ExtrasSpecification, IndexStrategy, NoBinary,
|
||||
NoBuild, Reinstall, SourceStrategy, Upgrade,
|
||||
NoBuild, Reinstall, SourceStrategy, TrustedHost, Upgrade,
|
||||
};
|
||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
|
@ -75,6 +75,7 @@ pub(crate) async fn pip_compile(
|
|||
index_locations: IndexLocations,
|
||||
index_strategy: IndexStrategy,
|
||||
keyring_provider: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
config_settings: ConfigSettings,
|
||||
connectivity: Connectivity,
|
||||
no_build_isolation: bool,
|
||||
|
@ -107,7 +108,8 @@ pub(crate) async fn pip_compile(
|
|||
let client_builder = BaseClientBuilder::new()
|
||||
.connectivity(connectivity)
|
||||
.native_tls(native_tls)
|
||||
.keyring(keyring_provider);
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host);
|
||||
|
||||
// Read all requirements from the provided sources.
|
||||
let RequirementsSpecification {
|
||||
|
|
|
@ -3,18 +3,18 @@ use std::fmt::Write;
|
|||
use anstream::eprint;
|
||||
use itertools::Itertools;
|
||||
use owo_colors::OwoColorize;
|
||||
use pep508_rs::PackageName;
|
||||
use tracing::{debug, enabled, Level};
|
||||
|
||||
use distribution_types::{IndexLocations, Resolution, UnresolvedRequirementSpecification};
|
||||
use install_wheel_rs::linker::LinkMode;
|
||||
use pep508_rs::PackageName;
|
||||
use pypi_types::Requirement;
|
||||
use uv_auth::store_credentials_from_url;
|
||||
use uv_cache::Cache;
|
||||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, ExtrasSpecification, HashCheckingMode,
|
||||
IndexStrategy, Reinstall, SourceStrategy, Upgrade,
|
||||
IndexStrategy, Reinstall, SourceStrategy, TrustedHost, Upgrade,
|
||||
};
|
||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
|
@ -53,6 +53,7 @@ pub(crate) async fn pip_install(
|
|||
index_locations: IndexLocations,
|
||||
index_strategy: IndexStrategy,
|
||||
keyring_provider: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
reinstall: Reinstall,
|
||||
link_mode: LinkMode,
|
||||
compile: bool,
|
||||
|
@ -83,7 +84,8 @@ pub(crate) async fn pip_install(
|
|||
let client_builder = BaseClientBuilder::new()
|
||||
.connectivity(connectivity)
|
||||
.native_tls(native_tls)
|
||||
.keyring(keyring_provider);
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host);
|
||||
|
||||
// Read all requirements from the provided sources.
|
||||
let RequirementsSpecification {
|
||||
|
|
|
@ -3,17 +3,17 @@ use std::fmt::Write;
|
|||
use anstream::eprint;
|
||||
use anyhow::Result;
|
||||
use owo_colors::OwoColorize;
|
||||
use pep508_rs::PackageName;
|
||||
use tracing::debug;
|
||||
|
||||
use distribution_types::{IndexLocations, Resolution};
|
||||
use install_wheel_rs::linker::LinkMode;
|
||||
use pep508_rs::PackageName;
|
||||
use uv_auth::store_credentials_from_url;
|
||||
use uv_cache::Cache;
|
||||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, ExtrasSpecification, HashCheckingMode,
|
||||
IndexStrategy, Reinstall, SourceStrategy, Upgrade,
|
||||
IndexStrategy, Reinstall, SourceStrategy, TrustedHost, Upgrade,
|
||||
};
|
||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
|
@ -48,6 +48,7 @@ pub(crate) async fn pip_sync(
|
|||
index_locations: IndexLocations,
|
||||
index_strategy: IndexStrategy,
|
||||
keyring_provider: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
allow_empty_requirements: bool,
|
||||
connectivity: Connectivity,
|
||||
config_settings: &ConfigSettings,
|
||||
|
@ -73,7 +74,8 @@ pub(crate) async fn pip_sync(
|
|||
let client_builder = BaseClientBuilder::new()
|
||||
.connectivity(connectivity)
|
||||
.native_tls(native_tls)
|
||||
.keyring(keyring_provider);
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host);
|
||||
|
||||
// Initialize a few defaults.
|
||||
let overrides = &[];
|
||||
|
|
|
@ -11,7 +11,7 @@ use pypi_types::Requirement;
|
|||
use pypi_types::VerbatimParsedUrl;
|
||||
use uv_cache::Cache;
|
||||
use uv_client::{BaseClientBuilder, Connectivity};
|
||||
use uv_configuration::KeyringProviderType;
|
||||
use uv_configuration::{KeyringProviderType, TrustedHost};
|
||||
use uv_fs::Simplified;
|
||||
use uv_python::EnvironmentPreference;
|
||||
use uv_python::PythonRequest;
|
||||
|
@ -33,6 +33,7 @@ pub(crate) async fn pip_uninstall(
|
|||
connectivity: Connectivity,
|
||||
native_tls: bool,
|
||||
keyring_provider: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
printer: Printer,
|
||||
) -> Result<ExitStatus> {
|
||||
let start = std::time::Instant::now();
|
||||
|
@ -40,7 +41,8 @@ pub(crate) async fn pip_uninstall(
|
|||
let client_builder = BaseClientBuilder::new()
|
||||
.connectivity(connectivity)
|
||||
.native_tls(native_tls)
|
||||
.keyring(keyring_provider);
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host);
|
||||
|
||||
// Read all requirements from the provided sources.
|
||||
let spec = RequirementsSpecification::from_simple_sources(sources, &client_builder).await?;
|
||||
|
|
|
@ -234,6 +234,7 @@ async fn do_lock(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
config_setting,
|
||||
|
@ -342,6 +343,7 @@ async fn do_lock(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(index_strategy)
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host.to_vec())
|
||||
.markers(interpreter.markers())
|
||||
.platform(interpreter.platform())
|
||||
.build();
|
||||
|
|
|
@ -410,6 +410,7 @@ pub(crate) async fn resolve_names(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution: _,
|
||||
prerelease: _,
|
||||
config_setting,
|
||||
|
@ -436,6 +437,7 @@ pub(crate) async fn resolve_names(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(*index_strategy)
|
||||
.keyring(*keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host.clone())
|
||||
.markers(interpreter.markers())
|
||||
.platform(interpreter.platform())
|
||||
.build();
|
||||
|
@ -510,6 +512,7 @@ pub(crate) async fn resolve_environment<'a>(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
config_setting,
|
||||
|
@ -549,6 +552,7 @@ pub(crate) async fn resolve_environment<'a>(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(index_strategy)
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host.to_vec())
|
||||
.markers(interpreter.markers())
|
||||
.platform(interpreter.platform())
|
||||
.build();
|
||||
|
@ -660,6 +664,7 @@ pub(crate) async fn sync_environment(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
config_setting,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
|
@ -690,6 +695,7 @@ pub(crate) async fn sync_environment(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(index_strategy)
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host.to_vec())
|
||||
.markers(interpreter.markers())
|
||||
.platform(interpreter.platform())
|
||||
.build();
|
||||
|
@ -804,6 +810,7 @@ pub(crate) async fn update_environment(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
resolution,
|
||||
prerelease,
|
||||
config_setting,
|
||||
|
@ -871,6 +878,7 @@ pub(crate) async fn update_environment(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(*index_strategy)
|
||||
.keyring(*keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host.clone())
|
||||
.markers(interpreter.markers())
|
||||
.platform(interpreter.platform())
|
||||
.build();
|
||||
|
|
|
@ -143,6 +143,7 @@ pub(super) async fn do_sync(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
config_setting,
|
||||
no_build_isolation,
|
||||
no_build_isolation_package,
|
||||
|
@ -209,6 +210,7 @@ pub(super) async fn do_sync(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(index_strategy)
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host.to_vec())
|
||||
.markers(venv.interpreter().markers())
|
||||
.platform(venv.interpreter().platform())
|
||||
.build();
|
||||
|
|
|
@ -17,7 +17,7 @@ use uv_cache::Cache;
|
|||
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
|
||||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, IndexStrategy, KeyringProviderType, NoBinary,
|
||||
NoBuild, SourceStrategy,
|
||||
NoBuild, SourceStrategy, TrustedHost,
|
||||
};
|
||||
use uv_dispatch::BuildDispatch;
|
||||
use uv_fs::{Simplified, CWD};
|
||||
|
@ -49,6 +49,7 @@ pub(crate) async fn venv(
|
|||
index_locations: &IndexLocations,
|
||||
index_strategy: IndexStrategy,
|
||||
keyring_provider: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
prompt: uv_virtualenv::Prompt,
|
||||
system_site_packages: bool,
|
||||
connectivity: Connectivity,
|
||||
|
@ -69,6 +70,7 @@ pub(crate) async fn venv(
|
|||
index_locations,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
prompt,
|
||||
system_site_packages,
|
||||
connectivity,
|
||||
|
@ -122,6 +124,7 @@ async fn venv_impl(
|
|||
index_locations: &IndexLocations,
|
||||
index_strategy: IndexStrategy,
|
||||
keyring_provider: KeyringProviderType,
|
||||
allow_insecure_host: Vec<TrustedHost>,
|
||||
prompt: uv_virtualenv::Prompt,
|
||||
system_site_packages: bool,
|
||||
connectivity: Connectivity,
|
||||
|
@ -251,6 +254,7 @@ async fn venv_impl(
|
|||
.index_urls(index_locations.index_urls())
|
||||
.index_strategy(index_strategy)
|
||||
.keyring(keyring_provider)
|
||||
.allow_insecure_host(allow_insecure_host)
|
||||
.markers(interpreter.markers())
|
||||
.platform(interpreter.platform())
|
||||
.build();
|
||||
|
|
|
@ -325,6 +325,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.index_locations,
|
||||
args.settings.index_strategy,
|
||||
args.settings.keyring_provider,
|
||||
args.settings.allow_insecure_host,
|
||||
args.settings.config_setting,
|
||||
globals.connectivity,
|
||||
args.settings.no_build_isolation,
|
||||
|
@ -391,6 +392,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.index_locations,
|
||||
args.settings.index_strategy,
|
||||
args.settings.keyring_provider,
|
||||
args.settings.allow_insecure_host,
|
||||
args.settings.allow_empty_requirements,
|
||||
globals.connectivity,
|
||||
&args.settings.config_setting,
|
||||
|
@ -474,6 +476,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
args.settings.index_locations,
|
||||
args.settings.index_strategy,
|
||||
args.settings.keyring_provider,
|
||||
args.settings.allow_insecure_host,
|
||||
args.settings.reinstall,
|
||||
args.settings.link_mode,
|
||||
args.settings.compile_bytecode,
|
||||
|
@ -532,6 +535,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
globals.connectivity,
|
||||
globals.native_tls,
|
||||
args.settings.keyring_provider,
|
||||
args.settings.allow_insecure_host,
|
||||
printer,
|
||||
)
|
||||
.await
|
||||
|
@ -692,6 +696,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
|||
&args.settings.index_locations,
|
||||
args.settings.index_strategy,
|
||||
args.settings.keyring_provider,
|
||||
args.settings.allow_insecure_host,
|
||||
uv_virtualenv::Prompt::from_args(prompt),
|
||||
args.system_site_packages,
|
||||
globals.connectivity,
|
||||
|
|
|
@ -24,7 +24,7 @@ use uv_client::Connectivity;
|
|||
use uv_configuration::{
|
||||
BuildOptions, Concurrency, ConfigSettings, ExtrasSpecification, HashCheckingMode,
|
||||
IndexStrategy, InstallOptions, KeyringProviderType, NoBinary, NoBuild, PreviewMode, Reinstall,
|
||||
SourceStrategy, TargetTriple, Upgrade,
|
||||
SourceStrategy, TargetTriple, TrustedHost, Upgrade,
|
||||
};
|
||||
use uv_normalize::PackageName;
|
||||
use uv_python::{Prefix, PythonDownloads, PythonPreference, PythonVersion, Target};
|
||||
|
@ -1308,6 +1308,7 @@ impl PipUninstallSettings {
|
|||
requirement,
|
||||
python,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
system,
|
||||
no_system,
|
||||
break_system_packages,
|
||||
|
@ -1328,6 +1329,12 @@ impl PipUninstallSettings {
|
|||
target,
|
||||
prefix,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
..PipOptions::default()
|
||||
},
|
||||
filesystem,
|
||||
|
@ -1558,6 +1565,7 @@ impl VenvSettings {
|
|||
index_args,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
exclude_newer,
|
||||
link_mode,
|
||||
compat_args: _,
|
||||
|
@ -1576,6 +1584,12 @@ impl VenvSettings {
|
|||
system: flag(system, no_system),
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host: allow_insecure_host.map(|allow_insecure_host| {
|
||||
allow_insecure_host
|
||||
.into_iter()
|
||||
.filter_map(Maybe::into_option)
|
||||
.collect()
|
||||
}),
|
||||
exclude_newer,
|
||||
link_mode,
|
||||
..PipOptions::from(index_args)
|
||||
|
@ -1595,6 +1609,7 @@ pub(crate) struct InstallerSettingsRef<'a> {
|
|||
pub(crate) index_locations: &'a IndexLocations,
|
||||
pub(crate) index_strategy: IndexStrategy,
|
||||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) allow_insecure_host: &'a [TrustedHost],
|
||||
pub(crate) config_setting: &'a ConfigSettings,
|
||||
pub(crate) no_build_isolation: bool,
|
||||
pub(crate) no_build_isolation_package: &'a [PackageName],
|
||||
|
@ -1616,6 +1631,7 @@ pub(crate) struct ResolverSettings {
|
|||
pub(crate) index_locations: IndexLocations,
|
||||
pub(crate) index_strategy: IndexStrategy,
|
||||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) allow_insecure_host: Vec<TrustedHost>,
|
||||
pub(crate) resolution: ResolutionMode,
|
||||
pub(crate) prerelease: PrereleaseMode,
|
||||
pub(crate) config_setting: ConfigSettings,
|
||||
|
@ -1633,6 +1649,7 @@ pub(crate) struct ResolverSettingsRef<'a> {
|
|||
pub(crate) index_locations: &'a IndexLocations,
|
||||
pub(crate) index_strategy: IndexStrategy,
|
||||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) allow_insecure_host: &'a [TrustedHost],
|
||||
pub(crate) resolution: ResolutionMode,
|
||||
pub(crate) prerelease: PrereleaseMode,
|
||||
pub(crate) config_setting: &'a ConfigSettings,
|
||||
|
@ -1663,6 +1680,7 @@ impl ResolverSettings {
|
|||
index_locations: &self.index_locations,
|
||||
index_strategy: self.index_strategy,
|
||||
keyring_provider: self.keyring_provider,
|
||||
allow_insecure_host: &self.allow_insecure_host,
|
||||
resolution: self.resolution,
|
||||
prerelease: self.prerelease,
|
||||
config_setting: &self.config_setting,
|
||||
|
@ -1690,6 +1708,7 @@ impl From<ResolverOptions> for ResolverSettings {
|
|||
prerelease: value.prerelease.unwrap_or_default(),
|
||||
index_strategy: value.index_strategy.unwrap_or_default(),
|
||||
keyring_provider: value.keyring_provider.unwrap_or_default(),
|
||||
allow_insecure_host: value.allow_insecure_host.unwrap_or_default(),
|
||||
config_setting: value.config_settings.unwrap_or_default(),
|
||||
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
||||
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
||||
|
@ -1718,6 +1737,7 @@ pub(crate) struct ResolverInstallerSettingsRef<'a> {
|
|||
pub(crate) index_locations: &'a IndexLocations,
|
||||
pub(crate) index_strategy: IndexStrategy,
|
||||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) allow_insecure_host: &'a [TrustedHost],
|
||||
pub(crate) resolution: ResolutionMode,
|
||||
pub(crate) prerelease: PrereleaseMode,
|
||||
pub(crate) config_setting: &'a ConfigSettings,
|
||||
|
@ -1744,6 +1764,7 @@ pub(crate) struct ResolverInstallerSettings {
|
|||
pub(crate) index_locations: IndexLocations,
|
||||
pub(crate) index_strategy: IndexStrategy,
|
||||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) allow_insecure_host: Vec<TrustedHost>,
|
||||
pub(crate) resolution: ResolutionMode,
|
||||
pub(crate) prerelease: PrereleaseMode,
|
||||
pub(crate) config_setting: ConfigSettings,
|
||||
|
@ -1779,6 +1800,7 @@ impl ResolverInstallerSettings {
|
|||
index_locations: &self.index_locations,
|
||||
index_strategy: self.index_strategy,
|
||||
keyring_provider: self.keyring_provider,
|
||||
allow_insecure_host: &self.allow_insecure_host,
|
||||
resolution: self.resolution,
|
||||
prerelease: self.prerelease,
|
||||
config_setting: &self.config_setting,
|
||||
|
@ -1808,6 +1830,7 @@ impl From<ResolverInstallerOptions> for ResolverInstallerSettings {
|
|||
prerelease: value.prerelease.unwrap_or_default(),
|
||||
index_strategy: value.index_strategy.unwrap_or_default(),
|
||||
keyring_provider: value.keyring_provider.unwrap_or_default(),
|
||||
allow_insecure_host: value.allow_insecure_host.unwrap_or_default(),
|
||||
config_setting: value.config_settings.unwrap_or_default(),
|
||||
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
||||
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
||||
|
@ -1852,6 +1875,7 @@ pub(crate) struct PipSettings {
|
|||
pub(crate) prefix: Option<Prefix>,
|
||||
pub(crate) index_strategy: IndexStrategy,
|
||||
pub(crate) keyring_provider: KeyringProviderType,
|
||||
pub(crate) allow_insecure_host: Vec<TrustedHost>,
|
||||
pub(crate) no_build_isolation: bool,
|
||||
pub(crate) no_build_isolation_package: Vec<PackageName>,
|
||||
pub(crate) build_options: BuildOptions,
|
||||
|
@ -1906,6 +1930,7 @@ impl PipSettings {
|
|||
find_links,
|
||||
index_strategy,
|
||||
keyring_provider,
|
||||
allow_insecure_host,
|
||||
no_build,
|
||||
no_binary,
|
||||
only_binary,
|
||||
|
@ -1955,6 +1980,7 @@ impl PipSettings {
|
|||
find_links: top_level_find_links,
|
||||
index_strategy: top_level_index_strategy,
|
||||
keyring_provider: top_level_keyring_provider,
|
||||
allow_insecure_host: top_level_allow_insecure_host,
|
||||
resolution: top_level_resolution,
|
||||
prerelease: top_level_prerelease,
|
||||
config_settings: top_level_config_settings,
|
||||
|
@ -1984,6 +2010,7 @@ impl PipSettings {
|
|||
let find_links = find_links.combine(top_level_find_links);
|
||||
let index_strategy = index_strategy.combine(top_level_index_strategy);
|
||||
let keyring_provider = keyring_provider.combine(top_level_keyring_provider);
|
||||
let allow_insecure_host = allow_insecure_host.combine(top_level_allow_insecure_host);
|
||||
let resolution = resolution.combine(top_level_resolution);
|
||||
let prerelease = prerelease.combine(top_level_prerelease);
|
||||
let config_settings = config_settings.combine(top_level_config_settings);
|
||||
|
@ -2043,6 +2070,10 @@ impl PipSettings {
|
|||
.keyring_provider
|
||||
.combine(keyring_provider)
|
||||
.unwrap_or_default(),
|
||||
allow_insecure_host: args
|
||||
.allow_insecure_host
|
||||
.combine(allow_insecure_host)
|
||||
.unwrap_or_default(),
|
||||
generate_hashes: args
|
||||
.generate_hashes
|
||||
.combine(generate_hashes)
|
||||
|
@ -2156,6 +2187,7 @@ impl<'a> From<ResolverInstallerSettingsRef<'a>> for ResolverSettingsRef<'a> {
|
|||
index_locations: settings.index_locations,
|
||||
index_strategy: settings.index_strategy,
|
||||
keyring_provider: settings.keyring_provider,
|
||||
allow_insecure_host: settings.allow_insecure_host,
|
||||
resolution: settings.resolution,
|
||||
prerelease: settings.prerelease,
|
||||
config_setting: settings.config_setting,
|
||||
|
@ -2176,6 +2208,7 @@ impl<'a> From<ResolverInstallerSettingsRef<'a>> for InstallerSettingsRef<'a> {
|
|||
index_locations: settings.index_locations,
|
||||
index_strategy: settings.index_strategy,
|
||||
keyring_provider: settings.keyring_provider,
|
||||
allow_insecure_host: settings.allow_insecure_host,
|
||||
config_setting: settings.config_setting,
|
||||
no_build_isolation: settings.no_build_isolation,
|
||||
no_build_isolation_package: settings.no_build_isolation_package,
|
||||
|
|
|
@ -128,6 +128,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -266,6 +267,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -405,6 +407,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -576,6 +579,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -693,6 +697,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -842,6 +847,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1028,6 +1034,7 @@ fn resolve_index_url() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1213,6 +1220,7 @@ fn resolve_index_url() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1376,6 +1384,7 @@ fn resolve_find_links() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1515,6 +1524,7 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1692,6 +1702,7 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1852,6 +1863,7 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -1991,6 +2003,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -2113,6 +2126,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -2235,6 +2249,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -2359,6 +2374,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -2488,6 +2504,7 @@ fn resolve_tool() -> anyhow::Result<()> {
|
|||
find_links: None,
|
||||
index_strategy: None,
|
||||
keyring_provider: None,
|
||||
allow_insecure_host: None,
|
||||
resolution: Some(
|
||||
LowestDirect,
|
||||
),
|
||||
|
@ -2523,6 +2540,7 @@ fn resolve_tool() -> anyhow::Result<()> {
|
|||
},
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
resolution: LowestDirect,
|
||||
prerelease: IfNecessaryOrExplicit,
|
||||
config_setting: ConfigSettings(
|
||||
|
@ -2653,6 +2671,7 @@ fn resolve_poetry_toml() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -2826,6 +2845,7 @@ fn resolve_both() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -2991,6 +3011,7 @@ fn resolve_config_file() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -3208,6 +3229,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
@ -3333,6 +3355,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> {
|
|||
prefix: None,
|
||||
index_strategy: FirstIndex,
|
||||
keyring_provider: Disabled,
|
||||
allow_insecure_host: [],
|
||||
no_build_isolation: false,
|
||||
no_build_isolation_package: [],
|
||||
build_options: BuildOptions {
|
||||
|
|
|
@ -74,6 +74,23 @@ If client certificate authentication (mTLS) is desired, set the `SSL_CLIENT_CERT
|
|||
variable to the path of the PEM formatted file containing the certificate followed by the private
|
||||
key.
|
||||
|
||||
Finally, if you're using a setup in which you want to trust a self-signed certificate or otherwise
|
||||
disable certificate verification, you can instruct uv to allow insecure connections to dedicated
|
||||
hosts via the `allow-insecure-host` configuration option. For example, adding the following to
|
||||
`pyproject.toml` will allow insecure connections to `example.com`:
|
||||
|
||||
```toml
|
||||
[tool.uv]
|
||||
allow-insecure-host = ["example.com"]
|
||||
```
|
||||
|
||||
`allow-insecure-host` expects to receive a hostname (e.g., `localhost`) or hostname-port pair (e.g.,
|
||||
`localhost:8080`), and is only applicable to HTTPS connections, as HTTP connections are inherently
|
||||
insecure.
|
||||
|
||||
Use `allow-insecure-host` with caution and only in trusted environments, as it can expose you to
|
||||
security risks due to the lack of certificate verification.
|
||||
|
||||
## Authentication with alternative package indexes
|
||||
|
||||
See the [alternative indexes integration guide](../guides/integration/alternative-indexes.md) for
|
||||
|
|
|
@ -70,6 +70,14 @@ uv run [OPTIONS] <COMMAND>
|
|||
|
||||
<p>This option is only available when running in a project.</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
@ -483,7 +491,15 @@ uv add [OPTIONS] <PACKAGES|--requirements <REQUIREMENTS>>
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--branch</code> <i>branch</i></dt><dd><p>Branch to use when adding a dependency from Git</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--branch</code> <i>branch</i></dt><dd><p>Branch to use when adding a dependency from Git</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
|
@ -767,7 +783,15 @@ uv remove [OPTIONS] <PACKAGES>...
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
||||
|
@ -1023,6 +1047,14 @@ uv sync [OPTIONS]
|
|||
|
||||
<dl class="cli-reference"><dt><code>--all-extras</code></dt><dd><p>Include all optional dependencies</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
@ -1289,7 +1321,15 @@ uv lock [OPTIONS]
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
||||
|
@ -1513,7 +1553,15 @@ uv tree [OPTIONS]
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
||||
|
@ -1839,7 +1887,15 @@ uv tool run [OPTIONS] [COMMAND]
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
||||
|
@ -2081,7 +2137,15 @@ uv tool install [OPTIONS] <PACKAGE>
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
||||
|
@ -2323,6 +2387,14 @@ uv tool upgrade [OPTIONS] <NAME>
|
|||
|
||||
<dl class="cli-reference"><dt><code>--all</code></dt><dd><p>Upgrade all tools</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
@ -3586,6 +3658,14 @@ uv pip compile [OPTIONS] <SRC_FILE>...
|
|||
|
||||
<p>Only applies to <code>pyproject.toml</code>, <code>setup.py</code>, and <code>setup.cfg</code> sources.</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--annotation-style</code> <i>annotation-style</i></dt><dd><p>The style of the annotation comments included in the output file, used to indicate the source of each package.</p>
|
||||
|
||||
<p>Defaults to <code>split</code>.</p>
|
||||
|
@ -3944,6 +4024,14 @@ uv pip sync [OPTIONS] <SRC_FILE>...
|
|||
|
||||
<dl class="cli-reference"><dt><code>--allow-empty-requirements</code></dt><dd><p>Allow sync of empty requirements, which will clear the environment of all packages</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--break-system-packages</code></dt><dd><p>Allow uv to modify an <code>EXTERNALLY-MANAGED</code> Python installation.</p>
|
||||
|
||||
<p>WARNING: <code>--break-system-packages</code> is intended for use in continuous integration (CI) environments, when installing into Python installations that are managed by an external package manager, like <code>apt</code>. It should be used with caution, as such Python installations explicitly recommend against modifications by other package managers (like uv or <code>pip</code>).</p>
|
||||
|
@ -4235,6 +4323,14 @@ uv pip install [OPTIONS] <PACKAGE|--requirement <REQUIREMENT>|--editable <EDITAB
|
|||
|
||||
<p>Only applies to <code>pyproject.toml</code>, <code>setup.py</code>, and <code>setup.cfg</code> sources.</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--break-system-packages</code></dt><dd><p>Allow uv to modify an <code>EXTERNALLY-MANAGED</code> Python installation.</p>
|
||||
|
||||
<p>WARNING: <code>--break-system-packages</code> is intended for use in continuous integration (CI) environments, when installing into Python installations that are managed by an external package manager, like <code>apt</code>. It should be used with caution, as such Python installations explicitly recommend against modifications by other package managers (like uv or <code>pip</code>).</p>
|
||||
|
@ -4582,7 +4678,15 @@ uv pip uninstall [OPTIONS] <PACKAGE|--requirement <REQUIREMENT>>
|
|||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--break-system-packages</code></dt><dd><p>Allow uv to modify an <code>EXTERNALLY-MANAGED</code> Python installation.</p>
|
||||
<dl class="cli-reference"><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--break-system-packages</code></dt><dd><p>Allow uv to modify an <code>EXTERNALLY-MANAGED</code> Python installation.</p>
|
||||
|
||||
<p>WARNING: <code>--break-system-packages</code> is intended for use in continuous integration (CI) environments, when installing into Python installations that are managed by an external package manager, like <code>apt</code>. It should be used with caution, as such Python installations explicitly recommend against modifications by other package managers (like uv or <code>pip</code>).</p>
|
||||
|
||||
|
@ -5228,6 +5332,14 @@ uv venv [OPTIONS] [NAME]
|
|||
|
||||
<p>WARNING: This option can lead to unexpected behavior if the existing virtual environment and the newly-created virtual environment are linked to different Python interpreters.</p>
|
||||
|
||||
</dd><dt><code>--allow-insecure-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
|
||||
|
||||
<p>Can be provided multiple times.</p>
|
||||
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system’s certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
|
||||
</dd><dt><code>--cache-dir</code> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
|
||||
<p>Defaults to <code>$HOME/Library/Caches/uv</code> on macOS, <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
|
|
|
@ -1,4 +1,36 @@
|
|||
## Global
|
||||
#### [`allow-insecure-host`](#allow-insecure-host) {: #allow-insecure-host }
|
||||
|
||||
Allow insecure connections to host.
|
||||
|
||||
Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
`localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
|
||||
WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
bypasses SSL verification and could expose you to MITM attacks.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
=== "pyproject.toml"
|
||||
|
||||
```toml
|
||||
[tool.uv]
|
||||
allow-insecure-host = ["localhost:8080"]
|
||||
```
|
||||
=== "uv.toml"
|
||||
|
||||
```toml
|
||||
|
||||
allow-insecure-host = ["localhost:8080"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`cache-dir`](#cache-dir) {: #cache-dir }
|
||||
|
||||
Path to the cache directory.
|
||||
|
@ -1176,6 +1208,39 @@ packages.
|
|||
|
||||
---
|
||||
|
||||
#### [`allow-insecure-host`](#pip_allow-insecure-host) {: #pip_allow-insecure-host }
|
||||
<span id="allow-insecure-host"></span>
|
||||
|
||||
Allow insecure connections to host.
|
||||
|
||||
Expects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g.,
|
||||
`localhost:8080`), or a URL (e.g., `https://localhost`).
|
||||
|
||||
WARNING: Hosts included in this list will not be verified against the system's certificate
|
||||
store. Only use `--allow-insecure-host` in a secure network with verified sources, as it
|
||||
bypasses SSL verification and could expose you to MITM attacks.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
=== "pyproject.toml"
|
||||
|
||||
```toml
|
||||
[tool.uv.pip]
|
||||
allow-insecure-host = ["localhost:8080"]
|
||||
```
|
||||
=== "uv.toml"
|
||||
|
||||
```toml
|
||||
[pip]
|
||||
allow-insecure-host = ["localhost:8080"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`annotation-style`](#pip_annotation-style) {: #pip_annotation-style }
|
||||
<span id="annotation-style"></span>
|
||||
|
||||
|
|
24
uv.schema.json
generated
24
uv.schema.json
generated
|
@ -4,6 +4,16 @@
|
|||
"description": "Metadata and configuration for uv.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow-insecure-host": {
|
||||
"description": "Allow insecure connections to host.\n\nExpects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g., `localhost:8080`), or a URL (e.g., `https://localhost`).\n\nWARNING: Hosts included in this list will not be verified against the system's certificate store. Only use `--allow-insecure-host` in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/TrustedHost"
|
||||
}
|
||||
},
|
||||
"cache-dir": {
|
||||
"description": "Path to the cache directory.\n\nDefaults to `$HOME/Library/Caches/uv` on macOS, `$XDG_CACHE_HOME/uv` or `$HOME/.cache/uv` on Linux, and `%LOCALAPPDATA%\\uv\\cache` on Windows.",
|
||||
"type": [
|
||||
|
@ -561,6 +571,16 @@
|
|||
"null"
|
||||
]
|
||||
},
|
||||
"allow-insecure-host": {
|
||||
"description": "Allow insecure connections to host.\n\nExpects to receive either a hostname (e.g., `localhost`), a host-port pair (e.g., `localhost:8080`), or a URL (e.g., `https://localhost`).\n\nWARNING: Hosts included in this list will not be verified against the system's certificate store. Only use `--allow-insecure-host` in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/TrustedHost"
|
||||
}
|
||||
},
|
||||
"annotation-style": {
|
||||
"description": "The style of the annotation comments included in the output file, used to indicate the source of each package.",
|
||||
"anyOf": [
|
||||
|
@ -1426,6 +1446,10 @@
|
|||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"TrustedHost": {
|
||||
"description": "A host or host-port pair.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue