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 E981D748CB for ; Tue, 22 Jun 2021 10:56:31 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E755823ED5 for ; Tue, 22 Jun 2021 10:56:31 +0200 (CEST) Received: from dev7.proxmox.com (unknown [94.136.29.99]) by firstgate.proxmox.com (Proxmox) with ESMTP id B05D423E57 for ; Tue, 22 Jun 2021 10:56:28 +0200 (CEST) Received: by dev7.proxmox.com (Postfix, from userid 0) id 84BAB80E27; 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:10 +0200 Message-Id: <20210622085620.1551677-3-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.704 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. [domain.rs, domains.rs, config.rs] Subject: [pbs-devel] [PATH proxmox-backup v1 02/12] config: new domains.cfg to configure openid realm 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:56:32 -0000 Or other realmy types... --- src/api2/access/domain.rs | 21 +++++++ src/config.rs | 1 + src/config/domains.rs | 122 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/config/domains.rs diff --git a/src/api2/access/domain.rs b/src/api2/access/domain.rs index a2fd746d..2dff9d32 100644 --- a/src/api2/access/domain.rs +++ b/src/api2/access/domain.rs @@ -38,10 +38,31 @@ use crate::api2::types::*; )] /// Authentication domain/realm index. fn list_domains() -> Result { + let mut list = Vec::new(); + list.push(json!({ "realm": "pam", "comment": "Linux PAM standard authentication", "default": true })); list.push(json!({ "realm": "pbs", "comment": "Proxmox Backup authentication server" })); + + let (config, _digest) = crate::config::domains::config()?; + + for (realm, (section_type, v)) in config.sections.iter() { + let mut item = json!({ + "type": section_type, + "realm": realm, + }); + + if v["comment"].as_str().is_some() { + item["comment"] = v["comment"].clone(); + } + list.push(item); + + } + Ok(list.into()) + + + } pub const ROUTER: Router = Router::new() diff --git a/src/config.rs b/src/config.rs index b9cd6281..329315ec 100644 --- a/src/config.rs +++ b/src/config.rs @@ -31,6 +31,7 @@ pub mod drive; pub mod media_pool; pub mod tape_encryption_keys; pub mod tape_job; +pub mod domains; /// Check configuration directory permissions /// diff --git a/src/config/domains.rs b/src/config/domains.rs new file mode 100644 index 00000000..ee6fd754 --- /dev/null +++ b/src/config/domains.rs @@ -0,0 +1,122 @@ +use anyhow::{Error}; +use lazy_static::lazy_static; +use std::collections::HashMap; +use serde::{Serialize, Deserialize}; + +use proxmox::api::{ + api, + schema::*, + section_config::{ + SectionConfig, + SectionConfigData, + SectionConfigPlugin, + } +}; + +use proxmox::tools::fs::{ + open_file_locked, + replace_file, + CreateOptions, +}; + +use crate::api2::types::*; + +pub const OPENID_STATE_DIR: &str = "/var/run/proxmox-backup"; + +lazy_static! { + pub static ref CONFIG: SectionConfig = init(); +} + + +#[api( + properties: { + realm: { + schema: REALM_ID_SCHEMA, + }, + "issuer-url": { + description: "OpenID Issuer Url", + type: String, + }, + "client-id": { + description: "OpenID Client ID", + type: String, + }, + "client-key": { + description: "OpenID Client Key", + type: String, + optional: true, + }, + comment: { + optional: true, + schema: SINGLE_LINE_COMMENT_SCHEMA, + }, + }, +)] +#[derive(Serialize,Deserialize)] +#[serde(rename_all="kebab-case")] +/// OpenID configuration properties. +pub struct OpenIdRealmConfig { + pub realm: String, + pub issuer_url: String, + pub client_id: String, + #[serde(skip_serializing_if="Option::is_none")] + pub client_key: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub comment: Option, +} + +fn init() -> SectionConfig { + let obj_schema = match OpenIdRealmConfig::API_SCHEMA { + Schema::Object(ref obj_schema) => obj_schema, + _ => unreachable!(), + }; + + let plugin = SectionConfigPlugin::new("openid".to_string(), Some(String::from("realm")), obj_schema); + let mut config = SectionConfig::new(&REALM_ID_SCHEMA); + config.register_plugin(plugin); + + config +} + +pub const DOMAINS_CFG_FILENAME: &str = "/etc/proxmox-backup/domains.cfg"; +pub const DOMAINS_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.domains.lck"; + +/// Get exclusive lock +pub fn lock_config() -> Result { + open_file_locked(DOMAINS_CFG_LOCKFILE, std::time::Duration::new(10, 0), true) +} + +pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> { + + let content = proxmox::tools::fs::file_read_optional_string(DOMAINS_CFG_FILENAME)? + .unwrap_or_else(|| "".to_string()); + + let digest = openssl::sha::sha256(content.as_bytes()); + let data = CONFIG.parse(DOMAINS_CFG_FILENAME, &content)?; + Ok((data, digest)) +} + +pub fn save_config(config: &SectionConfigData) -> Result<(), Error> { + let raw = CONFIG.write(DOMAINS_CFG_FILENAME, &config)?; + + let backup_user = crate::backup::backup_user()?; + let mode = nix::sys::stat::Mode::from_bits_truncate(0o0640); + // set the correct owner/group/permissions while saving file + // owner(rw) = root, group(r)= backup + let options = CreateOptions::new() + .perm(mode) + .owner(nix::unistd::ROOT) + .group(backup_user.gid); + + replace_file(DOMAINS_CFG_FILENAME, raw.as_bytes(), options)?; + + Ok(()) +} + +// shell completion helper +pub fn complete_realm_name(_arg: &str, _param: &HashMap) -> Vec { + match config() { + Ok((data, _digest)) => data.sections.iter().map(|(id, _)| id.to_string()).collect(), + Err(_) => return vec![], + } +} -- 2.30.2