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.
This commit is contained in:
Bjørn Forsman 2021-10-23 13:22:35 +02:00
parent d0c89302be
commit 4106a73e75
5 changed files with 25 additions and 6 deletions

11
Cargo.lock generated
View file

@ -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"

View file

@ -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]

View file

@ -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 {

View file

@ -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<String>,
#[serde(rename = "targetUser")]
target_user: String,
target_user: Option<String>,
#[serde(rename = "targetPort")]
target_port: Option<u16>,
@ -140,7 +141,12 @@ impl NodeConfig {
pub fn to_ssh_host(&self) -> Option<Ssh> {
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 {

View file

@ -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]