threat_intel/
sources.rs

1//! Threat intelligence source implementations
2
3use crate::{config::SourceConfig, feeds::FeedFetcher, ThreatData};
4use anyhow::Result;
5use async_trait::async_trait;
6
7/// Trait for threat intelligence sources
8#[async_trait]
9pub trait ThreatSource: Send + Sync {
10    /// Fetch latest threat intelligence data from the source
11    async fn fetch(&mut self) -> Result<ThreatData>;
12
13    /// Get the source configuration
14    fn config(&self) -> &SourceConfig;
15
16    /// Get the source name
17    fn name(&self) -> &str {
18        &self.config().name
19    }
20}
21
22/// MITRE ATT&CK source implementation
23pub struct MitreAttackSource {
24    config: SourceConfig,
25    fetcher: FeedFetcher,
26}
27
28impl MitreAttackSource {
29    pub fn new(config: SourceConfig) -> Self {
30        let fetcher = FeedFetcher::new(config.clone());
31        Self { config, fetcher }
32    }
33}
34
35#[async_trait]
36impl ThreatSource for MitreAttackSource {
37    async fn fetch(&mut self) -> Result<ThreatData> {
38        let json = self.fetcher.fetch_json_secure().await?;
39
40        // Parse MITRE ATT&CK JSON format
41        // For now, return raw data
42        Ok(ThreatData {
43            vulnerabilities: vec![],
44            iocs: vec![],
45            threat_actors: vec![], // Would parse from JSON
46            raw_data: Some(json),
47        })
48    }
49
50    fn config(&self) -> &SourceConfig {
51        &self.config
52    }
53}
54
55/// CVE Database source implementation
56pub struct CVESource {
57    config: SourceConfig,
58    fetcher: FeedFetcher,
59}
60
61impl CVESource {
62    pub fn new(config: SourceConfig) -> Self {
63        let fetcher = FeedFetcher::new(config.clone());
64        Self { config, fetcher }
65    }
66}
67
68#[async_trait]
69impl ThreatSource for CVESource {
70    async fn fetch(&mut self) -> Result<ThreatData> {
71        let json = self.fetcher.fetch_json_secure().await?;
72
73        // Parse CVE JSON format
74        Ok(ThreatData {
75            vulnerabilities: vec![], // Would parse from JSON
76            iocs: vec![],
77            threat_actors: vec![],
78            raw_data: Some(json),
79        })
80    }
81
82    fn config(&self) -> &SourceConfig {
83        &self.config
84    }
85}
86
87/// OSINT source implementation (Abuse.ch, etc.)
88pub struct OSINTSource {
89    config: SourceConfig,
90    fetcher: FeedFetcher,
91}
92
93impl OSINTSource {
94    pub fn new(config: SourceConfig) -> Self {
95        let fetcher = FeedFetcher::new(config.clone());
96        Self { config, fetcher }
97    }
98}
99
100#[async_trait]
101impl ThreatSource for OSINTSource {
102    async fn fetch(&mut self) -> Result<ThreatData> {
103        let json = self.fetcher.fetch_json_secure().await?;
104
105        // Parse OSINT JSON format
106        Ok(ThreatData {
107            vulnerabilities: vec![],
108            iocs: vec![], // Would parse IOCs from JSON
109            threat_actors: vec![],
110            raw_data: Some(json),
111        })
112    }
113
114    fn config(&self) -> &SourceConfig {
115        &self.config
116    }
117}
118
119/// Generic source for custom/commercial feeds
120pub struct GenericSource {
121    config: SourceConfig,
122    fetcher: FeedFetcher,
123}
124
125impl GenericSource {
126    pub fn new(config: SourceConfig) -> Self {
127        let fetcher = FeedFetcher::new(config.clone());
128        Self { config, fetcher }
129    }
130}
131
132#[async_trait]
133impl ThreatSource for GenericSource {
134    async fn fetch(&mut self) -> Result<ThreatData> {
135        let json = self.fetcher.fetch_json_secure().await?;
136
137        Ok(ThreatData {
138            vulnerabilities: vec![],
139            iocs: vec![],
140            threat_actors: vec![],
141            raw_data: Some(json),
142        })
143    }
144
145    fn config(&self) -> &SourceConfig {
146        &self.config
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153    use crate::config::{AuthType, SourceCapability, SourceType, UpdateFrequency};
154
155    fn create_test_config() -> SourceConfig {
156        SourceConfig {
157            id: "test".to_string(),
158            name: "Test Source".to_string(),
159            source_type: SourceType::Custom,
160            enabled: true,
161            api_url: Some("https://example.com/api".to_string()),
162            api_key: None,
163            auth_type: AuthType::None,
164            update_frequency: UpdateFrequency::Manual,
165            priority: 5,
166            capabilities: vec![SourceCapability::Vulnerabilities],
167            timeout_secs: 30,
168            retry_count: 1,
169        }
170    }
171
172    #[test]
173    fn test_source_creation() {
174        let config = create_test_config();
175        let source = GenericSource::new(config.clone());
176
177        assert_eq!(source.name(), "Test Source");
178        assert_eq!(source.config().id, "test");
179    }
180
181    #[test]
182    fn test_mitre_attack_source_creation() {
183        let config = create_test_config();
184        let source = MitreAttackSource::new(config);
185
186        assert_eq!(source.name(), "Test Source");
187    }
188
189    #[test]
190    fn test_cve_source_creation() {
191        let config = create_test_config();
192        let source = CVESource::new(config);
193
194        assert_eq!(source.name(), "Test Source");
195    }
196
197    #[test]
198    fn test_osint_source_creation() {
199        let config = create_test_config();
200        let source = OSINTSource::new(config);
201
202        assert_eq!(source.name(), "Test Source");
203    }
204}
205