[client] Set up environment, spawn subprocess

- Coffer client sets up the environment from the keys and secrets read
- Coffer client spawns a subprocess and reaps itself

Signed-off-by: Armin Friedl <dev@friedl.net>
This commit is contained in:
Armin Friedl 2019-11-27 23:00:18 +01:00
parent 3344ca4877
commit b3b86b4238
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
7 changed files with 112 additions and 32 deletions

44
Cargo.lock generated
View file

@ -66,9 +66,10 @@ dependencies = [
[[package]] [[package]]
name = "coffer-client" name = "coffer-client"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"exec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -78,7 +79,7 @@ dependencies = [
[[package]] [[package]]
name = "coffer-companion" name = "coffer-companion"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
@ -89,7 +90,7 @@ dependencies = [
[[package]] [[package]]
name = "coffer-server" name = "coffer-server"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -126,6 +127,34 @@ dependencies = [
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "errno"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "exec"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.8" version = "0.2.8"
@ -220,6 +249,11 @@ dependencies = [
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "half" name = "half"
version = "1.4.0" version = "1.4.0"
@ -612,6 +646,9 @@ dependencies = [
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
"checksum exec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "886b70328cba8871bfc025858e1de4be16b1d5088f2ba50b57816f4210672615"
"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d"
"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" "checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987"
"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" "checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86"
@ -622,6 +659,7 @@ dependencies = [
"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" "checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16"
"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" "checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9"
"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0" "checksum half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120"

View file

@ -1,5 +1,4 @@
[workspace] [workspace]
members = [ members = [
"coffer-server", "coffer-server",
"coffer-client", "coffer-client",

15
TODO.org Normal file
View file

@ -0,0 +1,15 @@
* General
** TODO Add a license
** TODO Better communication protocol
* Coffer Server
* Coffer Client
** DONE Set environment variables
CLOSED: [2019-11-27 Wed 22:51]
** TODO Send key requests encrypted/signed
* Coffer Companion
** TODO Add Subcommands
- [ ] Generate master key
- [ ] Generate client key
- [ ] Encrypt/Decrypt secrets with master key
- [ ] Encrypt/Decrypt key request with client key
- [ ] Generate trampolin sh from dockerfile

View file

@ -1,6 +1,6 @@
[package] [package]
name = "coffer-client" name = "coffer-client"
version = "0.1.0" version = "0.2.0"
authors = ["Armin Friedl <dev@friedl.net>"] authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018" edition = "2018"
@ -15,3 +15,5 @@ structopt = "0.3"
serde = { version = "1.0", features = ["derive"]} serde = { version = "1.0", features = ["derive"]}
serde_yaml = "0.8" serde_yaml = "0.8"
serde_cbor = "0.10.2" serde_cbor = "0.10.2"
# Executing subcommand
exec = "0.3.1"

View file

@ -7,7 +7,6 @@ use std::fs::File;
use std::error::Error; use std::error::Error;
use std::net::TcpStream; use std::net::TcpStream;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::io::Read;
use std::net::IpAddr; use std::net::IpAddr;
use std::path::PathBuf; use std::path::PathBuf;
use std::io::BufRead; use std::io::BufRead;
@ -16,51 +15,78 @@ use std::io::Write;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
struct Args { struct Args {
/// Path to the keys file
#[structopt(short, long, parse(from_os_str), env = "SECSRV_SECRETS", hide_env_values = true)]
secrets: PathBuf,
/// The port secsrv is listening on /// The port secsrv is listening on
#[structopt(short, long, env = "SECSRV_PORT", default_value = "9187")] #[structopt(short, long, env = "SECSRV_PORT", default_value = "9187")]
port: u16, port: u16,
/// The address secsrv binds to /// The address secsrv binds to
#[structopt(short, long, env = "SECSRV_IP", default_value = "127.0.0.1")] #[structopt(short, long, env = "SECSRV_IP", default_value = "127.0.0.1")]
ip: IpAddr ip: IpAddr,
}
type Secrets = Vec<String>; /// Path to the keys file
#[structopt(parse(from_os_str), env = "SECSRV_SECRETS", hide_env_values = true)]
secrets: PathBuf,
/// The subcommand spawned by coffer-client
cmd: String,
/// Arguments to the subcommand spawned by coffer-client
cmd_args: Vec<String>
}
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
env_logger::init(); env_logger::init();
let args = Args::from_args(); let args = Args::from_args();
info!{"Parsing sec requests"} info!{"Connecting to coffer server"}
let addr = SocketAddr::from((args.ip, args.port));
let stream: TcpStream = TcpStream::connect(addr)?;
let secrets = parse_from_path(&args.secrets)?; info!{"Parsing key requests"}
let keys = parse_from_path(&args.secrets)?;
info!{"Connecting"}
let mut channel: TcpStream = TcpStream::connect(SocketAddr::from((args.ip, args.port)))?;
info!{"Reading secrets"} info!{"Reading secrets"}
retrieve_secrets(&keys, stream)?;
for s in secrets { info!{"Spawning coffer'ed command, reaping coffer"}
let buf = serde_cbor::to_vec(&s)?; reap_coffer(&args.cmd, &args.cmd_args);
channel.write_all(&buf.len().to_be_bytes())?;
channel.write_all(&buf)?;
info!{"Wrote secret {} as {:?}", s, buf}
Err("Could not spawn sub-command".into())
}
fn retrieve_secrets(keys: &Vec<String>, mut stream: TcpStream) -> Result<(), Box<dyn Error>>{
for k in keys {
let buf = serde_cbor::to_vec(&k)?;
info!{"Sending key request {} as {:?}", k, buf}
stream.write_all(&buf.len().to_be_bytes())?;
stream.write_all(&buf)?;
info!{"Reading response"}
let mut reader = BufReader::new(&stream); // get buffered reader for line-wise reading from stream
// read line
let mut resp = String::new(); let mut resp = String::new();
let mut reader = BufReader::new(&channel); reader.read_line(&mut resp)?;
reader.read_line(&mut resp);
println!{"Resp: {:?}", resp}; info!{"Retrieved secret. Setting environment"}
std::env::set_var(k.trim(), resp.trim());
} }
Ok(()) Ok(())
} }
pub fn parse_from_path(path: &PathBuf) -> Result<Secrets, Box<dyn Error>> { fn reap_coffer(cmd: &str, args: &Vec<String>) {
let mut cmd = exec::Command::new(cmd);
// TODO Push cmd as first arg if not already set?
cmd.args(args);
let err = cmd.exec();
error!{"Could not execute sub-command {}", err};
}
fn parse_from_path(path: &PathBuf) -> Result<Vec<String>, Box<dyn Error>> {
let sec_file = File::open(path)?; let sec_file = File::open(path)?;
Ok(serde_yaml::from_reader::<_,Secrets>(sec_file)?) Ok(serde_yaml::from_reader::<_, Vec<String>>(sec_file)?)
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "coffer-companion" name = "coffer-companion"
version = "0.1.0" version = "0.2.0"
authors = ["Armin Friedl <dev@friedl.net>"] authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018" edition = "2018"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "coffer-server" name = "coffer-server"
version = "0.1.0" version = "0.2.0"
authors = ["Armin Friedl <dev@friedl.net>"] authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018" edition = "2018"