Changeset View
Changeset View
Standalone View
Standalone View
services/identity/src/config.rs
use curve25519_dalek::ristretto::RistrettoPoint; | use curve25519_dalek::ristretto::RistrettoPoint; | ||||
use once_cell::sync::Lazy; | use once_cell::sync::Lazy; | ||||
use opaque_ke::{errors::PakeError, keypair::KeyPair}; | use opaque_ke::{errors::PakeError, keypair::KeyPair}; | ||||
use std::{env, fmt, fs, io, path}; | use std::{collections::HashSet, env, fmt, fs, io, path}; | ||||
use crate::constants::{ | use crate::constants::{ | ||||
AUTH_TOKEN, LOCALSTACK_ENDPOINT, SECRETS_DIRECTORY, SECRETS_FILE_EXTENSION, | AUTH_TOKEN, LOCALSTACK_ENDPOINT, SECRETS_DIRECTORY, SECRETS_FILE_EXTENSION, | ||||
SECRETS_FILE_NAME, SECRETS_SETUP_FILE, | SECRETS_FILE_NAME, SECRETS_SETUP_FILE, | ||||
}; | }; | ||||
pub static CONFIG: Lazy<Config> = | pub static CONFIG: Lazy<Config> = | ||||
Lazy::new(|| Config::load().expect("failed to load config")); | Lazy::new(|| Config::load().expect("failed to load config")); | ||||
pub(super) fn load_config() { | pub(super) fn load_config() { | ||||
Lazy::force(&CONFIG); | Lazy::force(&CONFIG); | ||||
} | } | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct Config { | pub struct Config { | ||||
// Opaque 1.2 server secrets | // Opaque 1.2 server secrets | ||||
pub server_keypair: KeyPair<RistrettoPoint>, | pub server_keypair: KeyPair<RistrettoPoint>, | ||||
// this is temporary, while the only authorized caller is ashoat's keyserver | // this is temporary, while the only authorized caller is ashoat's keyserver | ||||
pub keyserver_auth_token: String, | pub keyserver_auth_token: String, | ||||
pub localstack_endpoint: Option<String>, | pub localstack_endpoint: Option<String>, | ||||
// Opaque 2.0 server secrets | // Opaque 2.0 server secrets | ||||
pub server_setup: comm_opaque2::ServerSetup<comm_opaque2::Cipher>, | pub server_setup: comm_opaque2::ServerSetup<comm_opaque2::Cipher>, | ||||
// Reserved usernames | |||||
pub reserved_usernames: HashSet<String>, | |||||
} | } | ||||
impl Config { | impl Config { | ||||
fn load() -> Result<Self, Error> { | fn load() -> Result<Self, Error> { | ||||
let mut path = path::PathBuf::new(); | let mut path = path::PathBuf::new(); | ||||
path.push(SECRETS_DIRECTORY); | path.push(SECRETS_DIRECTORY); | ||||
path.push(SECRETS_FILE_NAME); | path.push(SECRETS_FILE_NAME); | ||||
path.set_extension(SECRETS_FILE_EXTENSION); | path.set_extension(SECRETS_FILE_EXTENSION); | ||||
let server_keypair = get_keypair_from_file(path)?; | let server_keypair = get_keypair_from_file(path)?; | ||||
let keyserver_auth_token = | let keyserver_auth_token = | ||||
env::var(AUTH_TOKEN).unwrap_or_else(|_| String::from("test")); | env::var(AUTH_TOKEN).unwrap_or_else(|_| String::from("test")); | ||||
let localstack_endpoint = env::var(LOCALSTACK_ENDPOINT).ok(); | let localstack_endpoint = env::var(LOCALSTACK_ENDPOINT).ok(); | ||||
let mut path = path::PathBuf::new(); | let mut path = path::PathBuf::new(); | ||||
path.push(SECRETS_DIRECTORY); | path.push(SECRETS_DIRECTORY); | ||||
path.push(SECRETS_SETUP_FILE); | path.push(SECRETS_SETUP_FILE); | ||||
let server_setup = get_server_setup_from_file(&path)?; | let server_setup = get_server_setup_from_file(&path)?; | ||||
let reserved_usernames = get_reserved_usernames_set()?; | |||||
Ok(Self { | Ok(Self { | ||||
server_keypair, | server_keypair, | ||||
keyserver_auth_token, | keyserver_auth_token, | ||||
localstack_endpoint, | localstack_endpoint, | ||||
server_setup, | server_setup, | ||||
reserved_usernames, | |||||
}) | }) | ||||
} | } | ||||
} | } | ||||
impl fmt::Debug for Config { | impl fmt::Debug for Config { | ||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
f.debug_struct("Config") | f.debug_struct("Config") | ||||
.field("server_keypair", &"** redacted **") | .field("server_keypair", &"** redacted **") | ||||
.field("keyserver_auth_token", &"** redacted **") | .field("keyserver_auth_token", &"** redacted **") | ||||
.field("localstack_endpoint", &self.localstack_endpoint) | .field("localstack_endpoint", &self.localstack_endpoint) | ||||
.finish() | .finish() | ||||
} | } | ||||
} | } | ||||
#[derive(Debug, derive_more::Display, derive_more::From)] | #[derive(Debug, derive_more::Display, derive_more::From)] | ||||
pub enum Error { | pub enum Error { | ||||
#[display(...)] | #[display(...)] | ||||
Pake(PakeError), | Pake(PakeError), | ||||
#[display(...)] | #[display(...)] | ||||
Opaque(comm_opaque2::ProtocolError), | Opaque(comm_opaque2::ProtocolError), | ||||
#[display(...)] | #[display(...)] | ||||
IO(io::Error), | IO(io::Error), | ||||
#[display(...)] | #[display(...)] | ||||
Env(env::VarError), | Env(env::VarError), | ||||
#[display(...)] | |||||
JSON(serde_json::Error), | |||||
} | } | ||||
fn get_keypair_from_file<P: AsRef<path::Path>>( | fn get_keypair_from_file<P: AsRef<path::Path>>( | ||||
path: P, | path: P, | ||||
) -> Result<KeyPair<RistrettoPoint>, Error> { | ) -> Result<KeyPair<RistrettoPoint>, Error> { | ||||
let bytes = fs::read(path)?; | let bytes = fs::read(path)?; | ||||
KeyPair::from_private_key_slice(&bytes) | KeyPair::from_private_key_slice(&bytes) | ||||
.map_err(|e| Error::Pake(PakeError::CryptoError(e))) | .map_err(|e| Error::Pake(PakeError::CryptoError(e))) | ||||
} | } | ||||
fn get_server_setup_from_file<P: AsRef<path::Path>>( | fn get_server_setup_from_file<P: AsRef<path::Path>>( | ||||
path: &P, | path: &P, | ||||
) -> Result<comm_opaque2::ServerSetup<comm_opaque2::Cipher>, Error> { | ) -> Result<comm_opaque2::ServerSetup<comm_opaque2::Cipher>, Error> { | ||||
let bytes = fs::read(path)?; | let bytes = fs::read(path)?; | ||||
comm_opaque2::ServerSetup::deserialize(&bytes).map_err(Error::Opaque) | comm_opaque2::ServerSetup::deserialize(&bytes).map_err(Error::Opaque) | ||||
} | } | ||||
fn get_reserved_usernames_set() -> Result<HashSet<String>, Error> { | |||||
let contents = include_str!("../reserved_usernames.json"); | |||||
let reserved_usernames: Vec<String> = serde_json::from_str(&contents)?; | |||||
Ok(reserved_usernames.into_iter().collect()) | |||||
} |