Skip to content

Commit

Permalink
feat Added support for SecurityHub integration findings
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandogoncalves-me committed Nov 13, 2024
1 parent 48587a1 commit 47b7c13
Show file tree
Hide file tree
Showing 9 changed files with 1,057 additions and 12 deletions.
60 changes: 58 additions & 2 deletions awsfindingsmanagerlib/awsfindingsmanagerlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ def product_arn(self) -> str:
"""Product ARN."""
return self._data.get('ProductArn')

@property
def product_name(self) -> str:
"""Product Name."""
return self._data.get('ProductName')

@property
def region(self) -> str:
"""Region."""
Expand Down Expand Up @@ -357,10 +362,15 @@ def is_matching_rule(self, rule: Rule) -> bool:
self.match_if_set(self.security_control_id,
rule.security_control_id),
self.match_if_set(self.control_id, rule.rule_or_control_id),
self.match_if_set(self.rule_id, rule.rule_or_control_id)
self.match_if_set(self.rule_id, rule.rule_or_control_id),
self.match_if_set(self.product_name, rule.product_name),
]):
self._logger.debug(
f'Matched with rule "{rule.note}" on one of "control_id, security_control_id"')
f'Matched with rule "{rule.note}" on one of "control_id, security_control_id, product_name"')
if self.match_if_set(self.title, rule.title):
self._logger.debug(
f'Matched with rule "{rule.note}" on title.')
return True
if not any([rule.tags, rule.resource_id_regexps]):
self._logger.debug(
f'Rule "{rule.note}" does not seem to have filters for resources or tags.')
Expand Down Expand Up @@ -411,6 +421,11 @@ def match_on(self) -> Dict:
"""The match_on data of the rule."""
return self._data.get('match_on')

@property
def product_name(self) -> str:
"""The product name if any, empty string otherwise."""
return self.match_on.get('product_name', '')

@property
def security_control_id(self) -> str:
"""The security control ID if any, empty string otherwise."""
Expand All @@ -426,11 +441,33 @@ def resource_id_regexps(self) -> List[Optional[str]]:
"""The resource ids specified under the match_on attribute."""
return self.match_on.get('resource_id_regexps', [])

@property
def title(self) -> str:
"""The title if any, empty string otherwise."""
return self.match_on.get('title', '')

@property
def tags(self) -> List[Optional[str]]:
"""The tags specified under the match_on attribute."""
return self.match_on.get('tags', [])

@staticmethod
def _get_product_name_query(match_on_data) -> Dict:
"""Constructs a valid query based on product name if any.
Args:
match_on_data: The match_on data of the Rule
Returns:
The query matching the product name, empty dictionary otherwise.
"""
product_name = match_on_data.get('product_name')
if not product_name:
return {}
return {'ProductName': [{'Value': product_name,
'Comparison': 'EQUALS'}]}

@staticmethod
def _get_rule_or_control_id_query(match_on_data) -> Dict:
"""Constructs a valid query based on a set control ID if any.
Expand Down Expand Up @@ -490,6 +527,23 @@ def _get_tag_query(match_on_data) -> Dict:
'Comparison': 'EQUALS'}
for tag in tags]}

@staticmethod
def _get_title_query(match_on_data) -> Dict:
"""Constructs a valid query based on title if any.
Args:
match_on_data: The match_on data of the Rule
Returns:
The query matching the title, empty dictionary otherwise.
"""
title = match_on_data.get('title')
if not title:
return {}
return {'Title': [{'Value': title,
'Comparison': 'EQUALS'}]}

@property
def query_filter(self) -> Dict:
"""The query filter of the Rule based on all set attributes.
Expand All @@ -502,6 +556,8 @@ def query_filter(self) -> Dict:
query.update(self._get_rule_or_control_id_query(self.match_on))
query.update(self._get_security_control_id_query(self.match_on))
query.update(self._get_tag_query(self.match_on))
query.update(self._get_title_query(self.match_on))
query.update(self._get_product_name_query(self.match_on))
return deepcopy(query)


Expand Down
2 changes: 2 additions & 0 deletions awsfindingsmanagerlib/validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
__status__ = '''Development''' # "Prototype", "Development", "Production".

