Rebranding to coffer, restructuring
Signed-off-by: Armin Friedl <dev@friedl.net>
This commit is contained in:
parent
b39a3ef1ac
commit
3344ca4877
16 changed files with 312 additions and 221 deletions
83
Cargo.lock
generated
83
Cargo.lock
generated
|
@ -64,6 +64,43 @@ dependencies = [
|
||||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coffer-client"
|
||||||
|
version = "0.1.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)",
|
||||||
|
"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)",
|
||||||
|
"structopt 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coffer-companion"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"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_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)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coffer-server"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"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)",
|
||||||
|
"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)",
|
||||||
|
"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]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -355,43 +392,6 @@ name = "rle-decode-fast"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "secsrv"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"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)",
|
|
||||||
"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_cbor 0.10.2 (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)",
|
|
||||||
"toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "secsrv-client"
|
|
||||||
version = "0.1.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)",
|
|
||||||
"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)",
|
|
||||||
"structopt 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "secsrv-util"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"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_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)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.102"
|
version = "1.0.102"
|
||||||
|
@ -522,14 +522,6 @@ dependencies = [
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -669,7 +661,6 @@ dependencies = [
|
||||||
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
|
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
|
||||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||||
"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf"
|
|
||||||
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"secsrv",
|
"coffer-server",
|
||||||
"secsrv-companion",
|
"coffer-client",
|
||||||
"secsrv-client"
|
"coffer-companion"
|
||||||
]
|
]
|
11
README.md
11
README.md
|
@ -1,10 +1 @@
|
||||||
# SecServ
|
# Coffer
|
||||||
The simple secret service
|
|
||||||
|
|
||||||
# Protocol
|
|
||||||
Alice (secret service): keypair (apk, ask)
|
|
||||||
Bob (client): keypair (bpk, bsk)
|
|
||||||
|
|
||||||
KEY {id: string, keyid: string, nonce: b64, tag: signature}
|
|
||||||
// alice checks access rights of id for keyid
|
|
||||||
EKY {nonce1:b64, enc(key, nonce:64, bpk), tag: signature}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "secsrv-client"
|
name = "coffer-client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Armin Friedl <dev@friedl.net>"]
|
authors = ["Armin Friedl <dev@friedl.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "secsrv-util"
|
name = "coffer-companion"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Armin Friedl <dev@friedl.net>"]
|
authors = ["Armin Friedl <dev@friedl.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
|
@ -1,22 +1,20 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sodiumoxide::crypto::box_;
|
||||||
|
use sodiumoxide::crypto::sealedbox;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use sodiumoxide::crypto::box_;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum Key {
|
struct MasterKey {
|
||||||
MasterKey {
|
public_key: box_::PublicKey,
|
||||||
|
secret_key: box_::SecretKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ClientKey {
|
||||||
id: String,
|
id: String,
|
||||||
public_key: box_::PublicKey,
|
public_key: box_::PublicKey,
|
||||||
secret_key: box_::SecretKey
|
|
||||||
},
|
|
||||||
|
|
||||||
ClientKey {
|
|
||||||
id: String,
|
|
||||||
public_key: box_::PublicKey
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Secrets = HashMap<String, String>;
|
pub type Secrets = HashMap<String, String>;
|
||||||
|
@ -24,10 +22,9 @@ pub type Secs = Vec<String>;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let keypair = box_::gen_keypair();
|
let keypair = box_::gen_keypair();
|
||||||
let masterkey: Key = Key::MasterKey {
|
let masterkey: MasterKey = MasterKey {
|
||||||
id: "master".to_owned(),
|
|
||||||
public_key: keypair.0,
|
public_key: keypair.0,
|
||||||
secret_key: keypair.1
|
secret_key: keypair.1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let f = File::create("./masterkey.cbor")?;
|
let f = File::create("./masterkey.cbor")?;
|
||||||
|
@ -36,10 +33,16 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let secrets: Secrets = [
|
let secrets: Secrets = [
|
||||||
("ABC".to_owned(), "DEF".to_owned()),
|
("ABC".to_owned(), "DEF".to_owned()),
|
||||||
("XYZ".to_owned(), "ABC".to_owned()),
|
("XYZ".to_owned(), "ABC".to_owned()),
|
||||||
].iter().cloned().collect();
|
]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
let f = File::create("./secrets.cbor")?;
|
let sc_res = serde_cbor::to_vec(&secrets)?;
|
||||||
serde_cbor::to_writer(f, &secrets)?;
|
let sc_res = sealedbox::seal(&sc_res, &masterkey.public_key);
|
||||||
|
let mut f = File::create("./secrets.cbor")?;
|
||||||
|
f.write(&sc_res)?;
|
||||||
|
f.flush()?;
|
||||||
|
|
||||||
let secreta = "ABC".to_owned();
|
let secreta = "ABC".to_owned();
|
||||||
let mut f = File::create("./keyreq_a.cbor")?;
|
let mut f = File::create("./keyreq_a.cbor")?;
|
||||||
|
@ -53,7 +56,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
f.write(&buf.len().to_be_bytes())?;
|
f.write(&buf.len().to_be_bytes())?;
|
||||||
f.write(&buf)?;
|
f.write(&buf)?;
|
||||||
|
|
||||||
let secs = vec!{"ABC", "XYZ"};
|
let secs = vec!["ABC", "XYZ"];
|
||||||
let f = File::create("./secreq.yaml")?;
|
let f = File::create("./secreq.yaml")?;
|
||||||
serde_yaml::to_writer(f, &secs)?;
|
serde_yaml::to_writer(f, &secs)?;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "secsrv"
|
name = "coffer-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Armin Friedl <dev@friedl.net>"]
|
authors = ["Armin Friedl <dev@friedl.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -9,10 +9,10 @@ edition = "2018"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger="0.7"
|
env_logger="0.7"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
|
quick-error = "1.2"
|
||||||
# Key management/Cryptography
|
# Key management/Cryptography
|
||||||
sodiumoxide = "0.2.5"
|
sodiumoxide = "0.2.5"
|
||||||
# Communication
|
# Communication
|
||||||
serde = { version = "1.0", features = ["derive"]}
|
serde = { version = "1.0", features = ["derive"]}
|
||||||
serde_cbor = "0.10.2"
|
serde_cbor = "0.10.2"
|
||||||
toml = "0.5"
|
|
||||||
futures = { version = "0.3.1", features = ["thread-pool"]}
|
futures = { version = "0.3.1", features = ["thread-pool"]}
|
83
coffer-server/src/coffer/keyring.rs
Normal file
83
coffer-server/src/coffer/keyring.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use log::{debug, error, info, trace, warn};
|
||||||
|
use quick_error::quick_error;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use sodiumoxide::crypto::sealedbox;
|
||||||
|
use sodiumoxide::crypto::box_;
|
||||||
|
|
||||||
|
quick_error! {
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum KeyringError {
|
||||||
|
Io(err: std::io::Error) {
|
||||||
|
from()
|
||||||
|
}
|
||||||
|
Cbor(err: serde_cbor::Error) {
|
||||||
|
from()
|
||||||
|
}
|
||||||
|
Crypto {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct MasterKey {
|
||||||
|
public_key: box_::PublicKey,
|
||||||
|
secret_key: box_::SecretKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MasterKey {
|
||||||
|
pub fn decrypt(&self, c: &[u8]) -> Result<Vec<u8>, KeyringError> {
|
||||||
|
sealedbox::open(c, &self.public_key, &self.secret_key)
|
||||||
|
.map_err(|_| KeyringError::Crypto)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encrypt(&self, m: &[u8]) -> Vec<u8> {
|
||||||
|
sealedbox::seal(m, &self.public_key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ClientKey {
|
||||||
|
id: String,
|
||||||
|
public_key: box_::PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Keyring {
|
||||||
|
pub master: MasterKey,
|
||||||
|
pub clients: HashMap<String, ClientKey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Keyring {
|
||||||
|
pub fn new_from_path(path: &PathBuf, keep: bool) -> Result<Keyring, KeyringError> {
|
||||||
|
let keyring = Keyring {
|
||||||
|
master: key_from_path(path, keep)?,
|
||||||
|
clients: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(keyring)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_key_from_path(&mut self, path: &PathBuf, keep: bool) -> Result<(), KeyringError> {
|
||||||
|
let client_key: ClientKey = key_from_path(path, keep)?;
|
||||||
|
self.clients.insert(client_key.id.clone(), client_key);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_from_path<T>(path: &PathBuf, keep: bool) -> Result<T, KeyringError>
|
||||||
|
where T: serde::de::DeserializeOwned
|
||||||
|
{
|
||||||
|
|
||||||
|
let mk_file = File::open(path)?;
|
||||||
|
let key = serde_cbor::from_reader(mk_file)?;
|
||||||
|
|
||||||
|
if !keep { std::fs::remove_file(path)? };
|
||||||
|
|
||||||
|
Ok(key)
|
||||||
|
}
|
70
coffer-server/src/coffer/mod.rs
Normal file
70
coffer-server/src/coffer/mod.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use log::{debug, error, info, trace, warn};
|
||||||
|
use quick_error::quick_error;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
// do not provide a path to keyring through coffer module. keyring is hence
|
||||||
|
// effectively private outside coffer
|
||||||
|
mod keyring;
|
||||||
|
use keyring::Keyring;
|
||||||
|
|
||||||
|
quick_error! {
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CofferError {
|
||||||
|
Keyring(err: keyring::KeyringError) {
|
||||||
|
from()
|
||||||
|
}
|
||||||
|
Io(err: std::io::Error) {
|
||||||
|
from()
|
||||||
|
}
|
||||||
|
Cbor(err: serde_cbor::Error) {
|
||||||
|
from()
|
||||||
|
}
|
||||||
|
Coffer(err: &'static str) {
|
||||||
|
from()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, CofferError>;
|
||||||
|
type Secrets = HashMap<String, String>; // move this to a module if it gathers crust
|
||||||
|
|
||||||
|
pub struct Coffer {
|
||||||
|
// do not expose inner structure of coffer
|
||||||
|
keyring: Keyring,
|
||||||
|
secrets: Secrets
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Coffer {
|
||||||
|
/// Create a coffer from a masterkey and secrets encrypted with the masterkey's
|
||||||
|
/// public key
|
||||||
|
pub fn new_from_path_encrypted(masterkey: &PathBuf, secrets: &PathBuf, keep: bool) -> Result<Coffer> {
|
||||||
|
debug!{"Initializing keyring"}
|
||||||
|
let keyring = Keyring::new_from_path(masterkey, keep)?;
|
||||||
|
|
||||||
|
debug!{"Loading secrets"}
|
||||||
|
let mut sec_data = Vec::new();
|
||||||
|
File::open(secrets)?.read_to_end(&mut sec_data)?;
|
||||||
|
|
||||||
|
debug!{"Removing files"}
|
||||||
|
if !keep {
|
||||||
|
std::fs::remove_file(secrets)?;
|
||||||
|
std::fs::remove_file(masterkey)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!{"Decrypting secrets"}
|
||||||
|
sec_data = keyring.master.decrypt(&sec_data)?;
|
||||||
|
let secrets = serde_cbor::from_slice::<Secrets>(&sec_data)?;
|
||||||
|
|
||||||
|
debug!{"Filling coffer"};
|
||||||
|
Ok(Coffer{keyring, secrets})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_secret(&self, key: &str) -> Result<&String> {
|
||||||
|
self.secrets.get(key).ok_or("No secret found in coffer for".into())
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,28 +7,29 @@ use std::io::{Write};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use futures::executor::ThreadPool;
|
use futures::executor::ThreadPool;
|
||||||
|
|
||||||
use crate::secrets::{Secrets};
|
use crate::coffer::Coffer;
|
||||||
|
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
pub executor: ThreadPool,
|
pub executor: ThreadPool,
|
||||||
pub address: SocketAddr,
|
pub address: SocketAddr,
|
||||||
|
pub coffer: Arc<Coffer>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
pub fn listen(self, secrets: Arc<Secrets>) {
|
pub fn listen(self) {
|
||||||
|
|
||||||
let listener:TcpListener = TcpListener::bind(self.address).unwrap();
|
let listener:TcpListener = TcpListener::bind(self.address).unwrap();
|
||||||
|
|
||||||
listener.incoming().for_each(|inc| {
|
listener.incoming().for_each(|inc| {
|
||||||
match inc {
|
match inc {
|
||||||
Ok(tcp_stream) => self.executor.spawn_ok(handler(tcp_stream, secrets.clone())),
|
Ok(tcp_stream) => self.executor.spawn_ok(handler(tcp_stream, self.coffer.clone())),
|
||||||
Err(e) => error!{"Failed binding incoming connection {}", e}
|
Err(e) => error!{"Failed binding incoming connection {}", e}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(mut stream: TcpStream, secrets: Arc<Secrets>) {
|
async fn handler(mut stream: TcpStream, coffer: Arc<Coffer>) {
|
||||||
let mut peek_buf = [0x00; 1];
|
let mut peek_buf = [0x00; 1];
|
||||||
|
|
||||||
while stream.peek(&mut peek_buf).unwrap() != 0 {
|
while stream.peek(&mut peek_buf).unwrap() != 0 {
|
||||||
|
@ -41,12 +42,12 @@ async fn handler(mut stream: TcpStream, secrets: Arc<Secrets>) {
|
||||||
let mut handle = (&stream).take(len);
|
let mut handle = (&stream).take(len);
|
||||||
handle.read_to_end(&mut buf);
|
handle.read_to_end(&mut buf);
|
||||||
debug!{"Read vec {:?}", buf};
|
debug!{"Read vec {:?}", buf};
|
||||||
|
|
||||||
let res: Result<String, serde_cbor::Error> = serde_cbor::from_slice(&buf);
|
let res: Result<String, serde_cbor::Error> = serde_cbor::from_slice(&buf);
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(request) => {
|
Ok(request) => {
|
||||||
|
if let Ok(secret) = coffer.get_secret(&request) {
|
||||||
if let Some(secret) = secrets.get(&request) {
|
|
||||||
writeln!(stream, "{}", secret)
|
writeln!(stream, "{}", secret)
|
||||||
.unwrap_or_else(|err| {error!{"Could not write key response to stream {}", err}});
|
.unwrap_or_else(|err| {error!{"Could not write key response to stream {}", err}});
|
||||||
debug!{"Wrote {:?}", secret}
|
debug!{"Wrote {:?}", secret}
|
82
coffer-server/src/main.rs
Normal file
82
coffer-server/src/main.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use log::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
|
use env_logger;
|
||||||
|
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use futures::executor::ThreadPool;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
mod coffer;
|
||||||
|
mod comm;
|
||||||
|
|
||||||
|
use comm::Channel;
|
||||||
|
|
||||||
|
#[derive(StructOpt, Debug)]
|
||||||
|
struct Args {
|
||||||
|
/// Path to the master key file. Will be deleted after processing.
|
||||||
|
#[structopt(short, long, parse(from_os_str), env = "SECSRV_MASTER", hide_env_values = true)]
|
||||||
|
master: PathBuf,
|
||||||
|
|
||||||
|
/// Path to the secret keys file. Will be deleted after processing.
|
||||||
|
/// Must be encrypted with the public key of the master key
|
||||||
|
#[structopt(short, long, parse(from_os_str), env = "SECSRV_KEYS", hide_env_values = true)]
|
||||||
|
secrets: PathBuf,
|
||||||
|
|
||||||
|
/// The port secsrv listens on
|
||||||
|
#[structopt(short, long, env = "SECSRV_PORT", default_value = "9187")]
|
||||||
|
port: u16,
|
||||||
|
|
||||||
|
/// The address secsrv binds to
|
||||||
|
#[structopt(short, long, env = "SECSRV_IP", default_value = "127.0.0.1")]
|
||||||
|
ip: IpAddr,
|
||||||
|
|
||||||
|
/// Prevent deletion of key files
|
||||||
|
#[structopt(short)]
|
||||||
|
keep_keys: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
let args = Args::from_args();
|
||||||
|
|
||||||
|
_print_banner();
|
||||||
|
|
||||||
|
info!{"Setting up executor"}
|
||||||
|
let address: SocketAddr = (args.ip, args.port).try_into()
|
||||||
|
.expect("Parsing binding address failed");
|
||||||
|
let executor = ThreadPool::new()
|
||||||
|
.expect("Setting up executor failed");
|
||||||
|
|
||||||
|
info!{"Filling coffer"}
|
||||||
|
let coffer = coffer::Coffer::new_from_path_encrypted(&args.master, &args.secrets, args.keep_keys)
|
||||||
|
.expect("Could not fill coffer");
|
||||||
|
|
||||||
|
debug!{"Connecting on {}", address}
|
||||||
|
let channel = Channel {executor, address, coffer: Arc::from(coffer)};
|
||||||
|
channel.listen();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _print_banner() {
|
||||||
|
println!{r#"
|
||||||
|
|
||||||
|
|
||||||
|
@@@@@@@ @@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@
|
||||||
|
@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@
|
||||||
|
!@@ @@! @@@ @@! @@! @@! @@! @@@
|
||||||
|
!@! !@! @!@ !@! !@! !@! !@! @!@
|
||||||
|
!@! @!@ !@! @!!!:! @!!!:! @!!!:! @!@!!@!
|
||||||
|
!!! !@! !!! !!!!!: !!!!!: !!!!!: !!@!@!
|
||||||
|
:!! !!: !!! !!: !!: !!: !!: :!!
|
||||||
|
:!: :!: !:! :!: :!: :!: :!: !:!
|
||||||
|
::: ::: ::::: :: :: :: :: :::: :: :::
|
||||||
|
:: :: : : : : : : : :: :: : : :
|
||||||
|
|
||||||
|
|
||||||
|
"#}
|
||||||
|
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
#[allow(unused_imports)]
|
|
||||||
use log::{debug, error, info, trace, warn};
|
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
use sodiumoxide::crypto::box_;
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
#[derive(Debug,Serialize,Deserialize)]
|
|
||||||
pub enum Key {
|
|
||||||
MasterKey {
|
|
||||||
id: String,
|
|
||||||
public_key: box_::PublicKey,
|
|
||||||
secret_key: box_::SecretKey
|
|
||||||
},
|
|
||||||
|
|
||||||
ClientKey {
|
|
||||||
id: String,
|
|
||||||
public_key: box_::PublicKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_from_path(path: &PathBuf, keep: bool) -> Result<Key, Box<dyn Error>> {
|
|
||||||
let mut mk_file = File::open(path)?;
|
|
||||||
|
|
||||||
let mut mk_data = Vec::new();
|
|
||||||
mk_file.read_to_end(&mut mk_data)?;
|
|
||||||
if !keep { std::fs::remove_file(path)?; };
|
|
||||||
|
|
||||||
Ok(serde_cbor::from_slice::<Key>(&mk_data)?)
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
#[allow(unused_imports)]
|
|
||||||
use log::{debug, error, info, trace, warn};
|
|
||||||
|
|
||||||
use env_logger;
|
|
||||||
|
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::error::Error;
|
|
||||||
use futures::executor::ThreadPool;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use structopt::StructOpt;
|
|
||||||
use std::net::IpAddr;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
mod comm;
|
|
||||||
mod keyring;
|
|
||||||
mod secrets;
|
|
||||||
|
|
||||||
use comm::Channel;
|
|
||||||
|
|
||||||
#[derive(StructOpt, Debug)]
|
|
||||||
struct Args {
|
|
||||||
/// Path to the master key file. Will be deleted after processing.
|
|
||||||
#[structopt(short, long, parse(from_os_str), env = "SECSRV_MASTER", hide_env_values = true)]
|
|
||||||
master: PathBuf,
|
|
||||||
|
|
||||||
/// Path to the secret keys file. Will be deleted after processing.
|
|
||||||
#[structopt(long, parse(from_os_str), env = "SECSRV_KEYS", hide_env_values = true)]
|
|
||||||
keys: PathBuf,
|
|
||||||
|
|
||||||
/// The port secsrv is listening on
|
|
||||||
#[structopt(short, long, env = "SECSRV_PORT", default_value = "9187")]
|
|
||||||
port: u16,
|
|
||||||
|
|
||||||
/// The address secsrv binds to
|
|
||||||
#[structopt(short, long, env = "SECSRV_IP", default_value = "127.0.0.1")]
|
|
||||||
ip: IpAddr,
|
|
||||||
|
|
||||||
/// Prevent deletion of key files
|
|
||||||
#[structopt(short)]
|
|
||||||
keep_keys: bool
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>>{
|
|
||||||
env_logger::init();
|
|
||||||
let args = Args::from_args();
|
|
||||||
|
|
||||||
_print_banner();
|
|
||||||
|
|
||||||
debug!{"Parsing master key from {}", args.master.display()}
|
|
||||||
let _master_key = keyring::parse_from_path(&args.master, args.keep_keys)?;
|
|
||||||
|
|
||||||
debug!{"Parsing secrets from {}", args.keys.display()}
|
|
||||||
let secrets = secrets::parse_from_path(&args.keys, args.keep_keys)?;
|
|
||||||
|
|
||||||
info!{"Setting up the connection pool"}
|
|
||||||
let executor = ThreadPool::new()?;
|
|
||||||
let address: SocketAddr = (args.ip, args.port).try_into()?;
|
|
||||||
debug!{"Connecting on {}", address}
|
|
||||||
let channel = Channel {executor, address};
|
|
||||||
channel.listen(secrets.into());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _print_banner() {
|
|
||||||
info!{r#"
|
|
||||||
|
|
||||||
|
|
||||||
___ ___ ___ ___ ___ _ ____ __
|
|
||||||
/ __|/ _ \/ __/ __|/ _ \ '__\ \ / /
|
|
||||||
\__ \ __/ (__\__ \ __/ | \ V /
|
|
||||||
|___/\___|\___|___/\___|_| \_/
|
|
||||||
|
|
||||||
|
|
||||||
"#}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
#[allow(unused_imports)]
|
|
||||||
use log::{debug, error, info, trace, warn};
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
pub type Secrets = HashMap<String, String>;
|
|
||||||
|
|
||||||
pub fn parse_from_path(path: &PathBuf, keep: bool) -> Result<Secrets, Box<dyn Error>> {
|
|
||||||
let mut sec_file = File::open(path)?;
|
|
||||||
|
|
||||||
let mut sec_data = Vec::new();
|
|
||||||
sec_file.read_to_end(&mut sec_data)?;
|
|
||||||
if !keep { std::fs::remove_file(path)?; };
|
|
||||||
|
|
||||||
Ok(serde_cbor::from_slice::<Secrets>(&sec_data)?)
|
|
||||||
}
|
|
Loading…
Reference in a new issue