Skip to main content

oxirs_stream/security/
traits.rs

1//! # Security Traits and Primitives
2//!
3//! Authentication, authorization, audit, and threat detection traits,
4//! plus supporting data types used throughout the security framework.
5
6use anyhow::Result;
7use chrono::{DateTime, Utc};
8use serde::{Deserialize, Serialize};
9use std::collections::{HashMap, HashSet};
10use uuid::Uuid;
11
12use super::{AuditEvent, AuthMethod, Permission, ThreatSeverity};
13
14/// Authentication provider trait
15#[async_trait::async_trait]
16pub trait AuthenticationProvider: Send + Sync {
17    async fn authenticate(&self, credentials: &Credentials) -> Result<super::SecurityContext>;
18    async fn validate_token(&self, token: &str) -> Result<super::SecurityContext>;
19    async fn refresh_token(&self, refresh_token: &str) -> Result<(String, String)>; // (access_token, refresh_token)
20}
21
22/// Authorization provider trait
23#[async_trait::async_trait]
24pub trait AuthorizationProvider: Send + Sync {
25    async fn authorize(
26        &self,
27        context: &super::SecurityContext,
28        resource: &str,
29        action: &Permission,
30    ) -> Result<bool>;
31    async fn get_user_permissions(&self, user_id: &str) -> Result<HashSet<Permission>>;
32    async fn get_user_roles(&self, user_id: &str) -> Result<HashSet<String>>;
33}
34
35/// Audit logger trait
36#[async_trait::async_trait]
37pub trait AuditLogger: Send + Sync {
38    async fn log(&self, entry: AuditLogEntry) -> Result<()>;
39    async fn query(&self, filter: AuditFilter) -> Result<Vec<AuditLogEntry>>;
40}
41
42/// Threat detector trait
43#[async_trait::async_trait]
44pub trait ThreatDetector: Send + Sync {
45    async fn detect_threat(&self, context: &ThreatContext) -> Result<Option<ThreatAlert>>;
46    async fn learn_pattern(&self, context: &ThreatContext) -> Result<()>;
47}
48
49/// Rate limiter trait
50#[async_trait::async_trait]
51pub trait RateLimiter: Send + Sync {
52    async fn check_limit(&self, identifier: &str) -> Result<()>;
53    async fn reset_limit(&self, identifier: &str) -> Result<()>;
54}
55
56/// Credentials for authentication
57#[derive(Debug, Clone)]
58pub enum Credentials {
59    ApiKey {
60        key: String,
61        ip_address: Option<String>,
62    },
63    JWT {
64        token: String,
65        ip_address: Option<String>,
66    },
67    UserPassword {
68        username: String,
69        password: String,
70        ip_address: Option<String>,
71    },
72    Certificate {
73        cert: Vec<u8>,
74        ip_address: Option<String>,
75    },
76}
77
78impl Credentials {
79    pub fn identifier(&self) -> String {
80        match self {
81            Credentials::ApiKey { key, .. } => format!("api_key:{key}"),
82            Credentials::JWT { token, .. } => format!("jwt:{token}"),
83            Credentials::UserPassword { username, .. } => format!("user:{username}"),
84            Credentials::Certificate { .. } => "certificate".to_string(),
85        }
86    }
87
88    pub fn user_id(&self) -> Option<&str> {
89        match self {
90            Credentials::UserPassword { username, .. } => Some(username),
91            _ => None,
92        }
93    }
94
95    pub fn ip_address(&self) -> Option<&str> {
96        match self {
97            Credentials::ApiKey { ip_address, .. }
98            | Credentials::JWT { ip_address, .. }
99            | Credentials::UserPassword { ip_address, .. }
100            | Credentials::Certificate { ip_address, .. } => ip_address.as_deref(),
101        }
102    }
103}
104
105/// Audit log entry
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct AuditLogEntry {
108    pub event_type: AuditEvent,
109    pub timestamp: DateTime<Utc>,
110    pub user_id: Option<String>,
111    pub ip_address: Option<String>,
112    pub success: bool,
113    pub details: String,
114}
115
116/// Audit filter for queries
117#[derive(Debug, Clone)]
118pub struct AuditFilter {
119    pub event_types: Option<Vec<AuditEvent>>,
120    pub user_id: Option<String>,
121    pub ip_address: Option<String>,
122    pub start_time: Option<DateTime<Utc>>,
123    pub end_time: Option<DateTime<Utc>>,
124    pub success: Option<bool>,
125}
126
127/// Threat context
128#[derive(Debug, Clone)]
129pub struct ThreatContext {
130    pub event_type: String,
131    pub user_id: Option<String>,
132    pub ip_address: Option<String>,
133    pub timestamp: DateTime<Utc>,
134    pub details: HashMap<String, String>,
135}
136
137/// Threat alert
138#[derive(Debug, Clone)]
139pub struct ThreatAlert {
140    pub id: Uuid,
141    pub rule_name: String,
142    pub severity: ThreatSeverity,
143    pub description: String,
144    pub context: ThreatContext,
145    pub timestamp: DateTime<Utc>,
146    pub resolved: bool,
147}
148
149/// Security metrics
150#[derive(Debug, Clone, Default)]
151pub struct SecurityMetrics {
152    pub authentication_attempts: u64,
153    pub authentication_successes: u64,
154    pub authentication_failures: u64,
155    pub authorization_checks: u64,
156    pub authorization_successes: u64,
157    pub authorization_failures: u64,
158    pub threat_alerts: u64,
159    pub rate_limit_violations: u64,
160    pub authentication_latency_ms: f64,
161    pub authorization_latency_ms: f64,
162}
163
164/// Security context for requests
165#[derive(Debug, Clone)]
166pub struct SecurityContext {
167    pub user_id: Option<String>,
168    pub session_id: Option<String>,
169    pub roles: HashSet<String>,
170    pub permissions: HashSet<Permission>,
171    pub attributes: HashMap<String, String>,
172    pub ip_address: Option<String>,
173    pub user_agent: Option<String>,
174    pub authentication_method: Option<AuthMethod>,
175    pub authenticated_at: Option<DateTime<Utc>>,
176}
177
178impl SecurityContext {
179    /// Check if user has permission
180    pub fn has_permission(&self, permission: &Permission) -> bool {
181        self.permissions.contains(permission)
182    }
183
184    /// Check if user has role
185    pub fn has_role(&self, role: &str) -> bool {
186        self.roles.contains(role)
187    }
188
189    /// Check if user has any of the specified roles
190    pub fn has_any_role(&self, roles: &[String]) -> bool {
191        roles.iter().any(|role| self.roles.contains(role))
192    }
193
194    /// Get attribute value
195    pub fn get_attribute(&self, name: &str) -> Option<&String> {
196        self.attributes.get(name)
197    }
198}