From 8427a6ad53bafe262319f4af132847b1c7d3da73 Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Thu, 28 Nov 2019 23:49:19 +0100 Subject: [PATCH] [companion] Introduce subcommands Subcommands for `generate`-ing keys and `encrypt`-ing secrets. Generated artifacts can be consumed by `coffer-server`. Signed-off-by: Armin Friedl --- .gitignore | 2 +- Cargo.lock | 3 ++ TODO.org | 6 ++++ coffer-companion/Cargo.toml | 3 ++ coffer-companion/src/encrypt.rs | 26 ++++++++++++++ coffer-companion/src/generate.rs | 33 +++++++++++++++++ coffer-companion/src/main.rs | 61 +++++++++++++------------------- 7 files changed, 96 insertions(+), 38 deletions(-) create mode 100644 coffer-companion/src/encrypt.rs create mode 100644 coffer-companion/src/generate.rs diff --git a/.gitignore b/.gitignore index 70bff37..ea7757d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /target **/*.rs.bk *.cbor -secreq.yaml \ No newline at end of file +*.yaml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index dfc840e..582ee72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,11 +81,14 @@ dependencies = [ name = "coffer-companion" version = "0.2.0" dependencies = [ + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (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_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/TODO.org b/TODO.org index 936c4a1..b8798b3 100644 --- a/TODO.org +++ b/TODO.org @@ -1,7 +1,13 @@ * General ** TODO Add a license ** TODO Better communication protocol +** TODO Add tests * Coffer Server +** TODO Add secrets on-the-fly +** TODO Store secrets in secure memory + - Not persisted + - Nulled out + - Optional encrypted * Coffer Client ** DONE Set environment variables CLOSED: [2019-11-27 Wed 22:51] diff --git a/coffer-companion/Cargo.toml b/coffer-companion/Cargo.toml index e51cca0..fcb1d2c 100644 --- a/coffer-companion/Cargo.toml +++ b/coffer-companion/Cargo.toml @@ -9,6 +9,9 @@ edition = "2018" [dependencies] # Base tools log = "0.4" +env_logger="0.7" +structopt = "0.3" +quick-error = "1.2" # Key management/Cryptography sodiumoxide = "0.2.5" # Communication diff --git a/coffer-companion/src/encrypt.rs b/coffer-companion/src/encrypt.rs new file mode 100644 index 0000000..c4388a7 --- /dev/null +++ b/coffer-companion/src/encrypt.rs @@ -0,0 +1,26 @@ +use sodiumoxide::crypto::sealedbox; +use std::collections::HashMap; +use std::fs::File; +use std::io::{Write}; +use std::path::PathBuf; + +use crate::generate::MasterKey; + +type Secrets = HashMap; + +pub fn generate_encrypted_secrets(yaml: PathBuf, out: PathBuf, masterkey: PathBuf) { + let reader = File::open(&yaml) + .expect(&format!{"Could not read file {}", masterkey.display()}); + + let secrets: Secrets = serde_yaml::from_reader(reader) + .expect(&format!{"Could not deserialize secrets from {}", &yaml.display()}); + + let masterkey: MasterKey = (&masterkey).into(); + + let secrets_bin = serde_cbor::to_vec(&secrets).unwrap(); + let sealed_secrets_bin = sealedbox::seal(&secrets_bin, &masterkey.public_key); + + File::create(&out) + .and_then(|mut f| f.write(&sealed_secrets_bin)) + .expect(&format!{"Could not create out file {}", &out.display()}); +} diff --git a/coffer-companion/src/generate.rs b/coffer-companion/src/generate.rs new file mode 100644 index 0000000..529a043 --- /dev/null +++ b/coffer-companion/src/generate.rs @@ -0,0 +1,33 @@ +use sodiumoxide::crypto::box_; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; +use std::fs::File; + +#[derive(Debug, Serialize, Deserialize)] +pub struct MasterKey { + pub public_key: box_::PublicKey, + secret_key: box_::SecretKey, +} + +pub fn generate_key(out: PathBuf) { + let keypair = box_::gen_keypair(); + let masterkey: MasterKey = MasterKey { + public_key: keypair.0, + secret_key: keypair.1, + }; + + let writer = File::create(&out) + .expect(&format!{"Could not create out file {}", &out.display()}); + + serde_cbor::to_writer(writer, &masterkey) + .expect(&format!{"Couldn't deserialize to key file {}", &out.display()}); +} + +impl From<&PathBuf> for MasterKey { + fn from(masterkey: &PathBuf) -> Self { + let reader = File::open(masterkey) + .expect(&format!{"Could not read file {}", masterkey.display()}); + + serde_cbor::from_reader(reader).unwrap() + } +} diff --git a/coffer-companion/src/main.rs b/coffer-companion/src/main.rs index 59f7f31..f3bd098 100644 --- a/coffer-companion/src/main.rs +++ b/coffer-companion/src/main.rs @@ -1,48 +1,35 @@ -use serde::{Deserialize, Serialize}; -use sodiumoxide::crypto::box_; -use sodiumoxide::crypto::sealedbox; -use std::collections::HashMap; use std::error::Error; use std::fs::File; use std::io::Write; +use std::path::PathBuf; +use structopt::StructOpt; -#[derive(Debug, Serialize, Deserialize)] -struct MasterKey { - public_key: box_::PublicKey, - secret_key: box_::SecretKey, +mod generate; +mod encrypt; + +#[derive(StructOpt, Debug)] +enum Args { + Generate { + #[structopt(short, long, parse(from_os_str))] + out: PathBuf + }, + Encrypt { + #[structopt(short, long, parse(from_os_str))] + yaml: PathBuf, + #[structopt(short, long, parse(from_os_str))] + out: PathBuf, + #[structopt(short, long, parse(from_os_str))] + masterkey: PathBuf, + } } -struct ClientKey { - id: String, - public_key: box_::PublicKey, -} - -pub type Secrets = HashMap; -pub type Secs = Vec; - fn main() -> Result<(), Box> { - let keypair = box_::gen_keypair(); - let masterkey: MasterKey = MasterKey { - public_key: keypair.0, - secret_key: keypair.1, - }; + let args: Args = Args::from_args(); - let f = File::create("./masterkey.cbor")?; - serde_cbor::to_writer(f, &masterkey)?; - - let secrets: Secrets = [ - ("ABC".to_owned(), "DEF".to_owned()), - ("XYZ".to_owned(), "ABC".to_owned()), - ] - .iter() - .cloned() - .collect(); - - let sc_res = serde_cbor::to_vec(&secrets)?; - let sc_res = sealedbox::seal(&sc_res, &masterkey.public_key); - let mut f = File::create("./secrets.cbor")?; - f.write(&sc_res)?; - f.flush()?; + match args { + Args::Generate {out} => generate::generate_key(out), + Args::Encrypt {yaml, out, masterkey} => encrypt::generate_encrypted_secrets(yaml, out, masterkey) + } let secreta = "ABC".to_owned(); let mut f = File::create("./keyreq_a.cbor")?;