Test case: Don't redact username git for SSH (#13814)
Some checks are pending
CI / typos (push) Waiting to run
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions

This commit is contained in:
konsti 2025-06-04 09:57:24 +02:00 committed by GitHub
parent 3ca8d074a4
commit e7c066cf16
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 140 additions and 1 deletions

18
Cargo.lock generated
View file

@ -4738,6 +4738,7 @@ dependencies = [
"version-ranges",
"walkdir",
"which",
"whoami",
"wiremock",
"zip",
]
@ -6111,6 +6112,12 @@ dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "wasite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
@ -6267,6 +6274,17 @@ dependencies = [
"winsafe",
]
[[package]]
name = "whoami"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7"
dependencies = [
"redox_syscall 0.5.8",
"wasite",
"web-sys",
]
[[package]]
name = "widestring"
version = "1.1.0"

View file

@ -124,6 +124,7 @@ reqwest = { workspace = true, features = ["blocking"], default-features = false
similar = { version = "2.6.0" }
tar = { workspace = true }
tempfile = { workspace = true }
whoami = { version = "1.6.0" }
wiremock = { workspace = true }
zip = { workspace = true }

View file

@ -1626,6 +1626,8 @@ pub const READ_ONLY_GITHUB_TOKEN_2: &[&str] = &[
"SHIzUG1tRVZRSHMzQTl2a3NiVnB4Tmk0eTR3R2JVYklLck1qY05naHhMSFVMTDZGVElIMXNYeFhYN2gK",
];
pub const SSH_DEPLOY_KEY: &str = "LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFNd0FBQUF0emMyZ3RaVwpReU5UVXhPUUFBQUNBeTF1SnNZK1JXcWp1NkdIY3Z6a3AwS21yWDEwdmo3RUZqTkpNTkRqSGZPZ0FBQUpqWUpwVnAyQ2FWCmFRQUFBQXR6YzJndFpXUXlOVFV4T1FBQUFDQXkxdUpzWStSV3FqdTZHSGN2emtwMEttclgxMHZqN0VGak5KTU5EakhmT2cKQUFBRUMwbzBnd1BxbGl6TFBJOEFXWDVaS2dVZHJyQ2ptMDhIQm9FenB4VDg3MXBqTFc0bXhqNUZhcU83b1lkeS9PU25RcQphdGZYUytQc1FXTTBrdzBPTWQ4NkFBQUFFR3R2Ym5OMGFVQmhjM1J5WVd3dWMyZ0JBZ01FQlE9PQotLS0tLUVORCBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0K";
/// Decode a split, base64 encoded authentication token.
/// We split and encode the token to bypass revoke by GitHub's secret scanning
pub fn decode_token(content: &[&str]) -> String {

View file

@ -1,14 +1,16 @@
#![allow(clippy::disallowed_types)]
use crate::common::{
READ_ONLY_GITHUB_TOKEN, TestContext, apply_filters, decode_token, uv_snapshot,
READ_ONLY_GITHUB_TOKEN, SSH_DEPLOY_KEY, TestContext, apply_filters, decode_token, uv_snapshot,
};
use anyhow::{Ok, Result};
use assert_cmd::assert::OutputAssertExt;
use assert_fs::prelude::*;
use indoc::{formatdoc, indoc};
use insta::assert_snapshot;
use std::path::Path;
use std::process::Stdio;
use uv_fs::Simplified;
#[test]
fn requirements_txt_dependency() -> Result<()> {
@ -1174,6 +1176,122 @@ fn requirements_txt_https_git_credentials() -> Result<()> {
Ok(())
}
/// SSH blocks too permissive key files.
fn reduce_key_permissions(key_file: &Path) -> Result<()> {
#[cfg(unix)]
{
use std::fs::Permissions;
use std::os::unix::fs::PermissionsExt;
fs_err::set_permissions(key_file, Permissions::from_mode(0o400))?;
}
#[cfg(windows)]
{
use std::process::Command;
// https://superuser.com/a/1489152
Command::new("icacls")
.arg(key_file)
.arg("/inheritance:r")
.assert()
.success();
Command::new("icacls")
.arg(key_file)
.arg("/grant:r")
.arg(format!("{}:R", whoami::username()))
.assert()
.success();
}
Ok(())
}
/// Don't redact the username `git` in SSH URLs.
#[cfg(feature = "git")]
#[test]
fn requirements_txt_ssh_git_username() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "debug"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["uv-private-pypackage @ git+ssh://git@github.com/astral-test/uv-private-pypackage.git@d780faf0ac91257d4d5a4f0c5a0e4509608c0071"]
"#,
)?;
let fake_deploy_key = context.temp_dir.child("fake_deploy_key");
fake_deploy_key.write_str("not a key")?;
reduce_key_permissions(&fake_deploy_key)?;
// Ensure that we're loading the key and fail if it isn't present
let failing_git_ssh_command = format!(
"ssh -i {} -o IdentitiesOnly=yes -F /dev/null -o StrictHostKeyChecking=no",
fake_deploy_key.portable_display()
);
let mut filters = context.filters();
filters.push((
"process didn't exit successfully: .*",
"process didn't exit successfully: [GIT_COMMAND_ERROR]",
));
let load_key_error = regex::escape(r#"Load key "[TEMP_DIR]/fake_deploy_key":"#) + ".*";
filters.push((
&load_key_error,
r#"Load key "[TEMP_DIR]/fake_deploy_key": [ERROR]"#,
));
filters.push((
" *Warning: Permanently added 'github.com' \\(ED25519\\) to the list of known hosts.*\n",
"",
));
filters.push(("failed to clone into: .*", "failed to clone into: [PATH]"));
uv_snapshot!(filters, context.export().env("GIT_SSH_COMMAND", failing_git_ssh_command), @r#"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
× Failed to download and build `uv-private-pypackage @ git+ssh://git@github.com/astral-test/uv-private-pypackage.git@d780faf0ac91257d4d5a4f0c5a0e4509608c0071`
Git operation failed
failed to clone into: [PATH]
failed to fetch branch, tag, or commit `d780faf0ac91257d4d5a4f0c5a0e4509608c0071`
process didn't exit successfully: [GIT_COMMAND_ERROR]
--- stderr
Load key "[TEMP_DIR]/fake_deploy_key": [ERROR]
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
"#);
let ssh_deploy_key = context.temp_dir.child("uv_test_key");
ssh_deploy_key.write_str((decode_token(&[SSH_DEPLOY_KEY]) + "\n").as_str())?;
reduce_key_permissions(&ssh_deploy_key)?;
// Use the specified SSH key, and only that key, ignore `~/.ssh/config`, disable host key
// verification for Windows.
let git_ssh_command = format!(
"ssh -i {} -o IdentitiesOnly=yes -F /dev/null -o StrictHostKeyChecking=no",
ssh_deploy_key.portable_display()
);
uv_snapshot!(context.filters(), context.export().env("GIT_SSH_COMMAND", git_ssh_command), @r"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv export --cache-dir [CACHE_DIR]
uv-private-pypackage @ git+ssh://git@github.com/astral-test/uv-private-pypackage.git@d780faf0ac91257d4d5a4f0c5a0e4509608c0071
# via debug
----- stderr -----
Resolved 2 packages in [TIME]
");
Ok(())
}
#[test]
fn requirements_txt_https_credentials() -> Result<()> {
let context = TestContext::new("3.12");