Skip to main content

clawdstrike_ocsf/objects/
process.rs

1//! OCSF Process object.
2
3use serde::{Deserialize, Serialize};
4
5use super::file::OcsfFile;
6
7/// OCSF Process object.
8#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
9#[serde(deny_unknown_fields)]
10pub struct OcsfProcess {
11    /// Process ID.
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub pid: Option<u32>,
14    /// Process name.
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub name: Option<String>,
17    /// Full command line.
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub cmd_line: Option<String>,
20    /// The binary / executable file.
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub file: Option<OcsfFile>,
23    /// User who owns the process.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub user: Option<OcsfUser>,
26    /// Parent process.
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub parent_process: Option<Box<OcsfProcess>>,
29    /// Current working directory.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub cwd: Option<String>,
32}
33
34/// Minimal user object embedded within process.
35#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
36#[serde(deny_unknown_fields)]
37pub struct OcsfUser {
38    /// User name.
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub name: Option<String>,
41    /// User UID.
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub uid: Option<String>,
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn process_roundtrip() {
52        let p = OcsfProcess {
53            pid: Some(1234),
54            name: Some("curl".to_string()),
55            cmd_line: Some("curl https://example.com".to_string()),
56            file: Some(OcsfFile {
57                path: Some("/usr/bin/curl".to_string()),
58                name: Some("curl".to_string()),
59                uid: None,
60                type_id: None,
61                size: None,
62                hashes: None,
63            }),
64            user: Some(OcsfUser {
65                name: Some("root".to_string()),
66                uid: Some("0".to_string()),
67            }),
68            parent_process: None,
69            cwd: Some("/tmp".to_string()),
70        };
71        let json = serde_json::to_string(&p).unwrap();
72        let p2: OcsfProcess = serde_json::from_str(&json).unwrap();
73        assert_eq!(p, p2);
74    }
75
76    #[test]
77    fn minimal_process() {
78        let p = OcsfProcess {
79            pid: None,
80            name: Some("sh".to_string()),
81            cmd_line: None,
82            file: None,
83            user: None,
84            parent_process: None,
85            cwd: None,
86        };
87        let json = serde_json::to_value(&p).unwrap();
88        assert!(json.get("pid").is_none());
89        assert_eq!(json["name"], "sh");
90    }
91}