218 lines
6.0 KiB
Rust
218 lines
6.0 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct RbacSystem {
|
|
roles: HashMap<String, Role>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Role {
|
|
pub name: String,
|
|
pub permissions: Vec<Permission>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum Permission {
|
|
// Server permissions
|
|
ServerCreate,
|
|
ServerDelete,
|
|
ServerRead,
|
|
ServerUpdate,
|
|
ServerSsh,
|
|
|
|
// Taskserv permissions
|
|
TaskservCreate,
|
|
TaskservDelete,
|
|
TaskservRead,
|
|
TaskservUpdate,
|
|
|
|
// Cluster permissions
|
|
ClusterCreate,
|
|
ClusterDelete,
|
|
ClusterRead,
|
|
ClusterUpdate,
|
|
|
|
// Workspace permissions
|
|
WorkspaceCreate,
|
|
WorkspaceDelete,
|
|
WorkspaceRead,
|
|
WorkspaceUpdate,
|
|
WorkspaceActivate,
|
|
|
|
// Workflow permissions
|
|
WorkflowSubmit,
|
|
WorkflowCancel,
|
|
WorkflowRead,
|
|
|
|
// Extension permissions
|
|
ExtensionLoad,
|
|
ExtensionRead,
|
|
|
|
// Operation permissions
|
|
OperationRead,
|
|
OperationCancel,
|
|
|
|
// System permissions
|
|
SystemAdmin,
|
|
SystemMetrics,
|
|
SystemHealth,
|
|
AuditRead,
|
|
}
|
|
|
|
impl RbacSystem {
|
|
pub fn new() -> Self {
|
|
let mut roles = HashMap::new();
|
|
|
|
// Admin role - full permissions
|
|
roles.insert(
|
|
"admin".to_string(),
|
|
Role {
|
|
name: "admin".to_string(),
|
|
permissions: vec![Permission::SystemAdmin],
|
|
},
|
|
);
|
|
|
|
// Operator role - infrastructure operations
|
|
roles.insert(
|
|
"operator".to_string(),
|
|
Role {
|
|
name: "operator".to_string(),
|
|
permissions: vec![
|
|
Permission::ServerCreate,
|
|
Permission::ServerDelete,
|
|
Permission::ServerRead,
|
|
Permission::ServerUpdate,
|
|
Permission::TaskservCreate,
|
|
Permission::TaskservDelete,
|
|
Permission::TaskservRead,
|
|
Permission::ClusterCreate,
|
|
Permission::ClusterDelete,
|
|
Permission::ClusterRead,
|
|
Permission::WorkflowSubmit,
|
|
Permission::WorkflowCancel,
|
|
Permission::WorkflowRead,
|
|
Permission::OperationRead,
|
|
Permission::OperationCancel,
|
|
],
|
|
},
|
|
);
|
|
|
|
// Developer role - read and limited create
|
|
roles.insert(
|
|
"developer".to_string(),
|
|
Role {
|
|
name: "developer".to_string(),
|
|
permissions: vec![
|
|
Permission::ServerRead,
|
|
Permission::ServerSsh,
|
|
Permission::TaskservRead,
|
|
Permission::ClusterRead,
|
|
Permission::WorkspaceRead,
|
|
Permission::WorkflowRead,
|
|
Permission::OperationRead,
|
|
Permission::ExtensionRead,
|
|
],
|
|
},
|
|
);
|
|
|
|
// Viewer role - read-only
|
|
roles.insert(
|
|
"viewer".to_string(),
|
|
Role {
|
|
name: "viewer".to_string(),
|
|
permissions: vec![
|
|
Permission::ServerRead,
|
|
Permission::TaskservRead,
|
|
Permission::ClusterRead,
|
|
Permission::WorkspaceRead,
|
|
Permission::WorkflowRead,
|
|
Permission::OperationRead,
|
|
Permission::SystemHealth,
|
|
],
|
|
},
|
|
);
|
|
|
|
Self { roles }
|
|
}
|
|
|
|
pub fn check_permission(&self, user_roles: &[String], permission: Permission) -> bool {
|
|
// Admin role has all permissions
|
|
if user_roles.contains(&"admin".to_string()) {
|
|
return true;
|
|
}
|
|
|
|
// Check if any user role has the required permission
|
|
for role_name in user_roles {
|
|
if let Some(role) = self.roles.get(role_name) {
|
|
if role.permissions.contains(&permission)
|
|
|| role.permissions.contains(&Permission::SystemAdmin)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub fn get_role(&self, role_name: &str) -> Option<&Role> {
|
|
self.roles.get(role_name)
|
|
}
|
|
|
|
pub fn add_role(&mut self, role: Role) {
|
|
self.roles.insert(role.name.clone(), role);
|
|
}
|
|
|
|
pub fn remove_role(&mut self, role_name: &str) -> Option<Role> {
|
|
self.roles.remove(role_name)
|
|
}
|
|
|
|
pub fn list_roles(&self) -> Vec<&Role> {
|
|
self.roles.values().collect()
|
|
}
|
|
}
|
|
|
|
impl Default for RbacSystem {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_admin_has_all_permissions() {
|
|
let rbac = RbacSystem::new();
|
|
assert!(rbac.check_permission(&["admin".to_string()], Permission::ServerCreate));
|
|
assert!(rbac.check_permission(&["admin".to_string()], Permission::WorkspaceDelete));
|
|
}
|
|
|
|
#[test]
|
|
fn test_operator_permissions() {
|
|
let rbac = RbacSystem::new();
|
|
assert!(rbac.check_permission(&["operator".to_string()], Permission::ServerCreate));
|
|
assert!(rbac.check_permission(&["operator".to_string()], Permission::TaskservCreate));
|
|
assert!(!rbac.check_permission(&["operator".to_string()], Permission::AuditRead));
|
|
}
|
|
|
|
#[test]
|
|
fn test_viewer_read_only() {
|
|
let rbac = RbacSystem::new();
|
|
assert!(rbac.check_permission(&["viewer".to_string()], Permission::ServerRead));
|
|
assert!(!rbac.check_permission(&["viewer".to_string()], Permission::ServerCreate));
|
|
assert!(!rbac.check_permission(&["viewer".to_string()], Permission::ServerDelete));
|
|
}
|
|
|
|
#[test]
|
|
fn test_multiple_roles() {
|
|
let rbac = RbacSystem::new();
|
|
let roles = vec!["viewer".to_string(), "developer".to_string()];
|
|
assert!(rbac.check_permission(&roles, Permission::ServerRead));
|
|
assert!(rbac.check_permission(&roles, Permission::ServerSsh));
|
|
}
|
|
}
|