fix(cloudwatch): if no CloudWatch log groups found resource arn should be the account

This commit is contained in:
Andoni A.
2025-04-08 11:25:55 +02:00
parent ded3a0fcae
commit 851286d23e
13 changed files with 35 additions and 24 deletions
@@ -7,9 +7,9 @@
],
"ServiceName": "cloudwatch",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:account",
"Severity": "medium",
"ResourceType": "AwsCloudWatchAlarm",
"ResourceType": "AwsAccount",
"Description": "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL).",
"Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.",
"RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html",
@@ -31,7 +31,9 @@ class cloudwatch_changes_to_network_acls_alarm_configured(Check):
report.status_extended = "No CloudWatch log groups found with metric filters or alarms associated."
report.region = logs_client.region
report.resource_id = logs_client.audited_account
report.resource_arn = logs_client.log_group_arn_template
report.resource_arn = logs_client._get_account_arn_template(
logs_client.region
)
report.resource_tags = []
findings.append(report)
@@ -7,9 +7,9 @@
],
"ServiceName": "cloudwatch",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:account",
"Severity": "medium",
"ResourceType": "AwsCloudWatchAlarm",
"ResourceType": "AwsAccount",
"Description": "Ensure a log metric filter and alarm exist for changes to network gateways.",
"Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.",
"RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html",
@@ -31,7 +31,9 @@ class cloudwatch_changes_to_network_gateways_alarm_configured(Check):
report.status_extended = "No CloudWatch log groups found with metric filters or alarms associated."
report.region = logs_client.region
report.resource_id = logs_client.audited_account
report.resource_arn = logs_client.log_group_arn_template
report.resource_arn = logs_client._get_account_arn_template(
logs_client.region
)
report.resource_tags = []
findings.append(report)
@@ -7,9 +7,9 @@
],
"ServiceName": "cloudwatch",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:account",
"Severity": "medium",
"ResourceType": "AwsCloudWatchAlarm",
"ResourceType": "AwsAccount",
"Description": "Real-time monitoring of API calls can be achieved by directing Cloud Trail Logs to CloudWatch Logs, or an external Security information and event management (SIEM)environment, and establishing corresponding metric filters and alarms. Routing tablesare used to route network traffic between subnets and to network gateways. It isrecommended that a metric filter and alarm be established for changes to route tables.",
"Risk": "CloudWatch is an AWS native service that allows you to ob serve and monitor resources and applications. CloudTrail Logs can also be sent to an external Security informationand event management (SIEM) environment for monitoring and alerting.Monitoring changes to route tables will help ensure that all VPC traffic flows through anexpected path and prevent any accidental or intentional modifications that may lead touncontrolled network traffic. An alarm should be triggered every time an AWS API call isperformed to create, replace, delete, or disassociate a Route Table.",
"RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html",
@@ -31,7 +31,9 @@ class cloudwatch_changes_to_network_route_tables_alarm_configured(Check):
report.status_extended = "No CloudWatch log groups found with metric filters or alarms associated."
report.region = logs_client.region
report.resource_id = logs_client.audited_account
report.resource_arn = logs_client.log_group_arn_template
report.resource_arn = logs_client._get_account_arn_template(
logs_client.region
)
report.resource_tags = []
findings.append(report)
@@ -7,9 +7,9 @@
],
"ServiceName": "cloudwatch",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id",
"ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:account",
"Severity": "medium",
"ResourceType": "AwsCloudWatchAlarm",
"ResourceType": "AwsAccount",
"Description": "Ensure a log metric filter and alarm exist for VPC changes.",
"Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.",
"RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html",
@@ -31,7 +31,9 @@ class cloudwatch_changes_to_vpcs_alarm_configured(Check):
report.status_extended = "No CloudWatch log groups found with metric filters or alarms associated."
report.region = logs_client.region
report.resource_id = logs_client.audited_account
report.resource_arn = logs_client.log_group_arn_template
report.resource_arn = logs_client._get_account_arn_template(
logs_client.region
)
report.resource_tags = []
findings.append(report)
@@ -102,6 +102,9 @@ class Logs(AWSService):
self._list_tags_for_resource, self.log_groups.values()
)
def _get_account_arn_template(self, region):
return f"arn:{self.audited_partition}:cloudwatch:{region}:{self.audited_account}:account"
def _describe_metric_filters(self, regional_client):
logger.info("CloudWatch Logs - Describing metric filters...")
try:
@@ -71,7 +71,7 @@ class Test_cloudwatch_changes_to_network_acls_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -139,7 +139,7 @@ class Test_cloudwatch_changes_to_network_acls_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_US_EAST_1
@@ -213,7 +213,7 @@ class Test_cloudwatch_changes_to_network_acls_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_US_EAST_1
@@ -71,7 +71,7 @@ class Test_cloudwatch_changes_to_network_gateways_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -139,7 +139,7 @@ class Test_cloudwatch_changes_to_network_gateways_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -213,7 +213,7 @@ class Test_cloudwatch_changes_to_network_gateways_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -71,7 +71,7 @@ class Test_cloudwatch_changes_to_network_route_tables_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -139,7 +139,7 @@ class Test_cloudwatch_changes_to_network_route_tables_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -213,7 +213,7 @@ class Test_cloudwatch_changes_to_network_route_tables_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -71,7 +71,7 @@ class Test_cloudwatch_changes_to_vpcs_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -139,7 +139,7 @@ class Test_cloudwatch_changes_to_vpcs_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1
@@ -213,7 +213,7 @@ class Test_cloudwatch_changes_to_vpcs_alarm_configured:
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert (
result[0].resource_arn
== f"arn:aws:logs:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:log-group"
== f"arn:aws:cloudwatch:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:account"
)
assert result[0].region == AWS_REGION_EU_WEST_1