1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2024-11-26 15:29:21 +00:00

Can generate admin key enrollment challenge

This commit is contained in:
Pierre HUBERT 2021-05-14 09:30:59 +02:00
parent 158d35171d
commit 70860ab184
11 changed files with 147 additions and 11 deletions

45
Cargo.lock generated
View File

@ -816,6 +816,7 @@ dependencies = [
"serde_json", "serde_json",
"sha1", "sha1",
"tokio 0.2.25", "tokio 0.2.25",
"webauthn-rs",
"webpage", "webpage",
"webrtc-sdp", "webrtc-sdp",
"yaml-rust", "yaml-rust",
@ -1401,6 +1402,12 @@ dependencies = [
"tracing-futures", "tracing-futures",
] ]
[[package]]
name = "half"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.9.1" version = "0.9.1"
@ -2948,6 +2955,25 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde_bytes"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9"
dependencies = [
"serde",
]
[[package]]
name = "serde_cbor"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
dependencies = [
"half",
"serde",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.123" version = "1.0.123"
@ -3798,6 +3824,25 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "webauthn-rs"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca232368e409a186d2cc0a83380398429a5b6c39608143c2a9bcc16e96b08d0"
dependencies = [
"base64 0.12.3",
"log",
"nom",
"openssl",
"rand 0.7.3",
"serde",
"serde_bytes",
"serde_cbor",
"serde_derive",
"serde_json",
"thiserror",
]
[[package]] [[package]]
name = "webpage" name = "webpage"
version = "1.2.0" version = "1.2.0"

View File

@ -41,3 +41,4 @@ zip = "0.5.10"
webpage = "1.2.0" webpage = "1.2.0"
gouth = "0.2.0" gouth = "0.2.0"
tokio = { version = "0.2" } tokio = { version = "0.2" }
webauthn-rs = "0.2.5"

View File

@ -2,6 +2,8 @@
//! //!
//! @author Pierre Hubert //! @author Pierre Hubert
use crate::api_data::admin::admin_auth_options::AdminAuthOptions; use crate::api_data::admin::admin_auth_options::AdminAuthOptions;
use crate::api_data::admin::admin_auth_success::AdminAuthSuccess; use crate::api_data::admin::admin_auth_success::AdminAuthSuccess;
use crate::api_data::admin::admin_id_api::AdminIDAPI; use crate::api_data::admin::admin_id_api::AdminIDAPI;
@ -9,7 +11,8 @@ use crate::api_data::admin::admin_info_api::AdminInfoAPI;
use crate::data::admin::NewAdminGeneralSettings; use crate::data::admin::NewAdminGeneralSettings;
use crate::data::base_request_handler::BaseRequestHandler; use crate::data::base_request_handler::BaseRequestHandler;
use crate::data::http_request_handler::HttpRequestHandler; use crate::data::http_request_handler::HttpRequestHandler;
use crate::helpers::{admin_access_token_helper, admin_account_helper}; use crate::data::webauthn_config::get_wan;
use crate::helpers::{admin_access_token_helper, admin_account_helper, admin_key_registration_challenges_helper};
use crate::routes::RequestResult; use crate::routes::RequestResult;
use crate::utils::date_utils::time; use crate::utils::date_utils::time;
@ -90,3 +93,14 @@ pub fn update_general_settings(r: &mut HttpRequestHandler) -> RequestResult {
r.ok() r.ok()
} }
/// Generate a challenge to register a new key
pub fn challenge_register_key(r: &mut HttpRequestHandler) -> RequestResult {
let mut wan = get_wan();
let (res, state) = wan.generate_challenge_register(&r.admin_id()?.id_str(), None)?;
admin_key_registration_challenges_helper::set(r.admin_id()?, state)?;
r.set_response(res)
}

View File

