mirror of https://github.com/astral-sh/uv
Disable SSL in Git commands for `--allow-insecure-host` (#11210)
## Summary Closes https://github.com/astral-sh/uv/issues/11176. ## Test Plan - Created a self-signed certificate. - Ran `openssl s_server -cert cert.pem -key key.pem -WWW -port 8443`. - Verified that `cargo run pip install git+https://localhost:8443/repo.git` failed with: ``` error: Git operation failed Caused by: failed to fetch into: /Users/crmarsh/.cache/uv/git-v0/db/0773914b3ec4a56e Caused by: process didn't exit successfully: `/usr/bin/git fetch --force --update-head-ok 'https://localhost:8443/repo.git' '+HEAD:refs/remotes/origin/HEAD'` (exit status: 128) --- stderr fatal: unable to access 'https://localhost:8443/repo.git/': SSL certificate problem: self signed certificate ``` - Verified that `cargo run pip install git+https://localhost:8443/repo.git --allow-insecure-host https://localhost:8443` continued further.
This commit is contained in:
parent
d9907f6fda
commit
748582ee6f
|
|
@ -387,17 +387,20 @@ enum Security {
|
|||
impl BaseClient {
|
||||
/// 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))
|
||||
{
|
||||
if self.disable_ssl(url) {
|
||||
&self.dangerous_client
|
||||
} else {
|
||||
&self.client
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the host is trusted to use the insecure client.
|
||||
pub fn disable_ssl(&self, url: &Url) -> bool {
|
||||
self.allow_insecure_host
|
||||
.iter()
|
||||
.any(|allow_insecure_host| allow_insecure_host.matches(url))
|
||||
}
|
||||
|
||||
/// The configured client timeout, in seconds.
|
||||
pub fn timeout(&self) -> Duration {
|
||||
self.timeout
|
||||
|
|
|
|||
|
|
@ -215,6 +215,11 @@ impl RegistryClient {
|
|||
self.client.uncached().for_host(url)
|
||||
}
|
||||
|
||||
/// Returns `true` if SSL verification is disabled for the given URL.
|
||||
pub fn disable_ssl(&self, url: &Url) -> bool {
|
||||
self.client.uncached().disable_ssl(url)
|
||||
}
|
||||
|
||||
/// Return the [`Connectivity`] mode used by this client.
|
||||
pub fn connectivity(&self) -> Connectivity {
|
||||
self.connectivity
|
||||
|
|
|
|||
|
|
@ -1430,7 +1430,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.git()
|
||||
.fetch(
|
||||
resource.git,
|
||||
client.unmanaged.uncached_client(resource.url).clone(),
|
||||
client
|
||||
.unmanaged
|
||||
.uncached_client(resource.git.repository())
|
||||
.clone(),
|
||||
client.unmanaged.disable_ssl(resource.git.repository()),
|
||||
self.build_context.cache().bucket(CacheBucket::Git),
|
||||
self.reporter
|
||||
.clone()
|
||||
|
|
@ -1530,7 +1534,10 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.git()
|
||||
.github_fast_path(
|
||||
resource.git,
|
||||
client.unmanaged.uncached_client(resource.url).clone(),
|
||||
client
|
||||
.unmanaged
|
||||
.uncached_client(resource.git.repository())
|
||||
.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
|
@ -1582,7 +1589,11 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.git()
|
||||
.fetch(
|
||||
resource.git,
|
||||
client.unmanaged.uncached_client(resource.url).clone(),
|
||||
client
|
||||
.unmanaged
|
||||
.uncached_client(resource.git.repository())
|
||||
.clone(),
|
||||
client.unmanaged.disable_ssl(resource.git.repository()),
|
||||
self.build_context.cache().bucket(CacheBucket::Git),
|
||||
self.reporter
|
||||
.clone()
|
||||
|
|
@ -1812,6 +1823,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.fetch(
|
||||
git,
|
||||
client.unmanaged.uncached_client(git.repository()).clone(),
|
||||
client.unmanaged.disable_ssl(git.repository()),
|
||||
self.build_context.cache().bucket(CacheBucket::Git),
|
||||
self.reporter
|
||||
.clone()
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ impl GitRemote {
|
|||
reference: &GitReference,
|
||||
locked_rev: Option<GitOid>,
|
||||
client: &ClientWithMiddleware,
|
||||
disable_ssl: bool,
|
||||
) -> Result<(GitDatabase, GitOid)> {
|
||||
let reference = locked_rev
|
||||
.map(ReferenceOrOid::Oid)
|
||||
|
|
@ -310,7 +311,7 @@ impl GitRemote {
|
|||
let enable_lfs_fetch = env::var(EnvVars::UV_GIT_LFS).is_ok();
|
||||
|
||||
if let Some(mut db) = db {
|
||||
fetch(&mut db.repo, &self.url, reference, client)
|
||||
fetch(&mut db.repo, &self.url, reference, client, disable_ssl)
|
||||
.with_context(|| format!("failed to fetch into: {}", into.user_display()))?;
|
||||
|
||||
let resolved_commit_hash = match locked_rev {
|
||||
|
|
@ -320,7 +321,7 @@ impl GitRemote {
|
|||
|
||||
if let Some(rev) = resolved_commit_hash {
|
||||
if enable_lfs_fetch {
|
||||
fetch_lfs(&mut db.repo, &self.url, &rev)
|
||||
fetch_lfs(&mut db.repo, &self.url, &rev, disable_ssl)
|
||||
.with_context(|| format!("failed to fetch LFS objects at {rev}"))?;
|
||||
}
|
||||
return Ok((db, rev));
|
||||
|
|
@ -338,14 +339,14 @@ impl GitRemote {
|
|||
|
||||
fs_err::create_dir_all(into)?;
|
||||
let mut repo = GitRepository::init(into)?;
|
||||
fetch(&mut repo, &self.url, reference, client)
|
||||
fetch(&mut repo, &self.url, reference, client, disable_ssl)
|
||||
.with_context(|| format!("failed to clone into: {}", into.user_display()))?;
|
||||
let rev = match locked_rev {
|
||||
Some(rev) => rev,
|
||||
None => reference.resolve(&repo)?,
|
||||
};
|
||||
if enable_lfs_fetch {
|
||||
fetch_lfs(&mut repo, &self.url, &rev)
|
||||
fetch_lfs(&mut repo, &self.url, &rev, disable_ssl)
|
||||
.with_context(|| format!("failed to fetch LFS objects at {rev}"))?;
|
||||
}
|
||||
|
||||
|
|
@ -502,6 +503,7 @@ fn fetch(
|
|||
remote_url: &Url,
|
||||
reference: ReferenceOrOid<'_>,
|
||||
client: &ClientWithMiddleware,
|
||||
disable_ssl: bool,
|
||||
) -> Result<()> {
|
||||
let oid_to_fetch = match github_fast_path(repo, remote_url, reference, client) {
|
||||
Ok(FastPathRev::UpToDate) => return Ok(()),
|
||||
|
|
@ -577,14 +579,21 @@ fn fetch(
|
|||
|
||||
debug!("Performing a Git fetch for: {remote_url}");
|
||||
let result = match refspec_strategy {
|
||||
RefspecStrategy::All => fetch_with_cli(repo, remote_url, refspecs.as_slice(), tags),
|
||||
RefspecStrategy::All => {
|
||||
fetch_with_cli(repo, remote_url, refspecs.as_slice(), tags, disable_ssl)
|
||||
}
|
||||
RefspecStrategy::First => {
|
||||
// Try each refspec
|
||||
let mut errors = refspecs
|
||||
.iter()
|
||||
.map_while(|refspec| {
|
||||
let fetch_result =
|
||||
fetch_with_cli(repo, remote_url, std::slice::from_ref(refspec), tags);
|
||||
let fetch_result = fetch_with_cli(
|
||||
repo,
|
||||
remote_url,
|
||||
std::slice::from_ref(refspec),
|
||||
tags,
|
||||
disable_ssl,
|
||||
);
|
||||
|
||||
// Stop after the first success and log failures
|
||||
match fetch_result {
|
||||
|
|
@ -629,12 +638,17 @@ fn fetch_with_cli(
|
|||
url: &Url,
|
||||
refspecs: &[String],
|
||||
tags: bool,
|
||||
disable_ssl: bool,
|
||||
) -> Result<()> {
|
||||
let mut cmd = ProcessBuilder::new(GIT.as_ref()?);
|
||||
cmd.arg("fetch");
|
||||
if tags {
|
||||
cmd.arg("--tags");
|
||||
}
|
||||
if disable_ssl {
|
||||
debug!("Disabling SSL verification for Git fetch");
|
||||
cmd.env(EnvVars::GIT_SSL_NO_VERIFY, "true");
|
||||
}
|
||||
cmd.arg("--force") // handle force pushes
|
||||
.arg("--update-head-ok") // see discussion in #2078
|
||||
.arg(url.as_str())
|
||||
|
|
@ -674,7 +688,12 @@ static GIT_LFS: LazyLock<Result<ProcessBuilder>> = LazyLock::new(|| {
|
|||
});
|
||||
|
||||
/// Attempts to use `git-lfs` CLI to fetch required LFS objects for a given revision.
|
||||
fn fetch_lfs(repo: &mut GitRepository, url: &Url, revision: &GitOid) -> Result<()> {
|
||||
fn fetch_lfs(
|
||||
repo: &mut GitRepository,
|
||||
url: &Url,
|
||||
revision: &GitOid,
|
||||
disable_ssl: bool,
|
||||
) -> Result<()> {
|
||||
let mut cmd = if let Ok(lfs) = GIT_LFS.as_ref() {
|
||||
debug!("Fetching Git LFS objects");
|
||||
lfs.clone()
|
||||
|
|
@ -684,6 +703,11 @@ fn fetch_lfs(repo: &mut GitRepository, url: &Url, revision: &GitOid) -> Result<(
|
|||
return Ok(());
|
||||
};
|
||||
|
||||
if disable_ssl {
|
||||
debug!("Disabling SSL verification for Git LFS");
|
||||
cmd.env(EnvVars::GIT_SSL_NO_VERIFY, "true");
|
||||
}
|
||||
|
||||
cmd.arg("fetch")
|
||||
.arg(url.as_str())
|
||||
.arg(revision.as_str())
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ impl GitResolver {
|
|||
&self,
|
||||
url: &GitUrl,
|
||||
client: ClientWithMiddleware,
|
||||
disable_ssl: bool,
|
||||
cache: PathBuf,
|
||||
reporter: Option<Arc<dyn Reporter>>,
|
||||
) -> Result<Fetch, GitResolverError> {
|
||||
|
|
@ -139,6 +140,14 @@ impl GitResolver {
|
|||
} else {
|
||||
GitSource::new(url.as_ref().clone(), client, cache)
|
||||
};
|
||||
|
||||
// If necessary, disable SSL.
|
||||
let source = if disable_ssl {
|
||||
source.dangerous()
|
||||
} else {
|
||||
source
|
||||
};
|
||||
|
||||
let fetch = tokio::task::spawn_blocking(move || source.fetch())
|
||||
.await?
|
||||
.map_err(GitResolverError::Git)?;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ pub struct GitSource {
|
|||
git: GitUrl,
|
||||
/// The HTTP client to use for fetching.
|
||||
client: ClientWithMiddleware,
|
||||
/// Whether to disable SSL verification.
|
||||
disable_ssl: bool,
|
||||
/// The path to the Git source database.
|
||||
cache: PathBuf,
|
||||
/// The reporter to use for this source.
|
||||
|
|
@ -37,12 +39,22 @@ impl GitSource {
|
|||
) -> Self {
|
||||
Self {
|
||||
git,
|
||||
disable_ssl: false,
|
||||
client: client.into(),
|
||||
cache: cache.into(),
|
||||
reporter: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable SSL verification for this [`GitSource`].
|
||||
#[must_use]
|
||||
pub fn dangerous(self) -> Self {
|
||||
Self {
|
||||
disable_ssl: true,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the [`Reporter`] to use for the [`GitSource`].
|
||||
#[must_use]
|
||||
pub fn with_reporter(self, reporter: Arc<dyn Reporter>) -> Self {
|
||||
|
|
@ -96,6 +108,7 @@ impl GitSource {
|
|||
&self.git.reference,
|
||||
locked_rev.map(GitOid::from),
|
||||
&self.client,
|
||||
self.disable_ssl,
|
||||
)?;
|
||||
|
||||
(db, actual_rev, task)
|
||||
|
|
|
|||
|
|
@ -449,6 +449,10 @@ impl EnvVars {
|
|||
#[attr_hidden]
|
||||
pub const GIT_ALTERNATE_OBJECT_DIRECTORIES: &'static str = "GIT_ALTERNATE_OBJECT_DIRECTORIES";
|
||||
|
||||
/// Disables SSL verification for git operations.
|
||||
#[attr_hidden]
|
||||
pub const GIT_SSL_NO_VERIFY: &'static str = "GIT_SSL_NO_VERIFY";
|
||||
|
||||
/// Used in tests for better git isolation.
|
||||
///
|
||||
/// For example, we run some tests in ~/.local/share/uv/tests.
|
||||
|
|
|
|||
Loading…
Reference in New Issue