From d9f659ce9875b26130dbee875a54c3b55cb26daf Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Mon, 24 Apr 2023 15:43:49 +0200 Subject: [PATCH] Add basic providers configuration --- src/constants.rs | 3 ++ src/controllers/admin_controller.rs | 22 ++++++++ src/data/app_config.rs | 6 ++- src/data/mod.rs | 1 + src/data/provider.rs | 60 ++++++++++++++++++++++ src/main.rs | 11 ++++ templates/settings/base_settings_page.html | 8 ++- templates/settings/providers_list.html | 27 ++++++++++ 8 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/data/provider.rs create mode 100644 templates/settings/providers_list.html diff --git a/src/constants.rs b/src/constants.rs index a8fc7ef..37b372b 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -6,6 +6,9 @@ pub const USERS_LIST_FILE: &str = "users.json"; /// File in storage containing clients list pub const CLIENTS_LIST_FILE: &str = "clients.yaml"; +/// File in storage containing providers list +pub const PROVIDERS_LIST_FILE: &str = "providers.yaml"; + /// Default built-in credentials pub const DEFAULT_ADMIN_USERNAME: &str = "admin"; pub const DEFAULT_ADMIN_PASSWORD: &str = "admin"; diff --git a/src/controllers/admin_controller.rs b/src/controllers/admin_controller.rs index c6955c2..445abe0 100644 --- a/src/controllers/admin_controller.rs +++ b/src/controllers/admin_controller.rs @@ -12,6 +12,7 @@ use crate::controllers::settings_controller::BaseSettingsPage; use crate::data::action_logger::{Action, ActionLogger}; use crate::data::client::{Client, ClientID, ClientManager}; use crate::data::current_user::CurrentUser; +use crate::data::provider::{Provider, ProvidersManager}; use crate::data::user::{GeneralSettings, GrantedClients, User, UserID}; use crate::utils::string_utils::rand_str; @@ -22,6 +23,13 @@ struct ClientsListTemplate { clients: Vec, } +#[derive(Template)] +#[template(path = "settings/providers_list.html")] +struct ProvidersListTemplate { + _p: BaseSettingsPage, + providers: Vec, +} + #[derive(Template)] #[template(path = "settings/users_list.html")] struct UsersListTemplate { @@ -51,6 +59,20 @@ pub async fn clients_route( ) } +pub async fn providers_route( + user: CurrentUser, + providers: web::Data>, +) -> impl Responder { + HttpResponse::Ok().body( + ProvidersListTemplate { + _p: BaseSettingsPage::get("OpenID Providers list", &user, None, None), + providers: providers.cloned(), + } + .render() + .unwrap(), + ) +} + #[derive(serde::Deserialize, Debug)] pub struct UpdateUserQuery { uid: UserID, diff --git a/src/data/app_config.rs b/src/data/app_config.rs index f5298b5..791a46a 100644 --- a/src/data/app_config.rs +++ b/src/data/app_config.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; use clap::Parser; -use crate::constants::{APP_NAME, CLIENTS_LIST_FILE, USERS_LIST_FILE}; +use crate::constants::{APP_NAME, CLIENTS_LIST_FILE, PROVIDERS_LIST_FILE, USERS_LIST_FILE}; /// Basic OIDC provider #[derive(Parser, Debug, Clone)] @@ -72,6 +72,10 @@ impl AppConfig { self.storage_path().join(CLIENTS_LIST_FILE) } + pub fn providers_file(&self) -> PathBuf { + self.storage_path().join(PROVIDERS_LIST_FILE) + } + pub fn full_url(&self, uri: &str) -> String { if uri.starts_with('/') { format!("{}{}", self.website_origin, uri) diff --git a/src/data/mod.rs b/src/data/mod.rs index 7e431b6..d0df343 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -11,6 +11,7 @@ pub mod jwt_signer; pub mod login_redirect; pub mod open_id_user_info; pub mod openid_config; +pub mod provider; pub mod remote_ip; pub mod session_identity; pub mod totp_key; diff --git a/src/data/provider.rs b/src/data/provider.rs new file mode 100644 index 0000000..ab51109 --- /dev/null +++ b/src/data/provider.rs @@ -0,0 +1,60 @@ +use crate::data::entity_manager::EntityManager; +use crate::utils::string_utils::apply_env_vars; + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq)] +pub struct ProviderID(pub String); + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub struct Provider { + /// The ID of the provider + pub id: ProviderID, + + /// The human-readable name of the client + pub name: String, + + /// A logo presented to the users of the provider + pub logo: String, + + /// The registration id of BasicOIDC on the provider + pub client_id: String, + + /// The registration secret of BasicOIDC on the provider + pub client_secret: String, + + /// Specify the URL of the OpenID configuration URL + /// + /// (.well-known/openid-configuration endpoint) + pub configuration_url: String, +} + +impl PartialEq for Provider { + fn eq(&self, other: &Self) -> bool { + self.id.eq(&other.id) + } +} + +impl Eq for Provider {} + +pub type ProvidersManager = EntityManager; + +impl EntityManager { + pub fn find_by_id(&self, u: &ProviderID) -> Option { + for entry in self.iter() { + if entry.id.eq(u) { + return Some(entry.clone()); + } + } + None + } + + pub fn apply_environment_variables(&mut self) { + for c in self.iter_mut() { + c.id = ProviderID(apply_env_vars(&c.id.0)); + c.name = apply_env_vars(&c.name); + c.logo = apply_env_vars(&c.logo); + c.client_id = apply_env_vars(&c.client_id); + c.client_secret = apply_env_vars(&c.client_secret); + c.configuration_url = apply_env_vars(&c.configuration_url); + } + } +} diff --git a/src/main.rs b/src/main.rs index 975590c..11bb727 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ use basic_oidc::data::app_config::AppConfig; use basic_oidc::data::client::ClientManager; use basic_oidc::data::entity_manager::EntityManager; use basic_oidc::data::jwt_signer::JWTSigner; +use basic_oidc::data::provider::ProvidersManager; use basic_oidc::data::user::User; use basic_oidc::data::webauthn_manager::WebAuthManager; use basic_oidc::middlewares::auth_middleware::AuthMiddleware; @@ -77,6 +78,11 @@ async fn main() -> std::io::Result<()> { clients.apply_environment_variables(); let clients = Arc::new(clients); + let mut providers = ProvidersManager::open_or_create(config.providers_file()) + .expect("Failed to load providers list!"); + providers.apply_environment_variables(); + let providers = Arc::new(providers); + log::info!("Server will listen on {}", config.listen_address); let listen_address = config.listen_address.to_string(); @@ -101,6 +107,7 @@ async fn main() -> std::io::Result<()> { .app_data(web::Data::new(bruteforce_actor.clone())) .app_data(web::Data::new(openid_sessions_actor.clone())) .app_data(web::Data::new(clients.clone())) + .app_data(web::Data::new(providers.clone())) .app_data(web::Data::new(jwt_signer.clone())) .app_data(web::Data::new(webauthn_manager.clone())) .wrap( @@ -207,6 +214,10 @@ async fn main() -> std::io::Result<()> { "/admin/clients", web::get().to(admin_controller::clients_route), ) + .route( + "/admin/providers", + web::get().to(admin_controller::providers_route), + ) .route("/admin/users", web::get().to(admin_controller::users_route)) .route( "/admin/users", diff --git a/templates/settings/base_settings_page.html b/templates/settings/base_settings_page.html index 88328b7..a99ec21 100644 --- a/templates/settings/base_settings_page.html +++ b/templates/settings/base_settings_page.html @@ -15,7 +15,7 @@ {{ _p.app_name }} {% if _p.is_admin %} - Version {{ _p.version }} + Version {{ _p.version }} {% endif %}