ssh: Fix shell escaping

The previous `sh -c` invocation was incorrect and just happened
to work on hosts with a Bourne-compatible shell set as the login
shell. Commands in the deploy script were being executed in the
login shell.
This commit is contained in:
Zhaofeng Li 2021-02-12 13:55:44 -08:00
parent 95ddbcbfd6
commit d0bba90d04
4 changed files with 16 additions and 6 deletions

7
Cargo.lock generated
View file

@ -131,6 +131,7 @@ dependencies = [
"regex",
"serde",
"serde_json",
"shell-escape",
"snafu",
"sys-info",
"tempfile",
@ -680,6 +681,12 @@ dependencies = [
"serde",
]
[[package]]
name = "shell-escape"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
[[package]]
name = "signal-hook-registry"
version = "1.2.2"

View file

@ -22,6 +22,7 @@ quit = "1.1.2"
regex = "1"
serde = { version = "1.0.118", features = ["derive"] }
serde_json = "1.0"
shell-escape = "0.1.5"
sys-info = "0.7.0"
snafu = "0.6.10"
tempfile = "3.1.0"

View file

@ -14,7 +14,7 @@ in rustPlatform.buildRustPackage {
src = ./.;
};
};
cargoSha256 = "0rkpv9afkg33i1d0yjlq34zrdqy3i6ldbdag0hgsvxi3v3jfg4qv";
cargoSha256 = "1yjaqhv9gd86jq56vsrhv6qv3k5qh2pnc4zyxbi2fm2hdrvy0440";
# Recursive Nix is not stable yet
doCheck = false;

View file

@ -5,6 +5,7 @@ use std::process::Stdio;
use async_trait::async_trait;
use futures::future::join3;
use shell_escape::unix::escape;
use tokio::process::Command;
use tokio::io::{AsyncWriteExt, BufReader};
@ -199,13 +200,14 @@ impl Ssh {
let dest_path = key.dest_dir().join(name);
let remote_command = DEPLOY_KEY_TEMPLATE.to_string()
let key_script = DEPLOY_KEY_TEMPLATE.to_string()
.replace("%DESTINATION%", dest_path.to_str().unwrap())
.replace("%USER%", &key.user())
.replace("%GROUP%", &key.group())
.replace("%PERMISSIONS%", &key.permissions());
.replace("%USER%", &escape(key.user().into()))
.replace("%GROUP%", &escape(key.group().into()))
.replace("%PERMISSIONS%", &escape(key.permissions().into()));
let key_script = escape(key_script.into());
let mut command = self.ssh(&["sh", "-c", &remote_command]);
let mut command = self.ssh(&["sh", "-c", &key_script]);
command.stdin(Stdio::piped());
command.stderr(Stdio::piped());