From 16b38f3197167c344bb522dcfa83292ddb3c1026 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 17 Nov 2023 16:42:25 +0100 Subject: integrate storage choice in config --- src/login/static_provider.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index b9be5a6..378a863 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -7,6 +7,7 @@ use async_trait::async_trait; use crate::config::*; use crate::cryptoblob::{Key, SecretKey}; use crate::login::*; +use crate::storage; pub struct StaticLoginProvider { default_bucket: Option, -- cgit v1.2.3 From 36f4050a40c3ba7b9637a973063b6b5549a2c208 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 17 Nov 2023 18:46:22 +0100 Subject: WIP provider config --- src/login/static_provider.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 378a863..df1432f 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -10,18 +10,13 @@ use crate::login::*; use crate::storage; pub struct StaticLoginProvider { - default_bucket: Option, users: HashMap>, users_by_email: HashMap>, - - k2v_region: Region, - s3_region: Region, } impl StaticLoginProvider { - pub fn new(config: LoginStaticConfig, k2v_region: Region, s3_region: Region) -> Result { + pub fn new(config: LoginStaticConfig) -> Result { let users = config - .users .into_iter() .map(|(k, v)| (k, Arc::new(v))) .collect::>(); @@ -36,11 +31,8 @@ impl StaticLoginProvider { } Ok(Self { - default_bucket: config.default_bucket, users, users_by_email, - k2v_region, - s3_region, }) } } @@ -59,23 +51,30 @@ impl LoginProvider for StaticLoginProvider { bail!("Wrong password"); } + /* tracing::debug!(user=%username, "fetch bucket"); let bucket = user .bucket .clone() .or_else(|| self.default_bucket.clone()) .ok_or(anyhow!( - "No bucket configured and no default bucket specieid" - ))?; + "No bucket configured and no default bucket specified" + ))?;*/ tracing::debug!(user=%username, "fetch keys"); - let storage = StorageCredentials { + let storage: storage::Builders = match user.storage { + StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), + StaticStorage::Garage(c) => Box::new(storage::garage::GrgCreds {}), + }; + + /* + StorageCredentials { k2v_region: self.k2v_region.clone(), s3_region: self.s3_region.clone(), aws_access_key_id: user.aws_access_key_id.clone(), aws_secret_access_key: user.aws_secret_access_key.clone(), bucket, - }; + };*/ let keys = match (&user.master_key, &user.secret_key) { (Some(m), Some(s)) => { -- cgit v1.2.3 From bd6c3464e609dc76e119457ea583af0f08eeabb4 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Tue, 21 Nov 2023 09:04:54 +0100 Subject: remove old storagecredentials --- src/login/static_provider.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index df1432f..d013c6f 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -106,6 +106,7 @@ impl LoginProvider for StaticLoginProvider { Some(u) => u, }; + /* let bucket = user .bucket .clone() @@ -120,6 +121,10 @@ impl LoginProvider for StaticLoginProvider { aws_access_key_id: user.aws_access_key_id.clone(), aws_secret_access_key: user.aws_secret_access_key.clone(), bucket, + };*/ + let storage: storage::Builders = match user.storage { + StaticStorage::InMemory => X, + StaticStorage::Garage => Y, }; let k2v_client = storage.k2v_client()?; -- cgit v1.2.3 From a7c9d554f6523c384cc0a14a789e0c8d9070e605 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Tue, 21 Nov 2023 15:09:39 +0100 Subject: fix login mod --- src/login/static_provider.rs | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index d013c6f..0e86cff 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -51,31 +51,12 @@ impl LoginProvider for StaticLoginProvider { bail!("Wrong password"); } - /* - tracing::debug!(user=%username, "fetch bucket"); - let bucket = user - .bucket - .clone() - .or_else(|| self.default_bucket.clone()) - .ok_or(anyhow!( - "No bucket configured and no default bucket specified" - ))?;*/ - tracing::debug!(user=%username, "fetch keys"); let storage: storage::Builders = match user.storage { StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), StaticStorage::Garage(c) => Box::new(storage::garage::GrgCreds {}), }; - /* - StorageCredentials { - k2v_region: self.k2v_region.clone(), - s3_region: self.s3_region.clone(), - aws_access_key_id: user.aws_access_key_id.clone(), - aws_secret_access_key: user.aws_secret_access_key.clone(), - bucket, - };*/ - let keys = match (&user.master_key, &user.secret_key) { (Some(m), Some(s)) => { let master_key = -- cgit v1.2.3 From 8cd9801030e24c58621b3bed8723e8a8a4722ef8 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 23 Nov 2023 15:16:44 +0100 Subject: various fixes --- src/login/static_provider.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 0e86cff..bd22060 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -104,11 +104,11 @@ impl LoginProvider for StaticLoginProvider { bucket, };*/ let storage: storage::Builders = match user.storage { - StaticStorage::InMemory => X, - StaticStorage::Garage => Y, + StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), + StaticStorage::Garage(c) => Box::new(storage::garage::GrgCreds {}), }; - let k2v_client = storage.k2v_client()?; + let k2v_client = storage.row_store()?; let (_, public_key) = CryptoKeys::load_salt_and_public(&k2v_client).await?; Ok(PublicCredentials { -- cgit v1.2.3 From 0722886efbeef3713bd7a671d2c09c8af2bdb6bd Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 23 Nov 2023 17:19:35 +0100 Subject: it compiles! --- src/login/static_provider.rs | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index bd22060..0b726cb 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -52,9 +52,16 @@ impl LoginProvider for StaticLoginProvider { } tracing::debug!(user=%username, "fetch keys"); - let storage: storage::Builders = match user.storage { + let storage: storage::Builders = match &user.storage { StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), - StaticStorage::Garage(c) => Box::new(storage::garage::GrgCreds {}), + StaticStorage::Garage(grgconf) => Box::new(storage::garage::GrgCreds { + region: grgconf.aws_region.clone(), + k2v_endpoint: grgconf.k2v_endpoint.clone(), + s3_endpoint: grgconf.s3_endpoint.clone(), + aws_access_key_id: grgconf.aws_access_key_id.clone(), + aws_secret_access_key: grgconf.aws_secret_access_key.clone(), + bucket: grgconf.bucket.clone(), + }), }; let keys = match (&user.master_key, &user.secret_key) { @@ -87,25 +94,16 @@ impl LoginProvider for StaticLoginProvider { Some(u) => u, }; - /* - let bucket = user - .bucket - .clone() - .or_else(|| self.default_bucket.clone()) - .ok_or(anyhow!( - "No bucket configured and no default bucket specieid" - ))?; - - let storage = StorageCredentials { - k2v_region: self.k2v_region.clone(), - s3_region: self.s3_region.clone(), - aws_access_key_id: user.aws_access_key_id.clone(), - aws_secret_access_key: user.aws_secret_access_key.clone(), - bucket, - };*/ - let storage: storage::Builders = match user.storage { + let storage: storage::Builders = match &user.storage { StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), - StaticStorage::Garage(c) => Box::new(storage::garage::GrgCreds {}), + StaticStorage::Garage(grgconf) => Box::new(storage::garage::GrgCreds { + region: grgconf.aws_region.clone(), + k2v_endpoint: grgconf.k2v_endpoint.clone(), + s3_endpoint: grgconf.s3_endpoint.clone(), + aws_access_key_id: grgconf.aws_access_key_id.clone(), + aws_secret_access_key: grgconf.aws_secret_access_key.clone(), + bucket: grgconf.bucket.clone(), + }), }; let k2v_client = storage.row_store()?; -- cgit v1.2.3 From 3ddbce4529225fe004acde3ab2e95261673bafc3 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 6 Dec 2023 20:57:25 +0100 Subject: WIP refactor --- src/login/static_provider.rs | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 0b726cb..3f6a840 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::sync::Arc; +use std::path::PathBuf; use anyhow::{anyhow, bail, Result}; use async_trait::async_trait; @@ -10,13 +11,28 @@ use crate::login::*; use crate::storage; pub struct StaticLoginProvider { - users: HashMap>, - users_by_email: HashMap>, + user_list: PathBuf, + users: HashMap>, + users_by_email: HashMap>, } impl StaticLoginProvider { pub fn new(config: LoginStaticConfig) -> Result { - let users = config + let mut lp = Self { + user_list: config.user_list, + users: HashMap::new(), + users_by_email: HashMap::new(), + }; + + lp.update_user_list(); + + Ok(lp) + } + + pub fn update_user_list(&mut self) -> Result<()> { + let ulist: UserList = read_config(self.user_list)?; + + let users = ulist .into_iter() .map(|(k, v)| (k, Arc::new(v))) .collect::>(); @@ -29,11 +45,7 @@ impl StaticLoginProvider { users_by_email.insert(m.clone(), u.clone()); } } - - Ok(Self { - users, - users_by_email, - }) + Ok(()) } } @@ -64,24 +76,18 @@ impl LoginProvider for StaticLoginProvider { }), }; - let keys = match (&user.master_key, &user.secret_key) { - (Some(m), Some(s)) => { + let keys = match user.crypto_root { /*(&user.master_key, &user.secret_key) {*/ + CryptographyRoot::InPlace { master_key: m, secret_key: s } => { let master_key = Key::from_slice(&base64::decode(m)?).ok_or(anyhow!("Invalid master key"))?; let secret_key = SecretKey::from_slice(&base64::decode(s)?) .ok_or(anyhow!("Invalid secret key"))?; CryptoKeys::open_without_password(&storage, &master_key, &secret_key).await? } - (None, None) => { - let user_secrets = UserSecrets { - user_secret: user.user_secret.clone(), - alternate_user_secrets: user.alternate_user_secrets.clone(), - }; - CryptoKeys::open(&storage, &user_secrets, password).await? + CryptographyRoot::PasswordProtected => { + CryptoKeys::open(&storage, password).await? } - _ => bail!( - "Either both master and secret key or none of them must be specified for user" - ), + CryptographyRoot::Keyring => unimplemented!(), }; tracing::debug!(user=%username, "logged"); -- cgit v1.2.3 From cf18eb8afb76a25150c885c6cf525aedcc25facc Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 8 Dec 2023 15:23:50 +0100 Subject: now compile again --- src/login/static_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 3f6a840..d0a4624 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -30,7 +30,7 @@ impl StaticLoginProvider { } pub fn update_user_list(&mut self) -> Result<()> { - let ulist: UserList = read_config(self.user_list)?; + let ulist: UserList = read_config(self.user_list.clone())?; let users = ulist .into_iter() @@ -76,7 +76,7 @@ impl LoginProvider for StaticLoginProvider { }), }; - let keys = match user.crypto_root { /*(&user.master_key, &user.secret_key) {*/ + let keys = match &user.crypto_root { /*(&user.master_key, &user.secret_key) {*/ CryptographyRoot::InPlace { master_key: m, secret_key: s } => { let master_key = Key::from_slice(&base64::decode(m)?).ok_or(anyhow!("Invalid master key"))?; -- cgit v1.2.3 From 532c99f3d30ab8adc0963f0814ce3151e1b61caf Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 8 Dec 2023 18:13:00 +0100 Subject: rework static login provider --- src/login/static_provider.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index d0a4624..0f6ab3a 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -19,12 +19,17 @@ pub struct StaticLoginProvider { impl StaticLoginProvider { pub fn new(config: LoginStaticConfig) -> Result { let mut lp = Self { - user_list: config.user_list, + user_list: config.user_list.clone(), users: HashMap::new(), users_by_email: HashMap::new(), }; - lp.update_user_list(); + lp + .update_user_list() + .context( + format!( + "failed to read {:?}, make sure it exists and it's correctly formatted", + config.user_list))?; Ok(lp) } @@ -32,17 +37,18 @@ impl StaticLoginProvider { pub fn update_user_list(&mut self) -> Result<()> { let ulist: UserList = read_config(self.user_list.clone())?; - let users = ulist + self.users = ulist .into_iter() .map(|(k, v)| (k, Arc::new(v))) .collect::>(); - let mut users_by_email = HashMap::new(); - for (_, u) in users.iter() { + + self.users_by_email.clear(); + for (_, u) in self.users.iter() { for m in u.email_addresses.iter() { - if users_by_email.contains_key(m) { + if self.users_by_email.contains_key(m) { bail!("Several users have same email address: {}", m); } - users_by_email.insert(m.clone(), u.clone()); + self.users_by_email.insert(m.clone(), u.clone()); } } Ok(()) -- cgit v1.2.3 From 47e25cd7f710fcd82356377cf48eccf9f65d31cc Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Tue, 12 Dec 2023 09:17:59 +0100 Subject: WIP --- src/login/static_provider.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 0f6ab3a..7fadf2f 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -83,15 +83,15 @@ impl LoginProvider for StaticLoginProvider { }; let keys = match &user.crypto_root { /*(&user.master_key, &user.secret_key) {*/ - CryptographyRoot::InPlace { master_key: m, secret_key: s } => { + CryptographyRoot::ClearText { master_key: m, secret_key: s } => { let master_key = Key::from_slice(&base64::decode(m)?).ok_or(anyhow!("Invalid master key"))?; let secret_key = SecretKey::from_slice(&base64::decode(s)?) .ok_or(anyhow!("Invalid secret key"))?; CryptoKeys::open_without_password(&storage, &master_key, &secret_key).await? } - CryptographyRoot::PasswordProtected => { - CryptoKeys::open(&storage, password).await? + CryptographyRoot::PasswordProtected { root_blob } => { + CryptoKeys::open(password, root_blob).await? } CryptographyRoot::Keyring => unimplemented!(), }; -- cgit v1.2.3 From 064a1077c8c66fe8d3ee71f831c930e1ddfbc34a Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 13 Dec 2023 16:09:01 +0100 Subject: it compiles again! --- src/login/static_provider.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 7fadf2f..178d97e 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -6,7 +6,6 @@ use anyhow::{anyhow, bail, Result}; use async_trait::async_trait; use crate::config::*; -use crate::cryptoblob::{Key, SecretKey}; use crate::login::*; use crate::storage; @@ -82,19 +81,8 @@ impl LoginProvider for StaticLoginProvider { }), }; - let keys = match &user.crypto_root { /*(&user.master_key, &user.secret_key) {*/ - CryptographyRoot::ClearText { master_key: m, secret_key: s } => { - let master_key = - Key::from_slice(&base64::decode(m)?).ok_or(anyhow!("Invalid master key"))?; - let secret_key = SecretKey::from_slice(&base64::decode(s)?) - .ok_or(anyhow!("Invalid secret key"))?; - CryptoKeys::open_without_password(&storage, &master_key, &secret_key).await? - } - CryptographyRoot::PasswordProtected { root_blob } => { - CryptoKeys::open(password, root_blob).await? - } - CryptographyRoot::Keyring => unimplemented!(), - }; + let cr = CryptoRoot(user.crypto_root); + let keys = cr.crypto_keys(password)?; tracing::debug!(user=%username, "logged"); Ok(Credentials { storage, keys }) @@ -118,8 +106,8 @@ impl LoginProvider for StaticLoginProvider { }), }; - let k2v_client = storage.row_store()?; - let (_, public_key) = CryptoKeys::load_salt_and_public(&k2v_client).await?; + let cr = CryptoRoot(user.crypto_root); + let public_key = cr.public_key()?; Ok(PublicCredentials { storage, -- cgit v1.2.3 From 29561dde41b402362f8baa3d9cd87a07f743b9fd Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 13 Dec 2023 18:04:04 +0100 Subject: CLI tools --- src/login/static_provider.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 178d97e..85d55ef 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -81,7 +81,7 @@ impl LoginProvider for StaticLoginProvider { }), }; - let cr = CryptoRoot(user.crypto_root); + let cr = CryptoRoot(user.crypto_root.clone()); let keys = cr.crypto_keys(password)?; tracing::debug!(user=%username, "logged"); @@ -106,7 +106,7 @@ impl LoginProvider for StaticLoginProvider { }), }; - let cr = CryptoRoot(user.crypto_root); + let cr = CryptoRoot(user.crypto_root.clone()); let public_key = cr.public_key()?; Ok(PublicCredentials { -- cgit v1.2.3 From 1f6e64d34e44b8b7bc7247af38bccf3ade86cf0b Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 14 Dec 2023 13:03:04 +0100 Subject: add support for hot reloading --- src/login/static_provider.rs | 73 ++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 29 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 85d55ef..4a8d484 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; use std::sync::Arc; use std::path::PathBuf; +use tokio::sync::watch; +use tokio::signal::unix::{signal, SignalKind}; use anyhow::{anyhow, bail, Result}; use async_trait::async_trait; @@ -9,48 +11,59 @@ use crate::config::*; use crate::login::*; use crate::storage; -pub struct StaticLoginProvider { - user_list: PathBuf, +#[derive(Default)] +pub struct UserDatabase { users: HashMap>, users_by_email: HashMap>, } -impl StaticLoginProvider { - pub fn new(config: LoginStaticConfig) -> Result { - let mut lp = Self { - user_list: config.user_list.clone(), - users: HashMap::new(), - users_by_email: HashMap::new(), - }; - - lp - .update_user_list() - .context( - format!( - "failed to read {:?}, make sure it exists and it's correctly formatted", - config.user_list))?; +pub struct StaticLoginProvider { + user_db: watch::Receiver, +} - Ok(lp) - } +pub async fn update_user_list(config: PathBuf, up: watch::Sender) -> Result<()> { + let mut stream = signal(SignalKind::user_defined1()).expect("failed to install SIGUSR1 signal hander for reload"); - pub fn update_user_list(&mut self) -> Result<()> { - let ulist: UserList = read_config(self.user_list.clone())?; + loop { + let ulist: UserList = match read_config(config.clone()) { + Ok(x) => x, + Err(e) => { + tracing::warn!(path=%config.as_path().to_string_lossy(), error=%e, "Unable to load config"); + continue; + } + }; - self.users = ulist + let users = ulist .into_iter() .map(|(k, v)| (k, Arc::new(v))) .collect::>(); - self.users_by_email.clear(); - for (_, u) in self.users.iter() { + let mut users_by_email = HashMap::new(); + for (_, u) in users.iter() { for m in u.email_addresses.iter() { - if self.users_by_email.contains_key(m) { - bail!("Several users have same email address: {}", m); + if users_by_email.contains_key(m) { + tracing::warn!("Several users have the same email address: {}", m); + continue } - self.users_by_email.insert(m.clone(), u.clone()); + users_by_email.insert(m.clone(), u.clone()); } } - Ok(()) + + tracing::info!("{} users loaded", users.len()); + up.send(UserDatabase { users, users_by_email }).context("update user db config")?; + stream.recv().await; + tracing::info!("Received SIGUSR1, reloading"); + } +} + +impl StaticLoginProvider { + pub async fn new(config: LoginStaticConfig) -> Result { + let (tx, mut rx) = watch::channel(UserDatabase::default()); + + tokio::spawn(update_user_list(config.user_list, tx)); + rx.changed().await?; + + Ok(Self { user_db: rx }) } } @@ -58,7 +71,8 @@ impl StaticLoginProvider { impl LoginProvider for StaticLoginProvider { async fn login(&self, username: &str, password: &str) -> Result { tracing::debug!(user=%username, "login"); - let user = match self.users.get(username) { + let user_db = self.user_db.borrow(); + let user = match user_db.users.get(username) { None => bail!("User {} does not exist", username), Some(u) => u, }; @@ -89,7 +103,8 @@ impl LoginProvider for StaticLoginProvider { } async fn public_login(&self, email: &str) -> Result { - let user = match self.users_by_email.get(email) { + let user_db = self.user_db.borrow(); + let user = match user_db.users_by_email.get(email) { None => bail!("No user for email address {}", email), Some(u) => u, }; -- cgit v1.2.3 From 684f4de225c44464abcb6a9cb2ef6dcae90537a8 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Sat, 16 Dec 2023 11:13:32 +0100 Subject: new new new storage interface --- src/login/static_provider.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 4a8d484..788a4c5 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -11,10 +11,15 @@ use crate::config::*; use crate::login::*; use crate::storage; +pub struct ContextualUserEntry { + pub username: String, + pub config: UserEntry, +} + #[derive(Default)] pub struct UserDatabase { - users: HashMap>, - users_by_email: HashMap>, + users: HashMap>, + users_by_email: HashMap>, } pub struct StaticLoginProvider { @@ -35,12 +40,12 @@ pub async fn update_user_list(config: PathBuf, up: watch::Sender) let users = ulist .into_iter() - .map(|(k, v)| (k, Arc::new(v))) + .map(|(username, config)| (username.clone() , Arc::new(ContextualUserEntry { username, config }))) .collect::>(); let mut users_by_email = HashMap::new(); for (_, u) in users.iter() { - for m in u.email_addresses.iter() { + for m in u.config.email_addresses.iter() { if users_by_email.contains_key(m) { tracing::warn!("Several users have the same email address: {}", m); continue @@ -78,13 +83,13 @@ impl LoginProvider for StaticLoginProvider { }; tracing::debug!(user=%username, "verify password"); - if !verify_password(password, &user.password)? { + if !verify_password(password, &user.config.password)? { bail!("Wrong password"); } tracing::debug!(user=%username, "fetch keys"); - let storage: storage::Builders = match &user.storage { - StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), + let storage: storage::Builders = match &user.config.storage { + StaticStorage::InMemory => Box::new(storage::in_memory::FullMem::new(username)), StaticStorage::Garage(grgconf) => Box::new(storage::garage::GrgCreds { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), @@ -95,7 +100,7 @@ impl LoginProvider for StaticLoginProvider { }), }; - let cr = CryptoRoot(user.crypto_root.clone()); + let cr = CryptoRoot(user.config.crypto_root.clone()); let keys = cr.crypto_keys(password)?; tracing::debug!(user=%username, "logged"); @@ -109,8 +114,8 @@ impl LoginProvider for StaticLoginProvider { Some(u) => u, }; - let storage: storage::Builders = match &user.storage { - StaticStorage::InMemory => Box::new(storage::in_memory::FullMem {}), + let storage: storage::Builders = match &user.config.storage { + StaticStorage::InMemory => Box::new(storage::in_memory::FullMem::new(&user.username)), StaticStorage::Garage(grgconf) => Box::new(storage::garage::GrgCreds { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), @@ -121,7 +126,7 @@ impl LoginProvider for StaticLoginProvider { }), }; - let cr = CryptoRoot(user.crypto_root.clone()); + let cr = CryptoRoot(user.config.crypto_root.clone()); let public_key = cr.public_key()?; Ok(PublicCredentials { -- cgit v1.2.3 From 3d41f40dc8cd6bdfa7a9279ab1959564d06eefaf Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 18 Dec 2023 17:09:44 +0100 Subject: Storage trait new implementation --- src/login/static_provider.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 788a4c5..5896f16 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -88,16 +88,16 @@ impl LoginProvider for StaticLoginProvider { } tracing::debug!(user=%username, "fetch keys"); - let storage: storage::Builders = match &user.config.storage { - StaticStorage::InMemory => Box::new(storage::in_memory::FullMem::new(username)), - StaticStorage::Garage(grgconf) => Box::new(storage::garage::GrgCreds { + let storage: storage::Builder = match &user.config.storage { + StaticStorage::InMemory => storage::in_memory::MemBuilder::new(username), + StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), s3_endpoint: grgconf.s3_endpoint.clone(), aws_access_key_id: grgconf.aws_access_key_id.clone(), aws_secret_access_key: grgconf.aws_secret_access_key.clone(), bucket: grgconf.bucket.clone(), - }), + })?, }; let cr = CryptoRoot(user.config.crypto_root.clone()); @@ -114,16 +114,16 @@ impl LoginProvider for StaticLoginProvider { Some(u) => u, }; - let storage: storage::Builders = match &user.config.storage { - StaticStorage::InMemory => Box::new(storage::in_memory::FullMem::new(&user.username)), - StaticStorage::Garage(grgconf) => Box::new(storage::garage::GrgCreds { + let storage: storage::Builder = match &user.config.storage { + StaticStorage::InMemory => storage::in_memory::MemBuilder::new(&user.username), + StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), s3_endpoint: grgconf.s3_endpoint.clone(), aws_access_key_id: grgconf.aws_access_key_id.clone(), aws_secret_access_key: grgconf.aws_secret_access_key.clone(), bucket: grgconf.bucket.clone(), - }), + })?, }; let cr = CryptoRoot(user.config.crypto_root.clone()); -- cgit v1.2.3 From 2830e62df99dc236cd2ba63a909849cf973d2654 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 20 Dec 2023 13:55:23 +0100 Subject: working in memory storage --- src/login/static_provider.rs | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 5896f16..2e2e034 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -24,6 +24,7 @@ pub struct UserDatabase { pub struct StaticLoginProvider { user_db: watch::Receiver, + in_memory_store: tokio::sync::Mutex>>, } pub async fn update_user_list(config: PathBuf, up: watch::Sender) -> Result<()> { @@ -68,7 +69,7 @@ impl StaticLoginProvider { tokio::spawn(update_user_list(config.user_list, tx)); rx.changed().await?; - Ok(Self { user_db: rx }) + Ok(Self { user_db: rx, in_memory_store: tokio::sync::Mutex::new(HashMap::new()) }) } } @@ -76,10 +77,12 @@ impl StaticLoginProvider { impl LoginProvider for StaticLoginProvider { async fn login(&self, username: &str, password: &str) -> Result { tracing::debug!(user=%username, "login"); - let user_db = self.user_db.borrow(); - let user = match user_db.users.get(username) { - None => bail!("User {} does not exist", username), - Some(u) => u, + let user = { + let user_db = self.user_db.borrow(); + match user_db.users.get(username) { + None => bail!("User {} does not exist", username), + Some(u) => u.clone(), + } }; tracing::debug!(user=%username, "verify password"); @@ -89,7 +92,13 @@ impl LoginProvider for StaticLoginProvider { tracing::debug!(user=%username, "fetch keys"); let storage: storage::Builder = match &user.config.storage { - StaticStorage::InMemory => storage::in_memory::MemBuilder::new(username), + StaticStorage::InMemory => { + let mut global_storage = self.in_memory_store.lock().await; + global_storage + .entry(username.to_string()) + .or_insert(storage::in_memory::MemBuilder::new(username)) + .clone() + }, StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), @@ -108,14 +117,23 @@ impl LoginProvider for StaticLoginProvider { } async fn public_login(&self, email: &str) -> Result { - let user_db = self.user_db.borrow(); - let user = match user_db.users_by_email.get(email) { - None => bail!("No user for email address {}", email), - Some(u) => u, + let user = { + let user_db = self.user_db.borrow(); + match user_db.users_by_email.get(email) { + None => bail!("Email {} does not exist", email), + Some(u) => u.clone(), + } }; + tracing::debug!(user=%user.username, "public_login"); let storage: storage::Builder = match &user.config.storage { - StaticStorage::InMemory => storage::in_memory::MemBuilder::new(&user.username), + StaticStorage::InMemory => { + let mut global_storage = self.in_memory_store.lock().await; + global_storage + .entry(user.username.to_string()) + .or_insert(storage::in_memory::MemBuilder::new(&user.username)) + .clone() + }, StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), -- cgit v1.2.3 From a3a9f87d2c1d2f1c01ecba3a00c592e477a6b22b Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 21 Dec 2023 09:32:48 +0100 Subject: avoid infinite loop --- src/login/static_provider.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 2e2e034..76ad6a6 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -35,6 +35,7 @@ pub async fn update_user_list(config: PathBuf, up: watch::Sender) Ok(x) => x, Err(e) => { tracing::warn!(path=%config.as_path().to_string_lossy(), error=%e, "Unable to load config"); + stream.recv().await; continue; } }; @@ -49,6 +50,7 @@ pub async fn update_user_list(config: PathBuf, up: watch::Sender) for m in u.config.email_addresses.iter() { if users_by_email.contains_key(m) { tracing::warn!("Several users have the same email address: {}", m); + stream.recv().await; continue } users_by_email.insert(m.clone(), u.clone()); -- cgit v1.2.3 From e9aabe8e82e3c3a8190c0224cd1fdf2fc4d2505a Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 21 Dec 2023 15:36:05 +0100 Subject: move storage logic into the storage module --- src/login/static_provider.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 76ad6a6..b11123c 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -24,7 +24,7 @@ pub struct UserDatabase { pub struct StaticLoginProvider { user_db: watch::Receiver, - in_memory_store: tokio::sync::Mutex>>, + in_memory_store: storage::in_memory::MemDb, } pub async fn update_user_list(config: PathBuf, up: watch::Sender) -> Result<()> { @@ -71,7 +71,7 @@ impl StaticLoginProvider { tokio::spawn(update_user_list(config.user_list, tx)); rx.changed().await?; - Ok(Self { user_db: rx, in_memory_store: tokio::sync::Mutex::new(HashMap::new()) }) + Ok(Self { user_db: rx, in_memory_store: storage::in_memory::MemDb::new() }) } } @@ -94,13 +94,7 @@ impl LoginProvider for StaticLoginProvider { tracing::debug!(user=%username, "fetch keys"); let storage: storage::Builder = match &user.config.storage { - StaticStorage::InMemory => { - let mut global_storage = self.in_memory_store.lock().await; - global_storage - .entry(username.to_string()) - .or_insert(storage::in_memory::MemBuilder::new(username)) - .clone() - }, + StaticStorage::InMemory => self.in_memory_store.builder(username).await, StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), @@ -129,13 +123,7 @@ impl LoginProvider for StaticLoginProvider { tracing::debug!(user=%user.username, "public_login"); let storage: storage::Builder = match &user.config.storage { - StaticStorage::InMemory => { - let mut global_storage = self.in_memory_store.lock().await; - global_storage - .entry(user.username.to_string()) - .or_insert(storage::in_memory::MemBuilder::new(&user.username)) - .clone() - }, + StaticStorage::InMemory => self.in_memory_store.builder(&user.username).await, StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { region: grgconf.aws_region.clone(), k2v_endpoint: grgconf.k2v_endpoint.clone(), -- cgit v1.2.3 From 7ac24ad913fa081e1bd6f5b042b9da0173dad267 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 27 Dec 2023 14:58:28 +0100 Subject: cargo format --- src/login/static_provider.rs | 63 ++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'src/login/static_provider.rs') diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index b11123c..1e1ecbf 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; -use std::sync::Arc; use std::path::PathBuf; -use tokio::sync::watch; +use std::sync::Arc; use tokio::signal::unix::{signal, SignalKind}; +use tokio::sync::watch; use anyhow::{anyhow, bail, Result}; use async_trait::async_trait; @@ -28,7 +28,8 @@ pub struct StaticLoginProvider { } pub async fn update_user_list(config: PathBuf, up: watch::Sender) -> Result<()> { - let mut stream = signal(SignalKind::user_defined1()).expect("failed to install SIGUSR1 signal hander for reload"); + let mut stream = signal(SignalKind::user_defined1()) + .expect("failed to install SIGUSR1 signal hander for reload"); loop { let ulist: UserList = match read_config(config.clone()) { @@ -42,7 +43,12 @@ pub async fn update_user_list(config: PathBuf, up: watch::Sender) let users = ulist .into_iter() - .map(|(username, config)| (username.clone() , Arc::new(ContextualUserEntry { username, config }))) + .map(|(username, config)| { + ( + username.clone(), + Arc::new(ContextualUserEntry { username, config }), + ) + }) .collect::>(); let mut users_by_email = HashMap::new(); @@ -51,14 +57,18 @@ pub async fn update_user_list(config: PathBuf, up: watch::Sender) if users_by_email.contains_key(m) { tracing::warn!("Several users have the same email address: {}", m); stream.recv().await; - continue + continue; } users_by_email.insert(m.clone(), u.clone()); } } tracing::info!("{} users loaded", users.len()); - up.send(UserDatabase { users, users_by_email }).context("update user db config")?; + up.send(UserDatabase { + users, + users_by_email, + }) + .context("update user db config")?; stream.recv().await; tracing::info!("Received SIGUSR1, reloading"); } @@ -71,7 +81,10 @@ impl StaticLoginProvider { tokio::spawn(update_user_list(config.user_list, tx)); rx.changed().await?; - Ok(Self { user_db: rx, in_memory_store: storage::in_memory::MemDb::new() }) + Ok(Self { + user_db: rx, + in_memory_store: storage::in_memory::MemDb::new(), + }) } } @@ -95,14 +108,16 @@ impl LoginProvider for StaticLoginProvider { tracing::debug!(user=%username, "fetch keys"); let storage: storage::Builder = match &user.config.storage { StaticStorage::InMemory => self.in_memory_store.builder(username).await, - StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { - region: grgconf.aws_region.clone(), - k2v_endpoint: grgconf.k2v_endpoint.clone(), - s3_endpoint: grgconf.s3_endpoint.clone(), - aws_access_key_id: grgconf.aws_access_key_id.clone(), - aws_secret_access_key: grgconf.aws_secret_access_key.clone(), - bucket: grgconf.bucket.clone(), - })?, + StaticStorage::Garage(grgconf) => { + storage::garage::GarageBuilder::new(storage::garage::GarageConf { + region: grgconf.aws_region.clone(), + k2v_endpoint: grgconf.k2v_endpoint.clone(), + s3_endpoint: grgconf.s3_endpoint.clone(), + aws_access_key_id: grgconf.aws_access_key_id.clone(), + aws_secret_access_key: grgconf.aws_secret_access_key.clone(), + bucket: grgconf.bucket.clone(), + })? + } }; let cr = CryptoRoot(user.config.crypto_root.clone()); @@ -124,14 +139,16 @@ impl LoginProvider for StaticLoginProvider { let storage: storage::Builder = match &user.config.storage { StaticStorage::InMemory => self.in_memory_store.builder(&user.username).await, - StaticStorage::Garage(grgconf) => storage::garage::GarageBuilder::new(storage::garage::GarageConf { - region: grgconf.aws_region.clone(), - k2v_endpoint: grgconf.k2v_endpoint.clone(), - s3_endpoint: grgconf.s3_endpoint.clone(), - aws_access_key_id: grgconf.aws_access_key_id.clone(), - aws_secret_access_key: grgconf.aws_secret_access_key.clone(), - bucket: grgconf.bucket.clone(), - })?, + StaticStorage::Garage(grgconf) => { + storage::garage::GarageBuilder::new(storage::garage::GarageConf { + region: grgconf.aws_region.clone(), + k2v_endpoint: grgconf.k2v_endpoint.clone(), + s3_endpoint: grgconf.s3_endpoint.clone(), + aws_access_key_id: grgconf.aws_access_key_id.clone(), + aws_secret_access_key: grgconf.aws_secret_access_key.clone(), + bucket: grgconf.bucket.clone(), + })? + } }; let cr = CryptoRoot(user.config.crypto_root.clone()); -- cgit v1.2.3