1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
10pub struct DiscoveryConfig {
11 #[serde(default)]
12 pub enabled: bool,
13
14 #[serde(default = "default_discovery_methods")]
15 pub methods: Vec<DiscoveryMethod>,
16
17 pub output: Option<PathBuf>,
18
19 #[serde(default)]
20 pub on_findings: DiscoveryActions,
21}
22
23#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
24#[serde(rename_all = "snake_case")]
25pub enum DiscoveryMethod {
26 ConfigFiles,
27 Processes,
28 Network,
29 Dns,
30 WellKnown,
31}
32
33fn default_discovery_methods() -> Vec<DiscoveryMethod> {
34 vec![DiscoveryMethod::ConfigFiles, DiscoveryMethod::Processes]
35}
36
37#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
38pub struct DiscoveryActions {
39 #[serde(default)]
40 pub unmanaged_server: ActionLevel,
41
42 #[serde(default)]
43 pub no_auth: ActionLevel,
44}
45
46#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Default)]
47#[serde(rename_all = "snake_case")]
48pub enum ActionLevel {
49 #[default]
50 Log,
51 Warn,
52 Fail,
53}
54
55#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
60pub struct RuntimeMonitorConfig {
61 #[serde(default)]
62 pub enabled: bool,
63
64 #[serde(default)]
65 pub provider: MonitorProvider,
66
67 #[serde(default)]
69 pub scope: MonitorScopeConfig,
70
71 #[serde(default)]
72 pub rules: Vec<MonitorRule>,
73}
74
75#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
76#[serde(rename_all = "snake_case")]
77pub struct MonitorScopeConfig {
78 #[serde(default)]
79 pub mode: MonitorMode,
80
81 #[serde(default)]
82 pub cgroup: CgroupConfig,
83}
84
85impl Default for MonitorScopeConfig {
86 fn default() -> Self {
87 Self {
88 mode: MonitorMode::CgroupV2,
89 cgroup: CgroupConfig::default(),
90 }
91 }
92}
93
94#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Default)]
95#[serde(rename_all = "snake_case")]
96pub enum MonitorMode {
97 #[default]
98 CgroupV2,
99 PidSet, }
101
102#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
103pub struct CgroupConfig {
104 #[serde(default = "default_true")]
105 pub freeze_on_incident: bool,
106
107 #[serde(default = "default_true")]
108 pub create_leaf: bool,
109
110 #[serde(default = "default_assay_prefix")]
111 pub name_prefix: String,
112
113 #[serde(default = "default_true")]
114 pub cleanup: bool,
115
116 #[serde(default = "default_pids_max")]
117 pub pids_max: u32,
118}
119
120impl Default for CgroupConfig {
121 fn default() -> Self {
122 Self {
123 freeze_on_incident: true,
124 create_leaf: true,
125 name_prefix: default_assay_prefix(),
126 cleanup: true,
127 pids_max: default_pids_max(),
128 }
129 }
130}
131
132fn default_assay_prefix() -> String {
133 "assay".to_string()
134}
135
136fn default_pids_max() -> u32 {
137 2048
138}
139
140#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
141#[serde(rename_all = "snake_case")]
142pub enum MonitorProvider {
143 #[default]
144 Ebpf,
145}
146
147#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
149#[serde(rename_all = "snake_case")]
150pub enum Severity {
151 Low,
152 #[default]
153 Medium,
154 High,
155 Critical,
156}
157
158#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
159pub struct MonitorRule {
160 pub id: String,
161
162 #[serde(rename = "type")]
163 pub rule_type: MonitorRuleType,
164
165 #[serde(rename = "match")]
166 pub match_config: MonitorMatch,
167
168 #[serde(default)]
169 pub severity: Severity,
170
171 #[serde(default)]
172 pub action: MonitorAction,
173}
174
175#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
176#[serde(rename_all = "snake_case")]
177pub enum MonitorRuleType {
178 FileOpen,
179 NetConnect,
180 ProcExec,
181}
182
183#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
184pub struct MonitorMatch {
185 #[serde(default)]
186 pub path_globs: Vec<String>,
187
188 #[serde(default)]
189 pub dest_globs: Vec<String>,
190
191 #[serde(default)]
192 pub not: Option<Box<MonitorMatch>>,
193}
194
195#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Default)]
196#[serde(rename_all = "snake_case")]
197pub enum MonitorAction {
198 #[default]
199 Log,
200 Alert,
201 Deny,
202 TriggerKill,
203}
204
205#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
210pub struct KillSwitchConfig {
211 #[serde(default = "default_true")]
212 pub enabled: bool,
213
214 #[serde(default)]
215 pub mode: KillMode,
216
217 #[serde(default)]
218 pub kill_scope: KillScope,
219
220 #[serde(default = "default_grace_period")]
221 pub grace_period_ms: u64,
222
223 #[serde(default = "default_true")]
224 pub kill_children: bool,
225
226 #[serde(default)]
227 pub capture_state: bool,
228
229 pub output_dir: Option<PathBuf>,
230
231 #[serde(default)]
232 pub triggers: Vec<KillTrigger>,
233}
234
235impl Default for KillSwitchConfig {
236 fn default() -> Self {
237 Self {
238 enabled: true,
239 mode: KillMode::Graceful,
240 kill_scope: KillScope::default(),
241 grace_period_ms: default_grace_period(),
242 kill_children: true,
243 capture_state: false,
244 output_dir: None,
245 triggers: Vec::new(),
246 }
247 }
248}
249
250#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Default)]
251#[serde(rename_all = "snake_case")]
252pub enum KillMode {
253 #[default]
254 Graceful,
255 Immediate,
256}
257
258#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Default)]
259#[serde(rename_all = "snake_case")]
260pub enum KillScope {
261 #[default]
262 Cgroup,
263 PidFd,
264 LegacyPid,
265}
266
267#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
268pub struct KillTrigger {
269 pub on_rule: String,
270
271 #[serde(default)]
272 pub mode: Option<KillMode>,
273}
274
275fn default_true() -> bool {
276 true
277}
278fn default_grace_period() -> u64 {
279 3000
280}