From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 76EDD74966 for ; Tue, 22 Jun 2021 10:57:05 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 7DAAA24037 for ; Tue, 22 Jun 2021 10:56:34 +0200 (CEST) Received: from dev7.proxmox.com (unknown [94.136.29.99]) by firstgate.proxmox.com (Proxmox) with ESMTP id DE90A23E6B for ; Tue, 22 Jun 2021 10:56:28 +0200 (CEST) Received: by dev7.proxmox.com (Postfix, from userid 0) id 9C21A80F5E; Tue, 22 Jun 2021 10:56:22 +0200 (CEST) From: Dietmar Maurer To: pbs-devel@lists.proxmox.com Date: Tue, 22 Jun 2021 10:56:19 +0200 Message-Id: <20210622085620.1551677-12-dietmar@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210622085620.1551677-1-dietmar@proxmox.com> References: <20210622085620.1551677-1-dietmar@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.688 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [access.rs, openid.rs, domains.rs] Subject: [pbs-devel] [PATH proxmox-backup v1 11/12] add openid autocreate account feature X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Jun 2021 08:57:05 -0000 --- src/api2/access.rs | 25 ++++++++++++++++++++++++- src/api2/config/access/openid.rs | 10 ++++++++++ src/config/domains.rs | 8 ++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/api2/access.rs b/src/api2/access.rs index e95db88b..115779f3 100644 --- a/src/api2/access.rs +++ b/src/api2/access.rs @@ -11,6 +11,7 @@ use proxmox::api::router::{Router, SubdirMap}; use proxmox::api::{api, Permission, RpcEnvironment}; use proxmox::{http_err, list_subdirs_api_method}; use proxmox::{identity, sortable}; +use proxmox::tools::fs::open_file_locked; use proxmox_openid::OpenIdAuthenticator; @@ -306,7 +307,29 @@ pub fn openid_login( let user_id = Userid::try_from(format!("{}@{}", unique_name, realm))?; if !user_info.is_active_user_id(&user_id) { - bail!("user account '{}' disabled or expired.", user_id); + if config.autocreate.unwrap_or(false) { + use crate::config::user; + let _lock = open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0), true)?; + let user = user::User { + userid: user_id.clone(), + comment: None, + enable: None, + expire: None, + firstname: info.given_name().and_then(|n| n.get(None)).map(|n| n.to_string()), + lastname: info.family_name().and_then(|n| n.get(None)).map(|n| n.to_string()), + email: info.email().map(|e| e.to_string()), + }; + let (mut config, _digest) = user::config()?; + if config.sections.get(user.userid.as_str()).is_some() { + bail!("autocreate user failed - '{}' already exists.", user.userid); + } + config.set_data(user.userid.as_str(), "user", &user)?; + user::save_config(&config)?; + // fixme: replace sleep with shared memory change notification + std::thread::sleep(std::time::Duration::new(6, 0)); + } else { + bail!("user account '{}' missing, disabled or expired.", user_id); + } } let api_ticket = ApiTicket::full(user_id.clone()); diff --git a/src/api2/config/access/openid.rs b/src/api2/config/access/openid.rs index 15fddaf0..9325de94 100644 --- a/src/api2/config/access/openid.rs +++ b/src/api2/config/access/openid.rs @@ -153,6 +153,8 @@ pub enum DeletableProperty { client_key, /// Delete the comment property. comment, + /// Delete the autocreate property + autocreate, } #[api( @@ -177,6 +179,11 @@ pub enum DeletableProperty { type: String, optional: true, }, + autocreate: { + description: "Automatically create users if they do not exist.", + optional: true, + type: bool, + }, comment: { schema: SINGLE_LINE_COMMENT_SCHEMA, optional: true, @@ -206,6 +213,7 @@ pub fn update_openid_realm( issuer_url: Option, client_id: Option, client_key: Option, + autocreate: Option, comment: Option, delete: Option>, digest: Option, @@ -228,6 +236,7 @@ pub fn update_openid_realm( match delete_prop { DeletableProperty::client_key => { config.client_key = None; }, DeletableProperty::comment => { config.comment = None; }, + DeletableProperty::autocreate => { config.autocreate = None; }, } } } @@ -245,6 +254,7 @@ pub fn update_openid_realm( if let Some(client_id) = client_id { config.client_id = client_id; } if client_key.is_some() { config.client_key = client_key; } + if autocreate.is_some() { config.autocreate = autocreate; } domains.set_data(&realm, "openid", &config)?; diff --git a/src/config/domains.rs b/src/config/domains.rs index 007cf357..7db1f0be 100644 --- a/src/config/domains.rs +++ b/src/config/domains.rs @@ -52,6 +52,12 @@ lazy_static! { optional: true, schema: SINGLE_LINE_COMMENT_SCHEMA, }, + autocreate: { + description: "Automatically create users if they do not exist.", + optional: true, + type: bool, + default: false, + }, }, )] #[derive(Serialize,Deserialize)] @@ -65,6 +71,8 @@ pub struct OpenIdRealmConfig { pub client_key: Option, #[serde(skip_serializing_if="Option::is_none")] pub comment: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub autocreate: Option, } impl OpenIdRealmConfig { -- 2.30.2