forked from PierreGode/Ragnar
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlynis_parser.py
More file actions
83 lines (65 loc) · 2.52 KB
/
lynis_parser.py
File metadata and controls
83 lines (65 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""Utility helpers for parsing Lynis /var/log/lynis-report.dat files."""
from __future__ import annotations
from typing import Dict, List, Tuple
ENTRY_KEYS: Tuple[str, ...] = ("code", "message", "detail", "remediation")
PLACEHOLDER_VALUES = {"-", ""}
def _cleanup(value: str) -> str:
"""Normalize placeholder values that Lynis uses for empty fields."""
if value is None:
return ""
stripped = value.strip()
return "" if stripped in PLACEHOLDER_VALUES else stripped
def _split_pipe_payload(payload: str) -> Dict[str, str]:
parts = [part.strip() for part in payload.split("|")]
# Extend the list so unpacking always works even if Lynis omits fields
while len(parts) < len(ENTRY_KEYS):
parts.append("")
code, message, detail, remediation, *rest = parts + [""]
return {
"code": _cleanup(code),
"message": _cleanup(message) or payload.strip(),
"detail": _cleanup(detail),
"remediation": _cleanup(remediation or (rest[0] if rest else "")),
"raw": payload.strip()
}
def _parse_vulnerable_package(payload: str) -> Dict[str, str]:
parts = [part.strip() for part in payload.split("|")]
while len(parts) < 4:
parts.append("")
package, version, status, reference, *rest = parts + [""]
return {
"package": _cleanup(package),
"version": _cleanup(version),
"status": _cleanup(status),
"reference": _cleanup(reference or (rest[0] if rest else "")),
"raw": payload.strip()
}
def parse_lynis_dat(content: str) -> Dict[str, object]:
"""Parse the contents of lynis-report.dat into structured data."""
data = {
"metadata": {},
"warnings": [],
"suggestions": [],
"vulnerable_packages": [],
}
if not content:
return data
for line in content.splitlines():
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
if "=" not in stripped:
continue
key, value = stripped.split("=", 1)
key = key.strip()
value = value.strip()
base_key = key.split("[", 1)[0]
if base_key == "warning":
data["warnings"].append(_split_pipe_payload(value))
elif base_key == "suggestion":
data["suggestions"].append(_split_pipe_payload(value))
elif base_key == "vulnerable_package":
data["vulnerable_packages"].append(_parse_vulnerable_package(value))
else:
data["metadata"][base_key] = value
return data