clawdstrike_ocsf/objects/
file.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
7#[serde(deny_unknown_fields)]
8pub struct OcsfFile {
9 #[serde(skip_serializing_if = "Option::is_none")]
11 pub path: Option<String>,
12 #[serde(skip_serializing_if = "Option::is_none")]
14 pub name: Option<String>,
15 #[serde(skip_serializing_if = "Option::is_none")]
17 pub uid: Option<String>,
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub type_id: Option<u8>,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub size: Option<u64>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub hashes: Option<Vec<FileHash>>,
27}
28
29#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(deny_unknown_fields)]
32pub struct FileHash {
33 pub algorithm_id: u8,
35 pub value: String,
37}
38
39impl OcsfFile {
40 #[must_use]
42 pub fn with_name_from_path(mut self) -> Self {
43 if self.name.is_none() {
44 if let Some(ref path) = self.path {
45 self.name = path.rsplit('/').next().map(String::from);
46 }
47 }
48 self
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn file_roundtrip() {
58 let f = OcsfFile {
59 path: Some("/etc/shadow".to_string()),
60 name: Some("shadow".to_string()),
61 uid: None,
62 type_id: Some(1),
63 size: Some(1024),
64 hashes: Some(vec![FileHash {
65 algorithm_id: 3,
66 value: "abc123".to_string(),
67 }]),
68 };
69 let json = serde_json::to_string(&f).unwrap();
70 let f2: OcsfFile = serde_json::from_str(&json).unwrap();
71 assert_eq!(f, f2);
72 }
73
74 #[test]
75 fn name_from_path() {
76 let f = OcsfFile {
77 path: Some("/usr/bin/curl".to_string()),
78 name: None,
79 uid: None,
80 type_id: None,
81 size: None,
82 hashes: None,
83 }
84 .with_name_from_path();
85 assert_eq!(f.name.as_deref(), Some("curl"));
86 }
87
88 #[test]
89 fn name_from_path_preserves_existing() {
90 let f = OcsfFile {
91 path: Some("/usr/bin/curl".to_string()),
92 name: Some("custom".to_string()),
93 uid: None,
94 type_id: None,
95 size: None,
96 hashes: None,
97 }
98 .with_name_from_path();
99 assert_eq!(f.name.as_deref(), Some("custom"));
100 }
101}