2019-11-23 21:42:07 +00:00
|
|
|
#[allow(unused_imports)]
|
|
|
|
use log::{debug, error, info, trace, warn};
|
|
|
|
|
2020-01-19 10:31:33 +00:00
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
2019-11-23 21:42:07 +00:00
|
|
|
use env_logger;
|
|
|
|
use structopt::StructOpt;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::error::Error;
|
|
|
|
use std::net::TcpStream;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::io::BufRead;
|
|
|
|
use std::io::BufReader;
|
|
|
|
use std::io::Write;
|
|
|
|
|
|
|
|
#[derive(StructOpt, Debug)]
|
|
|
|
struct Args {
|
2020-01-19 10:31:33 +00:00
|
|
|
/// Address of the coffer server
|
|
|
|
#[structopt(short, long, parse(try_from_str), env = "COFFER_SERVER_ADDRESS", default_value = "127.0.0.1:9187")]
|
|
|
|
server_address: SocketAddr,
|
2019-11-27 22:00:18 +00:00
|
|
|
|
2020-01-19 10:31:33 +00:00
|
|
|
/// Path to the request file sent to the server
|
|
|
|
#[structopt(parse(from_os_str), env = "COFFER_REQUEST", hide_env_values = true)]
|
2019-11-27 22:00:18 +00:00
|
|
|
secrets: PathBuf,
|
2019-11-23 21:42:07 +00:00
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
/// The subcommand spawned by coffer-client
|
|
|
|
cmd: String,
|
2019-11-23 21:42:07 +00:00
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
/// Arguments to the subcommand spawned by coffer-client
|
|
|
|
cmd_args: Vec<String>
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
2019-11-23 21:42:07 +00:00
|
|
|
env_logger::init();
|
|
|
|
let args = Args::from_args();
|
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
info!{"Connecting to coffer server"}
|
2020-01-19 10:31:33 +00:00
|
|
|
let stream: TcpStream = TcpStream::connect(args.server_address)?;
|
2019-11-23 21:42:07 +00:00
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
info!{"Parsing key requests"}
|
|
|
|
let keys = parse_from_path(&args.secrets)?;
|
2019-11-23 21:42:07 +00:00
|
|
|
|
|
|
|
info!{"Reading secrets"}
|
2019-11-27 22:00:18 +00:00
|
|
|
retrieve_secrets(&keys, stream)?;
|
2019-11-23 21:42:07 +00:00
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
info!{"Spawning coffer'ed command, reaping coffer"}
|
|
|
|
reap_coffer(&args.cmd, &args.cmd_args);
|
2019-11-23 21:42:07 +00:00
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
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
|
2019-11-23 21:42:07 +00:00
|
|
|
let mut resp = String::new();
|
2019-11-27 22:00:18 +00:00
|
|
|
reader.read_line(&mut resp)?;
|
|
|
|
|
|
|
|
info!{"Retrieved secret. Setting environment"}
|
|
|
|
std::env::set_var(k.trim(), resp.trim());
|
2019-11-23 21:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
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>> {
|
2019-11-23 21:42:07 +00:00
|
|
|
let sec_file = File::open(path)?;
|
|
|
|
|
2019-11-27 22:00:18 +00:00
|
|
|
Ok(serde_yaml::from_reader::<_, Vec<String>>(sec_file)?)
|
2019-11-23 21:42:07 +00:00
|
|
|
}
|