[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 <dev@friedl.net>
This commit is contained in:
parent
b3b86b4238
commit
8427a6ad53
7 changed files with 96 additions and 38 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
*.cbor
|
||||
secreq.yaml
|
||||
*.yaml
|
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -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]]
|
||||
|
|
6
TODO.org
6
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]
|
||||
|
|
|
@ -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
|
||||
|
|
26
coffer-companion/src/encrypt.rs
Normal file
26
coffer-companion/src/encrypt.rs
Normal file
|
@ -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<String, String>;
|
||||
|
||||
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()});
|
||||
}
|
33
coffer-companion/src/generate.rs
Normal file
33
coffer-companion/src/generate.rs
Normal file
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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<String, String>;
|
||||
pub type Secs = Vec<String>;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
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")?;
|
||||
|
|
Loading…
Reference in a new issue