Configure AWS Network Firewall Logging

The aws:networkfirewall/loggingConfiguration:LoggingConfiguration resource, part of the Pulumi AWS provider, configures where Network Firewall sends its logs: S3 for archival, CloudWatch for real-time monitoring, or Kinesis Data Firehose for streaming pipelines. This guide focuses on three capabilities: S3 archival with prefix organization, CloudWatch real-time monitoring, and Kinesis Data Firehose streaming integration.

Logging configurations attach to existing Network Firewall firewalls and route logs to pre-existing destinations. The examples are intentionally small. Combine them with your own firewall and destination resources.

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

The logDestinationConfigs array defines where logs go. Each entry specifies a logDestinationType (S3, CloudWatchLogs, or KinesisDataFirehose) and a logType (FLOW, ALERT, or TLS). The logDestination object contains destination-specific properties: for S3, that’s bucketName and an optional prefix for organizing objects.

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

When logDestinationType is CloudWatchLogs, the logDestination object requires a logGroup property pointing to an existing CloudWatch log group. Setting logType to ALERT captures rule match events rather than connection flow data, enabling real-time querying and alarming.

Route TLS logs through Kinesis Data Firehose

Organizations that need to transform or enrich logs before storage route them through Kinesis Data Firehose.

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

For KinesisDataFirehose destinations, the logDestination object specifies a deliveryStream name. The logType property set to TLS captures TLS inspection events. Firehose can then apply Lambda transformations or deliver to multiple destinations like S3, Redshift, or Elasticsearch.

Beyond these examples

These snippets focus on specific logging configuration features: log destination routing (S3, CloudWatch, Kinesis) and log type selection (FLOW, ALERT, TLS). They’re intentionally minimal rather than complete logging architectures.

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 destinations.

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

  • Monitoring dashboard enablement (enableMonitoringDashboard)
  • Multiple simultaneous log destinations
  • Log retention and lifecycle policies
  • IAM permissions for log delivery

These omissions are intentional: the goal is to illustrate how each logging destination is wired, not provide drop-in monitoring solutions. 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

Log Destinations & Configuration
What log destinations can I use with Network Firewall?

You can send logs to three destination types:

  1. S3 - Requires bucketName and optional prefix in logDestination
  2. CloudWatchLogs - Requires logGroup in logDestination
  3. KinesisDataFirehose - Requires deliveryStream in logDestination
Can I send logs to multiple destinations at the same time?
Yes, logDestinationConfigs accepts an array of configurations, allowing you to send logs to multiple destinations simultaneously.
What log types are available?
The examples show three logType values: FLOW, ALERT, and TLS. The schema doesn’t provide detailed descriptions of each type’s content.
Resource Management
Can I change the firewall ARN after creating the logging configuration?
No, firewallArn is immutable and cannot be changed after creation. To associate logging with a different firewall, you must destroy and recreate the resource.

Using a different cloud?

Explore security guides for other cloud providers: