Allow nested clients
Tables can be nested arbitrary, only tables with `id` attribute are considered
This commit is contained in:
parent
e5032b33eb
commit
7e723c7f02
11 changed files with 94 additions and 57 deletions
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.enc filter=lfs diff=lfs merge=lfs -text
|
||||
*.cert filter=lfs diff=lfs merge=lfs -text
|
|
@ -75,7 +75,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
Err("Could not spawn sub-command".into())
|
||||
}
|
||||
|
||||
fn reap_coffer(cmd: &str, args: &Vec<String>) {
|
||||
fn reap_coffer(cmd: &str, args: &[String]) {
|
||||
let mut cmd = exec::Command::new(cmd);
|
||||
|
||||
// TODO Push cmd as first arg if not already set?
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read};
|
||||
|
@ -87,51 +88,51 @@ pub trait Coffer {
|
|||
_ => panic!{"Invalid secrets file"}
|
||||
};
|
||||
|
||||
/*
|
||||
* Walk through the table of clients, where each client is a table which
|
||||
* is either empty, or contains a table with at least an id and any
|
||||
* number of secrets
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* files.id = "AAAA-BBBB-CCCC"
|
||||
* pad.id = "FFFF-EEEE-DDDD"
|
||||
*
|
||||
* [files]
|
||||
* secret_string = "secret value1"
|
||||
* secret_int = 12345
|
||||
* secret_bool = true
|
||||
*/
|
||||
for (_k, v) in clients {
|
||||
coffer.from_toml_table(&clients);
|
||||
|
||||
let client = match v {
|
||||
TomlValue::Table(t) => t,
|
||||
_ => panic!{"Invalid secrets file"}
|
||||
};
|
||||
coffer
|
||||
}
|
||||
|
||||
for (k, v) in client.iter() {
|
||||
|
||||
if "id" == k { continue } // ids are for sharding
|
||||
|
||||
let value = match v {
|
||||
TomlValue::String(s) => CofferValue::String(s.to_owned()),
|
||||
TomlValue::Integer(i) => CofferValue::Integer(*i as i32),
|
||||
TomlValue::Float(f) => CofferValue::Float(*f as f32),
|
||||
TomlValue::Boolean(b) => CofferValue::Boolean(*b),
|
||||
_ => panic!{"Value {:?} unsupported", v}
|
||||
};
|
||||
|
||||
match client.get("id") {
|
||||
Some(TomlValue::String(shard)) => {
|
||||
let shard = shard.to_owned();
|
||||
let key = k.to_owned();
|
||||
coffer.put(CofferKey{shard, key}, value).unwrap();
|
||||
fn from_toml_table(&mut self, toml_table: &toml::value::Table) {
|
||||
// table has an no id, recourse into subtables
|
||||
if toml_table.get("id").is_none() {
|
||||
for (_key, val) in toml_table.iter() {
|
||||
match val {
|
||||
TomlValue::Table(subtable) => {
|
||||
self.from_toml_table(subtable);
|
||||
},
|
||||
_ => panic!{"Invalid secrets file"}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return coffer;
|
||||
/*
|
||||
* Parse a single shard/table, this is known to have an id
|
||||
*
|
||||
* [files]
|
||||
* id = "ABC-DEF-GHE"
|
||||
* secret_string = "secret value1"
|
||||
* secret_int = 12345
|
||||
* secret_bool = true
|
||||
*/
|
||||
let shard = toml_table.get("id").and_then(|id| id.as_str()).unwrap();
|
||||
|
||||
for (key, val) in toml_table {
|
||||
if "id" == key { continue } // ids are for sharding
|
||||
|
||||
let value = match val {
|
||||
TomlValue::String(s) => CofferValue::String(s.to_owned()),
|
||||
TomlValue::Integer(i) => CofferValue::Integer(*i as i32),
|
||||
TomlValue::Float(f) => CofferValue::Float(*f as f32),
|
||||
TomlValue::Boolean(b) => CofferValue::Boolean(*b),
|
||||
_ => panic!{"Value {:?} unsupported", val}
|
||||
};
|
||||
|
||||
let key = key.to_owned();
|
||||
let shard = shard.to_string();
|
||||
self.put(CofferKey{shard, key}, value).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,25 +65,33 @@ impl Keyring {
|
|||
_ => panic!{"Invalid secrets file"}
|
||||
};
|
||||
|
||||
for (_k, v) in clients {
|
||||
self.add_known_keys_toml_table(&clients)?;
|
||||
|
||||
let client = match v {
|
||||
TomlValue::Table(client) => client,
|
||||
_ => panic!{"Invalid secrets file"}
|
||||
};
|
||||
|
||||
match client.get("id") {
|
||||
Some(TomlValue::String(id)) => {
|
||||
let id = id.to_owned();
|
||||
self.add_known_key(&hex::decode(id)?)?;
|
||||
},
|
||||
_ => panic!{"Invalid id, only hex encoded ids supported"}
|
||||
}
|
||||
}
|
||||
debug!{"Known keys {:?}", self.known_keys}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_known_keys_toml_table(&mut self, toml_table: &toml::value::Table) -> Result<(), KeyringError> {
|
||||
// table has an no id, recourse into subtables
|
||||
if toml_table.get("id").is_none() {
|
||||
debug!{"{:?}", toml_table}
|
||||
for (_key, val) in toml_table.iter() {
|
||||
match val {
|
||||
TomlValue::Table(subtable) => {
|
||||
self.add_known_keys_toml_table(subtable)?;
|
||||
},
|
||||
_ => panic!{"Invalid secrets file"}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let shard = toml_table.get("id").and_then(|id| id.as_str()).ok_or(KeyringError::Msg("Invalid key parsing state"))?;
|
||||
self.add_known_key(&hex::decode(shard)?)
|
||||
}
|
||||
|
||||
pub fn add_known_key(&mut self, key: &[u8]) -> Result<(), KeyringError> {
|
||||
let public_key = box_::PublicKey::from_slice(key)
|
||||
.ok_or(KeyringError::InvalidClientKey)?;
|
||||
|
@ -94,7 +102,7 @@ impl Keyring {
|
|||
|
||||
pub fn open(&self, message: &[u8]) -> Result<Vec<u8>, KeyringError> {
|
||||
self.certificate.open(message)
|
||||
.map_err(|e| KeyringError::from(e))
|
||||
.map_err(KeyringError::from)
|
||||
}
|
||||
|
||||
pub fn seal(&self, client: &[u8], message: &[u8]) -> Result<Vec<u8>, KeyringError> {
|
||||
|
|
BIN
testcoffer/client.cert
(Stored with Git LFS)
BIN
testcoffer/client.cert
(Stored with Git LFS)
Binary file not shown.
BIN
testcoffer/client1.cert
(Stored with Git LFS)
Normal file
BIN
testcoffer/client1.cert
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
testcoffer/client2.cert
(Stored with Git LFS)
Normal file
BIN
testcoffer/client2.cert
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
testcoffer/coffer.enc
(Stored with Git LFS)
BIN
testcoffer/coffer.enc
(Stored with Git LFS)
Binary file not shown.
|
@ -2,3 +2,14 @@
|
|||
id = "F11C86D52A70977D866F813903BC73DB4CB8AC40249DF668475B1BFE48AD1E41"
|
||||
key1 = "secret1"
|
||||
key2 = "secret2"
|
||||
|
||||
[clients]
|
||||
[client.1]
|
||||
id = "00E4A58C6905C2932F73F4D3AB449507E0166E53ED52F769721618F8C836E736"
|
||||
client1key1 = "client1secret"
|
||||
client1key2 = "client1secret2"
|
||||
|
||||
[client.2]
|
||||
id = "D4A39CD8C4695A70F758252E9D877ACE24BD3DE98BC09E90C37C06F99061CD5B"
|
||||
client2key1 = "client2secret"
|
||||
client2key2 = "client2secret2"
|
||||
|
|
BIN
testcoffer/no_keys_client.cert
(Stored with Git LFS)
Normal file
BIN
testcoffer/no_keys_client.cert
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
testcoffer/server.cert
(Stored with Git LFS)
BIN
testcoffer/server.cert
(Stored with Git LFS)
Binary file not shown.
Loading…
Reference in a new issue