MEDIUM CloudWatch · CIS 4.14

VPC changes alarm

Check ID: aws-cw-014

AWS-CW-014 is an AWS security check performed by cloud-audit, an open-source AWS security scanner. Checks if a CloudWatch metric filter and alarm exist to detect VPC changes (CreateVpc, DeleteVpc, ModifyVpcAttribute, AcceptVpcPeeringConnection). Without this monitoring, VPC-level changes go undetected.

Why it matters

VPC changes affect the foundational network architecture of your AWS environment. Accepting a VPC peering connection from an unknown account can bridge your private network to an attacker-controlled VPC, bypassing all perimeter security. Creating unauthorized VPCs can establish shadow infrastructure that operates outside your organization's monitoring and compliance controls. Modifying VPC attributes like DNS resolution settings can redirect DNS queries to malicious resolvers for DNS poisoning attacks. In multi-account architectures, VPC changes can have cascading effects across the organization. These changes are rare in stable environments and should always be correlated with approved change requests.

Common causes

VPC peering requests can originate from any AWS account, and accepting them without verification creates network bridges to untrusted environments. Developer sandbox accounts may create VPCs freely without governance, and those patterns get replicated in production. Organizations that grew organically may have VPCs created years ago by former employees with no documented architecture or monitoring.

Detection

Run cloud-audit to detect this issue:

pip install cloud-audit
cloud-audit scan -R

The -R flag includes remediation details for every finding, including this one.

Remediation: AWS CLI

# Create metric filter:
aws logs put-metric-filter \
  --log-group-name <CLOUDTRAIL_LOG_GROUP> \
  --filter-name CIS-4.14 \
  --filter-pattern '{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }' \
  --metric-transformations metricName=CIS-4-14,metricNamespace=CISBenchmark,metricValue=1
# Create alarm:
aws cloudwatch put-metric-alarm \
  --alarm-name CIS-4.14 \
  --metric-name CIS-4-14 \
  --namespace CISBenchmark \
  --statistic Sum --period 300 --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1 \
  --alarm-actions <SNS_TOPIC_ARN>

Remediation: Terraform

resource "aws_cloudwatch_log_metric_filter" "cis_4_14" {
  name           = "CIS-4.14"
  log_group_name = aws_cloudwatch_log_group.cloudtrail.name
  pattern        = "{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) }"

  metric_transformation {
    name      = "CIS-4-14"
    namespace = "CISBenchmark"
    value     = "1"
  }
}

resource "aws_cloudwatch_metric_alarm" "cis_4_14" {
  alarm_name          = "CIS-4.14"
  metric_name         = "CIS-4-14"
  namespace           = "CISBenchmark"
  statistic           = "Sum"
  period              = 300
  threshold           = 1
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  alarm_actions       = [aws_sns_topic.alerts.arn]
}

Compliance mapping

This check maps to CIS 4.14 in the CIS AWS Foundations Benchmark. The CIS Benchmark provides prescriptive guidance for configuring security options for a subset of AWS services.

This check is part of cloud-audit - install with pip install cloud-audit