rule_schema = Schema({'match_on': {Optional('rule_or_control_id'): str,
Optional('title'): str,
Optional('product_name'): str,
Optional('security_control_id'): str,
Optional('resource_id_regexps'): [str],
Optional('tags'): [{'key': str,
Expand Down
25 changes: 24 additions & 1 deletion tests/fixtures/batch_update_findings_full.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,28 @@
"Text": "MF-Neigh",
"UpdatedBy": "FindingsManager"
}
},
{
"FindingIdentifiers": [
{
"Id": "arn:aws:inspector2:eu-west-1:012345678912:finding/ff4ebfb9d83b0ee89c7140b30eed5ef9",
"ProductArn": "arn:aws:securityhub:eu-west-1::product/aws/inspector"
},
{
"Id": "arn:aws:inspector2:eu-west-1:012345678912:finding/ioperfb9d83b0ee89c7140b30eed5lf9",
"ProductArn": "arn:aws:securityhub:eu-west-1::product/aws/inspector"
},
{
"Id": "arn:aws:inspector2:eu-west-1:012345678912:finding/m58hv3b9d83b0ee89c7140b30eed55kv",
"ProductArn": "arn:aws:securityhub:eu-west-1::product/aws/inspector"
}
],
"Workflow": {
"Status": "SUPPRESSED"
},
"Note": {
"Text": "We support Inspector too",
"UpdatedBy": "FindingsManager"
}
}
]
]
154 changes: 154 additions & 0 deletions tests/fixtures/findings/full/Inspector/acc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{
"AwsAccountId": "012345678912",
"AwsAccountName": "account",
"CompanyName": "Amazon",
"CreatedAt": "2024-11-11T14:40:00.016Z",
"Description": "A flaw was found in python. An improperly handled HTTP response in the HTTP client code of python may allow a remote attacker, who controls the HTTP server, to make the client script enter an infinite loop, consuming CPU time. The highest threat from this vulnerability is to system availability.",
"FindingProviderFields": {
"Types": [
"Software and Configuration Checks/Vulnerabilities/CVE"
],
"Severity": {
"Normalized": 70,
"Label": "HIGH"
}
},
"FirstObservedAt": "2024-11-11T14:40:00.016Z",
"GeneratorId": "AWSInspector",
"Id": "arn:aws:inspector2:eu-west-1:012345678912:finding/ioperfb9d83b0ee89c7140b30eed5lf9",
"LastObservedAt": "2024-11-11T14:40:00.016Z",
"ProcessedAt": "2024-11-11T14:45:08.567Z",
"ProductArn": "arn:aws:securityhub:eu-west-1::product/aws/inspector",
"ProductFields": {
"aws/inspector/ProductVersion": "2",
"aws/inspector/FindingStatus": "CLOSED",
"aws/inspector/inspectorScore": "7.5",
"aws/inspector/instanceId": "i-01e8db61387e018b4",
"aws/inspector/resources/1/resourceDetails/awsEc2InstanceDetails/platform": "UBUNTU_22_04",
"aws/securityhub/FindingId": "arn:aws:securityhub:eu-west-1::product/aws/inspector/arn:aws:inspector2:eu-west-1:012345678912:finding/ff4ebfb9d83b0ee89c7140b30eed5ef9",
"aws/securityhub/ProductName": "Inspector",
"aws/securityhub/CompanyName": "Amazon"
},
"ProductName": "Inspector",
"RecordState": "ARCHIVED",
"Region": "eu-west-1",
"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."
}
},
"Resources": [
{
"Details": {
"AwsEc2Instance": {
"Type": "t3.large",
"VpcId": "vpc-0d165124e6f1211e6",
"ImageId": "ami-030c1a56dd9a0ccd8",
"IpV4Addresses": [
"192.168.0.74"
],
"SubnetId": "subnet-062ae210766aa9614",
"LaunchedAt": "2024-11-11T14:38:42.000Z",
"IamInstanceProfileArn": "arn:aws:iam::012345678912:instance-profile/example/example-profile"
}
},
"Id": "arn:aws:ec2:eu-west-1:012345678912:instance/i-01e8db61387e018b4",
"Partition": "aws",
"Region": "eu-west-1",
"Tags": {
"aws:ec2:fleet-id": "fleet-28b70307-1da4-e616-0cb8-0d20555fe75c",
"ghr:environment": "example",
"aws:ec2launchtemplate:version": "9",
"aws:ec2launchtemplate:id": "lt-0c064043433a6dcfe",
"Name": "example-action-runner"
},
"Type": "AwsEc2Instance"
}
],
"SchemaVersion": "2018-10-08",
"Severity": {
"Label": "HIGH",
"Normalized": 70
},
"Title": "CVE-2021-3737 - python3.10, python3.10-minimal",
"Types": [
"Software and Configuration Checks/Vulnerabilities/CVE"
],
"UpdatedAt": "2024-11-11T14:44:51.175Z",
"Vulnerabilities": [
{
"Cvss": [
{
"BaseScore": 7.5,
"BaseVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"Source": "UBUNTU_CVE",
"Version": "3.1"
},
{
"BaseScore": 7.5,
"BaseVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"Source": "NVD",
"Version": "3.1"
},
{
"BaseScore": 7.5,
"BaseVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"Source": "UBUNTU_CVE",
"Version": "3.1"
}
],
"EpssScore": 0.01559,
"ExploitAvailable": "NO",
"FixAvailable": "YES",
"Id": "CVE-2021-3737",
"ReferenceUrls": [
"https://ubuntu.com/security/notices/USN-5083-1",
"https://ubuntu.com/security/notices/USN-5201-1",
"https://ubuntu.com/security/notices/USN-5200-1",
"https://ubuntu.com/security/notices/USN-6891-1",
"https://bugs.python.org/issue44022",
"https://www.cve.org/CVERecord?id=CVE-2021-3737",
"https://ubuntu.com/security/notices/USN-5199-1"
],
"RelatedVulnerabilities": [
"USN-5200-1",
"USN-5201-1",
"USN-5083-1",
"USN-6891-1",
"USN-5199-1"
],
"Vendor": {
"VendorCreatedAt": "2022-03-04T19:15:00.000Z",
"VendorSeverity": "medium",
"Url": "https://people.canonical.com/~ubuntu-security/cve/2021/CVE-2021-3737.html",
"Name": "UBUNTU_CVE"
},
"VulnerablePackages": [
{
"Architecture": "X86_64",
"PackageManager": "OS",
"Version": "3.10.6",
"Epoch": "0",
"FixedInVersion": "0:3.10.12-1~22.04.4",
"Remediation": "apt-get update && apt-get upgrade",
"Release": "1~22.04.2ubuntu1.1",
"Name": "python3.10"
},
{
"Architecture": "X86_64",
"PackageManager": "OS",
"Version": "3.10.6",
"Epoch": "0",
"FixedInVersion": "0:3.10.12-1~22.04.4",
"Remediation": "apt-get update && apt-get upgrade",
"Release": "1~22.04.2ubuntu1.1",
"Name": "python3.10-minimal"
}
]
}
],
"Workflow": {
"Status": "NEW"
},
"WorkflowState": "NEW"
}
Loading

0 comments on commit 47b7c13

Please sign in to comment.