Skip to main content

attack/domain/
group.rs

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