Skip to main content

attack/domain/
data_source.rs

1use serde::{Deserialize, Serialize};
2use stix_rs::{CommonProperties, StixObject};
3use crate::domain::AttackObject;
4
5/// Represents a MITRE ATT&CK Data Source (x-mitre-data-source).
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct DataSource {
8    #[serde(flatten)]
9    pub common: CommonProperties,
10
11    pub name: String,
12    pub description: Option<String>,
13
14    #[serde(default, rename = "x_mitre_platforms")]
15    pub platforms: Vec<String>,
16
17    #[serde(default, rename = "x_mitre_collection_layers")]
18    pub collection_layers: Vec<String>,
19
20    // Extended ATT&CK fields
21    #[serde(default, rename = "x_mitre_version")]
22    pub version: Option<String>,
23
24    #[serde(default, rename = "x_mitre_contributors")]
25    pub contributors: Vec<String>,
26
27    #[serde(default, rename = "x_mitre_domains")]
28    pub domains: Vec<String>,
29}
30
31impl StixObject for DataSource {
32    fn id(&self) -> &str {
33        &self.common.id
34    }
35
36    fn type_(&self) -> &str {
37        &self.common.r#type
38    }
39
40    fn created(&self) -> chrono::DateTime<chrono::Utc> {
41        self.common.created
42    }
43}
44
45impl AttackObject for DataSource {
46    fn name(&self) -> &str {
47        &self.name
48    }
49
50    fn description(&self) -> Option<&str> {
51        self.description.as_deref()
52    }
53
54    fn revoked(&self) -> bool {
55        self.common.revoked.unwrap_or(false)
56    }
57
58    fn deprecated(&self) -> bool {
59        self.common.custom_properties.get("x_mitre_deprecated").and_then(|v| v.as_bool()).unwrap_or(false)
60    }
61}