@ -13,6 +13,10 @@ impl AdminID {
pub fn id(&self) -> u64 { pub fn id(&self) -> u64 {
self.0 self.0
} }
pub fn id_str(&self) -> String {
format!("{}", self.0)
}
} }
pub struct NewAdmin { pub struct NewAdmin {
@ -47,12 +51,12 @@ pub struct AdminKey {
pub struct AdminAccessToken { pub struct AdminAccessToken {
pub token: String, pub token: String,
pub id: AdminID, pub id: AdminID,
pub last_refresh: u64 pub last_refresh: u64,
} }
/// New admin general settings /// New admin general settings
pub struct NewAdminGeneralSettings { pub struct NewAdminGeneralSettings {
pub id: AdminID, pub id: AdminID,
pub name: String, pub name: String,
pub email: String pub email: String,
} }

View File

@ -42,3 +42,4 @@ pub mod new_notifications_settings;
pub mod push_notification; pub mod push_notification;
pub mod presence; pub mod presence;
pub mod admin; pub mod admin;
pub mod webauthn_config;

View File

@ -0,0 +1,36 @@
//! # Webauthn config
//!
//! @author Pierre Hubert
use webauthn_rs::{Webauthn, WebauthnConfig};
use crate::data::config::conf;
pub struct ComunicAdminWebauthnConfig {}
impl WebauthnConfig for ComunicAdminWebauthnConfig {
fn get_relying_party_name(&self) -> String {
"ComunicAdmin".to_string()
}
fn get_origin(&self) -> &String {
&conf().admin_url
}
fn get_relying_party_id(&self) -> String {
self.get_origin()
.replace("https://", "")
.replace("http://", "")
.split(":")
.next()
.unwrap()
.split("/")
.next()
.unwrap()
.to_string()
}
}
pub fn get_wan() -> Webauthn<ComunicAdminWebauthnConfig> {
Webauthn::new(ComunicAdminWebauthnConfig {})
}

View File

@ -13,7 +13,7 @@ use crate::utils::date_utils::time;
static mut CACHE: Option<Arc<Mutex<HashMap<AdminID, AdminAccessToken>>>> = None; static mut CACHE: Option<Arc<Mutex<HashMap<AdminID, AdminAccessToken>>>> = None;
/// Initialize this helper /// Initialize this helper's cache
pub fn init() { pub fn init() {
unsafe { unsafe {
let map = HashMap::new(); let map = HashMap::new();

View File

@ -0,0 +1,34 @@
//! # Administrators key registration challenges helper
//!
//! Allows to temporarily stores keys registration challenges
//!
//! @author Pierre Hubert
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use webauthn_rs::RegistrationState;
use crate::data::admin::AdminID;
use crate::data::error::Res;
static mut CACHE: Option<Arc<Mutex<HashMap<AdminID, RegistrationState>>>> = None;
/// Initialize this helper's cache
pub fn init() {
unsafe {
let map = HashMap::new();
CACHE = Some(Arc::new(Mutex::new(map)));
}
}
/// Store a new entry in the cache
pub fn set(admin: AdminID, key: RegistrationState) -> Res {
let cache = unsafe {
CACHE.as_ref().unwrap().lock()
};
cache?.insert(admin, key);
Ok(())
}

View File

@ -24,3 +24,4 @@ pub mod firebase_notifications_helper;
pub mod forez_presence_helper; pub mod forez_presence_helper;
pub mod admin_account_helper; pub mod admin_account_helper;
pub mod admin_access_token_helper; pub mod admin_access_token_helper;
pub mod admin_key_registration_challenges_helper;

View File

@ -353,5 +353,6 @@ pub fn get_routes() -> Vec<Route> {
Route::admin_post("/admin/accounts/id", Box::new(admin_account_controller::get_admin_id)), Route::admin_post("/admin/accounts/id", Box::new(admin_account_controller::get_admin_id)),
Route::admin_post("/admin/accounts/info", Box::new(admin_account_controller::get_admin_info)), Route::admin_post("/admin/accounts/info", Box::new(admin_account_controller::get_admin_info)),
Route::admin_post("/admin/accounts/update_general_settings", Box::new(admin_account_controller::update_general_settings)), Route::admin_post("/admin/accounts/update_general_settings", Box::new(admin_account_controller::update_general_settings)),
Route::admin_post("/admin/accounts/challenge_register_key", Box::new(admin_account_controller::challenge_register_key))
] ]
} }

View File

@ -17,7 +17,7 @@ use crate::controllers::{rtc_relay_controller, user_ws_controller};
use crate::data::base_request_handler::{BaseRequestHandler, PostFile, RequestValue}; use crate::data::base_request_handler::{BaseRequestHandler, PostFile, RequestValue};
use crate::data::config::Config; use crate::data::config::Config;
use crate::data::http_request_handler::HttpRequestHandler; use crate::data::http_request_handler::HttpRequestHandler;
use crate::helpers::{api_helper, requests_limit_helper, admin_access_token_helper}; use crate::helpers::{admin_access_token_helper, admin_key_registration_challenges_helper, api_helper, requests_limit_helper};
use crate::routes::{get_routes, RequestResult, Route, RouteScope}; use crate::routes::{get_routes, RequestResult, Route, RouteScope};
use crate::routes::Method::{GET, POST}; use crate::routes::Method::{GET, POST};
use crate::utils::user_data_utils::user_data_path; use crate::utils::user_data_utils::user_data_path;
@ -221,7 +221,7 @@ fn process_simple_route(route: &Route, req: &mut HttpRequestHandler) -> RequestR
if route.need_login || req.has_post_parameter("token") { if route.need_login || req.has_post_parameter("token") {
req.check_user_token()?; req.check_user_token()?;
} }
}, }
// "Admin" user scope // "Admin" user scope
RouteScope::ADMIN => { RouteScope::ADMIN => {
@ -234,7 +234,6 @@ fn process_simple_route(route: &Route, req: &mut HttpRequestHandler) -> RequestR
} }
let res: RequestResult = (route.func)(req); let res: RequestResult = (route.func)(req);
requests_limit_helper::trigger_after(res.is_ok(), req, route)?; requests_limit_helper::trigger_after(res.is_ok(), req, route)?;
@ -350,8 +349,8 @@ pub async fn start_server(conf: &Config) -> std::io::Result<()> {
// Initialize limit helper // Initialize limit helper
requests_limit_helper::init(); requests_limit_helper::init();
admin_access_token_helper::init(); admin_access_token_helper::init();
admin_key_registration_challenges_helper::init();
let addr = conf.server_listen_address(); let addr = conf.server_listen_address();
println!("Start to listen on http://{}/", addr); println!("Start to listen on http://{}/", addr);