public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Shannon Sterz <s.sterz@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH datacenter-manager v2 1/2] server/api-types: move AccessControlConfig to shared api types
Date: Wed, 22 Oct 2025 15:11:23 +0200	[thread overview]
Message-ID: <20251022131126.358790-8-s.sterz@proxmox.com> (raw)
In-Reply-To: <20251022131126.358790-1-s.sterz@proxmox.com>

this doesn't really contain any information that is secret. moving it
to the shared api types allows re-using it in the ui to check what
privileges a user needs to access certain features.

Signed-off-by: Shannon Sterz <s.sterz@proxmox.com>
---
 lib/pdm-api-types/Cargo.toml |   1 +
 lib/pdm-api-types/src/acl.rs | 158 ++++++++++++++++++++++++++++++++++
 server/src/acl.rs            | 162 +----------------------------------
 3 files changed, 161 insertions(+), 160 deletions(-)

diff --git a/lib/pdm-api-types/Cargo.toml b/lib/pdm-api-types/Cargo.toml
index e66558b..4b0edde 100644
--- a/lib/pdm-api-types/Cargo.toml
+++ b/lib/pdm-api-types/Cargo.toml
@@ -14,6 +14,7 @@ serde.workspace = true
 serde_plain.workspace = true
 
 proxmox-acme-api.workspace = true
+proxmox-access-control.workspace = true
 proxmox-auth-api = { workspace = true, features = ["api-types"] }
 proxmox-lang.workspace = true
 proxmox-config-digest.workspace = true
diff --git a/lib/pdm-api-types/src/acl.rs b/lib/pdm-api-types/src/acl.rs
index 9e69c2f..baba3da 100644
--- a/lib/pdm-api-types/src/acl.rs
+++ b/lib/pdm-api-types/src/acl.rs
@@ -1,6 +1,12 @@
+use std::collections::HashMap;
 use std::str::FromStr;
+use std::sync::LazyLock;
 
+use anyhow::{format_err, Context, Error};
 use const_format::concatcp;
+use proxmox_access_control::types::User;
+use proxmox_auth_api::types::Authid;
+use proxmox_section_config::SectionConfigData;
 use serde::de::{value, IntoDeserializer};
 use serde::{Deserialize, Serialize};
 
@@ -179,3 +185,155 @@ pub struct AclListItem {
     pub propagate: bool,
     pub roleid: String,
 }
