adaptive_pipeline_domain/entities/
security_context.rs

1// /////////////////////////////////////////////////////////////////////////////
2// Adaptive Pipeline
3// Copyright (c) 2025 Michael Gardner, A Bit of Help, Inc.
4// SPDX-License-Identifier: BSD-3-Clause
5// See LICENSE file in the project root.
6// /////////////////////////////////////////////////////////////////////////////
7
8//! # Security Context Entity
9//!
10//! The `SecurityContext` entity manages security-related information and access
11//! control for pipeline processing operations. It enforces security policies,
12//! tracks permissions, and maintains audit trails for secure data processing.
13//!
14//! ## Overview
15//!
16//! The security context provides:
17//!
18//! - **Access Control**: Permission-based authorization for operations
19//! - **Security Levels**: Hierarchical classification of data sensitivity
20//! - **Audit Tracking**: Session management and operation logging
21//! - **Key Management**: Integration with encryption key infrastructure
22//! - **Policy Enforcement**: Validation of security requirements
23//!
24//! ## Security Model
25//!
26//! The system implements a multi-layered security model:
27//!
28//! ### Permission-Based Access Control
29//! Fine-grained permissions control specific operations:
30//! - Read, Write, Execute for basic file operations
31//! - Encrypt, Decrypt for cryptographic operations
32//! - Compress, Decompress for data transformation
33//! - Admin for administrative functions
34//! - Custom permissions for extensibility
35//!
36//! ### Hierarchical Security Levels
37//! Data classification from Public to TopSecret:
38//! - **Public**: No restrictions, publicly accessible
39//! - **Internal**: Internal use only, basic protection
40//! - **Medium**: Moderate sensitivity, controlled access
41//! - **Confidential**: High sensitivity, restricted access
42//! - **Secret**: Very high sensitivity, need-to-know basis
43//! - **TopSecret**: Maximum sensitivity, highest protection
44//!
45//! ### Session Management
46//! Each context maintains a unique session for audit trails and tracking.
47
48use crate::services::datetime_serde;
49use serde::{Deserialize, Serialize};
50use std::collections::HashMap;
51use uuid::Uuid;
52
53/// Security context entity for managing access control and security policies.
54///
55/// The `SecurityContext` encapsulates all security-related information needed
56/// for pipeline processing operations. It enforces access control policies,
57/// maintains audit information, and integrates with encryption key management.
58///
59/// ## Security Features
60///
61/// - **Permission Management**: Fine-grained access control
62/// - **Security Classification**: Hierarchical data sensitivity levels
63/// - **Session Tracking**: Unique session identification for audit trails
64/// - **Key Integration**: Encryption key management and association
65/// - **Audit Support**: Comprehensive logging and tracking capabilities
66/// - **Policy Validation**: Enforcement of security requirements and
67///   constraints
68///
69/// ## Usage Examples
70///
71/// ### Creating a Basic Security Context
72///
73///
74/// ### Creating Context with Specific Permissions
75///
76///
77/// ### Managing Permissions Dynamically
78///
79///
80/// ### Security Level Validation
81///
82///
83/// ### Encryption Key Management
84///
85///
86/// ### Creating Restricted Contexts
87///
88///
89/// ### Audit and Session Management
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct SecurityContext {
92    user_id: Option<String>,
93    session_id: Uuid,
94    permissions: Vec<Permission>,
95    encryption_key_id: Option<String>,
96    integrity_required: bool,
97    audit_enabled: bool,
98    security_level: SecurityLevel,
99    metadata: HashMap<String, String>,
100    #[serde(with = "datetime_serde")]
101    created_at: chrono::DateTime<chrono::Utc>,
102}
103
104/// Security permission enumeration for fine-grained access control.
105///
106/// Permissions define specific operations that can be performed within the
107/// pipeline. The permission system supports both standard operations and custom
108/// extensions for specialized use cases.
109///
110/// ## Standard Permissions
111///
112/// ### File Operations
113/// - **Read**: Access to read files and data
114/// - **Write**: Ability to create and modify files
115/// - **Execute**: Permission to run processing operations
116///
117/// ### Cryptographic Operations
118/// - **Encrypt**: Ability to encrypt data
119/// - **Decrypt**: Ability to decrypt data
120///
121/// ### Data Transformation
122/// - **Compress**: Permission to compress data
123/// - **Decompress**: Permission to decompress data
124///
125/// ### Administrative
126/// - **Admin**: Full administrative access (implies all other permissions)
127///
128/// ### Extensibility
129/// - **Custom(String)**: Application-specific custom permissions
130///
131/// ## Permission Hierarchy
132///
133/// The Admin permission automatically grants all other permissions.
134/// Custom permissions are evaluated independently.
135///
136/// ## Usage Examples
137#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
138pub enum Permission {
139    Read,
140    Write,
141    Execute,
142    Admin,
143    Encrypt,
144    Decrypt,
145    Compress,
146    Decompress,
147    Custom(String),
148}
149
150/// Hierarchical security classification levels for data and operations.
151///
152/// Security levels provide a standardized way to classify the sensitivity of
153/// data and determine appropriate protection measures. Higher levels require
154/// stronger security controls and more restrictive access policies.
155///
156/// ## Security Level Hierarchy
157///
158/// Levels are ordered from lowest to highest sensitivity:
159///
160/// ### Public
161/// - **Sensitivity**: None
162/// - **Access**: Unrestricted public access
163/// - **Protection**: Minimal security controls
164/// - **Use Cases**: Public documentation, marketing materials
165///
166/// ### Internal
167/// - **Sensitivity**: Low
168/// - **Access**: Internal organization members
169/// - **Protection**: Basic access controls
170/// - **Use Cases**: Internal communications, general business data
171///
172/// ### Medium
173/// - **Sensitivity**: Moderate
174/// - **Access**: Authorized personnel only
175/// - **Protection**: Standard security measures
176/// - **Use Cases**: Business plans, financial reports
177///
178/// ### Confidential
179/// - **Sensitivity**: High
180/// - **Access**: Need-to-know basis
181/// - **Protection**: Strong encryption and access controls
182/// - **Use Cases**: Customer data, proprietary information
183///
184/// ### Secret
185/// - **Sensitivity**: Very High
186/// - **Access**: Strictly controlled
187/// - **Protection**: Advanced security measures
188/// - **Use Cases**: Trade secrets, sensitive personal data
189///
190/// ### TopSecret
191/// - **Sensitivity**: Maximum
192/// - **Access**: Highest clearance only
193/// - **Protection**: Maximum security controls
194/// - **Use Cases**: Critical infrastructure, national security data
195///
196/// ## Level Comparison
197///
198/// Security levels support comparison operations for policy enforcement:
199///
200///
201/// ## Usage Examples
202#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
203pub enum SecurityLevel {
204    Public,
205    Internal,
206    Medium,
207    Confidential,
208    Secret,
209    TopSecret,
210}
211
212impl Default for SecurityContext {
213    fn default() -> Self {
214        Self {
215            user_id: None,
216            session_id: Uuid::new_v4(),
217            permissions: vec![Permission::Read],
218            encryption_key_id: None,
219            integrity_required: false,
220            audit_enabled: true,
221            security_level: SecurityLevel::Internal,
222            metadata: HashMap::new(),
223            created_at: chrono::Utc::now(),
224        }
225    }
226}
227
228impl SecurityContext {
229    /// Creates a new security context
230    pub fn new(user_id: Option<String>, security_level: SecurityLevel) -> Self {
231        Self {
232            user_id,
233            security_level,
234            ..Default::default()
235        }
236    }
237
238    /// Creates a security context with permissions
239    pub fn with_permissions(
240        user_id: Option<String>,
241        permissions: Vec<Permission>,
242        security_level: SecurityLevel,
243    ) -> Self {
244        Self {
245            user_id,
246            permissions,
247            security_level,
248            ..Default::default()
249        }
250    }
251
252    /// Gets the user ID
253    pub fn user_id(&self) -> Option<&str> {
254        self.user_id.as_deref()
255    }
256
257    /// Gets the session ID
258    pub fn session_id(&self) -> Uuid {
259        self.session_id
260    }
261
262    /// Gets the permissions
263    pub fn permissions(&self) -> &[Permission] {
264        &self.permissions
265    }
266
267    /// Gets the encryption key ID
268    pub fn encryption_key_id(&self) -> Option<&str> {
269        self.encryption_key_id.as_deref()
270    }
271
272    /// Checks if integrity is required
273    pub fn integrity_required(&self) -> bool {
274        self.integrity_required
275    }
276
277    /// Checks if audit is enabled
278    pub fn audit_enabled(&self) -> bool {
279        self.audit_enabled
280    }
281
282    /// Gets the security level
283    pub fn security_level(&self) -> &SecurityLevel {
284        &self.security_level
285    }
286
287    /// Gets the metadata
288    pub fn metadata(&self) -> &HashMap<String, String> {
289        &self.metadata
290    }
291
292    /// Gets the creation timestamp
293    pub fn created_at(&self) -> chrono::DateTime<chrono::Utc> {
294        self.created_at
295    }
296
297    /// Sets the user ID
298    pub fn set_user_id(&mut self, user_id: Option<String>) {
299        self.user_id = user_id;
300    }
301
302    /// Adds a permission
303    pub fn add_permission(&mut self, permission: Permission) {
304        if !self.permissions.contains(&permission) {
305            self.permissions.push(permission);
306        }
307    }
308
309    /// Removes a permission
310    pub fn remove_permission(&mut self, permission: &Permission) {
311        self.permissions.retain(|p| p != permission);
312    }
313
314    /// Sets the encryption key ID
315    pub fn set_encryption_key_id(&mut self, key_id: Option<String>) {
316        self.encryption_key_id = key_id;
317    }
318
319    /// Sets integrity requirement
320    pub fn set_integrity_required(&mut self, required: bool) {
321        self.integrity_required = required;
322    }
323
324    /// Sets audit enablement
325    pub fn set_audit_enabled(&mut self, enabled: bool) {
326        self.audit_enabled = enabled;
327    }
328
329    /// Sets the security level
330    pub fn set_security_level(&mut self, level: SecurityLevel) {
331        self.security_level = level;
332    }
333
334    /// Adds metadata
335    pub fn add_metadata(&mut self, key: String, value: String) {
336        self.metadata.insert(key, value);
337    }
338
339    /// Removes metadata
340    pub fn remove_metadata(&mut self, key: &str) {
341        self.metadata.remove(key);
342    }
343
344    /// Checks if the context has a specific permission
345    pub fn has_permission(&self, permission: &Permission) -> bool {
346        self.permissions.contains(permission) || self.permissions.contains(&Permission::Admin)
347    }
348
349    /// Checks if the context can perform encryption
350    pub fn can_encrypt(&self) -> bool {
351        self.has_permission(&Permission::Encrypt) || self.has_permission(&Permission::Admin)
352    }
353
354    /// Checks if the context can perform decryption
355    pub fn can_decrypt(&self) -> bool {
356        self.has_permission(&Permission::Decrypt) || self.has_permission(&Permission::Admin)
357    }
358
359    /// Checks if the context can perform compression
360    pub fn can_compress(&self) -> bool {
361        self.has_permission(&Permission::Compress) || self.has_permission(&Permission::Admin)
362    }
363
364    /// Checks if the context can perform decompression
365    pub fn can_decompress(&self) -> bool {
366        self.has_permission(&Permission::Decompress) || self.has_permission(&Permission::Admin)
367    }
368
369    /// Checks if the context can read
370    pub fn can_read(&self) -> bool {
371        self.has_permission(&Permission::Read) || self.has_permission(&Permission::Admin)
372    }
373
374    /// Checks if the context can write
375    pub fn can_write(&self) -> bool {
376        self.has_permission(&Permission::Write) || self.has_permission(&Permission::Admin)
377    }
378
379    /// Checks if the context can execute
380    pub fn can_execute(&self) -> bool {
381        self.has_permission(&Permission::Execute) || self.has_permission(&Permission::Admin)
382    }
383
384    /// Checks if the security level meets the minimum requirement
385    pub fn meets_security_level(&self, minimum_level: &SecurityLevel) -> bool {
386        self.security_level >= *minimum_level
387    }
388
389    /// Creates a restricted copy of the security context
390    pub fn restrict(&self, allowed_permissions: Vec<Permission>) -> Self {
391        let restricted_permissions = self
392            .permissions
393            .iter()
394            .filter(|p| allowed_permissions.contains(p))
395            .cloned()
396            .collect();
397
398        Self {
399            user_id: self.user_id.clone(),
400            session_id: self.session_id,
401            permissions: restricted_permissions,
402            encryption_key_id: self.encryption_key_id.clone(),
403            integrity_required: self.integrity_required,
404            audit_enabled: self.audit_enabled,
405            security_level: self.security_level.clone(),
406            metadata: self.metadata.clone(),
407            created_at: self.created_at,
408        }
409    }
410
411    /// Validates the security context
412    pub fn validate(&self) -> Result<(), crate::PipelineError> {
413        if self.permissions.is_empty() {
414            return Err(crate::PipelineError::SecurityViolation(
415                "Security context must have at least one permission".to_string(),
416            ));
417        }
418
419        if self.integrity_required && self.encryption_key_id.is_none() {
420            return Err(crate::PipelineError::SecurityViolation(
421                "Integrity required but no encryption key specified".to_string(),
422            ));
423        }
424
425        Ok(())
426    }
427}
428
429impl std::fmt::Display for SecurityLevel {
430    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
431        match self {
432            SecurityLevel::Public => write!(f, "Public"),
433            SecurityLevel::Internal => write!(f, "Internal"),
434            SecurityLevel::Medium => write!(f, "Medium"),
435            SecurityLevel::Confidential => write!(f, "Confidential"),
436            SecurityLevel::Secret => write!(f, "Secret"),
437            SecurityLevel::TopSecret => write!(f, "Top Secret"),
438        }
439    }
440}
441
442impl std::fmt::Display for Permission {
443    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
444        match self {
445            Permission::Read => write!(f, "Read"),
446            Permission::Write => write!(f, "Write"),
447            Permission::Execute => write!(f, "Execute"),
448            Permission::Admin => write!(f, "Admin"),
449            Permission::Encrypt => write!(f, "Encrypt"),
450            Permission::Decrypt => write!(f, "Decrypt"),
451            Permission::Compress => write!(f, "Compress"),
452            Permission::Decompress => write!(f, "Decompress"),
453            Permission::Custom(name) => write!(f, "Custom({})", name),
454        }
455    }
456}