1use crate::config::db_schema_file;
2use crate::error::Result;
3
4pub const SCHEMA_PBSL: &str = include_str!("../../schema/schema.pbsl");
7
8pub const REQUIRED_COLLECTIONS: [&str; 6] = [
11 "Assets",
12 "Services",
13 "Findings",
14 "Observations",
15 "ScanRuns",
16 "ExploitExecutions",
17];
18
19pub struct FieldDef {
20 pub name: &'static str,
21 pub kind: &'static str,
22 pub required: bool,
23 pub unique: bool,
24}
25
26pub fn field_defs(collection: &str) -> &'static [FieldDef] {
27 match collection {
28 "Assets" => &[
29 FieldDef {
30 name: "stable_id",
31 kind: "text",
32 required: true,
33 unique: true,
34 },
35 FieldDef {
36 name: "asset_type",
37 kind: "select",
38 required: false,
39 unique: false,
40 },
41 FieldDef {
42 name: "name",
43 kind: "text",
44 required: true,
45 unique: false,
46 },
47 FieldDef {
48 name: "ip",
49 kind: "text",
50 required: false,
51 unique: false,
52 },
53 FieldDef {
54 name: "fqdn",
55 kind: "text",
56 required: false,
57 unique: false,
58 },
59 FieldDef {
60 name: "reverse_dns",
61 kind: "text",
62 required: false,
63 unique: false,
64 },
65 FieldDef {
66 name: "first_seen",
67 kind: "text",
68 required: false,
69 unique: false,
70 },
71 FieldDef {
72 name: "last_seen",
73 kind: "text",
74 required: false,
75 unique: false,
76 },
77 FieldDef {
78 name: "status",
79 kind: "text",
80 required: false,
81 unique: false,
82 },
83 FieldDef {
84 name: "metadata",
85 kind: "json",
86 required: false,
87 unique: false,
88 },
89 ],
90 "Services" => &[
91 FieldDef {
92 name: "stable_id",
93 kind: "text",
94 required: true,
95 unique: true,
96 },
97 FieldDef {
98 name: "asset_id",
99 kind: "text",
100 required: true,
101 unique: false,
102 },
103 FieldDef {
104 name: "port",
105 kind: "number",
106 required: false,
107 unique: false,
108 },
109 FieldDef {
110 name: "protocol",
111 kind: "text",
112 required: false,
113 unique: false,
114 },
115 FieldDef {
116 name: "service_name",
117 kind: "text",
118 required: false,
119 unique: false,
120 },
121 FieldDef {
122 name: "product",
123 kind: "text",
124 required: false,
125 unique: false,
126 },
127 FieldDef {
128 name: "version",
129 kind: "text",
130 required: false,
131 unique: false,
132 },
133 FieldDef {
134 name: "version_str",
135 kind: "text",
136 required: false,
137 unique: false,
138 },
139 FieldDef {
140 name: "banner",
141 kind: "text",
142 required: false,
143 unique: false,
144 },
145 FieldDef {
146 name: "technologies",
147 kind: "json",
148 required: false,
149 unique: false,
150 },
151 FieldDef {
152 name: "cpes",
153 kind: "json",
154 required: false,
155 unique: false,
156 },
157 FieldDef {
158 name: "first_seen",
159 kind: "text",
160 required: false,
161 unique: false,
162 },
163 FieldDef {
164 name: "last_seen",
165 kind: "text",
166 required: false,
167 unique: false,
168 },
169 FieldDef {
170 name: "status",
171 kind: "text",
172 required: false,
173 unique: false,
174 },
175 FieldDef {
176 name: "metadata",
177 kind: "json",
178 required: false,
179 unique: false,
180 },
181 ],
182 "Findings" => &[
183 FieldDef {
184 name: "stable_id",
185 kind: "text",
186 required: true,
187 unique: true,
188 },
189 FieldDef {
190 name: "asset_id",
191 kind: "text",
192 required: true,
193 unique: false,
194 },
195 FieldDef {
196 name: "service_id",
197 kind: "text",
198 required: false,
199 unique: false,
200 },
201 FieldDef {
202 name: "title",
203 kind: "text",
204 required: true,
205 unique: false,
206 },
207 FieldDef {
208 name: "severity",
209 kind: "text",
210 required: false,
211 unique: false,
212 },
213 FieldDef {
214 name: "tool",
215 kind: "text",
216 required: false,
217 unique: false,
218 },
219 FieldDef {
220 name: "target_url",
221 kind: "text",
222 required: false,
223 unique: false,
224 },
225 FieldDef {
226 name: "detail",
227 kind: "text",
228 required: false,
229 unique: false,
230 },
231 FieldDef {
232 name: "detail_path",
233 kind: "text",
234 required: false,
235 unique: false,
236 },
237 FieldDef {
238 name: "reference",
239 kind: "text",
240 required: false,
241 unique: false,
242 },
243 FieldDef {
244 name: "cves",
245 kind: "json",
246 required: false,
247 unique: false,
248 },
249 FieldDef {
250 name: "endpoints",
251 kind: "json",
252 required: false,
253 unique: false,
254 },
255 FieldDef {
256 name: "technologies",
257 kind: "json",
258 required: false,
259 unique: false,
260 },
261 FieldDef {
262 name: "first_seen",
263 kind: "text",
264 required: false,
265 unique: false,
266 },
267 FieldDef {
268 name: "last_seen",
269 kind: "text",
270 required: false,
271 unique: false,
272 },
273 FieldDef {
274 name: "status",
275 kind: "text",
276 required: false,
277 unique: false,
278 },
279 FieldDef {
280 name: "exploitability",
281 kind: "text",
282 required: false,
283 unique: false,
284 },
285 FieldDef {
286 name: "metadata",
287 kind: "json",
288 required: false,
289 unique: false,
290 },
291 ],
292 "Observations" => &[
293 FieldDef {
294 name: "stable_id",
295 kind: "text",
296 required: true,
297 unique: true,
298 },
299 FieldDef {
300 name: "run_id",
301 kind: "text",
302 required: true,
303 unique: false,
304 },
305 FieldDef {
306 name: "subject_type",
307 kind: "text",
308 required: true,
309 unique: false,
310 },
311 FieldDef {
312 name: "subject_id",
313 kind: "text",
314 required: true,
315 unique: false,
316 },
317 FieldDef {
318 name: "kind",
319 kind: "text",
320 required: true,
321 unique: false,
322 },
323 FieldDef {
324 name: "before",
325 kind: "json",
326 required: false,
327 unique: false,
328 },
329 FieldDef {
330 name: "after",
331 kind: "json",
332 required: false,
333 unique: false,
334 },
335 FieldDef {
336 name: "detail",
337 kind: "text",
338 required: false,
339 unique: false,
340 },
341 FieldDef {
342 name: "observed_at",
343 kind: "text",
344 required: false,
345 unique: false,
346 },
347 ],
348 "ScanRuns" => &[
349 FieldDef {
350 name: "stable_id",
351 kind: "text",
352 required: true,
353 unique: true,
354 },
355 FieldDef {
356 name: "target",
357 kind: "text",
358 required: true,
359 unique: false,
360 },
361 FieldDef {
362 name: "folder",
363 kind: "text",
364 required: false,
365 unique: false,
366 },
367 FieldDef {
368 name: "started_at",
369 kind: "text",
370 required: false,
371 unique: false,
372 },
373 FieldDef {
374 name: "finished_at",
375 kind: "text",
376 required: false,
377 unique: false,
378 },
379 FieldDef {
380 name: "tools",
381 kind: "json",
382 required: false,
383 unique: false,
384 },
385 FieldDef {
386 name: "artifacts",
387 kind: "json",
388 required: false,
389 unique: false,
390 },
391 FieldDef {
392 name: "content_hash",
393 kind: "text",
394 required: false,
395 unique: false,
396 },
397 FieldDef {
398 name: "imported_at",
399 kind: "text",
400 required: false,
401 unique: false,
402 },
403 FieldDef {
404 name: "stats",
405 kind: "json",
406 required: false,
407 unique: false,
408 },
409 ],
410 "ExploitExecutions" => &[
411 FieldDef {
412 name: "execution_id",
413 kind: "text",
414 required: true,
415 unique: true,
416 },
417 FieldDef {
418 name: "run_id",
419 kind: "text",
420 required: true,
421 unique: false,
422 },
423 FieldDef {
424 name: "asset_id",
425 kind: "text",
426 required: true,
427 unique: false,
428 },
429 FieldDef {
430 name: "vulnerability_id",
431 kind: "text",
432 required: true,
433 unique: false,
434 },
435 FieldDef {
436 name: "module_type",
437 kind: "text",
438 required: false,
439 unique: false,
440 },
441 FieldDef {
442 name: "module",
443 kind: "text",
444 required: true,
445 unique: false,
446 },
447 FieldDef {
448 name: "host",
449 kind: "text",
450 required: false,
451 unique: false,
452 },
453 FieldDef {
454 name: "payload",
455 kind: "text",
456 required: false,
457 unique: false,
458 },
459 FieldDef {
460 name: "status",
461 kind: "text",
462 required: false,
463 unique: false,
464 },
465 FieldDef {
466 name: "start_time",
467 kind: "text",
468 required: false,
469 unique: false,
470 },
471 FieldDef {
472 name: "finish_time",
473 kind: "text",
474 required: false,
475 unique: false,
476 },
477 FieldDef {
478 name: "job_id",
479 kind: "text",
480 required: false,
481 unique: false,
482 },
483 FieldDef {
484 name: "session_id",
485 kind: "text",
486 required: false,
487 unique: false,
488 },
489 FieldDef {
490 name: "error",
491 kind: "text",
492 required: false,
493 unique: false,
494 },
495 FieldDef {
496 name: "loot",
497 kind: "json",
498 required: false,
499 unique: false,
500 },
501 FieldDef {
502 name: "options",
503 kind: "json",
504 required: false,
505 unique: false,
506 },
507 FieldDef {
508 name: "selected",
509 kind: "bool",
510 required: false,
511 unique: false,
512 },
513 FieldDef {
514 name: "created_at",
515 kind: "text",
516 required: false,
517 unique: false,
518 },
519 ],
520 _ => &[],
521 }
522}
523
524pub fn write_schema_file() -> Result<std::path::PathBuf> {
528 let path = db_schema_file();
529 if let Some(parent) = path.parent() {
530 std::fs::create_dir_all(parent)?;
531 }
532 std::fs::write(&path, SCHEMA_PBSL)?;
533 Ok(path)
534}