Skip to main content

Ensure Network Firewall Logging is Enabled

Overview

This check verifies that AWS Network Firewall has logging enabled for at least one log type (FLOW, ALERT, or TLS) and that the log destination is active. Network Firewall logs provide visibility into network traffic patterns and potential security threats passing through your firewall.

Risk

Without firewall logging enabled, you lose visibility into:

  • Traffic patterns - No record of what traffic is flowing through your network
  • Security incidents - Malicious traffic, command-and-control communications, and data exfiltration attempts go undetected
  • Troubleshooting data - Difficult to diagnose connectivity issues or policy problems
  • Compliance evidence - Unable to demonstrate security monitoring for audits

This gap can lead to undetected breaches, delayed incident response, and compliance failures.

Remediation Steps

Prerequisites

  • AWS Console access with permissions to modify Network Firewall settings
  • An existing Network Firewall (if not, you will create logging during firewall setup)
  • A log destination ready: CloudWatch Logs group, S3 bucket, or Kinesis Data Firehose stream
Setting up a CloudWatch Log Group

If you do not have a log destination, create a CloudWatch Log Group first:

  1. Go to CloudWatch in the AWS Console
  2. Click Log groups in the left menu
  3. Click Create log group
  4. Enter a name like /aws/network-firewall/my-firewall/flow
  5. Set retention period (e.g., 90 days)
  6. Click Create

Repeat for each log type you want to capture (FLOW, ALERT, TLS).

AWS Console Method

  1. Open the VPC console at https://console.aws.amazon.com/vpc/
  2. In the left navigation, under Network Firewall, click Firewalls
  3. Select the firewall you want to configure
  4. Scroll down to the Logging section and click Edit
  5. For each log type you want to enable:
    • Check the box next to Flow logs, Alert logs, or TLS logs
    • Choose a destination type: CloudWatch log group, S3 bucket, or Kinesis Data Firehose
    • Select or enter the destination (e.g., your log group name)
  6. Click Save

Recommended: Enable at least FLOW and ALERT logs. Enable TLS logs if you are using TLS inspection.

AWS CLI (optional)

View current logging configuration:

aws network-firewall describe-logging-configuration \
--firewall-name my-firewall \
--region us-east-1

Enable FLOW logging to CloudWatch Logs:

aws network-firewall update-logging-configuration \
--firewall-name my-firewall \
--logging-configuration '{
"LogDestinationConfigs": [
{
"LogType": "FLOW",
"LogDestinationType": "CloudWatchLogs",
"LogDestination": {
"logGroup": "/aws/network-firewall/my-firewall/flow"
}
}
]
}' \
--region us-east-1

Enable ALERT logging to CloudWatch Logs:

aws network-firewall update-logging-configuration \
--firewall-name my-firewall \
--logging-configuration '{
"LogDestinationConfigs": [
{
"LogType": "ALERT",
"LogDestinationType": "CloudWatchLogs",
"LogDestination": {
"logGroup": "/aws/network-firewall/my-firewall/alert"
}
}
]
}' \
--region us-east-1

Important: The update-logging-configuration command can only add or modify one log destination at a time. Run the command separately for each log type.

Enable logging to S3 instead:

aws network-firewall update-logging-configuration \
--firewall-name my-firewall \
--logging-configuration '{
"LogDestinationConfigs": [
{
"LogType": "FLOW",
"LogDestinationType": "S3",
"LogDestination": {
"bucketName": "my-firewall-logs-bucket",
"prefix": "network-firewall/flow"
}
}
]
}' \
--region us-east-1
CloudFormation (optional)

This template creates a Network Firewall with logging enabled for both FLOW and ALERT logs:

AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Network Firewall with logging enabled

Parameters:
FirewallName:
Type: String
Description: Name of the Network Firewall
Default: my-network-firewall

VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC ID where the firewall will be deployed

SubnetId:
Type: AWS::EC2::Subnet::Id
Description: Subnet ID for the firewall endpoint

LogRetentionDays:
Type: Number
Description: Number of days to retain logs
Default: 90
AllowedValues:
- 1
- 3
- 5
- 7
- 14
- 30
- 60
- 90
- 120
- 150
- 180
- 365
- 400
- 545
- 731
- 1827
- 3653

Resources:
# CloudWatch Log Groups for each log type
FlowLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub '/aws/network-firewall/${FirewallName}/flow'
RetentionInDays: !Ref LogRetentionDays

AlertLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub '/aws/network-firewall/${FirewallName}/alert'
RetentionInDays: !Ref LogRetentionDays

# Basic stateless rule group (allow all for example)
StatelessRuleGroup:
Type: AWS::NetworkFirewall::RuleGroup
Properties:
RuleGroupName: !Sub '${FirewallName}-stateless-rg'
Type: STATELESS
Capacity: 100
RuleGroup:
RulesSource:
StatelessRulesAndCustomActions:
StatelessRules:
- RuleDefinition:
MatchAttributes:
Sources:
- AddressDefinition: 0.0.0.0/0
Destinations:
- AddressDefinition: 0.0.0.0/0
Actions:
- aws:forward_to_sfe
Priority: 1

# Firewall Policy
FirewallPolicy:
Type: AWS::NetworkFirewall::FirewallPolicy
Properties:
FirewallPolicyName: !Sub '${FirewallName}-policy'
FirewallPolicy:
StatelessDefaultActions:
- aws:forward_to_sfe
StatelessFragmentDefaultActions:
- aws:forward_to_sfe
StatelessRuleGroupReferences:
- ResourceArn: !Ref StatelessRuleGroup
Priority: 1

# Network Firewall
NetworkFirewall:
Type: AWS::NetworkFirewall::Firewall
Properties:
FirewallName: !Ref FirewallName
FirewallPolicyArn: !Ref FirewallPolicy
VpcId: !Ref VpcId
SubnetMappings:
- SubnetId: !Ref SubnetId

# Logging Configuration
LoggingConfiguration:
Type: AWS::NetworkFirewall::LoggingConfiguration
Properties:
FirewallArn: !Ref NetworkFirewall
LoggingConfiguration:
LogDestinationConfigs:
- LogType: FLOW
LogDestinationType: CloudWatchLogs
LogDestination:
logGroup: !Ref FlowLogGroup
- LogType: ALERT
LogDestinationType: CloudWatchLogs
LogDestination:
logGroup: !Ref AlertLogGroup

Outputs:
FirewallArn:
Description: ARN of the Network Firewall
Value: !Ref NetworkFirewall

FlowLogGroupArn:
Description: ARN of the Flow Log Group
Value: !GetAtt FlowLogGroup.Arn

AlertLogGroupArn:
Description: ARN of the Alert Log Group
Value: !GetAtt AlertLogGroup.Arn

To add logging to an existing firewall, use just the LoggingConfiguration resource:

Resources:
LoggingConfiguration:
Type: AWS::NetworkFirewall::LoggingConfiguration
Properties:
FirewallArn: arn:aws:network-firewall:us-east-1:123456789012:firewall/my-firewall
LoggingConfiguration:
LogDestinationConfigs:
- LogType: FLOW
LogDestinationType: CloudWatchLogs
LogDestination:
logGroup: /aws/network-firewall/my-firewall/flow
- LogType: ALERT
LogDestinationType: CloudWatchLogs
LogDestination:
logGroup: /aws/network-firewall/my-firewall/alert
Terraform (optional)

This configuration creates a Network Firewall with logging enabled:

terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "firewall_name" {
description = "Name of the Network Firewall"
type = string
default = "my-network-firewall"
}

variable "vpc_id" {
description = "VPC ID where the firewall will be deployed"
type = string
}

variable "subnet_id" {
description = "Subnet ID for the firewall endpoint"
type = string
}

variable "log_retention_days" {
description = "Number of days to retain logs in CloudWatch"
type = number
default = 90
}

# CloudWatch Log Groups
resource "aws_cloudwatch_log_group" "flow_logs" {
name = "/aws/network-firewall/${var.firewall_name}/flow"
retention_in_days = var.log_retention_days
}

resource "aws_cloudwatch_log_group" "alert_logs" {
name = "/aws/network-firewall/${var.firewall_name}/alert"
retention_in_days = var.log_retention_days
}

# Basic stateless rule group
resource "aws_networkfirewall_rule_group" "stateless" {
capacity = 100
name = "${var.firewall_name}-stateless-rg"
type = "STATELESS"

rule_group {
rules_source {
stateless_rules_and_custom_actions {
stateless_rule {
priority = 1
rule_definition {
actions = ["aws:forward_to_sfe"]
match_attributes {
source {
address_definition = "0.0.0.0/0"
}
destination {
address_definition = "0.0.0.0/0"
}
}
}
}
}
}
}
}

