Configure AWS Network Firewall Logging

The aws:networkfirewall/loggingConfiguration:LoggingConfiguration resource, part of the Pulumi AWS provider, configures where Network Firewall sends its logs: flow logs, alert logs, and TLS inspection logs. This guide focuses on three capabilities: S3 archival for flow logs, CloudWatch streaming for alert logs, and Kinesis Data Firehose integration for TLS logs.

Logging configurations reference an existing Network Firewall and destination resources. The examples are intentionally small. Combine them with your own firewall, IAM permissions, and log retention policies.

Send flow logs to S3 for long-term storage

Network security teams archive flow logs to S3 for compliance auditing and cost-effective long-term storage.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.networkfirewall.LoggingConfiguration("example", {
    firewallArn: exampleAwsNetworkfirewallFirewall.arn,
    loggingConfiguration: {
        logDestinationConfigs: [{
            logDestination: {
                bucketName: exampleAwsS3Bucket.bucket,
                prefix: "example",
            },
            logDestinationType: "S3",
            logType: "FLOW",
        }],
    },
});
import pulumi
import pulumi_aws as aws

example = aws.networkfirewall.LoggingConfiguration("example",
    firewall_arn=example_aws_networkfirewall_firewall["arn"],
    logging_configuration={
        "log_destination_configs": [{
            "log_destination": {
                "bucketName": example_aws_s3_bucket["bucket"],
                "prefix": "example",
            },
            "log_destination_type": "S3",
            "log_type": "FLOW",
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkfirewall.NewLoggingConfiguration(ctx, "example", &networkfirewall.LoggingConfigurationArgs{
			FirewallArn: pulumi.Any(exampleAwsNetworkfirewallFirewall.Arn),
			LoggingConfiguration: &networkfirewall.LoggingConfigurationLoggingConfigurationArgs{
				LogDestinationConfigs: networkfirewall.LoggingConfigurationLoggingConfigurationLogDestinationConfigArray{
					&networkfirewall.LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs{
						LogDestination: pulumi.StringMap{
							"bucketName": pulumi.Any(exampleAwsS3Bucket.Bucket),
							"prefix":     pulumi.String("example"),
						},
						LogDestinationType: pulumi.String("S3"),
						LogType:            pulumi.String("FLOW"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.NetworkFirewall.LoggingConfiguration("example", new()
    {
        FirewallArn = exampleAwsNetworkfirewallFirewall.Arn,
        LoggingConfig = new Aws.NetworkFirewall.Inputs.LoggingConfigurationLoggingConfigurationArgs
        {
            LogDestinationConfigs = new[]
            {
                new Aws.NetworkFirewall.Inputs.LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs
                {
                    LogDestination = 
                    {
                        { "bucketName", exampleAwsS3Bucket.Bucket },
                        { "prefix", "example" },
                    },
                    LogDestinationType = "S3",
                    LogType = "FLOW",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.LoggingConfiguration;
import com.pulumi.aws.networkfirewall.LoggingConfigurationArgs;
import com.pulumi.aws.networkfirewall.inputs.LoggingConfigurationLoggingConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LoggingConfiguration("example", LoggingConfigurationArgs.builder()
            .firewallArn(exampleAwsNetworkfirewallFirewall.arn())
            .loggingConfiguration(LoggingConfigurationLoggingConfigurationArgs.builder()
                .logDestinationConfigs(LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs.builder()
                    .logDestination(Map.ofEntries(
                        Map.entry("bucketName", exampleAwsS3Bucket.bucket()),
                        Map.entry("prefix", "example")
                    ))
                    .logDestinationType("S3")
                    .logType("FLOW")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:LoggingConfiguration
    properties:
      firewallArn: ${exampleAwsNetworkfirewallFirewall.arn}
      loggingConfiguration:
        logDestinationConfigs:
          - logDestination:
              bucketName: ${exampleAwsS3Bucket.bucket}
              prefix: example
            logDestinationType: S3
            logType: FLOW

When the firewall processes traffic, it writes flow logs to the specified S3 bucket. The logDestination block sets the bucketName and prefix for organizing logs. The logType property determines which logs to capture; FLOW logs record connection metadata like source IP, destination IP, and protocol.

Stream alert logs to CloudWatch for real-time monitoring

Security operations teams need immediate visibility into firewall alerts to detect and respond to threats.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.networkfirewall.LoggingConfiguration("example", {
    firewallArn: exampleAwsNetworkfirewallFirewall.arn,
    loggingConfiguration: {
        logDestinationConfigs: [{
            logDestination: {
                logGroup: exampleAwsCloudwatchLogGroup.name,
            },
            logDestinationType: "CloudWatchLogs",
            logType: "ALERT",
        }],
    },
});
import pulumi
import pulumi_aws as aws

example = aws.networkfirewall.LoggingConfiguration("example",
    firewall_arn=example_aws_networkfirewall_firewall["arn"],
    logging_configuration={
        "log_destination_configs": [{
            "log_destination": {
                "logGroup": example_aws_cloudwatch_log_group["name"],
            },
            "log_destination_type": "CloudWatchLogs",
            "log_type": "ALERT",
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkfirewall.NewLoggingConfiguration(ctx, "example", &networkfirewall.LoggingConfigurationArgs{
			FirewallArn: pulumi.Any(exampleAwsNetworkfirewallFirewall.Arn),
			LoggingConfiguration: &networkfirewall.LoggingConfigurationLoggingConfigurationArgs{
				LogDestinationConfigs: networkfirewall.LoggingConfigurationLoggingConfigurationLogDestinationConfigArray{
					&networkfirewall.LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs{
						LogDestination: pulumi.StringMap{
							"logGroup": pulumi.Any(exampleAwsCloudwatchLogGroup.Name),
						},
						LogDestinationType: pulumi.String("CloudWatchLogs"),
						LogType:            pulumi.String("ALERT"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.NetworkFirewall.LoggingConfiguration("example", new()
    {
        FirewallArn = exampleAwsNetworkfirewallFirewall.Arn,
        LoggingConfig = new Aws.NetworkFirewall.Inputs.LoggingConfigurationLoggingConfigurationArgs
        {
            LogDestinationConfigs = new[]
            {
                new Aws.NetworkFirewall.Inputs.LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs
                {
                    LogDestination = 
                    {
                        { "logGroup", exampleAwsCloudwatchLogGroup.Name },
                    },
                    LogDestinationType = "CloudWatchLogs",
                    LogType = "ALERT",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.LoggingConfiguration;
import com.pulumi.aws.networkfirewall.LoggingConfigurationArgs;
import com.pulumi.aws.networkfirewall.inputs.LoggingConfigurationLoggingConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LoggingConfiguration("example", LoggingConfigurationArgs.builder()
            .firewallArn(exampleAwsNetworkfirewallFirewall.arn())
            .loggingConfiguration(LoggingConfigurationLoggingConfigurationArgs.builder()
                .logDestinationConfigs(LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs.builder()
                    .logDestination(Map.of("logGroup", exampleAwsCloudwatchLogGroup.name()))
                    .logDestinationType("CloudWatchLogs")
                    .logType("ALERT")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:LoggingConfiguration
    properties:
      firewallArn: ${exampleAwsNetworkfirewallFirewall.arn}
      loggingConfiguration:
        logDestinationConfigs:
          - logDestination:
              logGroup: ${exampleAwsCloudwatchLogGroup.name}
            logDestinationType: CloudWatchLogs
            logType: ALERT

Alert logs stream to the specified CloudWatch Log Group in real-time. The logDestinationType property selects CloudWatchLogs as the destination. The logType property set to ALERT captures rule match events, enabling immediate querying and alarming through CloudWatch.

Route TLS inspection logs through Kinesis Data Firehose

Organizations with centralized log processing pipelines use Kinesis Data Firehose to transform and deliver logs to multiple destinations.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.networkfirewall.LoggingConfiguration("example", {
    firewallArn: exampleAwsNetworkfirewallFirewall.arn,
    loggingConfiguration: {
        logDestinationConfigs: [{
            logDestination: {
                deliveryStream: exampleAwsKinesisFirehoseDeliveryStream.name,
            },
            logDestinationType: "KinesisDataFirehose",
            logType: "TLS",
        }],
    },
});
import pulumi
import pulumi_aws as aws

example = aws.networkfirewall.LoggingConfiguration("example",
    firewall_arn=example_aws_networkfirewall_firewall["arn"],
    logging_configuration={
        "log_destination_configs": [{
            "log_destination": {
                "deliveryStream": example_aws_kinesis_firehose_delivery_stream["name"],
            },
            "log_destination_type": "KinesisDataFirehose",
            "log_type": "TLS",
        }],
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkfirewall"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := networkfirewall.NewLoggingConfiguration(ctx, "example", &networkfirewall.LoggingConfigurationArgs{
			FirewallArn: pulumi.Any(exampleAwsNetworkfirewallFirewall.Arn),
			LoggingConfiguration: &networkfirewall.LoggingConfigurationLoggingConfigurationArgs{
				LogDestinationConfigs: networkfirewall.LoggingConfigurationLoggingConfigurationLogDestinationConfigArray{
					&networkfirewall.LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs{
						LogDestination: pulumi.StringMap{
							"deliveryStream": pulumi.Any(exampleAwsKinesisFirehoseDeliveryStream.Name),
						},
						LogDestinationType: pulumi.String("KinesisDataFirehose"),
						LogType:            pulumi.String("TLS"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.NetworkFirewall.LoggingConfiguration("example", new()
    {
        FirewallArn = exampleAwsNetworkfirewallFirewall.Arn,
        LoggingConfig = new Aws.NetworkFirewall.Inputs.LoggingConfigurationLoggingConfigurationArgs
        {
            LogDestinationConfigs = new[]
            {
                new Aws.NetworkFirewall.Inputs.LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs
                {
                    LogDestination = 
                    {
                        { "deliveryStream", exampleAwsKinesisFirehoseDeliveryStream.Name },
                    },
                    LogDestinationType = "KinesisDataFirehose",
                    LogType = "TLS",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkfirewall.LoggingConfiguration;
import com.pulumi.aws.networkfirewall.LoggingConfigurationArgs;
import com.pulumi.aws.networkfirewall.inputs.LoggingConfigurationLoggingConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LoggingConfiguration("example", LoggingConfigurationArgs.builder()
            .firewallArn(exampleAwsNetworkfirewallFirewall.arn())
            .loggingConfiguration(LoggingConfigurationLoggingConfigurationArgs.builder()
                .logDestinationConfigs(LoggingConfigurationLoggingConfigurationLogDestinationConfigArgs.builder()
                    .logDestination(Map.of("deliveryStream", exampleAwsKinesisFirehoseDeliveryStream.name()))
                    .logDestinationType("KinesisDataFirehose")
                    .logType("TLS")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:networkfirewall:LoggingConfiguration
    properties:
      firewallArn: ${exampleAwsNetworkfirewallFirewall.arn}
      loggingConfiguration:
        logDestinationConfigs:
          - logDestination:
              deliveryStream: ${exampleAwsKinesisFirehoseDeliveryStream.name}
            logDestinationType: KinesisDataFirehose
            logType: TLS

TLS inspection logs flow through the specified Kinesis Data Firehose delivery stream. The logDestinationType property routes logs to KinesisDataFirehose. The logType property set to TLS captures decrypted traffic metadata when TLS inspection is enabled on the firewall.

Beyond these examples

These snippets focus on specific logging configuration features: S3, CloudWatch, and Kinesis Data Firehose destinations, and flow, alert, and TLS log types. They’re intentionally minimal rather than full logging solutions.

The examples reference pre-existing infrastructure such as Network Firewall firewalls, and S3 buckets, CloudWatch Log Groups, or Kinesis Data Firehose delivery streams. They focus on configuring log routing rather than provisioning the firewall or destination resources.

To keep things focused, common logging patterns are omitted, including:

  • Monitoring dashboard enablement (enableMonitoringDashboard)
  • Multiple log destinations in a single configuration
  • IAM permissions for log delivery
  • Log retention and lifecycle policies

These omissions are intentional: the goal is to illustrate how each logging destination is wired, not provide drop-in monitoring modules. See the Network Firewall Logging Configuration resource reference for all available configuration options.

Let's configure AWS Network Firewall Logging

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Setup
Can I change the firewall ARN after creating the logging configuration?
No, firewallArn is immutable and cannot be changed after the resource is created.
What logging destinations can I use with Network Firewall?
You can log to S3, CloudWatch Logs, or Kinesis Data Firehose by setting logDestinationType to S3, CloudWatchLogs, or KinesisDataFirehose.
What log types are available?
Network Firewall supports three log types: FLOW, ALERT, and TLS.
Is the monitoring dashboard enabled by default?
No, enableMonitoringDashboard defaults to false. You must explicitly enable it if you want detailed firewall monitoring.
Destination-Specific Configuration
What fields do I need in logDestination for each destination type?

The required fields vary by destination:

  • S3: bucketName and prefix
  • CloudWatch Logs: logGroup
  • Kinesis Data Firehose: deliveryStream

Using a different cloud?

Explore security guides for other cloud providers: