From 4106a73e75233be0b1affc94dad6e947a341afd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Forsman?= Date: Sat, 23 Oct 2021 13:22:35 +0200 Subject: [PATCH] Allow selecting ssh user dynamically ...by setting `deployment.targetUser = null`. This allows sharing a deployment file (hive.nix/flake.nix) between multiple admins, without having to use a shared root account. --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + src/nix/eval.nix | 5 +++-- src/nix/mod.rs | 10 ++++++++-- src/nix/tests/mod.rs | 4 ++-- 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1ca99a..01995ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,6 +133,7 @@ dependencies = [ "tempfile", "tokio", "tokio-test", + "users", "validator", ] @@ -890,6 +891,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + [[package]] name = "validator" version = "0.12.0" diff --git a/Cargo.toml b/Cargo.toml index e0bfe69..bb0ba77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ sys-info = "0.7.0" snafu = "0.6.10" tempfile = "3.1.0" tokio-test = "0.4.0" +users = "0.11.0" validator = { version = "0.12", features = ["derive"] } [dependencies.tokio] diff --git a/src/nix/eval.nix b/src/nix/eval.nix index a01f328..22798d7 100644 --- a/src/nix/eval.nix +++ b/src/nix/eval.nix @@ -113,9 +113,10 @@ let }; targetUser = lib.mkOption { description = '' - The user to use to log into the remote node. + The user to use to log into the remote node. If null, login as the + current user. ''; - type = types.str; + type = types.nullOr types.str; default = "root"; }; allowLocalDeployment = lib.mkOption { diff --git a/src/nix/mod.rs b/src/nix/mod.rs index c361ae5..90407d9 100644 --- a/src/nix/mod.rs +++ b/src/nix/mod.rs @@ -9,6 +9,7 @@ use serde::de::DeserializeOwned; use serde::Deserialize; use snafu::Snafu; use tokio::process::Command; +use users::get_current_username; use validator::{Validate, ValidationErrors, ValidationError as ValidationErrorType}; use crate::util::CommandExecution; @@ -115,7 +116,7 @@ pub struct NodeConfig { target_host: Option, #[serde(rename = "targetUser")] - target_user: String, + target_user: Option, #[serde(rename = "targetPort")] target_port: Option, @@ -140,7 +141,12 @@ impl NodeConfig { pub fn to_ssh_host(&self) -> Option { self.target_host.as_ref().map(|target_host| { - let mut host = Ssh::new(self.target_user.clone(), target_host.clone()); + let username = + match &self.target_user { + Some(uname) => uname.clone(), + None => get_current_username().unwrap().into_string().ok().unwrap(), + }; + let mut host = Ssh::new(username.clone(), target_host.clone()); host.set_privilege_escalation_command(self.privilege_escalation_command.clone()); if let Some(target_port) = self.target_port { diff --git a/src/nix/tests/mod.rs b/src/nix/tests/mod.rs index f7384d3..8ca478b 100644 --- a/src/nix/tests/mod.rs +++ b/src/nix/tests/mod.rs @@ -134,7 +134,7 @@ fn test_parse_simple() { )); assert_eq!(Some("host-a"), nodes["host-a"].target_host.as_deref()); assert_eq!(None, nodes["host-a"].target_port); - assert_eq!("root", &nodes["host-a"].target_user); + assert_eq!(Some("root"), nodes["host-a"].target_user.as_deref()); // host-b assert!(set_eq( @@ -143,7 +143,7 @@ fn test_parse_simple() { )); assert_eq!(Some("somehost.tld"), nodes["host-b"].target_host.as_deref()); assert_eq!(Some(1234), nodes["host-b"].target_port); - assert_eq!("luser", &nodes["host-b"].target_user); + assert_eq!(Some("luser"), nodes["host-b"].target_user.as_deref()); } #[test]