2021-05-14 18:38:46 +02:00
|
|
|
//! # Admin keys controller
|
|
|
|
//!
|
|
|
|
//! @author Pierre Hubert
|
|
|
|
|
|
|
|
|
2021-07-11 17:54:15 +02:00
|
|
|
use bcrypt::verify;
|
|
|
|
|
2021-05-14 18:38:46 +02:00
|
|
|
use crate::api_data::admin::admin_auth_success::AdminAuthSuccess;
|
2021-07-10 19:09:54 +02:00
|
|
|
use crate::api_data::admin::admin_keys_api::AdminKeyAPI;
|
|
|
|
use crate::constants::admin::AdminRole;
|
2021-05-14 18:38:46 +02:00
|
|
|
use crate::data::admin::AdminKey;
|
2021-07-10 19:09:54 +02:00
|
|
|
use crate::data::admin_action_log::AdminAction;
|
2021-05-14 18:38:46 +02:00
|
|
|
use crate::data::base_request_handler::BaseRequestHandler;
|
|
|
|
use crate::data::error::Res;
|
|
|
|
use crate::data::http_request_handler::HttpRequestHandler;
|
|
|
|
use crate::data::webauthn_config::get_wan;
|
|
|
|
use crate::helpers::{admin_access_token_helper, admin_account_helper, admin_account_key_helper, admin_key_authentication_challenges_helper, admin_key_registration_challenges_helper};
|
2021-07-10 19:09:54 +02:00
|
|
|
use crate::helpers::admin_log_helper::log_admin_action;
|
2021-05-14 18:38:46 +02:00
|
|
|
use crate::routes::RequestResult;
|
|
|
|
|
|
|
|
impl HttpRequestHandler {
|
|
|
|
pub fn post_admin_auth_key(&mut self, name_mail: &str, name_key_id: &str) -> Res<AdminKey> {
|
|
|
|
let mail = self.post_string(name_mail)?;
|
|
|
|
let key_id = self.post_u64(name_key_id)?;
|
|
|
|
|
|
|
|
let admin = admin_account_helper::find_admin_by_email(&mail)?;
|
|
|
|
let keys = admin_account_key_helper::get_admin_keys(admin.id)?;
|
|
|
|
|
|
|
|
let key = keys.into_iter()
|
|
|
|
.filter(|k| k.id == key_id)
|
|
|
|
.next();
|
|
|
|
|
|
|
|
match key {
|
|
|
|
Some(key) => Ok(key),
|
|
|
|
None => Err(self.bad_request("The key is not associated with this account!".to_string()).unwrap_err())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-14 18:45:48 +02:00
|
|
|
/// Get an admin keys
|
|
|
|
pub fn get_keys_list(r: &mut HttpRequestHandler) -> RequestResult {
|
|
|
|
let admin_id = r.post_admin_id("id")?;
|
|
|
|
|
|
|
|
if admin_id != r.admin_id()? {
|
2021-05-15 10:07:11 +02:00
|
|
|
r.check_admin_has_role(AdminRole::MANAGE_ADMINS)?;
|
2021-05-14 18:45:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
let keys = admin_account_key_helper::get_admin_keys(admin_id)?;
|
|
|
|
|
|
|
|
r.set_response(keys.iter().map(AdminKeyAPI::new).collect::<Vec<AdminKeyAPI>>())
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-14 18:38:46 +02:00
|
|
|
/// Generate a challenge to register a new key
|
|
|
|
pub fn challenge_register_key(r: &mut HttpRequestHandler) -> RequestResult {
|
2022-03-09 18:45:34 +01:00
|
|
|
let wan = get_wan();
|
2021-05-14 18:38:46 +02:00
|
|
|
|
2022-03-09 18:45:34 +01:00
|
|
|
let (res, state) = wan.generate_challenge_register(&r.admin_id()?.id_str(), false)?;
|
2021-05-14 18:38:46 +02:00
|
|
|
|
|
|
|
admin_key_registration_challenges_helper::set(r.admin_id()?, state)?;
|
|
|
|
|
|
|
|
r.set_response(res)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Register key
|
|
|
|
pub fn register_key(r: &mut HttpRequestHandler) -> RequestResult {
|
2021-07-11 13:49:59 +02:00
|
|
|
let key_name = r.post_string("name")?;
|
2021-07-11 17:54:15 +02:00
|
|
|
let key_password = r.post_string("password")?;
|
2021-05-14 18:38:46 +02:00
|
|
|
|
|
|
|
let creds = r.post_register_public_key_credential("key")?;
|
|
|
|
let state = r.some_or_internal_error(
|
|
|
|
admin_key_registration_challenges_helper::get(r.admin_id()?)?,
|
|
|
|
"No challenge found!",
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let wan = get_wan();
|
2022-03-09 18:45:34 +01:00
|
|
|
let key = wan.register_credential(&creds, &state, |_| Ok(false))?;
|
2021-05-14 18:38:46 +02:00
|
|
|
|
2022-03-09 18:45:34 +01:00
|
|
|
let key_id = admin_account_key_helper::add_key(r.admin_id()?, &key_name, key.0, key_password)?;
|
2021-05-14 18:38:46 +02:00
|
|
|
|
2021-07-10 19:09:54 +02:00
|
|
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
2021-07-11 13:49:59 +02:00
|
|
|
AdminAction::RegisteredAdminKey {
|
|
|
|
key_id,
|
|
|
|
key_name,
|
|
|
|
target: r.admin_id()?,
|
|
|
|
})?;
|
2021-07-10 19:09:54 +02:00
|
|
|
|
2021-05-14 18:38:46 +02:00
|
|
|
r.ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Delete an admin auth key
|
|
|
|
pub fn delete_auth_key(r: &mut HttpRequestHandler) -> RequestResult {
|
|
|
|
let admin_id = r.post_admin_id("adminID")?;
|
|
|
|
let key_id = r.post_u64("keyID")?;
|
|
|
|
|
|
|
|
if admin_id != r.admin_id()? {
|
|
|
|
unimplemented!(); // TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
for key in admin_account_key_helper::get_admin_keys(admin_id)? {
|
|
|
|
if key.id == key_id {
|
2021-07-10 19:09:54 +02:00
|
|
|
log_admin_action(r.admin_id()?, &r.remote_ip(),
|
2021-07-11 13:49:59 +02:00
|
|
|
AdminAction::DeletedAdminKey {
|
|
|
|
key_id,
|
|
|
|
key_name: key.name.to_string(),
|
|
|
|
target: admin_id,
|
|
|
|
})?;
|
2021-07-10 19:09:54 +02:00
|
|
|
|
2021-05-14 18:38:46 +02:00
|
|
|
admin_account_key_helper::delete_key(key)?;
|
|
|
|
|
|
|
|
return r.ok();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r.not_found("Requested key was not found!".to_string())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Generate a challenge to authenticate with a security key
|
|
|
|
pub fn challenge_auth_with_key(r: &mut HttpRequestHandler) -> RequestResult {
|
|
|
|
let key = r.post_admin_auth_key("mail", "key_id")?;
|
|
|
|
|
|
|
|
let (challenge_response, auth_state) =
|
2022-03-09 18:45:34 +01:00
|
|
|
get_wan().generate_challenge_authenticate(vec![key.key])?;
|
2021-05-14 18:38:46 +02:00
|
|
|
|
|
|
|
admin_key_authentication_challenges_helper::set(key.id, auth_state)?;
|
|
|
|
|
|
|
|
r.set_response(challenge_response)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Authenticate a user with a security key
|
|
|
|
pub fn auth_with_key(r: &mut HttpRequestHandler) -> RequestResult {
|
|
|
|
let key = r.post_admin_auth_key("mail", "key_id")?;
|
|
|
|
let credentials = r.post_auth_public_key_credential("credential")?;
|
|
|
|
|
|
|
|
let state = r.some_or_internal_error(
|
|
|
|
admin_key_authentication_challenges_helper::get(key.id)?,
|
|
|
|
"Associated authentication state not found!",
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// Perform authentication
|
2022-03-09 18:45:34 +01:00
|
|
|
let state = get_wan().authenticate_credential(&credentials, &state)?;
|
|
|
|
if !state.1.user_present {
|
|
|
|
r.forbidden("Invalid key!".to_string())?;
|
|
|
|
}
|
2021-05-14 18:38:46 +02:00
|
|
|
|
2021-07-11 17:54:15 +02:00
|
|
|
// Check key password (if any)
|
|
|
|
if let Some(pass_hash) = key.password {
|
|
|
|
let password = r.post_string("password")?;
|
|
|
|
|
|
|
|
if !verify(password, &pass_hash)? {
|
|
|
|
r.forbidden("Bad key password!".to_string())?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-14 18:38:46 +02:00
|
|
|
// Generate access token
|
|
|
|
let token = admin_access_token_helper::create(key.admin_id)?;
|
|
|
|
|
2021-07-10 19:09:54 +02:00
|
|
|
log_admin_action(key.admin_id, &r.remote_ip(),
|
|
|
|
AdminAction::AuthWithAccessKey { key: key.name, key_id: key.id })?;
|
|
|
|
|
2021-05-14 18:38:46 +02:00
|
|
|
r.set_response(AdminAuthSuccess::new(token))
|
|
|
|
}
|