+
+pub struct AccessControlConfig;
+
+impl proxmox_access_control::init::AccessControlConfig for AccessControlConfig {
+    fn privileges(&self) -> &HashMap<&str, u64> {
+        static PRIVS: LazyLock<HashMap<&str, u64>> =
+            LazyLock::new(|| PRIVILEGES.iter().copied().collect());
+
+        &PRIVS
+    }
+
+    #[rustfmt::skip]
+    fn roles(&self) -> &HashMap<&str, (u64, &str)> {
+        static ROLES: LazyLock<HashMap<&str, (u64, &str)>> = LazyLock::new(|| {
+            [
+                ("Administrator", (ROLE_ADMINISTRATOR, "Administrators can inspect and modify the system.")),
+                ("Auditor", (ROLE_AUDITOR, "An Auditor can inspect many aspects of the system, but not change them.")),
+                //("SystemAdministrator", pdm_api_types::ROLE_SYS_ADMINISTRATOR),
+                //("SystemAuditor", pdm_api_types::ROLE_SYS_AUDITOR),
+                //("ResourceAdministrator", pdm_api_types::ROLE_RESOURCE_ADMINISTRATOR),
+                //("ResourceAuditor", pdm_api_types::ROLE_RESOURCE_AUDITOR),
+                //("AccessAuditor", pdm_api_types::ROLE_ACCESS_AUDITOR),
+            ]
+            .into_iter()
+            .collect()
+        });
+
+        &ROLES
+    }
+
+    fn is_superuser(&self, auth_id: &Authid) -> bool {
+        !auth_id.is_token() && auth_id.user() == "root@pam"
+    }
+
+    fn role_admin(&self) -> Option<&str> {
+        Some("Administrator")
+    }
+
+    fn init_user_config(&self, config: &mut SectionConfigData) -> Result<(), Error> {
+        if !config.sections.contains_key("root@pam") {
+            config
+                .set_data(
+                    "root@pam",
+                    "user",
+                    User {
+                        userid: "root@pam".parse().expect("invalid user id"),
+                        comment: Some("Superuser".to_string()),
+                        enable: None,
+                        expire: None,
+                        firstname: None,
+                        lastname: None,
+                        email: None,
+                    },
+                )
+                .context("failed to insert default user into user config")?
+        }
+
+        Ok(())
+    }
+
+    fn acl_audit_privileges(&self) -> u64 {
+        PRIV_ACCESS_AUDIT
+    }
+
+    fn acl_modify_privileges(&self) -> u64 {
+        PRIV_ACCESS_MODIFY
+    }
+
+    fn check_acl_path(&self, path: &str) -> Result<(), Error> {
+        let components = proxmox_access_control::acl::split_acl_path(path);
+
+        let components_len = components.len();
+
+        if components_len == 0 {
+            return Ok(());
+        }
+        match components[0] {
+            "access" => {
+                if components_len == 1 {
+                    return Ok(());
+                }
+                match components[1] {
+                    "acl" | "users" | "realm" => {
+                        if components_len == 2 {
+                            return Ok(());
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            "resource" => {
+                // `/resource` and `/resource/{remote}`
+                if components_len <= 2 {
+                    return Ok(());
+                }
+                // `/resource/{remote-id}/{resource-type=guest,storage}/{resource-id}`
+                match components[2] {
+                    "guest" | "storage" => {
+                        // /resource/{remote-id}/{resource-type}
+                        // /resource/{remote-id}/{resource-type}/{resource-id}
+                        if components_len <= 4 {
+                            return Ok(());
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            "system" => {
+                if components_len == 1 {
+                    return Ok(());
+                }
+                match components[1] {
+                    "certificates" | "disks" | "log" | "notifications" | "status" | "tasks"
+                    | "time" => {
+                        if components_len == 2 {
+                            return Ok(());
+                        }
+                    }
+                    "services" => {
+                        // /system/services/{service}
+                        if components_len <= 3 {
+                            return Ok(());
+                        }
+                    }
+                    "network" => {
+                        if components_len == 2 {
+                            return Ok(());
+                        }
+                        match components[2] {
+                            "dns" => {
+                                if components_len == 3 {
+                                    return Ok(());
+                                }
+                            }
+                            "interfaces" => {
+                                // /system/network/interfaces/{iface}
+                                if components_len <= 4 {
+                                    return Ok(());
+                                }
+                            }
+                            _ => {}
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        Err(format_err!("invalid acl path '{}'.", path))
+    }
+}
diff --git a/server/src/acl.rs b/server/src/acl.rs
index 52a1f97..f421814 100644
--- a/server/src/acl.rs
+++ b/server/src/acl.rs
@@ -1,164 +1,6 @@
-use std::collections::HashMap;
-use std::sync::OnceLock;
-
-use anyhow::{format_err, Context as _, Error};
-
-use proxmox_access_control::types::User;
-use proxmox_auth_api::types::Authid;
-use proxmox_section_config::SectionConfigData;
-
-struct AccessControlConfig;
-
-static PRIVILEGES: OnceLock<HashMap<&str, u64>> = OnceLock::new();
-static ROLES: OnceLock<HashMap<&str, (u64, &str)>> = OnceLock::new();
-
-impl proxmox_access_control::init::AccessControlConfig for AccessControlConfig {
-    fn privileges(&self) -> &HashMap<&str, u64> {
-        PRIVILEGES.get_or_init(|| pdm_api_types::PRIVILEGES.iter().copied().collect())
-    }
-
-    #[rustfmt::skip]
-    fn roles(&self) -> &HashMap<&str, (u64, &str)> {
-        ROLES.get_or_init(|| {
-            [
-                ("Administrator", (pdm_api_types::ROLE_ADMINISTRATOR, "Administrators can inspect and modify the system.")),
-                ("Auditor", (pdm_api_types::ROLE_AUDITOR, "An Auditor can inspect many aspects of the system, but not change them.")),
-                //("SystemAdministrator", pdm_api_types::ROLE_SYS_ADMINISTRATOR),
-                //("SystemAuditor", pdm_api_types::ROLE_SYS_AUDITOR),
-                //("ResourceAdministrator", pdm_api_types::ROLE_RESOURCE_ADMINISTRATOR),
-                //("ResourceAuditor", pdm_api_types::ROLE_RESOURCE_AUDITOR),
-                //("AccessAuditor", pdm_api_types::ROLE_ACCESS_AUDITOR),
-            ]
-            .into_iter()
-            .collect()
-        })
-    }
-
-    fn is_superuser(&self, auth_id: &Authid) -> bool {
-        !auth_id.is_token() && auth_id.user() == "root@pam"
-    }
-
-    fn role_admin(&self) -> Option<&str> {
-        Some("Administrator")
-    }
-
-    fn init_user_config(&self, config: &mut SectionConfigData) -> Result<(), Error> {
-        if !config.sections.contains_key("root@pam") {
-            config
-                .set_data(
-                    "root@pam",
-                    "user",
-                    User {
-                        userid: "root@pam".parse().expect("invalid user id"),
-                        comment: Some("Superuser".to_string()),
-                        enable: None,
-                        expire: None,
-                        firstname: None,
-                        lastname: None,
-                        email: None,
-                    },
-                )
-                .context("failed to insert default user into user config")?
-        }
-
-        Ok(())
-    }
-
-    fn acl_audit_privileges(&self) -> u64 {
-        pdm_api_types::PRIV_ACCESS_AUDIT
-    }
-
-    fn acl_modify_privileges(&self) -> u64 {
-        pdm_api_types::PRIV_ACCESS_MODIFY
-    }
-
-    fn check_acl_path(&self, path: &str) -> Result<(), Error> {
-        let components = proxmox_access_control::acl::split_acl_path(path);
-
-        let components_len = components.len();
-
-        if components_len == 0 {
-            return Ok(());
-        }
-        match components[0] {
-            "access" => {
-                if components_len == 1 {
-                    return Ok(());
-                }
-                match components[1] {
-                    "acl" | "users" | "realm" => {
-                        if components_len == 2 {
-                            return Ok(());
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            "resource" => {
-                // `/resource` and `/resource/{remote}`
-                if components_len <= 2 {
-                    return Ok(());
-                }
-                // `/resource/{remote-id}/{resource-type=guest,storage}/{resource-id}`
-                match components[2] {
-                    "guest" | "storage" => {
-                        // /resource/{remote-id}/{resource-type}
-                        // /resource/{remote-id}/{resource-type}/{resource-id}
-                        if components_len <= 4 {
-                            return Ok(());
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            "system" => {
-                if components_len == 1 {
-                    return Ok(());
-                }
-                match components[1] {
-                    "certificates" | "disks" | "log" | "notifications" | "status" | "tasks"
-                    | "time" => {
-                        if components_len == 2 {
-                            return Ok(());
-                        }
-                    }
-                    "services" => {
-                        // /system/services/{service}
-                        if components_len <= 3 {
-                            return Ok(());
-                        }
-                    }
-                    "network" => {
-                        if components_len == 2 {
-                            return Ok(());
-                        }
-                        match components[2] {
-                            "dns" => {
-                                if components_len == 3 {
-                                    return Ok(());
-                                }
-                            }
-                            "interfaces" => {
-                                // /system/network/interfaces/{iface}
-                                if components_len <= 4 {
-                                    return Ok(());
-                                }
-                            }
-                            _ => {}
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            _ => {}
-        }
-
-        Err(format_err!("invalid acl path '{}'.", path))
-    }
-}
-
 pub(crate) fn init() {
-    static ACCESS_CONTROL_CONFIG: AccessControlConfig = AccessControlConfig;
+    static ACCESS_CONTROL_CONFIG: pdm_api_types::AccessControlConfig =
+        pdm_api_types::AccessControlConfig;
 
     proxmox_access_control::init::init(&ACCESS_CONTROL_CONFIG, pdm_buildcfg::configdir!("/access"))
         .expect("failed to setup access control config");
-- 
2.47.3



_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


  parent reply	other threads:[~2025-10-22 13:11 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-22 13:11 [pdm-devel] [PATCH datacenter-manager/proxmox/yew-comp v2 00/10] add support for checking acl permissions in (yew) front-ends Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH proxmox v2 1/4] access-control: add acl feature to only expose types and the AclTree Shannon Sterz
2025-10-23  9:24   ` Dominik Csapak
2025-10-23 11:32     ` Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH proxmox v2 2/4] access-control: move functions querying privileges to " Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH proxmox v2 3/4] access-control: derive Debug and PartialEq on AclTree and AclTreeNode Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH proxmox v2 4/4] access-control: allow reading all acls of the current authid Shannon Sterz
2025-10-23  9:31   ` Dominik Csapak
2025-10-23 11:32     ` Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH yew-comp v2 1/2] acl_context: add AclContext and AclContextProvider Shannon Sterz
2025-10-23 10:00   ` Dominik Csapak
2025-10-23 11:33     ` Shannon Sterz
2025-10-23 11:39       ` Dominik Csapak
2025-10-22 13:11 ` [pdm-devel] [PATCH yew-comp v2 2/2] http_helpers: reload LocalAclTree when logging in or refreshing a ticket Shannon Sterz
2025-10-22 13:11 ` Shannon Sterz [this message]
2025-10-22 13:11 ` [pdm-devel] [PATCH datacenter-manager v2 2/2] ui: add an AclContext via the AclContextProvider to the main app ui Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH yew-comp v2 1/1] notes view: allow hiding the toolbar if editing isn't supported Shannon Sterz
2025-10-23  9:36   ` Dominik Csapak
2025-10-23 11:33     ` Shannon Sterz
2025-10-22 13:11 ` [pdm-devel] [PATCH datacenter-manager v2 1/1] ui: main menu: use the AclContext to hide the Notes if appropriate Shannon Sterz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251022131126.358790-8-s.sterz@proxmox.com \
    --to=s.sterz@proxmox.com \
    --cc=pdm-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal