-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathjson_parser.py
More file actions
106 lines (86 loc) · 3.63 KB
/
json_parser.py
File metadata and controls
106 lines (86 loc) · 3.63 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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""
JSON parser for Orca Security alert exports.
This module handles parsing of Orca Security alerts exported in JSON format.
The JSON export is an array of alert objects with nested structures for
CloudAccount and Inventory fields.
Expected JSON structure:
[
{
"Title": "...",
"OrcaScore": 5.1,
"Category": "...",
"Source": "...",
"Status": "open",
"CreatedAt": "2025-01-15T10:30:00+00:00",
"LastSeen": "2025-02-01T12:00:00+00:00",
"Labels": ["label1", "label2"],
"CloudAccount": {"Name": "..."},
"Inventory": {"Name": "..."}
},
...
]
"""
import json
from dojo.models import Finding
from dojo.tools.orca_security.helpers import (
build_description,
build_severity_justification,
map_orca_severity,
parse_date,
truncate_title,
)
class OrcaSecurityJSONParser:
"""Parse Orca Security JSON alert exports."""
def parse(self, content):
"""
Parse JSON content and return a list of Finding objects.
Args:
content: String containing the JSON file content (array of alerts)
Returns:
list[Finding]: List of DefectDojo Finding objects
"""
data = json.loads(content)
findings = []
for item in data:
# Extract top-level fields
title_raw = (item.get("Title") or "").strip()
category = (item.get("Category") or "").strip()
source = (item.get("Source") or "").strip()
status = (item.get("Status") or "").strip()
created_at = (item.get("CreatedAt") or "").strip()
last_seen = (item.get("LastSeen") or "").strip()
orca_score = item.get("OrcaScore") # Keep as numeric, not string
labels = item.get("Labels") or [] # Already a list in JSON
# Extract nested fields from CloudAccount and Inventory objects
cloud_account = item.get("CloudAccount") or {}
cloud_account_name = (cloud_account.get("Name") or "").strip()
inventory = item.get("Inventory") or {}
inventory_name = (inventory.get("Name") or "").strip()
# Transform fields for DefectDojo
title = truncate_title(title_raw)
severity = map_orca_severity(orca_score)
# Build structured description with all alert metadata
description = build_description(
title_raw, category, source, inventory_name, cloud_account_name,
orca_score, status, created_at, last_seen, labels,
)
# Create the Finding object with all mapped fields
finding = Finding(
title=title,
severity=severity,
description=description,
# Preserve original OrcaScore in severity_justification
severity_justification=build_severity_justification(orca_score),
static_finding=True, # CSPM scan data is static analysis
dynamic_finding=False,
component_name=inventory_name or None, # Inventory is the specific resource
date=parse_date(created_at),
)
# Set active status based on Orca's status field
# "open" alerts are active, all other statuses (closed, resolved, etc.) are inactive
finding.active = status.lower() == "open" if status else True
# Store labels as tags for searchability in DefectDojo
if labels:
finding.unsaved_tags = labels
findings.append(finding)
return findings