Skip to content

Commit e7c066c

Browse files
authored
Test case: Don't redact username git for SSH (#13814)
1 parent 3ca8d07 commit e7c066c

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

Cargo.lock

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ reqwest = { workspace = true, features = ["blocking"], default-features = false
124124
similar = { version = "2.6.0" }
125125
tar = { workspace = true }
126126
tempfile = { workspace = true }
127+
whoami = { version = "1.6.0" }
127128
wiremock = { workspace = true }
128129
zip = { workspace = true }
129130

crates/uv/tests/it/common/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,8 @@ pub const READ_ONLY_GITHUB_TOKEN_2: &[&str] = &[
16261626
"SHIzUG1tRVZRSHMzQTl2a3NiVnB4Tmk0eTR3R2JVYklLck1qY05naHhMSFVMTDZGVElIMXNYeFhYN2gK",
16271627
];
16281628

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

crates/uv/tests/it/export.rs

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
#![allow(clippy::disallowed_types)]
22

33
use crate::common::{
4-
READ_ONLY_GITHUB_TOKEN, TestContext, apply_filters, decode_token, uv_snapshot,
4+
READ_ONLY_GITHUB_TOKEN, SSH_DEPLOY_KEY, TestContext, apply_filters, decode_token, uv_snapshot,
55
};
66
use anyhow::{Ok, Result};
77
use assert_cmd::assert::OutputAssertExt;
88
use assert_fs::prelude::*;
99
use indoc::{formatdoc, indoc};
1010
use insta::assert_snapshot;
11+
use std::path::Path;
1112
use std::process::Stdio;
13+
use uv_fs::Simplified;
1214

1315
#[test]
1416
fn requirements_txt_dependency() -> Result<()> {
@@ -1174,6 +1176,122 @@ fn requirements_txt_https_git_credentials() -> Result<()> {
11741176
Ok(())
11751177
}
11761178

1179+
/// SSH blocks too permissive key files.
1180+
fn reduce_key_permissions(key_file: &Path) -> Result<()> {
1181+
#[cfg(unix)]
1182+
{
1183+
use std::fs::Permissions;
1184+
use std::os::unix::fs::PermissionsExt;
1185+
fs_err::set_permissions(key_file, Permissions::from_mode(0o400))?;
1186+
}
1187+
#[cfg(windows)]
1188+
{
1189+
use std::process::Command;
1190+
1191+
// https://superuser.com/a/1489152
1192+
Command::new("icacls")
1193+
.arg(key_file)
1194+
.arg("/inheritance:r")
1195+
.assert()
1196+
.success();
1197+
Command::new("icacls")
1198+
.arg(key_file)
1199+
.arg("/grant:r")
1200+
.arg(format!("{}:R", whoami::username()))
1201+
.assert()
1202+
.success();
1203+
}
1204+
Ok(())
1205+
}
1206+
1207+
/// Don't redact the username `git` in SSH URLs.
1208+
#[cfg(feature = "git")]
1209+
#[test]
1210+
fn requirements_txt_ssh_git_username() -> Result<()> {
1211+
let context = TestContext::new("3.12");
1212+
1213+
let pyproject_toml = context.temp_dir.child("pyproject.toml");
1214+
pyproject_toml.write_str(
1215+
r#"
1216+
[project]
1217+
name = "debug"
1218+
version = "0.1.0"
1219+
requires-python = ">=3.12"
1220+
dependencies = ["uv-private-pypackage @ git+ssh://[email protected]/astral-test/uv-private-pypackage.git@d780faf0ac91257d4d5a4f0c5a0e4509608c0071"]
1221+
"#,
1222+
)?;
1223+
1224+
let fake_deploy_key = context.temp_dir.child("fake_deploy_key");
1225+
fake_deploy_key.write_str("not a key")?;
1226+
reduce_key_permissions(&fake_deploy_key)?;
1227+
1228+
// Ensure that we're loading the key and fail if it isn't present
1229+
let failing_git_ssh_command = format!(
1230+
"ssh -i {} -o IdentitiesOnly=yes -F /dev/null -o StrictHostKeyChecking=no",
1231+
fake_deploy_key.portable_display()
1232+
);
1233+
let mut filters = context.filters();
1234+
filters.push((
1235+
"process didn't exit successfully: .*",
1236+
"process didn't exit successfully: [GIT_COMMAND_ERROR]",
1237+
));
1238+
let load_key_error = regex::escape(r#"Load key "[TEMP_DIR]/fake_deploy_key":"#) + ".*";
1239+
filters.push((
1240+
&load_key_error,
1241+
r#"Load key "[TEMP_DIR]/fake_deploy_key": [ERROR]"#,
1242+
));
1243+
filters.push((
1244+
" *Warning: Permanently added 'github.com' \\(ED25519\\) to the list of known hosts.*\n",
1245+
"",
1246+
));
1247+
filters.push(("failed to clone into: .*", "failed to clone into: [PATH]"));
1248+
uv_snapshot!(filters, context.export().env("GIT_SSH_COMMAND", failing_git_ssh_command), @r#"
1249+
success: false
1250+
exit_code: 1
1251+
----- stdout -----
1252+
1253+
----- stderr -----
1254+
× Failed to download and build `uv-private-pypackage @ git+ssh://[email protected]/astral-test/uv-private-pypackage.git@d780faf0ac91257d4d5a4f0c5a0e4509608c0071`
1255+
├─▶ Git operation failed
1256+
├─▶ failed to clone into: [PATH]
1257+
├─▶ failed to fetch branch, tag, or commit `d780faf0ac91257d4d5a4f0c5a0e4509608c0071`
1258+
╰─▶ process didn't exit successfully: [GIT_COMMAND_ERROR]
1259+
--- stderr
1260+
Load key "[TEMP_DIR]/fake_deploy_key": [ERROR]
1261+
[email protected]: Permission denied (publickey).
1262+
fatal: Could not read from remote repository.
1263+
1264+
Please make sure you have the correct access rights
1265+
and the repository exists.
1266+
"#);
1267+
1268+
let ssh_deploy_key = context.temp_dir.child("uv_test_key");
1269+
ssh_deploy_key.write_str((decode_token(&[SSH_DEPLOY_KEY]) + "\n").as_str())?;
1270+
reduce_key_permissions(&ssh_deploy_key)?;
1271+
1272+
// Use the specified SSH key, and only that key, ignore `~/.ssh/config`, disable host key
1273+
// verification for Windows.
1274+
let git_ssh_command = format!(
1275+
"ssh -i {} -o IdentitiesOnly=yes -F /dev/null -o StrictHostKeyChecking=no",
1276+
ssh_deploy_key.portable_display()
1277+
);
1278+
1279+
uv_snapshot!(context.filters(), context.export().env("GIT_SSH_COMMAND", git_ssh_command), @r"
1280+
success: true
1281+
exit_code: 0
1282+
----- stdout -----
1283+
# This file was autogenerated by uv via the following command:
1284+
# uv export --cache-dir [CACHE_DIR]
1285+
uv-private-pypackage @ git+ssh://[email protected]/astral-test/uv-private-pypackage.git@d780faf0ac91257d4d5a4f0c5a0e4509608c0071
1286+
# via debug
1287+
1288+
----- stderr -----
1289+
Resolved 2 packages in [TIME]
1290+
");
1291+
1292+
Ok(())
1293+
}
1294+
11771295
#[test]
11781296
fn requirements_txt_https_credentials() -> Result<()> {
11791297
let context = TestContext::new("3.12");

0 commit comments

Comments
 (0)