Skip to content

Commit

Permalink
AWS Security Hub parser: organize and extend test cases (#8628)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaszn authored Sep 13, 2023
1 parent 7ed5d39 commit 98914f2
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 12 deletions.
6 changes: 4 additions & 2 deletions dojo/tools/awssecurityhub/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ def get_description_for_scan_types(self, scan_type):

def get_findings(self, filehandle, test):
tree = json.load(filehandle)
if not isinstance(tree, dict):
raise ValueError("Incorrect Security Hub report format")
return self.get_items(tree, test)

def get_items(self, tree, test):
def get_items(self, tree: dict, test):
items = {}
# DefectDojo/django-DefectDojo/issues/2780
findings = tree.get("Findings", tree.get("findings", None))
Expand All @@ -34,7 +36,7 @@ def get_items(self, tree, test):
return list(items.values())


def get_item(finding, test):
def get_item(finding: dict, test):
aws_scanner_type = finding.get("ProductFields", {}).get("aws/securityhub/ProductName", "")
finding_id = finding.get("Id", "")
title = finding.get("Title", "")
Expand Down
17 changes: 17 additions & 0 deletions unittests/scans/awssecurityhub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
AWS Security Hub consolidates findings from a multitude of sources. For a detailed list of integrations with AWS Services and third-party products, please refer to its [official documentation](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-providers.html).

Given the variety of finding contents, DefectDojo offers varying degrees of support for each provider. However, it should at least import basic information without errors.

This directory contains sample reports from Security Hub. They are meant as test cases.

To keep some order, let's keep them prefixed with the names of the services that generated them:

* `config_`: findings generated by AWS Config rules, for example by benchmarking against "AWS Foundational Security Best Practices"

* `inspector_ec2_`: findings from AWS Inspector with results of scanning EC2 instances

* `inspector_ecr_`: findings from AWS Inspector with results of Enhanced ECR Scanning

* `inspector_lambda_`: findings from AWS Inspector with results of scanning Lambdas

* `guardduty_`: findings from AWS Guard Duty
112 changes: 112 additions & 0 deletions unittests/scans/awssecurityhub/inspector_ec2_ghsa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"Findings": [
{
"SchemaVersion": "2018-10-08",
"Id": "arn:aws:inspector2:eu-central-1:012345678912:finding/e07acd3c1cac9df14b96604ceef247be",
"ProductArn": "arn:aws:securityhub:eu-central-1::product/aws/inspector",
"ProductName": "Inspector",
"CompanyName": "Amazon",
"Region": "eu-central-1",
"GeneratorId": "AWSInspector",
"AwsAccountId": "012345678912",
"Types": ["Software and Configuration Checks/Vulnerabilities/CVE"],
"FirstObservedAt": "2023-09-07T17:20:26Z",
"LastObservedAt": "2023-09-07T17:20:26Z",
"CreatedAt": "2023-09-07T17:20:26Z",
"UpdatedAt": "2023-09-07T17:20:26Z",
"Severity": {
"Label": "MEDIUM",
"Normalized": 40
},
"Title": "GHSA-p98r-538v-jgw5 - kernel-5.15",
"Description": "An out-of-bounds read issue was found in the Linux kernel’s crc16 implementation in lib/crc16.c when called from fs/ext4/super.c. ext4_group_desc_csum does not properly check an offset which may lead to out-of-bounds read.",
"Remediation": {
"Recommendation": {
"Text": "Remediation is available. Please refer to the Fixed version in the vulnerability details section above.For detailed remediation guidance for each of the affected packages, refer to the vulnerabilities section of the detailed finding JSON."
}
},
"ProductFields": {
"aws/inspector/ProductVersion": "2",
"aws/inspector/FindingStatus": "ACTIVE",
"aws/inspector/instanceId": "i-07c11cc535d830123",
"aws/inspector/resources/1/resourceDetails/awsEc2InstanceDetails/platform": "BOTTLEROCKET",
"aws/securityhub/FindingId": "arn:aws:securityhub:eu-central-1::product/aws/inspector/arn:aws:inspector2:eu-central-1:012345678912:finding/e07acd3c1cac9df14b96604ceef247be",
"aws/securityhub/ProductName": "Inspector",
"aws/securityhub/CompanyName": "Amazon"
},
"Resources": [
{
"Type": "AwsEc2Instance",
"Id": "arn:aws:ec2:eu-central-1:012345678912:instance/i-07c11cc535d830123",
"Partition": "aws",
"Region": "eu-central-1",
"Tags": {
"EKS_GROUP_NAME": "EKS managed node group",
"aws:eks:cluster-name": "eks01",
"eks:cluster-name": "eks01",
"kubernetes.io/cluster/eks01": "owned",
"aws:ec2launchtemplate:version": "3",
"k8s.io/cluster-autoscaler/enabled": "true",
"NODE_ROLE": "tester",
"k8s.io/cluster-autoscaler/eks01": "owned",
"Name": "eks01-testers",
"Role": "kubernetes",
"aws:autoscaling:groupName": "eks-eks01-testers-20230322111111111100000001-10c38473-1b1c-e880-202d-e076e43e6ece",
"aws:ec2:fleet-id": "fleet-2e2437ad-ea95-e13c-2c92-0e8875e53bff",
"eks:nodegroup-name": "eks01-testers-20230322103837516200000001",
"aws:ec2launchtemplate:id": "lt-040e834ea0c57553b"
},
"Details": {
"AwsEc2Instance": {
"Type": "c4.4xlarge",
"ImageId": "ami-0b4a5f1e4bcfe46a3",
"IpV4Addresses": ["123.123.123.123"],
"IamInstanceProfileArn": "arn:aws:iam::012345678912:instance-profile/eks-10c38473-1b1c-e880-202d-e076e43e6ece",
"VpcId": "vpc-11111111111111111",
"SubnetId": "subnet-11111111111111111",
"LaunchedAt": "2023-09-07T17:19:47Z"
}
}
}
],
"WorkflowState": "NEW",
"Workflow": {
"Status": "NEW"
},
"RecordState": "ACTIVE",
"Vulnerabilities": [
{
"Id": "GHSA-p98r-538v-jgw5",
"VulnerablePackages": [
{
"Name": "kernel-5.15",
"Version": "1.14.1",
"Epoch": "0",
"Release": "842c7134",
"Architecture": "X86_64",
"PackageManager": "OS",
"FixedInVersion": "0:1.14.2-0",
"Remediation": "apiclient update check && apiclient update apply"
}
],
"RelatedVulnerabilities": ["GHSA-p98r-538v-jgw5", "CVE-2023-34256"],
"Vendor": {
"Name": "BOTTLEROCKET",
"Url": "https://github.com/bottlerocket-os/bottlerocket/security/advisories/GHSA-p98r-538v-jgw5",
"VendorSeverity": "medium",
"VendorCreatedAt": "2023-07-07T20:56:55Z",
"VendorUpdatedAt": "2023-07-07T20:56:55Z"
},
"FixAvailable": "YES",
"ExploitAvailable": "NO"
}
],
"FindingProviderFields": {
"Severity": {
"Label": "MEDIUM"
},
"Types": ["Software and Configuration Checks/Vulnerabilities/CVE"]
}
}
]
}
33 changes: 23 additions & 10 deletions unittests/tools/test_awssecurityhub_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from dojo.models import Test


