Skip to content

EC2 VPN connections should have logging enabled

Site-to-Site VPN tunnels carry traffic between your on-premises network and AWS VPCs. Without logging on both tunnels, you lose visibility into tunnel state changes, IKE negotiation failures, and potential unauthorized connection attempts. Debugging intermittent connectivity issues becomes guesswork.

VPN connections use two tunnels for redundancy, so logging on only one creates a blind spot whenever traffic fails over. Enabling CloudWatch Logs on both gives you a complete record for operational troubleshooting and security investigation.

Retrofit consideration

Enabling or changing tunnel log options on an existing aws_vpn_connection may trigger a brief tunnel renegotiation, which can interrupt traffic for a few seconds.

Implementation

Choose the approach that matches how you manage Terraform.

If you use terraform-aws-modules/vpn-gateway/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "vpn_gateway" {
  source  = "terraform-aws-modules/vpn-gateway/aws"
  version = ">=4.0.0,<5.0.0"

  customer_gateway_id          = "cgw-abc123"
  vpc_id                       = "vpc-12345678"
  vpc_subnet_route_table_count = 1
  vpc_subnet_route_table_ids   = ["rtb-abc12345"]
  vpn_gateway_id               = "vgw-abc123"

  tunnel1_log_options = {
    cloudwatch_log_options = {
      log_enabled = true
    }
  }
  tunnel2_log_options = {
    cloudwatch_log_options = {
      log_enabled = true
    }
  }
}

Use AWS provider resources directly. See docs for the resources involved: aws_vpn_connection.

resource "aws_vpn_connection" "this" {
  customer_gateway_id = "cgw-abc123"
  type                = "ipsec.1"
  vpn_gateway_id      = "vgw-abc123"

  tunnel1_log_options {
    cloudwatch_log_options {
      log_enabled   = true
      log_group_arn = "arn:aws:logs:us-east-1:123456789012:log-group:example-log-group"
    }
  }

  tunnel2_log_options {
    cloudwatch_log_options {
      log_enabled   = true
      log_group_arn = "arn:aws:logs:us-east-1:123456789012:log-group:example-log-group"
    }
  }
}

What this control checks

In the aws_vpn_connection resource, both tunnel1_log_options and tunnel2_log_options must include a cloudwatch_log_options sub-block with log_enabled = true. Each sub-block also needs log_group_arn pointing to a valid aws_cloudwatch_log_group ARN and log_output_format set to "json" or "plain-text". A connection fails if either tunnel omits the log options block, sets log_enabled to false, or leaves it at the default (false). Both tunnels must be configured independently. Setting logging on tunnel 1 while omitting tunnel 2 still results in failure.

Common pitfalls

  • Only one tunnel configured

    Since tunnel 2 is the failover path, it gets overlooked more often than you'd expect. tunnel1_log_options is easy to configure first and easy to never revisit. The control requires both blocks explicitly, so a module that only wires up tunnel 1 will fail.

  • Log group does not exist yet

    If log_group_arn references an aws_cloudwatch_log_group that doesn't exist yet, the apply will error out. Reference the resource directly (aws_cloudwatch_log_group.example.arn) rather than hardcoding an ARN string, so Terraform creates the log group first. An explicit depends_on works too, but the implicit reference is cleaner.

  • Default log_enabled is false

    Providing the cloudwatch_log_options block without explicitly setting log_enabled = true does not enable logging. The default is false, so an empty or structurally incomplete block still fails the control. You have to set the argument.

  • Log group retention and costs

    VPN tunnel logs can generate significant volume in high-traffic environments. Without retention_in_days set on the aws_cloudwatch_log_group, storage costs grow unchecked. The control doesn't enforce retention, but your cloud bill will.

Audit evidence

An auditor expects to see Config rule evaluation results (or equivalent Security Hub findings) showing all AWS::EC2::VPNConnection resources as compliant. Supporting evidence includes VPN connection details in the AWS Console with CloudWatch log groups configured under both Tunnel 1 and Tunnel 2. Those log groups should contain recent VPN log entries, confirming that log delivery is active and not just configured.

For stronger evidence, provide output from aws ec2 describe-vpn-connections showing Options.TunnelOptions[].LogOptions.CloudWatchLogOptions.LogEnabled as true for both tunnels across all connections in every region.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: vpc_vpn_connection_logging_enabled

  • AWS Config Managed Rule: EC2_VPN_CONNECTION_LOGGING_ENABLED

  • Powerpipe Control: aws_compliance.control.vpc_vpn_connection_logging_enabled

  • AWS Security Hub Control: EC2.171

Last reviewed: 2026-03-09