mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
feat(SecurityHub): add compliance details to Security Hub findings (#2100)
This commit is contained in:
@@ -8,11 +8,17 @@ from prowler.config.config import (
|
||||
timestamp_utc,
|
||||
)
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.lib.outputs.models import Compliance, ProductFields, Resource, Severity
|
||||
from prowler.lib.outputs.models import (
|
||||
Compliance,
|
||||
ProductFields,
|
||||
Resource,
|
||||
Severity,
|
||||
get_check_compliance,
|
||||
)
|
||||
from prowler.lib.utils.utils import hash_sha512, open_file
|
||||
|
||||
|
||||
def fill_json_asff(finding_output, audit_info, finding):
|
||||
def fill_json_asff(finding_output, audit_info, finding, output_options):
|
||||
# Check if there are no resources in the finding
|
||||
if finding.resource_arn == "":
|
||||
if finding.resource_id == "":
|
||||
@@ -40,14 +46,22 @@ def fill_json_asff(finding_output, audit_info, finding):
|
||||
Region=finding.region,
|
||||
)
|
||||
]
|
||||
# Check if any Requirement has > 64 characters
|
||||
check_types = []
|
||||
for type in finding.check_metadata.CheckType:
|
||||
check_types.extend(type.split("/"))
|
||||
# Iterate for each compliance framework
|
||||
compliance_summary = []
|
||||
associated_standards = []
|
||||
check_compliance = get_check_compliance(finding, "aws", output_options)
|
||||
for key, value in check_compliance.items():
|
||||
associated_standards.append({"StandardsId": key})
|
||||
item = f"{key} {' '.join(value)}"
|
||||
if len(item) > 64:
|
||||
item = item[0:63]
|
||||
compliance_summary.append(item)
|
||||
|
||||
# Add ED to PASS or FAIL (PASSED/FAILED)
|
||||
finding_output.Compliance = Compliance(
|
||||
Status=finding.status + "ED",
|
||||
RelatedRequirements=check_types,
|
||||
AssociatedStandards=associated_standards,
|
||||
RelatedRequirements=compliance_summary,
|
||||
)
|
||||
finding_output.Remediation = {
|
||||
"Recommendation": finding.check_metadata.Remediation.Recommendation
|
||||
|
||||
@@ -518,6 +518,7 @@ class Resource(BaseModel):
|
||||
class Compliance(BaseModel):
|
||||
Status: str
|
||||
RelatedRequirements: List[str]
|
||||
AssociatedStandards: List[dict]
|
||||
|
||||
|
||||
class Check_Output_JSON_ASFF(BaseModel):
|
||||
|
||||
@@ -108,7 +108,9 @@ def report(check_findings, output_options, audit_info):
|
||||
|
||||
if "json-asff" in file_descriptors:
|
||||
finding_output = Check_Output_JSON_ASFF()
|
||||
fill_json_asff(finding_output, audit_info, finding)
|
||||
fill_json_asff(
|
||||
finding_output, audit_info, finding, output_options
|
||||
)
|
||||
|
||||
json.dump(
|
||||
finding_output.dict(),
|
||||
|
||||
@@ -451,13 +451,17 @@ class Test_Outputs:
|
||||
|
||||
expected.Compliance = Compliance(
|
||||
Status="PASS" + "ED",
|
||||
RelatedRequirements=finding.check_metadata.CheckType,
|
||||
RelatedRequirements=[],
|
||||
AssociatedStandards=[],
|
||||
)
|
||||
expected.Remediation = {
|
||||
"Recommendation": finding.check_metadata.Remediation.Recommendation
|
||||
}
|
||||
output_options = mock.MagicMock()
|
||||
|
||||
assert fill_json_asff(input, input_audit_info, finding) == expected
|
||||
assert (
|
||||
fill_json_asff(input, input_audit_info, finding, output_options) == expected
|
||||
)
|
||||
|
||||
@mock_s3
|
||||
def test_send_to_s3_bucket(self):
|
||||
@@ -651,8 +655,8 @@ class Test_Outputs:
|
||||
finding.status_extended = "This is a test"
|
||||
|
||||
finding_output = Check_Output_JSON_ASFF()
|
||||
|
||||
fill_json_asff(finding_output, input_audit_info, finding)
|
||||
output_options = mock.MagicMock()
|
||||
fill_json_asff(finding_output, input_audit_info, finding, output_options)
|
||||
|
||||
assert (
|
||||
send_to_security_hub(
|
||||
|
||||
Reference in New Issue
Block a user