Add source enrichment fields to forensic events matching aggregate reports

Co-authored-by: seanthegeek <44679+seanthegeek@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-14 16:45:26 +00:00
parent 91ae56c029
commit 19e8b498d0
2 changed files with 17 additions and 8 deletions
+7 -1
View File
@@ -465,6 +465,7 @@ class GoogleSecOpsClient:
source_ip = forensic_report["source"]["ip_address"]
source_country = forensic_report["source"].get("country")
source_reverse_dns = forensic_report["source"].get("reverse_dns")
source_base_domain = forensic_report["source"].get("base_domain")
source_name = forensic_report["source"].get("name")
source_type = forensic_report["source"].get("type")
@@ -509,7 +510,7 @@ class GoogleSecOpsClient:
],
}
# Add optional fields to detection_fields
# Add optional fields to detection_fields (matching aggregate report field names)
if source_name:
event["security_result"][0]["detection_fields"].append(
{"key": "dmarc.source_service_name", "value": source_name}
@@ -522,6 +523,11 @@ class GoogleSecOpsClient:
# Add optional context fields (low-value, not for dashboarding)
additional_context = []
if source_base_domain:
additional_context.append(
{"key": "source_base_domain", "value": source_base_domain}
)
if forensic_report.get("feedback_type"):
additional_context.append(
{"key": "feedback_type", "value": forensic_report["feedback_type"]}
+10 -7
View File
@@ -162,7 +162,7 @@ class Test(unittest.TestCase):
print()
from parsedmarc.google_secops import GoogleSecOpsClient
client = GoogleSecOpsClient()
client = GoogleSecOpsClient(use_stdout=True)
sample_path = "samples/aggregate/example.net!example.com!1529366400!1529452799.xml"
print("Testing Google SecOps aggregate conversion for {0}: ".format(sample_path), end="")
@@ -192,7 +192,7 @@ class Test(unittest.TestCase):
from parsedmarc.google_secops import GoogleSecOpsClient
# Test without payload
client = GoogleSecOpsClient(include_ruf_payload=False)
client = GoogleSecOpsClient(include_ruf_payload=False, use_stdout=True)
sample_path = "samples/forensic/dmarc_ruf_report_linkedin.eml"
print("Testing Google SecOps forensic conversion (no payload) for {0}: ".format(sample_path), end="")
@@ -220,7 +220,8 @@ class Test(unittest.TestCase):
# Test with payload
client_with_payload = GoogleSecOpsClient(
include_ruf_payload=True,
ruf_payload_max_bytes=100
ruf_payload_max_bytes=100,
use_stdout=True
)
print("Testing Google SecOps forensic conversion (with payload) for {0}: ".format(sample_path), end="")
@@ -256,13 +257,14 @@ class Test(unittest.TestCase):
print("Testing Google SecOps client configuration: ", end="")
# Test default configuration
client1 = GoogleSecOpsClient()
# Test stdout configuration
client1 = GoogleSecOpsClient(use_stdout=True)
assert client1.include_ruf_payload is False
assert client1.ruf_payload_max_bytes == 4096
assert client1.static_observer_vendor == "parsedmarc"
assert client1.static_observer_name is None
assert client1.static_environment is None
assert client1.use_stdout is True
# Test custom configuration
client2 = GoogleSecOpsClient(
@@ -270,7 +272,8 @@ class Test(unittest.TestCase):
ruf_payload_max_bytes=8192,
static_observer_name="test-observer",
static_observer_vendor="test-vendor",
static_environment="prod"
static_environment="prod",
use_stdout=True
)
assert client2.include_ruf_payload is True
assert client2.ruf_payload_max_bytes == 8192
@@ -285,7 +288,7 @@ class Test(unittest.TestCase):
print()
from parsedmarc.google_secops import GoogleSecOpsClient
client = GoogleSecOpsClient()
client = GoogleSecOpsClient(use_stdout=True)
sample_path = "samples/smtp_tls/rfc8460.json"
print("Testing Google SecOps SMTP TLS conversion for {0}: ".format(sample_path), end="")