1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Password schemes configuration

This commit is contained in:
Quentin Gliech
2022-12-13 15:51:23 +01:00
parent a6c3951d8c
commit ff2f009b0e
5 changed files with 140 additions and 3 deletions

View File

@ -20,7 +20,7 @@ use futures_util::stream::{StreamExt, TryStreamExt};
use itertools::Itertools;
use mas_config::RootConfig;
use mas_email::Mailer;
use mas_handlers::{AppState, HttpClientFactory, MatrixHomeserver};
use mas_handlers::{passwords::PasswordManager, AppState, HttpClientFactory, MatrixHomeserver};
use mas_listener::{server::Server, shutdown::ShutdownStream};
use mas_policy::PolicyFactory;
use mas_router::UrlBuilder;
@ -168,6 +168,24 @@ impl Options {
let listeners_config = config.http.listeners.clone();
let password_manager = config
.passwords
.load()
.await
.context("failed to load the password schemes")?
.into_iter()
.map(|(version, algorithm, secret)| {
use mas_handlers::passwords::Hasher;
let hasher = match algorithm {
mas_config::PasswordAlgorithm::Pbkdf2 => Hasher::pbkdf2(secret),
mas_config::PasswordAlgorithm::Bcrypt { cost } => Hasher::bcrypt(cost, secret),
mas_config::PasswordAlgorithm::Argon2id => Hasher::argon2id(secret),
};
(version, hasher)
});
let password_manager = PasswordManager::new(password_manager)?;
// Explicitely the config to properly zeroize secret keys
drop(config);
@ -199,6 +217,7 @@ impl Options {
policy_factory,
graphql_schema,
http_client_factory,
password_manager,
};
let mut fd_manager = listenfd::ListenFd::from_env();

View File

@ -23,6 +23,7 @@ mod database;
mod email;
mod http;
mod matrix;
mod passwords;
mod policy;
mod secrets;
mod telemetry;
@ -38,6 +39,7 @@ pub use self::{
Resource as HttpResource, TlsConfig as HttpTlsConfig, UnixOrTcp,
},
matrix::MatrixConfig,
passwords::{Algorithm as PasswordAlgorithm, PasswordsConfig},
policy::PolicyConfig,
secrets::SecretsConfig,
telemetry::{
@ -82,6 +84,10 @@ pub struct RootConfig {
/// Application secrets
pub secrets: SecretsConfig,
/// Configuration related to user passwords
#[serde(default)]
pub passwords: PasswordsConfig,
/// Configuration related to the homeserver
#[serde(default)]
pub matrix: MatrixConfig,
@ -109,6 +115,7 @@ impl ConfigurationSection<'_> for RootConfig {
templates: TemplatesConfig::generate(&mut rng).await?,
csrf: CsrfConfig::generate(&mut rng).await?,
email: EmailConfig::generate(&mut rng).await?,
passwords: PasswordsConfig::generate(&mut rng).await?,
secrets: SecretsConfig::generate(&mut rng).await?,
matrix: MatrixConfig::generate(&mut rng).await?,
policy: PolicyConfig::generate(&mut rng).await?,
@ -122,6 +129,7 @@ impl ConfigurationSection<'_> for RootConfig {
database: DatabaseConfig::test(),
telemetry: TelemetryConfig::test(),
templates: TemplatesConfig::test(),
passwords: PasswordsConfig::test(),
csrf: CsrfConfig::test(),
email: EmailConfig::test(),
secrets: SecretsConfig::test(),

View File

@ -23,7 +23,7 @@ use mas_router::UrlBuilder;
use mas_templates::Templates;
use sqlx::PgPool;
use crate::MatrixHomeserver;
use crate::{passwords::PasswordManager, MatrixHomeserver};
#[derive(Clone)]
pub struct AppState {
@ -37,6 +37,7 @@ pub struct AppState {
pub policy_factory: Arc<PolicyFactory>,
pub graphql_schema: mas_graphql::Schema,
pub http_client_factory: HttpClientFactory,
pub password_manager: PasswordManager,
}
impl FromRef<AppState> for PgPool {
@ -92,8 +93,15 @@ impl FromRef<AppState> for Arc<PolicyFactory> {
input.policy_factory.clone()
}
}
impl FromRef<AppState> for HttpClientFactory {
fn from_ref(input: &AppState) -> Self {
input.http_client_factory.clone()
}
}
impl FromRef<AppState> for PasswordManager {
fn from_ref(input: &AppState) -> Self {
input.password_manager.clone()
}
}

View File

@ -21,7 +21,7 @@ use pbkdf2::Pbkdf2;
use rand::{CryptoRng, Rng, RngCore, SeedableRng};
use zeroize::Zeroizing;
pub type SchemeVersion = u32;
pub type SchemeVersion = u16;
#[derive(Clone)]
pub struct PasswordManager {

View File

@ -128,6 +128,22 @@
}
]
},
"passwords": {
"description": "Configuration related to user passwords",
"default": {
"schemes": [
{
"algorithm": "argon2id",
"version": 1
}
]
},
"allOf": [
{
"$ref": "#/definitions/PasswordsConfig"
}
]
},
"policy": {
"description": "Configuration related to the OPA policies",
"default": {
@ -647,6 +663,74 @@
}
]
},
"HashingScheme": {
"description": "A hashing algorithm",
"type": "object",
"oneOf": [
{
"description": "bcrypt",
"type": "object",
"required": [
"algorithm"
],
"properties": {
"algorithm": {
"type": "string",
"enum": [
"bcrypt"
]
},
"cost": {
"description": "Hashing cost",
"default": 12,
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
}
},
{
"description": "argon2id",
"type": "object",
"required": [
"algorithm"
],
"properties": {
"algorithm": {
"type": "string",
"enum": [
"argon2id"
]
}
}
},
{
"description": "PBKDF2",
"type": "object",
"required": [
"algorithm"
],
"properties": {
"algorithm": {
"type": "string",
"enum": [
"pbkdf2"
]
}
}
}
],
"required": [
"version"
],
"properties": {
"version": {
"type": "integer",
"format": "uint16",
"minimum": 0.0
}
}
},
"HttpConfig": {
"description": "Configuration related to the web server",
"type": "object",
@ -1209,6 +1293,24 @@
}
]
},
"PasswordsConfig": {
"description": "User password hashing config",
"type": "object",
"properties": {
"schemes": {
"default": [
{
"algorithm": "argon2id",
"version": 1
}
],
"type": "array",
"items": {
"$ref": "#/definitions/HashingScheme"
}
}
}
},
"PolicyConfig": {
"description": "Application secrets",
"type": "object",