rustkernel_core/security/
rbac.rs

1//! Role-Based Access Control (RBAC)
2//!
3//! Provides fine-grained access control for kernel operations.
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashSet;
7
8/// Kernel-level permissions
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum Permission {
12    /// Execute kernels
13    KernelExecute,
14    /// Configure kernel parameters
15    KernelConfigure,
16    /// Monitor kernel metrics
17    KernelMonitor,
18    /// Administer kernels (register, unregister)
19    KernelAdmin,
20    /// Read kernel state
21    StateRead,
22    /// Write kernel state
23    StateWrite,
24    /// Access secrets
25    SecretsRead,
26    /// Manage secrets
27    SecretsWrite,
28    /// View tenant data
29    TenantRead,
30    /// Manage tenant settings
31    TenantAdmin,
32}
33
34/// Kernel permission aliases
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36#[serde(rename_all = "snake_case")]
37pub enum KernelPermission {
38    /// Execute kernels
39    Execute,
40    /// Configure kernels
41    Configure,
42    /// Monitor kernels
43    Monitor,
44    /// Administer kernels
45    Admin,
46}
47
48impl From<KernelPermission> for Permission {
49    fn from(p: KernelPermission) -> Self {
50        match p {
51            KernelPermission::Execute => Permission::KernelExecute,
52            KernelPermission::Configure => Permission::KernelConfigure,
53            KernelPermission::Monitor => Permission::KernelMonitor,
54            KernelPermission::Admin => Permission::KernelAdmin,
55        }
56    }
57}
58
59/// A set of permissions
60#[derive(Debug, Clone, Default, Serialize, Deserialize)]
61pub struct PermissionSet {
62    permissions: HashSet<Permission>,
63}
64
65impl PermissionSet {
66    /// Create an empty permission set
67    pub fn empty() -> Self {
68        Self {
69            permissions: HashSet::new(),
70        }
71    }
72
73    /// Create a permission set with all permissions
74    pub fn all() -> Self {
75        let mut permissions = HashSet::new();
76        permissions.insert(Permission::KernelExecute);
77        permissions.insert(Permission::KernelConfigure);
78        permissions.insert(Permission::KernelMonitor);
79        permissions.insert(Permission::KernelAdmin);
80        permissions.insert(Permission::StateRead);
81        permissions.insert(Permission::StateWrite);
82        permissions.insert(Permission::SecretsRead);
83        permissions.insert(Permission::SecretsWrite);
84        permissions.insert(Permission::TenantRead);
85        permissions.insert(Permission::TenantAdmin);
86        Self { permissions }
87    }
88
89    /// Check if the set contains a permission
90    pub fn contains(&self, permission: Permission) -> bool {
91        self.permissions.contains(&permission)
92    }
93
94    /// Add a permission
95    pub fn add(&mut self, permission: Permission) {
96        self.permissions.insert(permission);
97    }
98
99    /// Remove a permission
100    pub fn remove(&mut self, permission: Permission) {
101        self.permissions.remove(&permission);
102    }
103
104    /// Union with another permission set
105    pub fn union(&self, other: &PermissionSet) -> PermissionSet {
106        PermissionSet {
107            permissions: self
108                .permissions
109                .union(&other.permissions)
110                .cloned()
111                .collect(),
112        }
113    }
114
115    /// Intersection with another permission set
116    pub fn intersection(&self, other: &PermissionSet) -> PermissionSet {
117        PermissionSet {
118            permissions: self
119                .permissions
120                .intersection(&other.permissions)
121                .cloned()
122                .collect(),
123        }
124    }
125
126    /// Get all permissions
127    pub fn iter(&self) -> impl Iterator<Item = &Permission> {
128        self.permissions.iter()
129    }
130}
131
132impl FromIterator<Permission> for PermissionSet {
133    fn from_iter<I: IntoIterator<Item = Permission>>(iter: I) -> Self {
134        Self {
135            permissions: iter.into_iter().collect(),
136        }
137    }
138}
139
140/// Pre-defined roles
141#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
142#[serde(rename_all = "snake_case")]
143pub enum Role {
144    /// Read-only access
145    Viewer,
146    /// Execute kernels only
147    User,
148    /// Execute and configure kernels
149    Operator,
150    /// Full access
151    Admin,
152    /// Custom role with specific permissions
153    Custom(String),
154}
155
156impl Role {
157    /// Get the permissions for this role
158    pub fn permissions(&self) -> PermissionSet {
159        match self {
160            Role::Viewer => [Permission::KernelMonitor, Permission::StateRead]
161                .into_iter()
162                .collect(),
163            Role::User => [
164                Permission::KernelExecute,
165                Permission::KernelMonitor,
166                Permission::StateRead,
167            ]
168            .into_iter()
169            .collect(),
170            Role::Operator => [
171                Permission::KernelExecute,
172                Permission::KernelConfigure,
173                Permission::KernelMonitor,
174                Permission::StateRead,
175                Permission::StateWrite,
176            ]
177            .into_iter()
178            .collect(),
179            Role::Admin => PermissionSet::all(),
180            Role::Custom(_) => PermissionSet::empty(), // Custom roles need explicit permissions
181        }
182    }
183}
184
185/// Role binding - assigns a role to a user or group
186#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct RoleBinding {
188    /// Binding name
189    pub name: String,
190    /// Role to bind
191    pub role: Role,
192    /// Subjects (users or groups)
193    pub subjects: Vec<Subject>,
194    /// Scope (namespace, tenant, etc.)
195    pub scope: Option<String>,
196}
197
198impl RoleBinding {
199    /// Create a new role binding
200    pub fn new(name: impl Into<String>, role: Role) -> Self {
201        Self {
202            name: name.into(),
203            role,
204            subjects: Vec::new(),
205            scope: None,
206        }
207    }
208
209    /// Add a user subject
210    pub fn for_user(mut self, user_id: impl Into<String>) -> Self {
211        self.subjects.push(Subject::User(user_id.into()));
212        self
213    }
214
215    /// Add a group subject
216    pub fn for_group(mut self, group: impl Into<String>) -> Self {
217        self.subjects.push(Subject::Group(group.into()));
218        self
219    }
220
221    /// Set scope
222    pub fn in_scope(mut self, scope: impl Into<String>) -> Self {
223        self.scope = Some(scope.into());
224        self
225    }
226}
227
228/// Subject for role binding
229#[derive(Debug, Clone, Serialize, Deserialize)]
230#[serde(tag = "type", rename_all = "snake_case")]
231pub enum Subject {
232    /// User subject
233    User(String),
234    /// Group subject
235    Group(String),
236    /// Service account
237    ServiceAccount(String),
238}
239
240#[cfg(test)]
241mod tests {
242    use super::*;
243
244    #[test]
245    fn test_permission_set() {
246        let mut perms = PermissionSet::empty();
247        assert!(!perms.contains(Permission::KernelExecute));
248
249        perms.add(Permission::KernelExecute);
250        assert!(perms.contains(Permission::KernelExecute));
251
252        perms.remove(Permission::KernelExecute);
253        assert!(!perms.contains(Permission::KernelExecute));
254    }
255
256    #[test]
257    fn test_all_permissions() {
258        let perms = PermissionSet::all();
259        assert!(perms.contains(Permission::KernelExecute));
260        assert!(perms.contains(Permission::KernelAdmin));
261        assert!(perms.contains(Permission::SecretsWrite));
262    }
263
264    #[test]
265    fn test_role_permissions() {
266        let viewer_perms = Role::Viewer.permissions();
267        assert!(viewer_perms.contains(Permission::KernelMonitor));
268        assert!(!viewer_perms.contains(Permission::KernelExecute));
269
270        let user_perms = Role::User.permissions();
271        assert!(user_perms.contains(Permission::KernelExecute));
272        assert!(!user_perms.contains(Permission::KernelAdmin));
273
274        let admin_perms = Role::Admin.permissions();
275        assert!(admin_perms.contains(Permission::KernelAdmin));
276    }
277
278    #[test]
279    fn test_permission_union() {
280        let perms1: PermissionSet = [Permission::KernelExecute].into_iter().collect();
281        let perms2: PermissionSet = [Permission::KernelMonitor].into_iter().collect();
282
283        let union = perms1.union(&perms2);
284        assert!(union.contains(Permission::KernelExecute));
285        assert!(union.contains(Permission::KernelMonitor));
286    }
287
288    #[test]
289    fn test_role_binding() {
290        let binding = RoleBinding::new("admin-binding", Role::Admin)
291            .for_user("user-123")
292            .for_group("admins")
293            .in_scope("tenant-456");
294
295        assert_eq!(binding.role, Role::Admin);
296        assert_eq!(binding.subjects.len(), 2);
297        assert_eq!(binding.scope.as_deref(), Some("tenant-456"));
298    }
299}