use proxmox 0.1.25, use new EnumEntry feature
This commit is contained in:
		@ -5,7 +5,7 @@ use proxmox::api::{api, Router, RpcEnvironment, Permission};
 | 
			
		||||
 | 
			
		||||
use crate::api2::types::*;
 | 
			
		||||
use crate::config::acl;
 | 
			
		||||
use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
 | 
			
		||||
use crate::config::acl::{Role, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
 | 
			
		||||
 | 
			
		||||
#[api(
 | 
			
		||||
    properties: {
 | 
			
		||||
@ -23,7 +23,7 @@ use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
 | 
			
		||||
            description: "User or Group ID.",
 | 
			
		||||
        },
 | 
			
		||||
	roleid: {
 | 
			
		||||
            schema: ACL_ROLE_SCHEMA,
 | 
			
		||||
            type: Role,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
)]
 | 
			
		||||
@ -118,7 +118,7 @@ pub fn read_acl(
 | 
			
		||||
                schema: ACL_PATH_SCHEMA,
 | 
			
		||||
            },
 | 
			
		||||
	    role: {
 | 
			
		||||
                schema: ACL_ROLE_SCHEMA,
 | 
			
		||||
                type: Role,
 | 
			
		||||
            },
 | 
			
		||||
            propagate: {
 | 
			
		||||
                optional: true,
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ use proxmox::api::{api, Permission};
 | 
			
		||||
use proxmox::api::router::Router;
 | 
			
		||||
 | 
			
		||||
use crate::api2::types::*;
 | 
			
		||||
use crate::config::acl::ROLE_NAMES;
 | 
			
		||||
use crate::config::acl::{Role, ROLE_NAMES};
 | 
			
		||||
 | 
			
		||||
#[api(
 | 
			
		||||
    returns: {
 | 
			
		||||
@ -17,7 +17,7 @@ use crate::config::acl::ROLE_NAMES;
 | 
			
		||||
            description: "User name with description.",
 | 
			
		||||
            properties: {
 | 
			
		||||
                role: {
 | 
			
		||||
                    schema: ACL_ROLE_SCHEMA,
 | 
			
		||||
                    type: Role,
 | 
			
		||||
                },
 | 
			
		||||
                comment: {
 | 
			
		||||
                    schema: SINGLE_LINE_COMMENT_SCHEMA,
 | 
			
		||||
 | 
			
		||||
@ -31,15 +31,9 @@ pub const API_METHOD_UPGRADE_BACKUP: ApiMethod = ApiMethod::new(
 | 
			
		||||
        concat!("Upgraded to backup protocol ('", PROXMOX_BACKUP_READER_PROTOCOL_ID_V1!(), "')."),
 | 
			
		||||
        &sorted!([
 | 
			
		||||
            ("store", false, &DATASTORE_SCHEMA),
 | 
			
		||||
            ("backup-type", false, &StringSchema::new("Backup type.")
 | 
			
		||||
             .format(&ApiStringFormat::Enum(&["vm", "ct", "host"]))
 | 
			
		||||
             .schema()
 | 
			
		||||
            ),
 | 
			
		||||
            ("backup-id", false, &StringSchema::new("Backup ID.").schema()),
 | 
			
		||||
            ("backup-time", false, &IntegerSchema::new("Backup time (Unix epoch.)")
 | 
			
		||||
             .minimum(1_547_797_308)
 | 
			
		||||
             .schema()
 | 
			
		||||
            ),
 | 
			
		||||
            ("backup-type", false, &BACKUP_TYPE_SCHEMA),
 | 
			
		||||
            ("backup-id", false, &BACKUP_ID_SCHEMA),
 | 
			
		||||
            ("backup-time", false, &BACKUP_TIME_SCHEMA),
 | 
			
		||||
            ("debug", true, &BooleanSchema::new("Enable verbose debug logging.").schema()),
 | 
			
		||||
        ]),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@ -248,24 +248,9 @@ pub const ACL_PROPAGATE_SCHEMA: Schema = BooleanSchema::new(
 | 
			
		||||
 | 
			
		||||
pub const ACL_UGID_TYPE_SCHEMA: Schema = StringSchema::new(
 | 
			
		||||
    "Type of 'ugid' property.")
 | 
			
		||||
    .format(&ApiStringFormat::Enum(&["user", "group"]))
 | 
			
		||||
    .schema();
 | 
			
		||||
 | 
			
		||||
pub const ACL_ROLE_SCHEMA: Schema = StringSchema::new(
 | 
			
		||||
    "Role.")
 | 
			
		||||
    .format(&ApiStringFormat::Enum(&[
 | 
			
		||||
        "Admin",
 | 
			
		||||
        "Audit",
 | 
			
		||||
        "Datastore.Admin",
 | 
			
		||||
        "Datastore.Reader",
 | 
			
		||||
        "Datastore.Audit",
 | 
			
		||||
        "Datastore.Backup",
 | 
			
		||||
        "Datastore.PowerUser",
 | 
			
		||||
        "Remote.Admin",
 | 
			
		||||
        "Remote.Audit",
 | 
			
		||||
        "Remote.SyncOperator",
 | 
			
		||||
        "NoAccess",
 | 
			
		||||
    ]))
 | 
			
		||||
        EnumEntry::new("user", "User"),
 | 
			
		||||
        EnumEntry::new("group", "Group")]))
 | 
			
		||||
    .schema();
 | 
			
		||||
 | 
			
		||||
pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema =
 | 
			
		||||
@ -275,7 +260,10 @@ pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema =
 | 
			
		||||
 | 
			
		||||
pub const BACKUP_TYPE_SCHEMA: Schema =
 | 
			
		||||
    StringSchema::new("Backup type.")
 | 
			
		||||
    .format(&ApiStringFormat::Enum(&["vm", "ct", "host"]))
 | 
			
		||||
    .format(&ApiStringFormat::Enum(&[
 | 
			
		||||
        EnumEntry::new("vm", "Virtual Machine Backup"),
 | 
			
		||||
        EnumEntry::new("ct", "Container Backup"),
 | 
			
		||||
        EnumEntry::new("host", "Host Backup")]))
 | 
			
		||||
    .schema();
 | 
			
		||||
 | 
			
		||||
pub const BACKUP_ID_SCHEMA: Schema =
 | 
			
		||||
 | 
			
		||||
@ -1852,7 +1852,9 @@ fn key_mgmt_cli() -> CliCommandMap {
 | 
			
		||||
 | 
			
		||||
    const KDF_SCHEMA: Schema =
 | 
			
		||||
        StringSchema::new("Key derivation function. Choose 'none' to store the key unecrypted.")
 | 
			
		||||
        .format(&ApiStringFormat::Enum(&["scrypt", "none"]))
 | 
			
		||||
        .format(&ApiStringFormat::Enum(&[
 | 
			
		||||
            EnumEntry::new("scrypt", "SCrypt"),
 | 
			
		||||
            EnumEntry::new("none", "Do not encrypt the key")]))
 | 
			
		||||
        .default("scrypt")
 | 
			
		||||
        .schema();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,17 @@ use std::io::Write;
 | 
			
		||||
use std::collections::{HashMap, HashSet, BTreeMap, BTreeSet};
 | 
			
		||||
use std::path::{PathBuf, Path};
 | 
			
		||||
use std::sync::{Arc, RwLock};
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
 | 
			
		||||
use anyhow::{bail, Error};
 | 
			
		||||
 | 
			
		||||
use lazy_static::lazy_static;
 | 
			
		||||
 | 
			
		||||
use ::serde::{Deserialize, Serialize};
 | 
			
		||||
use serde::de::{value, IntoDeserializer};
 | 
			
		||||
 | 
			
		||||
use proxmox::tools::{fs::replace_file, fs::CreateOptions};
 | 
			
		||||
use proxmox::api::{api, schema::*};
 | 
			
		||||
 | 
			
		||||
// define Privilege bitfield
 | 
			
		||||
 | 
			
		||||
@ -83,56 +88,56 @@ PRIV_REMOTE_PRUNE;
 | 
			
		||||
 | 
			
		||||
pub const ROLE_NAME_NO_ACCESS: &str ="NoAccess";
 | 
			
		||||
 | 
			
		||||
#[api()]
 | 
			
		||||
#[repr(u64)]
 | 
			
		||||
#[derive(Serialize, Deserialize)]
 | 
			
		||||
/// Role
 | 
			
		||||
pub enum Role {
 | 
			
		||||
    /// Administrator
 | 
			
		||||
    Admin = ROLE_ADMIN,
 | 
			
		||||
    /// Auditor
 | 
			
		||||
    Audit = ROLE_AUDIT,
 | 
			
		||||
    /// Disable Access
 | 
			
		||||
    NoAccess = ROLE_NO_ACCESS,
 | 
			
		||||
    /// Datastore Administrator
 | 
			
		||||
    DatastoreAdmin = ROLE_DATASTORE_ADMIN,
 | 
			
		||||
    /// Datastore Reader (inspect datastore content and do restores)
 | 
			
		||||
    DatastoreReader = ROLE_DATASTORE_READER,
 | 
			
		||||
    /// Datastore Backup (backup and restore owned backups)
 | 
			
		||||
    DatastoreBackup = ROLE_DATASTORE_BACKUP,
 | 
			
		||||
    /// Datastore PowerUser (backup, restore and prune owned backup)
 | 
			
		||||
    DatastorePowerUser = ROLE_DATASTORE_POWERUSER,
 | 
			
		||||
    /// Datastore Auditor
 | 
			
		||||
    DatastoreAudit = ROLE_DATASTORE_AUDIT,
 | 
			
		||||
    /// Remote Auditor
 | 
			
		||||
    RemoteAudit = ROLE_REMOTE_AUDIT,
 | 
			
		||||
    /// Remote Administrator
 | 
			
		||||
    RemoteAdmin = ROLE_REMOTE_ADMIN,
 | 
			
		||||
    /// Syncronisation Opertator
 | 
			
		||||
    RemoteSyncOperator = ROLE_REMOTE_SYNC_OPERATOR,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromStr for Role {
 | 
			
		||||
    type Err = value::Error;
 | 
			
		||||
 | 
			
		||||
    fn from_str(s: &str) -> Result<Self, Self::Err> {
 | 
			
		||||
        Self::deserialize(s.into_deserializer())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lazy_static! {
 | 
			
		||||
    pub static ref ROLE_NAMES: HashMap<&'static str, (u64, &'static str)> = {
 | 
			
		||||
        let mut map = HashMap::new();
 | 
			
		||||
 | 
			
		||||
        map.insert("Admin", (
 | 
			
		||||
            ROLE_ADMIN,
 | 
			
		||||
            "Administrator",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Audit", (
 | 
			
		||||
            ROLE_AUDIT,
 | 
			
		||||
            "Auditor",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert(ROLE_NAME_NO_ACCESS, (
 | 
			
		||||
            ROLE_NO_ACCESS,
 | 
			
		||||
            "Disable access",
 | 
			
		||||
        ));
 | 
			
		||||
        let list = match Role::API_SCHEMA {
 | 
			
		||||
            Schema::String(StringSchema { format: Some(ApiStringFormat::Enum(list)), .. }) => list,
 | 
			
		||||
            _ => unreachable!(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        map.insert("Datastore.Admin", (
 | 
			
		||||
            ROLE_DATASTORE_ADMIN,
 | 
			
		||||
            "Datastore Administrator",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Datastore.Reader", (
 | 
			
		||||
            ROLE_DATASTORE_READER,
 | 
			
		||||
            "Datastore Reader (inspect datastore content and do restores)",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Datastore.Backup", (
 | 
			
		||||
            ROLE_DATASTORE_BACKUP,
 | 
			
		||||
            "Datastore Backup (backup and restore owned backups)",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Datastore.PowerUser", (
 | 
			
		||||
            ROLE_DATASTORE_POWERUSER,
 | 
			
		||||
            "Datastore PowerUser (backup, restore and prune owned backup)",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Datastore.Audit", (
 | 
			
		||||
            ROLE_DATASTORE_AUDIT,
 | 
			
		||||
            "Datastore Auditor",
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        map.insert("Remote.Audit", (
 | 
			
		||||
            ROLE_REMOTE_AUDIT,
 | 
			
		||||
            "Remote Auditor",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Remote.Admin", (
 | 
			
		||||
            ROLE_REMOTE_ADMIN,
 | 
			
		||||
            "Remote Administrator",
 | 
			
		||||
        ));
 | 
			
		||||
        map.insert("Remote.SyncOperator", (
 | 
			
		||||
            ROLE_REMOTE_SYNC_OPERATOR,
 | 
			
		||||
            "Syncronisation Opertator",
 | 
			
		||||
        ));
 | 
			
		||||
        for entry in list.iter() {
 | 
			
		||||
            let privs: u64 = Role::from_str(entry.value).unwrap() as u64;
 | 
			
		||||
            map.insert(entry.value, (privs, entry.description));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        map
 | 
			
		||||
    };
 | 
			
		||||
@ -615,15 +620,15 @@ mod test {
 | 
			
		||||
        let tree = AclTree::from_raw(r###"
 | 
			
		||||
acl:0:/store/store2:user1:Admin
 | 
			
		||||
acl:0:/store/store2:user2:Admin
 | 
			
		||||
acl:0:/store/store2:user1:Datastore.Backup
 | 
			
		||||
acl:0:/store/store2:user2:Datastore.Backup
 | 
			
		||||
acl:0:/store/store2:user1:DatastoreBackup
 | 
			
		||||
acl:0:/store/store2:user2:DatastoreBackup
 | 
			
		||||
"###)?;
 | 
			
		||||
 | 
			
		||||
        let mut raw: Vec<u8> = Vec::new();
 | 
			
		||||
        tree.write_config(&mut raw)?;
 | 
			
		||||
        let raw = std::str::from_utf8(&raw)?;
 | 
			
		||||
 | 
			
		||||
        assert_eq!(raw, "acl:0:/store/store2:user1,user2:Admin,Datastore.Backup\n");
 | 
			
		||||
        assert_eq!(raw, "acl:0:/store/store2:user1,user2:Admin,DatastoreBackup\n");
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -633,18 +638,18 @@ acl:0:/store/store2:user2:Datastore.Backup
 | 
			
		||||
 | 
			
		||||
        let tree = AclTree::from_raw(r###"
 | 
			
		||||
acl:1:/storage:user1@pbs:Admin
 | 
			
		||||
acl:1:/storage/store1:user1@pbs:Datastore.Backup
 | 
			
		||||
acl:1:/storage/store2:user2@pbs:Datastore.Backup
 | 
			
		||||
acl:1:/storage/store1:user1@pbs:DatastoreBackup
 | 
			
		||||
acl:1:/storage/store2:user2@pbs:DatastoreBackup
 | 
			
		||||
"###)?;
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/", "");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage", "Admin");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store1", "Datastore.Backup");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store1", "DatastoreBackup");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store2", "Admin");
 | 
			
		||||
 | 
			
		||||
        check_roles(&tree, "user2@pbs", "/", "");
 | 
			
		||||
        check_roles(&tree, "user2@pbs", "/storage", "");
 | 
			
		||||
        check_roles(&tree, "user2@pbs", "/storage/store1", "");
 | 
			
		||||
        check_roles(&tree, "user2@pbs", "/storage/store2", "Datastore.Backup");
 | 
			
		||||
        check_roles(&tree, "user2@pbs", "/storage/store2", "DatastoreBackup");
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -655,22 +660,22 @@ acl:1:/storage/store2:user2@pbs:Datastore.Backup
 | 
			
		||||
        let tree = AclTree::from_raw(r###"
 | 
			
		||||
acl:1:/:user1@pbs:Admin
 | 
			
		||||
acl:1:/storage:user1@pbs:NoAccess
 | 
			
		||||
acl:1:/storage/store1:user1@pbs:Datastore.Backup
 | 
			
		||||
acl:1:/storage/store1:user1@pbs:DatastoreBackup
 | 
			
		||||
"###)?;
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/", "Admin");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage", "NoAccess");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store1", "Datastore.Backup");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store1", "DatastoreBackup");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store2", "NoAccess");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/system", "Admin");
 | 
			
		||||
 | 
			
		||||
        let tree = AclTree::from_raw(r###"
 | 
			
		||||
acl:1:/:user1@pbs:Admin
 | 
			
		||||
acl:0:/storage:user1@pbs:NoAccess
 | 
			
		||||
acl:1:/storage/store1:user1@pbs:Datastore.Backup
 | 
			
		||||
acl:1:/storage/store1:user1@pbs:DatastoreBackup
 | 
			
		||||
"###)?;
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/", "Admin");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage", "NoAccess");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store1", "Datastore.Backup");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store1", "DatastoreBackup");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/storage/store2", "Admin");
 | 
			
		||||
        check_roles(&tree, "user1@pbs", "/system", "Admin");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user