1use crate::{config::SourceConfig, feeds::FeedFetcher, ThreatData};
4use anyhow::Result;
5use async_trait::async_trait;
6
7#[async_trait]
9pub trait ThreatSource: Send + Sync {
10 async fn fetch(&mut self) -> Result<ThreatData>;
12
13 fn config(&self) -> &SourceConfig;
15
16 fn name(&self) -> &str {
18 &self.config().name
19 }
20}
21
22pub 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 Ok(ThreatData {
43 vulnerabilities: vec![],
44 iocs: vec![],
45 threat_actors: vec![], raw_data: Some(json),
47 })
48 }
49
50 fn config(&self) -> &SourceConfig {
51 &self.config
52 }
53}
54
55pub 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 Ok(ThreatData {
75 vulnerabilities: vec![], 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
87pub 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 Ok(ThreatData {
107 vulnerabilities: vec![],
108 iocs: vec![], threat_actors: vec![],
110 raw_data: Some(json),
111 })
112 }
113
114 fn config(&self) -> &SourceConfig {
115 &self.config
116 }
117}
118
119pub 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