kindly_guard_server/storage/
mod.rs

1// Copyright 2025 Kindly Software Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! Storage abstraction layer for persistence
15//!
16//! This module provides trait-based storage abstractions that allow
17//! `KindlyGuard` to persist security events, rate limit states, and
18//! correlation data across restarts.
19
20use anyhow::Result;
21use async_trait::async_trait;
22use chrono::{DateTime, Utc};
23use serde::{Deserialize, Serialize};
24use std::sync::Arc;
25use std::time::Duration;
26
27#[cfg(feature = "enhanced")]
28pub mod enhanced;
29pub mod memory;
30
31// Re-exports
32#[cfg(feature = "enhanced")]
33pub use enhanced::EnhancedStorage;
34pub use memory::InMemoryStorage;
35
36use crate::traits::{RateLimitKey, SecurityEvent};
37
38/// Unique identifier for stored events
39#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
40pub struct EventId(pub String);
41
42/// Unique identifier for snapshots
43#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
44pub struct SnapshotId(pub String);
45
46/// Filter for querying events
47#[derive(Debug, Clone, Default, Serialize, Deserialize)]
48pub struct EventFilter {
49    /// Filter by client ID
50    pub client_id: Option<String>,
51    /// Filter by event type
52    pub event_type: Option<String>,
53    /// Events after this time
54    pub from_time: Option<DateTime<Utc>>,
55    /// Events before this time
56    pub to_time: Option<DateTime<Utc>>,
57    /// Maximum number of results
58    pub limit: Option<usize>,
59    /// Threat severity filter
60    pub min_severity: Option<String>,
61}
62
63/// Rate limit state that needs persistence
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct RateLimitState {
66    /// Current token count
67    pub tokens: f64,
68    /// Last refill time
69    pub last_refill: DateTime<Utc>,
70    /// Number of requests
71    pub request_count: u64,
72    /// Active penalty multiplier
73    pub penalty_multiplier: f64,
74}
75
76/// Correlation state for pattern detection
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct CorrelationState {
79    /// Active correlation windows
80    pub windows: Vec<CorrelationWindow>,
81    /// Detected patterns
82    pub patterns: Vec<DetectedPattern>,
83    /// Last update time
84    pub last_update: DateTime<Utc>,
85}
86
87/// Time window for correlation
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct CorrelationWindow {
90    pub id: String,
91    pub start_time: DateTime<Utc>,
92    pub end_time: DateTime<Utc>,
93    pub events: Vec<EventId>,
94}
95
96/// Detected threat pattern
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct DetectedPattern {
99    pub pattern_type: String,
100    pub confidence: f64,
101    pub events: Vec<EventId>,
102    pub detected_at: DateTime<Utc>,
103}
104
105/// Storage provider trait for persistence
106#[async_trait]
107pub trait StorageProvider: Send + Sync {
108    /// Store a security event
109    async fn store_event(&self, event: &SecurityEvent) -> Result<EventId>;
110
111    /// Retrieve an event by ID
112    async fn get_event(&self, id: &EventId) -> Result<Option<SecurityEvent>>;
113
114    /// Query events with filters
115    async fn query_events(&self, filter: EventFilter) -> Result<Vec<SecurityEvent>>;
116
117    /// Store rate limit state
118    async fn store_rate_limit_state(
119        &self,
120        key: &RateLimitKey,
121        state: &RateLimitState,
122    ) -> Result<()>;
123
124    /// Get rate limit state
125    async fn get_rate_limit_state(&self, key: &RateLimitKey) -> Result<Option<RateLimitState>>;
126
127    /// Clear old rate limit states
128    async fn cleanup_rate_limit_states(&self, older_than: Duration) -> Result<u64>;
129
130    /// Store correlation state
131    async fn store_correlation_state(
132        &self,
133        client_id: &str,
134        state: &CorrelationState,
135    ) -> Result<()>;
136
137    /// Get correlation state
138    async fn get_correlation_state(&self, client_id: &str) -> Result<Option<CorrelationState>>;
139
140    /// Create a snapshot
141    async fn create_snapshot(&self) -> Result<SnapshotId>;
142
143    /// List available snapshots
144    async fn list_snapshots(&self) -> Result<Vec<(SnapshotId, DateTime<Utc>)>>;
145
146    /// Restore from snapshot
147    async fn restore_snapshot(&self, id: &SnapshotId) -> Result<()>;
148
149    /// Delete a snapshot
150    async fn delete_snapshot(&self, id: &SnapshotId) -> Result<()>;
151
152    /// Get storage statistics
153    async fn get_stats(&self) -> Result<StorageStats>;
154
155    /// Compact/optimize storage
156    async fn compact(&self) -> Result<()>;
157}
158
159/// Extended storage with archival support
160#[async_trait]
161pub trait ArchivalStorage: StorageProvider {
162    /// Archive old events
163    async fn archive_events(&self, older_than: Duration) -> Result<u64>;
164
165    /// Query archived events
166    async fn query_archived_events(&self, filter: EventFilter) -> Result<Vec<SecurityEvent>>;
167
168    /// Restore events from archive
169    async fn restore_from_archive(&self, filter: EventFilter) -> Result<u64>;
170
171    /// Get archive statistics
172    async fn get_archive_stats(&self) -> Result<ArchiveStats>;
173}
174
175/// Storage statistics
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct StorageStats {
178    /// Total events stored
179    pub event_count: u64,
180    /// Total storage size in bytes
181    pub total_size: u64,
182    /// Number of rate limit entries
183    pub rate_limit_entries: u64,
184    /// Number of correlation states
185    pub correlation_states: u64,
186    /// Storage type identifier
187    pub storage_type: String,
188    /// Additional metadata
189    pub metadata: serde_json::Value,
190}
191
192/// Archive statistics
193#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct ArchiveStats {
195    /// Total archived events
196    pub archived_events: u64,
197    /// Archive size in bytes
198    pub archive_size: u64,
199    /// Oldest archived event
200    pub oldest_event: Option<DateTime<Utc>>,
201    /// Newest archived event
202    pub newest_event: Option<DateTime<Utc>>,
203}
204
205/// Storage configuration
206#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct StorageConfig {
208    /// Enable persistence
209    pub enabled: bool,
210    /// Storage type
211    pub storage_type: StorageType,
212    /// Data directory (for file-based storage)
213    pub data_dir: Option<String>,
214    /// Connection string (for remote storage)
215    pub connection_string: Option<String>,
216    /// Retention period in days
217    pub retention_days: u32,
218    /// Archive older than days
219    pub archive_after_days: Option<u32>,
220    /// Maximum storage size in MB
221    pub max_storage_mb: Option<u64>,
222    /// Enable compression
223    pub compression: bool,
224    /// Enable encryption at rest
225    pub encryption_at_rest: bool,
226}
227
228impl Default for StorageConfig {
229    fn default() -> Self {
230        Self {
231            enabled: false,
232            storage_type: StorageType::Memory,
233            data_dir: None,
234            connection_string: None,
235            retention_days: 30,
236            archive_after_days: None,
237            max_storage_mb: Some(1024), // 1GB default
238            compression: true,
239            encryption_at_rest: false,
240        }
241    }
242}
243
244/// Storage type selection
245#[derive(Debug, Clone, Serialize, Deserialize)]
246#[serde(rename_all = "lowercase")]
247pub enum StorageType {
248    /// In-memory storage (non-persistent)
249    Memory,
250    /// File-based storage
251    File,
252    /// `RocksDB` embedded database
253    RocksDb,
254    /// Redis for distributed cache
255    Redis,
256    /// `PostgreSQL` for structured queries
257    Postgres,
258    /// S3-compatible object storage
259    S3,
260    /// Enhanced storage with performance optimizations
261    #[cfg(feature = "enhanced")]
262    Enhanced,
263}
264
265/// Factory for creating storage providers
266pub trait StorageProviderFactory: Send + Sync {
267    /// Create a storage provider from configuration
268    fn create(&self, config: &StorageConfig) -> Result<Arc<dyn StorageProvider>>;
269}
270
271/// Default storage factory
272pub struct DefaultStorageFactory;
273
274impl StorageProviderFactory for DefaultStorageFactory {
275    fn create(&self, config: &StorageConfig) -> Result<Arc<dyn StorageProvider>> {
276        match config.storage_type {
277            StorageType::Memory => Ok(Arc::new(InMemoryStorage::new())),
278            #[cfg(feature = "enhanced")]
279            StorageType::Enhanced => Ok(Arc::new(EnhancedStorage::new(config.clone())?)),
280            _ => Ok(Arc::new(InMemoryStorage::new())), // Fallback to memory for now
281        }
282    }
283}
284
285/// Create a storage provider based on configuration
286pub fn create_storage_provider(_config: &crate::config::Config) -> Arc<dyn StorageProvider> {
287    let factory = DefaultStorageFactory;
288    // For now, use a default storage config
289    // TODO: Add storage config to main Config struct
290    let storage_config = StorageConfig::default();
291    factory
292        .create(&storage_config)
293        .unwrap_or_else(|_| Arc::new(InMemoryStorage::new()))
294}