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

Run OPA policies during registration

This commit is contained in:
Quentin Gliech
2022-06-02 11:07:00 +02:00
parent 9ebff410d1
commit a2b53f0395
5 changed files with 86 additions and 2 deletions

View File

@ -14,7 +14,7 @@
#![allow(clippy::trait_duplication_in_bounds)]
use std::str::FromStr;
use std::{str::FromStr, sync::Arc};
use argon2::Argon2;
use axum::{
@ -29,6 +29,7 @@ use mas_axum_utils::{
};
use mas_config::Encrypter;
use mas_email::Mailer;
use mas_policy::PolicyFactory;
use mas_router::Route;
use mas_storage::user::{
add_user_email, add_user_email_verification_code, register_user, start_session, username_exists,
@ -87,6 +88,7 @@ pub(crate) async fn get(
pub(crate) async fn post(
Extension(mailer): Extension<Mailer>,
Extension(policy_factory): Extension<Arc<PolicyFactory>>,
Extension(templates): Extension<Templates>,
Extension(pool): Extension<PgPool>,
Query(query): Query<OptionalPostAuthAction>,
@ -129,6 +131,15 @@ pub(crate) async fn post(
state.add_error_on_field(RegisterFormField::PasswordConfirm, FieldError::Unspecified);
}
let mut policy = policy_factory.instanciate().await?;
let res = policy
.evaluate_register(&form.username, &form.email)
.await?;
if !res {
state.add_error_on_form(FormError::Policy);
}
state
};

View File

@ -52,6 +52,9 @@ pub enum FormError {
/// There was an internal error
Internal,
/// Denied by the policy
Policy,
}
#[derive(Debug, Default, Serialize)]

Binary file not shown.

View File

@ -1,3 +1,41 @@
package register
allow := true
import future.keywords.in
default allow := false
allow := true {
count(violation) == 0
}
violation[{"field": "username", "msg": "username too short"}] {
count(input.user.username) <= 2
}
violation[{"field": "username", "msg": "username too long"}] {
count(input.user.username) >= 15
}
# Allow any domains if the data.allowed_domains array is not set
email_domain_allowed {
not data.allowed_domains
}
# Allow an email only if its domain is in the list of allowed domains
email_domain_allowed {
[_, domain] := split(input.user.email, "@")
some allowed_domain in data.allowed_domains
glob.match(allowed_domain, ["."], domain)
}
violation[{"field": "email", "msg": "email domain not allowed"}] {
not email_domain_allowed
}
# Deny emails with their domain in the domains banlist
violation[{"field": "email", "msg": "email domain not allowed"}] {
[_, domain] := split(input.user.email, "@")
some banned_domain in data.banned_domains
glob.match(banned_domain, ["."], domain)
}

View File

@ -0,0 +1,32 @@
package register
mock_user := {"username": "hello", "email": "hello@staging.element.io"}
test_allow_all_domains {
allow with input.user as mock_user
}
test_allowed_domain {
allow
with input.user as mock_user
with data.allowed_domains as ["*.element.io"]
}
test_not_allowed_domain {
not allow
with input.user as mock_user
with data.allowed_domains as ["example.com"]
}
test_banned_domain {
not allow
with input.user as mock_user
with data.banned_domains as ["*.element.io"]
}
test_banned_subdomain {
not allow
with input.user as mock_user
with data.allowed_domains as ["*.element.io"]
with data.banned_domains as ["staging.element.io"]
}