Skip to content

Commit a7341e2

Browse files
committed
fix: use current user instead of root as default username
- Replace hardcoded 'root' fallback with current user detection - Try USER, USERNAME, LOGNAME environment variables first - Use whoami crate to get system username as last resort - Add test to verify current user is used correctly - Ensures non-root users don't accidentally connect as root
1 parent 2a1d904 commit a7341e2

6 files changed

Lines changed: 83 additions & 9 deletions

File tree

Cargo.lock

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ directories = "6"
2929
dirs = "6.0"
3030
chrono = "0.4"
3131
glob = "0.3"
32+
whoami = "1.5"
3233

3334
[dev-dependencies]
3435
tempfile = "3"

src/cli.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ pub struct Cli {
4747
#[arg(short = 'u', long, help = "Default username for SSH connections")]
4848
pub user: Option<String>,
4949

50-
#[arg(short = 'i', long, help = "SSH private key file path (prompts for passphrase if encrypted)")]
50+
#[arg(
51+
short = 'i',
52+
long,
53+
help = "SSH private key file path (prompts for passphrase if encrypted)"
54+
)]
5155
pub identity: Option<PathBuf>,
5256

5357
#[arg(

src/config.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,18 @@ impl Config {
103103
// Get current user as default
104104
let default_user = env::var("USER")
105105
.or_else(|_| env::var("USERNAME"))
106-
.unwrap_or_else(|_| "root".to_string());
106+
.or_else(|_| env::var("LOGNAME"))
107+
.unwrap_or_else(|_| {
108+
// Try to get current user from system
109+
#[cfg(unix)]
110+
{
111+
whoami::username()
112+
}
113+
#[cfg(not(unix))]
114+
{
115+
"user".to_string()
116+
}
117+
});
107118

108119
// Backend.AI multi-node clusters use port 2200 by default
109120
nodes.push(NodeConfig::Simple(format!("{default_user}@{host}:2200")));
@@ -215,7 +226,20 @@ impl Config {
215226
.or_else(|| cluster.defaults.user.as_ref().map(|u| expand_env_vars(u)))
216227
.or_else(|| self.defaults.user.as_ref().map(|u| expand_env_vars(u)))
217228
.unwrap_or_else(|| {
218-
std::env::var("USER").unwrap_or_else(|_| "root".to_string())
229+
std::env::var("USER")
230+
.or_else(|_| std::env::var("USERNAME"))
231+
.or_else(|_| std::env::var("LOGNAME"))
232+
.unwrap_or_else(|_| {
233+
// Try to get current user from system
234+
#[cfg(unix)]
235+
{
236+
whoami::username()
237+
}
238+
#[cfg(not(unix))]
239+
{
240+
"user".to_string()
241+
}
242+
})
219243
});
220244

221245
let port = port

src/node.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,18 @@ impl Node {
6161
.unwrap_or_else(|| {
6262
std::env::var("USER")
6363
.or_else(|_| std::env::var("USERNAME"))
64-
.unwrap_or_else(|_| "root".to_string())
64+
.or_else(|_| std::env::var("LOGNAME"))
65+
.unwrap_or_else(|_| {
66+
// Try to get current user from system
67+
#[cfg(unix)]
68+
{
69+
whoami::username()
70+
}
71+
#[cfg(not(unix))]
72+
{
73+
"user".to_string()
74+
}
75+
})
6576
});
6677

6778
Ok(Node {
@@ -121,4 +132,20 @@ mod tests {
121132
let node = Node::parse("example.com", Some("default_user")).unwrap();
122133
assert_eq!(node.username, "default_user");
123134
}
135+
136+
#[test]
137+
fn test_parse_uses_current_user_when_no_default() {
138+
// When no user is specified, it should use current user from environment
139+
let node = Node::parse("example.com", None).unwrap();
140+
// Should not be "root" unless the current user is actually root
141+
let current_user = std::env::var("USER")
142+
.or_else(|_| std::env::var("USERNAME"))
143+
.or_else(|_| std::env::var("LOGNAME"))
144+
.unwrap_or_else(|_| whoami::username());
145+
assert_eq!(node.username, current_user);
146+
// Specifically verify it doesn't default to root when we're not root
147+
if current_user != "root" {
148+
assert_ne!(node.username, "root");
149+
}
150+
}
124151
}

src/ssh/client.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,10 +462,9 @@ impl SshClient {
462462
|| key_contents.contains("Proc-Type: 4,ENCRYPTED")
463463
{
464464
tracing::debug!("Detected encrypted SSH key, prompting for passphrase");
465-
let pass = rpassword::prompt_password(format!(
466-
"Enter passphrase for key {key_path:?}: "
467-
))
468-
.with_context(|| "Failed to read passphrase")?;
465+
let pass =
466+
rpassword::prompt_password(format!("Enter passphrase for key {key_path:?}: "))
467+
.with_context(|| "Failed to read passphrase")?;
469468
Some(pass)
470469
} else {
471470
None

0 commit comments

Comments
 (0)