From 90142ec5c15f3710d2686cd158325c3c316e498c Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Sun, 2 Feb 2020 05:40:07 +0100 Subject: [PATCH] [server] Allow nested clients Tables can be nested arbitrary, only tables with `id` attribute are considered --- .gitattributes | 2 + coffer-client/src/main.rs | 2 +- coffer-common/src/coffer.rs | 77 +++++++++++++++++----------------- coffer-common/src/keyring.rs | 38 ++++++++++------- testcoffer/client.cert | 4 +- testcoffer/client1.cert | 3 ++ testcoffer/client2.cert | 3 ++ testcoffer/coffer.enc | 4 +- testcoffer/coffer.yaml | 11 +++++ testcoffer/no_keys_client.cert | 3 ++ testcoffer/server.cert | 4 +- 11 files changed, 94 insertions(+), 57 deletions(-) create mode 100644 .gitattributes create mode 100644 testcoffer/client1.cert create mode 100644 testcoffer/client2.cert create mode 100644 testcoffer/no_keys_client.cert diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2c752ed --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.enc filter=lfs diff=lfs merge=lfs -text +*.cert filter=lfs diff=lfs merge=lfs -text diff --git a/coffer-client/src/main.rs b/coffer-client/src/main.rs index e443729..309cde4 100644 --- a/coffer-client/src/main.rs +++ b/coffer-client/src/main.rs @@ -75,7 +75,7 @@ fn main() -> Result<(), Box> { Err("Could not spawn sub-command".into()) } -fn reap_coffer(cmd: &str, args: &Vec) { +fn reap_coffer(cmd: &str, args: &[String]) { let mut cmd = exec::Command::new(cmd); // TODO Push cmd as first arg if not already set? diff --git a/coffer-common/src/coffer.rs b/coffer-common/src/coffer.rs index dc14a53..b43ac17 100644 --- a/coffer-common/src/coffer.rs +++ b/coffer-common/src/coffer.rs @@ -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(); + } } } diff --git a/coffer-common/src/keyring.rs b/coffer-common/src/keyring.rs index 61dd4e7..7179b15 100644 --- a/coffer-common/src/keyring.rs +++ b/coffer-common/src/keyring.rs @@ -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, KeyringError> { self.certificate.open(message) - .map_err(|e| KeyringError::from(e)) + .map_err(KeyringError::from) } pub fn seal(&self, client: &[u8], message: &[u8]) -> Result, KeyringError> { diff --git a/testcoffer/client.cert b/testcoffer/client.cert index 355073c..cc4b979 100644 --- a/testcoffer/client.cert +++ b/testcoffer/client.cert @@ -1 +1,3 @@ -jpublic_keyX *p}o9sL@$hG[HAkprivate_keyX ϫrhDI\Jp \ No newline at end of file +version https://git-lfs.github.com/spec/v1 +oid sha256:6274c811440245c8859ff78edfdf8c4d9f93c1022242707bd966ecf226836b45 +size 92 diff --git a/testcoffer/client1.cert b/testcoffer/client1.cert new file mode 100644 index 0000000..2ece5ee --- /dev/null +++ b/testcoffer/client1.cert @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6d7be75d0f208b19a606a1af56a8d319656b81112e8f4d2b8a3824958eeedd4 +size 92 diff --git a/testcoffer/client2.cert b/testcoffer/client2.cert new file mode 100644 index 0000000..ed06da3 --- /dev/null +++ b/testcoffer/client2.cert @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:422ca500dfbff53bf557f5ccbcd3326ed0622017f0e14800ecc062585e1d1ce5 +size 92 diff --git a/testcoffer/coffer.enc b/testcoffer/coffer.enc index a137035..f1e75a7 100644 --- a/testcoffer/coffer.enc +++ b/testcoffer/coffer.enc @@ -1 +1,3 @@ -܅ۈs;AG8LehzVB&VLf~B.5K*X~B`@,J\}GC2Kd0Ƈv"IAZ6OR KWjxohv{ɲcCD ]Շ?b/h $7p|9A$? \ No newline at end of file +version https://git-lfs.github.com/spec/v1 +oid sha256:76f742d88686e14e9db713bb38f2da1fea6ce20c8003b9bda136c778f992a550 +size 461 diff --git a/testcoffer/coffer.yaml b/testcoffer/coffer.yaml index 939159d..28d61cb 100644 --- a/testcoffer/coffer.yaml +++ b/testcoffer/coffer.yaml @@ -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" diff --git a/testcoffer/no_keys_client.cert b/testcoffer/no_keys_client.cert new file mode 100644 index 0000000..d0677b3 --- /dev/null +++ b/testcoffer/no_keys_client.cert @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e260e5e7bca479436ec22d449a5a255fb4971b4edc36f3f8f7c407a7ca92313d +size 92 diff --git a/testcoffer/server.cert b/testcoffer/server.cert index 077a185..4c32a64 100644 --- a/testcoffer/server.cert +++ b/testcoffer/server.cert @@ -1 +1,3 @@ -jpublic_keyX N%[#{P-jfPdx 4[kprivate_keyX Mٙgk{CM>;~3d+ \ No newline at end of file +version https://git-lfs.github.com/spec/v1 +oid sha256:a3b9724fd3dff9248bba5ff40f63d63eda6d705b810e65882648bbc9876615c3 +size 92