diff options
Diffstat (limited to 'src/login')
-rw-r--r-- | src/login/ldap_provider.rs | 3 | ||||
-rw-r--r-- | src/login/mod.rs | 76 | ||||
-rw-r--r-- | src/login/static_provider.rs | 37 |
3 files changed, 98 insertions, 18 deletions
diff --git a/src/login/ldap_provider.rs b/src/login/ldap_provider.rs index 6108e6e..54ddbd5 100644 --- a/src/login/ldap_provider.rs +++ b/src/login/ldap_provider.rs @@ -1,5 +1,6 @@ use anyhow::Result; use async_trait::async_trait; +use rusoto_signature::Region; use crate::config::*; use crate::login::*; @@ -9,7 +10,7 @@ pub struct LdapLoginProvider { } impl LdapLoginProvider { - pub fn new(_config: LoginLdapConfig) -> Result<Self> { + pub fn new(_config: LoginLdapConfig, _k2v_region: Region, _s3_region: Region) -> Result<Self> { unimplemented!() } } diff --git a/src/login/mod.rs b/src/login/mod.rs index 0845371..4022962 100644 --- a/src/login/mod.rs +++ b/src/login/mod.rs @@ -9,7 +9,7 @@ use rusoto_credential::{AwsCredentials, StaticProvider}; use rusoto_s3::S3Client; use rusoto_signature::Region; -use crate::cryptoblob::Key as SymmetricKey; +use crate::cryptoblob::*; #[async_trait] pub trait LoginProvider { @@ -18,14 +18,51 @@ pub trait LoginProvider { #[derive(Clone, Debug)] pub struct Credentials { + pub storage: StorageCredentials, + pub keys: CryptoKeys, +} + +#[derive(Clone, Debug)] +pub struct StorageCredentials { + pub s3_region: Region, + pub k2v_region: Region, + pub aws_access_key_id: String, pub aws_secret_access_key: String, pub bucket: String, - pub master_key: SymmetricKey, } +#[derive(Clone, Debug)] +pub struct CryptoKeys { + // Master key for symmetric encryption of mailbox data + pub master: Key, + // Public/private keypair for encryption of incomming emails + pub secret: SecretKey, + pub public: PublicKey, +} + +// ---- + impl Credentials { - pub fn k2v_client(&self, k2v_region: &Region) -> Result<K2vClient> { + pub fn k2v_client(&self) -> Result<K2vClient> { + self.storage.k2v_client() + } + pub fn s3_client(&self) -> Result<S3Client> { + self.storage.s3_client() + } + pub fn bucket(&self) -> &str { + self.storage.bucket.as_str() + } + pub fn dump_config(&self) { + println!("aws_access_key_id = \"{}\"", self.storage.aws_access_key_id); + println!("aws_secret_access_key = \"{}\"", self.storage.aws_secret_access_key); + println!("master_key = \"{}\"", base64::encode(&self.keys.master)); + println!("secret_key = \"{}\"", base64::encode(&self.keys.secret)); + } +} + +impl StorageCredentials { + pub fn k2v_client(&self) -> Result<K2vClient> { let aws_creds = AwsCredentials::new( self.aws_access_key_id.clone(), self.aws_secret_access_key.clone(), @@ -34,14 +71,14 @@ impl Credentials { ); Ok(K2vClient::new( - k2v_region.clone(), + self.k2v_region.clone(), self.bucket.clone(), aws_creds, None, )?) } - pub fn s3_client(&self, s3_region: &Region) -> Result<S3Client> { + pub fn s3_client(&self) -> Result<S3Client> { let aws_creds_provider = StaticProvider::new_minimal( self.aws_access_key_id.clone(), self.aws_secret_access_key.clone(), @@ -50,7 +87,34 @@ impl Credentials { Ok(S3Client::new_with( HttpClient::new()?, aws_creds_provider, - s3_region.clone(), + self.s3_region.clone(), )) } } + +impl CryptoKeys { + pub fn init(storage: &StorageCredentials) -> Result<Self> { + unimplemented!() + } + + pub fn init_without_password(storage: &StorageCredentials, master_key: &Key, secret_key: &SecretKey) -> Result<Self> { + unimplemented!() + } + + pub fn open(storage: &StorageCredentials, password: &str) -> Result<Self> { + unimplemented!() + } + + pub fn open_without_password(storage: &StorageCredentials, master_key: &Key, secret_key: &SecretKey) -> Result<Self> { + unimplemented!() + } + + pub fn add_password(&self, storage: &StorageCredentials, password: &str) -> Result<()> { + unimplemented!() + } + + pub fn remove_password(&self, storage: &StorageCredentials, password: &str, allow_remove_all: bool) -> Result<()> { + unimplemented!() + } +} + diff --git a/src/login/static_provider.rs b/src/login/static_provider.rs index 037948a..d7d791a 100644 --- a/src/login/static_provider.rs +++ b/src/login/static_provider.rs @@ -5,21 +5,23 @@ use async_trait::async_trait; use rusoto_signature::Region; use crate::config::*; -use crate::cryptoblob::Key; +use crate::cryptoblob::{Key, SecretKey}; use crate::login::*; pub struct StaticLoginProvider { default_bucket: Option<String>, users: HashMap<String, LoginStaticUser>, k2v_region: Region, + s3_region: Region, } impl StaticLoginProvider { - pub fn new(config: LoginStaticConfig, k2v_region: Region) -> Result<Self> { + pub fn new(config: LoginStaticConfig, k2v_region: Region, s3_region: Region) -> Result<Self> { Ok(Self { default_bucket: config.default_bucket, users: config.users, k2v_region, + s3_region, }) } } @@ -42,18 +44,31 @@ impl LoginProvider for StaticLoginProvider { "No bucket configured and no default bucket specieid" ))?; - // TODO if master key is not specified, retrieve it from K2V key storage - let master_key_str = u.master_key.as_ref().ok_or(anyhow!( - "Master key must be specified in config file for now, this will change" - ))?; - let master_key = Key::from_slice(&base64::decode(master_key_str)?) - .ok_or(anyhow!("Invalid master key"))?; - - Ok(Credentials { + let storage = StorageCredentials { + k2v_region: self.k2v_region.clone(), + s3_region: self.s3_region.clone(), aws_access_key_id: u.aws_access_key_id.clone(), aws_secret_access_key: u.aws_secret_access_key.clone(), bucket, - master_key, + }; + + let keys = match (&u.master_key, &u.secret_key) { + (Some(m), Some(s)) => { + let master_key = Key::from_slice(&base64::decode(m)?) + .ok_or(anyhow!("Invalid master key"))?; + let secret_key = SecretKey::from_slice(&base64::decode(m)?) + .ok_or(anyhow!("Invalid secret key"))?; + CryptoKeys::open_without_password(&storage, &master_key, &secret_key)? + } + (None, None) => { + CryptoKeys::open(&storage, password)? + } + _ => bail!("Either both master and secret key or none of them must be specified for user"), + }; + + Ok(Credentials { + storage, + keys, }) } } |