def sample_path(file_name):
def sample_path(file_name: str):
return os.path.join("/scans/awssecurityhub", file_name)


class TestAwsSecurityHubParser(DojoTestCase):

def test_one_finding(self):
with open(get_unit_tests_path() + sample_path("one_finding.json")) as test_file:
with open(get_unit_tests_path() + sample_path("config_one_finding.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(1, len(findings))
Expand All @@ -22,7 +22,7 @@ def test_one_finding(self):
self.assertFalse(finding.active)

def test_one_finding_active(self):
with open(get_unit_tests_path() + sample_path("one_finding_active.json")) as test_file:
with open(get_unit_tests_path() + sample_path("config_one_finding_active.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(1, len(findings))
Expand All @@ -32,34 +32,47 @@ def test_one_finding_active(self):
self.assertTrue(finding.active)

def test_many_findings(self):
with open(get_unit_tests_path() + sample_path("many_findings.json")) as test_file:
with open(get_unit_tests_path() + sample_path("config_many_findings.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(3, len(findings))

def test_repeated_findings(self):
with open(get_unit_tests_path() + sample_path("repeated_findings.json")) as test_file:
with open(get_unit_tests_path() + sample_path("config_repeated_findings.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(1, len(findings))

def test_unique_id(self):
with open(get_unit_tests_path() + sample_path("one_finding.json")) as test_file:
with open(get_unit_tests_path() + sample_path("config_one_finding.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(
"arn:aws:securityhub:us-east-1:012345678912:subscription/aws-foundational-security-best-practices/v/1.0.0/IAM.5/finding/de861909-2d26-4e45-bd86-19d2ab6ceef1",
findings[0].unique_id_from_tool
)

def test_inspector(self):
with open(get_unit_tests_path() + sample_path("securityhub_inspector.json")) as test_file:
def test_inspector_ec2(self):
with open(get_unit_tests_path() + sample_path("inspector_ec2_cve.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(5, len(findings))
finding = findings[0]
self.assertIn("CVE-2022-3643", finding.title)

def test_inspector_ec2_with_no_vulnerabilities(self):
with open(get_unit_tests_path() + sample_path("inspector_ec2_cve_no_vulnerabilities.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(1, len(findings))

def test_inspector_with_no_vulnerabilities(self):
with open(get_unit_tests_path() + sample_path("securityhub_inspector_no_vulnerabilities.json")) as test_file:
def test_inspector_ec2_ghsa(self):
with open(get_unit_tests_path() + sample_path("inspector_ec2_ghsa.json")) as test_file:
parser = AwsSecurityHubParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(1, len(findings))
finding = findings[0]
self.assertEqual("Medium", finding.severity)
self.assertFalse(finding.is_mitigated)
self.assertTrue(finding.active)
self.assertIn("GHSA-p98r-538v-jgw5", finding.title)

0 comments on commit 98914f2

Please sign in to comment.