CloudWatch Logs metric filter and alarm exist for changes to network gateways
CloudWatch log metric filters and alarms for network gateway changes are identified by matching CloudTrail events such as CreateCustomerGateway, DeleteCustomerGateway, AttachInternetGateway, CreateInternetGateway, DeleteInternetGateway, and DetachInternetGateway in log groups that receive trail logs.
Risk
Without this monitoring, gateway changes can expose private networks to the Internet or break connectivity. Adversaries or mistakes can enable data exfiltration, bypass network inspection, and trigger outages via deletions or detachments, impacting confidentiality and availability.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks cloudwatch_changes_to_network_gateways_alarm_configuredRecommendation
Send CloudTrail to CloudWatch Logs and create a metric filter for the listed gateway events with an alarm that notifies responders. Enforce least privilege for gateway modifications, require change approvals, and route alerts to monitored channels as part of defense in depth.
Remediation
Terraform
# CloudWatch Logs metric filter for network gateway changes
resource "aws_cloudwatch_log_metric_filter" "<example_resource_name>" {
name = "<example_resource_name>"
log_group_name = "<example_resource_name>"
pattern = "{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }" # Critical: matches gateway change events
metric_transformation {
name = "<example_resource_name>"
namespace = "<example_resource_name>"
value = "1"
}
}
# Alarm on the metric filter
resource "aws_cloudwatch_metric_alarm" "<example_resource_name>" {
alarm_name = "<example_resource_name>"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "<example_resource_name>" # Critical: must match metric from the filter
namespace = "<example_resource_name>"
period = 300
statistic = "Sum"
threshold = 1
}NativeIaC
# CloudFormation: Create metric filter and alarm for network gateway changes
Resources:
NetworkGatewayMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: <example_resource_name>
FilterPattern: '{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }' # Critical: matches gateway change events
MetricTransformations:
- MetricName: <example_resource_name>
MetricNamespace: <example_resource_name>
MetricValue: "1"
NetworkGatewayAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: 1
MetricName: <example_resource_name> # Critical: alarm targets the metric created by the filter
Namespace: <example_resource_name>
Period: 300
Statistic: Sum
Threshold: 1Other
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudtrail.cloudtrail_client import (
cloudtrail_client,
)
from prowler.providers.aws.services.cloudwatch.cloudwatch_client import (
cloudwatch_client,
)
from prowler.providers.aws.services.cloudwatch.lib.metric_filters import (
build_metric_filter_pattern,
check_cloudwatch_log_metric_filter,
)
from prowler.providers.aws.services.cloudwatch.logs_client import logs_client
class cloudwatch_changes_to_network_gateways_alarm_configured(Check):
"""CloudWatch Logs metric filter and alarm exist for changes to network gateways.
Looks for a CloudWatch Logs metric filter matching the expected pattern on a
log group used by a CloudTrail trail, with at least one alarm on its metric.
- PASS: A matching metric filter with an associated alarm exists.
- FAIL: No matching metric filter, or a filter without an alarm, was found.
- MANUAL: CloudTrail trails, log groups, metric filters or alarms could
not be listed in at least one region, so the absence of a filter/alarm
cannot be asserted.
"""
def execute(self) -> list[Check_Report_AWS]:
"""Evaluate the metric filter and alarm coverage for the account.
Returns:
list[Check_Report_AWS]: A single report for the account.
"""
pattern = build_metric_filter_pattern(
event_names=[
"CreateCustomerGateway",
"DeleteCustomerGateway",
"AttachInternetGateway",
"CreateInternetGateway",
"DeleteInternetGateway",
"DetachInternetGateway",
],
)
findings = []
report = check_cloudwatch_log_metric_filter(
pattern,
cloudtrail_client.trails,
logs_client.metric_filters,
cloudwatch_client.metric_alarms,
self.metadata(),
)
inventory_unavailable = (
cloudtrail_client.trails_unavailable
or logs_client.log_groups_unavailable
or logs_client.metric_filters_unavailable
or cloudwatch_client.metric_alarms_unavailable
)
if report is None:
report = Check_Report_AWS(metadata=self.metadata(), resource={})
report.status = "FAIL"
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_tags = []
# A denied listing in any region means the inventory is incomplete: a
# PASS is still backed by a real filter and alarm, but a FAIL (nothing
# found, or a filter found without its alarm) cannot be trusted.
if report.status == "FAIL" and inventory_unavailable:
report.status = "MANUAL"
report.status_extended = "Cannot evaluate CloudWatch metric filters and alarms: CloudTrail trails, log groups, metric filters or alarms could not be listed in at least one region. Verify that the scanning credentials are allowed to call cloudtrail:DescribeTrails, logs:DescribeLogGroups, logs:DescribeMetricFilters and cloudwatch:DescribeAlarms."
findings.append(report)
return findingsReferences
- https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html
- https://support.icompaas.com/support/solutions/articles/62000083807-ensure-a-log-metric-filter-and-alarm-exist-for-changes-to-network-gateways
- https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-12
- https://paper.bobylive.com/Security/CIS/CIS_Amazon_Web_Services_Foundations_Benchmark_v1_3_0.pdf