Skip to main content

clawdstrike_ocsf/objects/
attack.rs

1//! OCSF Attack (MITRE ATT&CK) object.
2
3use serde::{Deserialize, Serialize};
4
5/// OCSF Attack object for MITRE ATT&CK mapping.
6#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(deny_unknown_fields)]
8pub struct Attack {
9    /// MITRE ATT&CK tactic (e.g., "Credential Access").
10    #[serde(skip_serializing_if = "Option::is_none")]
11    pub tactic: Option<AttackTactic>,
12    /// MITRE ATT&CK technique.
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub technique: Option<AttackTechnique>,
15    /// Framework version.
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub version: Option<String>,
18}
19
20/// MITRE ATT&CK tactic.
21#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
22#[serde(deny_unknown_fields)]
23pub struct AttackTactic {
24    /// Tactic name (e.g., "Initial Access").
25    pub name: String,
26    /// Tactic UID (e.g., "TA0001").
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub uid: Option<String>,
29}
30
31/// MITRE ATT&CK technique.
32#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
33#[serde(deny_unknown_fields)]
34pub struct AttackTechnique {
35    /// Technique name (e.g., "Phishing").
36    pub name: String,
37    /// Technique UID (e.g., "T1566").
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub uid: Option<String>,
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn attack_roundtrip() {
48        let a = Attack {
49            tactic: Some(AttackTactic {
50                name: "Credential Access".to_string(),
51                uid: Some("TA0006".to_string()),
52            }),
53            technique: Some(AttackTechnique {
54                name: "OS Credential Dumping".to_string(),
55                uid: Some("T1003".to_string()),
56            }),
57            version: Some("14.1".to_string()),
58        };
59        let json = serde_json::to_string(&a).unwrap();
60        let a2: Attack = serde_json::from_str(&json).unwrap();
61        assert_eq!(a, a2);
62    }
63}