diff --git a/bffhd/actors/mod.rs b/bffhd/actors/mod.rs index 94f3ea9..dd27585 100644 --- a/bffhd/actors/mod.rs +++ b/bffhd/actors/mod.rs @@ -258,12 +258,16 @@ pub fn load( .compat(), ); - let mut actor_map: HashMap = config - .actor_connections + let mut actor_connections_data_vec: Vec<(String, String)> = vec![]; + for actor_connection in config.actor_connections.clone().into_iter() { + actor_connections_data_vec.push((actor_connection.machine, actor_connection.actor)); + } + + let mut actor_map: HashMap = actor_connections_data_vec .iter() .filter_map(|(k, v)| { - if let Some(resource) = resources.get_by_id(v) { - Some((k.clone(), resource.get_signal())) + if let Some(resource) = resources.get_by_id(k) { + Some((v.clone(), resource.get_signal())) } else { tracing::error!(actor=%k, machine=%v, "Machine configured for actor not found!"); None diff --git a/bffhd/authorization/permissions.rs b/bffhd/authorization/permissions.rs index 8360365..bfa0f23 100644 --- a/bffhd/authorization/permissions.rs +++ b/bffhd/authorization/permissions.rs @@ -32,7 +32,7 @@ pub struct PrivilegesBuf { // i.e. "bffh.perm" is not the same as "bffհ.реrm" (Armenian 'հ':Հ and Cyrillic 'е':Е) // See also https://util.unicode.org/UnicodeJsps/confusables.jsp pub struct PermissionBuf { - inner: String, + pub inner: String, } impl PermissionBuf { #[inline(always)] diff --git a/bffhd/authorization/roles.rs b/bffhd/authorization/roles.rs index ef9cb38..781813c 100644 --- a/bffhd/authorization/roles.rs +++ b/bffhd/authorization/roles.rs @@ -131,11 +131,11 @@ pub struct Role { /// This makes situations where different levels of access are required easier: Each higher /// level of access sets the lower levels of access as parent, inheriting their permission; if /// you are allowed to manage a machine you are then also allowed to use it and so on - parents: Vec, + pub parents: Vec, // If a role doesn't define permissions, default to an empty Vec. #[serde(default, skip_serializing_if = "Vec::is_empty")] - permissions: Vec, + pub permissions: Vec, } impl Role { diff --git a/bffhd/config/dhall.rs b/bffhd/config/dhall.rs index 4bfef15..3235afa 100644 --- a/bffhd/config/dhall.rs +++ b/bffhd/config/dhall.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; -use crate::authorization::permissions::PrivilegesBuf; +use crate::authorization::permissions::{PermRule, PermissionBuf, PrivilegesBuf}; use crate::authorization::roles::Role; use crate::capnp::{Listen, TlsListen}; use crate::logging::LogConfig; @@ -57,11 +57,7 @@ pub struct MachineDescription { #[serde(flatten)] pub privs: PrivilegesBuf, - #[serde( - default = "default_prodable", - skip_serializing_if = "bool_is_false", - deserialize_with = "deser_bool" - )] + #[serde(default = "default_prodable", skip_serializing_if = "bool_is_false", deserialize_with = "deser_bool")] pub prodable: bool, } @@ -74,28 +70,13 @@ fn bool_is_false(b: &bool) -> bool { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Config { + pub spacename: String, + + pub instanceurl: String, + /// A list of address/port pairs to listen on. pub listens: Vec, - /// Machine descriptions to load - pub machines: HashMap, - - /// Actors to load and their configuration options - pub actors: HashMap, - - /// Initiators to load and their configuration options - pub initiators: HashMap, - - pub mqtt_url: String, - - pub actor_connections: Vec<(String, String)>, - pub init_connections: Vec<(String, String)>, - - pub db_path: PathBuf, - pub auditlog_path: PathBuf, - - pub roles: HashMap, - #[serde(flatten)] pub tlsconfig: TlsListen, @@ -108,9 +89,22 @@ pub struct Config { #[serde(default, skip)] pub logging: LogConfig, - pub spacename: String, + pub mqtt_url: String, + pub db_path: PathBuf, + pub auditlog_path: PathBuf, - pub instanceurl: String, + pub roles: HashMap, + + /// Machine descriptions to load + pub machines: HashMap, + + /// Actors to load and their configuration options + pub actors: HashMap, + pub actor_connections: Vec, + + /// Initiators to load and their configuration options + pub initiators: HashMap, + pub init_connections: Vec, } impl Config { @@ -125,6 +119,24 @@ pub struct ModuleConfig { pub params: HashMap, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ParamsConfig { + pub module: String, + pub params: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ActorConnectionConfig { + pub machine: String, + pub actor: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InitiatorConnectionConfig { + pub machine: String, + pub initiator: String, +} + fn deser_bool<'de, D>(d: D) -> Result where D: serde::Deserializer<'de>, @@ -144,50 +156,153 @@ impl Default for Config { fn default() -> Self { let mut actors: HashMap = HashMap::new(); let mut initiators: HashMap = HashMap::new(); - let machines = HashMap::new(); + let mut roles: HashMap = HashMap::new(); + let mut machines: HashMap = HashMap::new(); + + let mut initiator_123_params: HashMap = HashMap::new(); + initiator_123_params.insert("args".to_string(), "".to_string()); + initiator_123_params.insert("cmd".to_string(), "echo".to_string()); + + let actor_connections_vec: Vec = vec![ActorConnectionConfig { + machine: "resource_a".to_string(), + actor: "actor_123".to_string(), + }]; + + let initiator_connections_vec: Vec = + vec![InitiatorConnectionConfig { + machine: "resource_a".to_string(), + initiator: "initiator_123".to_string(), + }]; + + roles.insert( + "admin".to_string(), + Role { + parents: Vec::new(), + permissions: vec![ + PermRule::Base(PermissionBuf { + inner: "bffh.users.info".to_string(), + }), + PermRule::Base(PermissionBuf { + inner: "bffh.users.manage".to_string(), + }), + PermRule::Base(PermissionBuf { + inner: "bffh.users.admin".to_string(), + }), + ], + }, + ); + + roles.insert( + "member".to_string(), + Role { + parents: Vec::new(), + permissions: vec![ + PermRule::Base(PermissionBuf { + inner: "lab.some.disclose".to_string(), + }), + PermRule::Base(PermissionBuf { + inner: "lab.some.read".to_string(), + }), + PermRule::Base(PermissionBuf { + inner: "lab.some.write".to_string(), + }), + PermRule::Base(PermissionBuf { + inner: "lab.some.manage".to_string(), + }), + ], + }, + ); + + machines.insert( + "resource_a".to_string(), + MachineDescription { + name: "Resource A".to_string(), + description: Option::from("A description".to_string()), + wiki: Option::from("https://some.wiki.url".to_string()), + category: Option::from("A category".to_string()), + prodable: true, + privs: PrivilegesBuf { + disclose: PermissionBuf { + inner: "lab.some.disclose".to_string(), + }, + read: PermissionBuf { + inner: "lab.some.read".to_string(), + }, + write: PermissionBuf { + inner: "lab.some.write".to_string(), + }, + manage: PermissionBuf { + inner: "lab.some.manage".to_string(), + }, + }, + }, + ); + + machines.insert( + "resource_b".to_string(), + MachineDescription { + name: "Resource B".to_string(), + description: Option::from("A description".to_string()), + wiki: Option::from("https://some.wiki.url".to_string()), + category: Option::from("A category".to_string()), + prodable: false, + privs: PrivilegesBuf { + disclose: PermissionBuf { + inner: "lab.some.disclose".to_string(), + }, + read: PermissionBuf { + inner: "lab.some.read".to_string(), + }, + write: PermissionBuf { + inner: "lab.some.write".to_string(), + }, + manage: PermissionBuf { + inner: "lab.some.manage".to_string(), + }, + }, + }, + ); actors.insert( - "Actor".to_string(), + "actor_123".to_string(), ModuleConfig { module: "Shelly".to_string(), params: HashMap::new(), }, ); + initiators.insert( - "Initiator".to_string(), + "initiator_123".to_string(), ModuleConfig { - module: "TCP-Listen".to_string(), - params: HashMap::new(), + module: "Process".to_string(), + params: initiator_123_params, }, ); Config { + spacename: "fabaccess.sample.space".into(), + instanceurl: "https://fabaccess.sample.space".into(), listens: vec![Listen { address: "127.0.0.1".to_string(), port: None, }], - actors, - initiators, - machines, - mqtt_url: "tcp://localhost:1883".to_string(), - actor_connections: vec![("Testmachine".to_string(), "Actor".to_string())], - init_connections: vec![("Initiator".to_string(), "Testmachine".to_string())], - - db_path: PathBuf::from("/run/bffh/database"), - auditlog_path: PathBuf::from("/var/log/bffh/audit.log"), - roles: HashMap::new(), - tlsconfig: TlsListen { - certfile: PathBuf::from("./bffh.crt"), - keyfile: PathBuf::from("./bffh.key"), + certfile: PathBuf::from("/etc/bffh/certs/bffh.crt"), + keyfile: PathBuf::from("/etc/bffh/certs/bffh.key"), ..Default::default() }, - tlskeylog: None, verbosity: 0, logging: LogConfig::default(), - instanceurl: "".into(), - spacename: "".into(), + mqtt_url: "mqtt://127.0.0.1:1883".to_string(), + db_path: PathBuf::from("/var/lib/bffh/bffh.db"), + auditlog_path: PathBuf::from("/var/log/bffh/audit.json"), + roles, + machines, + actors, + actor_connections: actor_connections_vec, + initiators, + init_connections: initiator_connections_vec, } } } diff --git a/bffhd/initiators/mod.rs b/bffhd/initiators/mod.rs index e293927..89787a4 100644 --- a/bffhd/initiators/mod.rs +++ b/bffhd/initiators/mod.rs @@ -103,12 +103,16 @@ pub fn load( let span = tracing::info_span!("loading initiators"); let _guard = span.enter(); - let mut initiator_map: HashMap = config - .init_connections + let mut init_connections_data_vec: Vec<(String, String)> = vec![]; + for init_connection in config.init_connections.clone().into_iter() { + init_connections_data_vec.push((init_connection.machine, init_connection.initiator)); + } + + let mut initiator_map: HashMap = init_connections_data_vec .iter() .filter_map(|(k, v)| { - if let Some(resource) = resources.get_by_id(v) { - Some((k.clone(), resource.clone())) + if let Some(resource) = resources.get_by_id(k) { + Some((v.clone(), resource.clone())) } else { tracing::error!(initiator=%k, machine=%v, "Machine configured for initiator not found!");