# Firewall Policy
resource "aws_networkfirewall_firewall_policy" "main" {
name = "${var.firewall_name}-policy"

firewall_policy {
stateless_default_actions = ["aws:forward_to_sfe"]
stateless_fragment_default_actions = ["aws:forward_to_sfe"]

stateless_rule_group_reference {
priority = 1
resource_arn = aws_networkfirewall_rule_group.stateless.arn
}
}
}

# Network Firewall
resource "aws_networkfirewall_firewall" "main" {
name = var.firewall_name
firewall_policy_arn = aws_networkfirewall_firewall_policy.main.arn
vpc_id = var.vpc_id

subnet_mapping {
subnet_id = var.subnet_id
}
}

# Logging Configuration
resource "aws_networkfirewall_logging_configuration" "main" {
firewall_arn = aws_networkfirewall_firewall.main.arn

logging_configuration {
log_destination_config {
log_type = "FLOW"
log_destination_type = "CloudWatchLogs"
log_destination = {
logGroup = aws_cloudwatch_log_group.flow_logs.name
}
}

log_destination_config {
log_type = "ALERT"
log_destination_type = "CloudWatchLogs"
log_destination = {
logGroup = aws_cloudwatch_log_group.alert_logs.name
}
}
}
}

output "firewall_arn" {
description = "ARN of the Network Firewall"
value = aws_networkfirewall_firewall.main.arn
}

output "flow_log_group_arn" {
description = "ARN of the Flow Log Group"
value = aws_cloudwatch_log_group.flow_logs.arn
}

output "alert_log_group_arn" {
description = "ARN of the Alert Log Group"
value = aws_cloudwatch_log_group.alert_logs.arn
}

To add logging to an existing firewall:

# Reference existing firewall by ARN
data "aws_networkfirewall_firewall" "existing" {
name = "my-existing-firewall"
}

resource "aws_cloudwatch_log_group" "flow_logs" {
name = "/aws/network-firewall/my-existing-firewall/flow"
retention_in_days = 90
}

resource "aws_cloudwatch_log_group" "alert_logs" {
name = "/aws/network-firewall/my-existing-firewall/alert"
retention_in_days = 90
}

resource "aws_networkfirewall_logging_configuration" "main" {
firewall_arn = data.aws_networkfirewall_firewall.existing.arn

logging_configuration {
log_destination_config {
log_type = "FLOW"
log_destination_type = "CloudWatchLogs"
log_destination = {
logGroup = aws_cloudwatch_log_group.flow_logs.name
}
}

log_destination_config {
log_type = "ALERT"
log_destination_type = "CloudWatchLogs"
log_destination = {
logGroup = aws_cloudwatch_log_group.alert_logs.name
}
}
}
}

Verification

After enabling logging, verify the configuration is working:

  1. In the VPC Console, go to Network Firewall > Firewalls
  2. Select your firewall and scroll to the Logging section
  3. Confirm that at least one log type shows a configured destination
  4. Wait a few minutes, then check your log destination (CloudWatch, S3, or Firehose) for incoming log entries
CLI verification commands

Check logging configuration:

aws network-firewall describe-logging-configuration \
--firewall-name my-firewall \
--region us-east-1

Expected output should show LogDestinationConfigs with at least one entry:

{
"FirewallArn": "arn:aws:network-firewall:us-east-1:123456789012:firewall/my-firewall",
"LoggingConfiguration": {
"LogDestinationConfigs": [
{
"LogType": "FLOW",
"LogDestinationType": "CloudWatchLogs",
"LogDestination": {
"logGroup": "/aws/network-firewall/my-firewall/flow"
}
}
]
}
}

Check for logs in CloudWatch:

aws logs describe-log-streams \
--log-group-name /aws/network-firewall/my-firewall/flow \
--region us-east-1 \
--limit 5

Additional Resources

Notes

  • Log types available: FLOW (all traffic), ALERT (traffic matching alert rules), and TLS (TLS inspection events)
  • Cost considerations: Logging generates CloudWatch Logs, S3, or Firehose charges. Set appropriate retention periods to manage costs
  • One destination per log type: Each log type can only be sent to one destination. To send to multiple destinations, use CloudWatch Logs subscriptions or S3 replication
  • Log destination must exist: The log group, S3 bucket, or Firehose stream must exist before enabling logging, or the configuration will fail
  • IAM permissions: Network Firewall needs permissions to write to your log destination. For CloudWatch Logs, this is automatic. For S3 or Firehose, ensure the appropriate resource policy or IAM role is configured