Bootstrap FreeKB - Amazon Web Services (AWS) - Configure Network Load Balancer (NLB) to log to an S3 Bucket using Terraform
Amazon Web Services (AWS) - Configure Network Load Balancer (NLB) to log to an S3 Bucket using Terraform

Updated:   |  Amazon Web Services (AWS) articles

This assumes you have setup Terraform with the Amazon Web Services (AWS) provider. If not, check out my article Amazon Web Services (AWS) Getting Started with Terraform.

After configuring your Network Load Balancer (NLB) to log to an S3 Bucket, the log may look something like this.

protocol datetime            load balancer                              load balancer id source ip:port    dest ip:port     status codes                  datetime
tls 2.0  2023-10-12T01:08:08 net/network-load-balancer/19dd9f59a3a084d8 1478a1951aa0a25c 10.11.12.13:51797 172.31.94.59:443 43 - 0 0 46 - - - - - - - - - 2023-10-12T01:08:08

 

Let's say you have the following files on your Terraform server.

├── required_providers.tf
├── network_load_balancers (directory)
│   ├── listener.tf
│   ├── load_balancer.tf
│   ├── provider.tf
│   ├── s3_bucket.tf
│   ├── target_group.tf

 

required_providers.tf will almost always have this.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
    }
  }
}

 

Let's say provider.tf has the following. In this example, the "default" profile in /home/username/.aws/config and /home/username/.aws/credentials is being used. This assumes you have setup Terraform as described in Amazon Web Services (AWS) - Getting Started with Terraform.

provider "aws" {
  alias   = "default"
  profile = "default"
  region  = "default"
}

 

And s3_bucket.tf could have the following to create an S3 Bucket that will be used by the Network Load Balancer. Replace 123456789012 with your Amazon Web Services (AWS) Account ID.

resource "aws_s3_bucket" "s3_bucket" {

  bucket = "my-bucket"

  tags = {
    Name        = "my-bucket"
    Environment = "production"
  }
}

resource "aws_s3_bucket_policy" "s3_bucket_policy" {

  depends_on = [aws_s3_bucket.s3_bucket]

  bucket = aws_s3_bucket.s3_bucket.id
  policy = data.aws_iam_policy_document.iam_policy_document.json
}

data "aws_iam_policy_document" "iam_policy_document" {
  statement {
    sid       = "AWSLogDeliveryAclCheck"
    effect    = "Allow"
    actions   = ["s3:GetBucketAcl"]
    resources = [aws_s3_bucket.s3_bucket.arn]
    principals {
      type        = "Service"
      identifiers = ["delivery.logs.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values   = ["123456789012"]
    }
    condition {
      test     = "ArnLike"
      variable = "aws:SourceArn"
      values   = ["arn:aws:logs:us-east-1:123456789012:*"]
    }
  }
  statement {
    sid       = "AWSLogDeliveryWrite"
    effect    = "Allow"
    actions   = ["s3:PutObject"]
    resources = ["${aws_s3_bucket.s3_bucket.arn}/AWSLogs/123456789012/*"]
    principals {
      type        = "Service"
      identifiers = ["delivery.logs.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values   = ["123456789012"]
    }
    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }
    condition {
      test     = "ArnLike"
      variable = "aws:SourceArn"
      values   = ["arn:aws:logs:us-east-1:123456789012:*"]
    }
  }
}

 

And load_balancer.tf could have the following to create a Network Load Balancer that will append it's access logs to the S3 Bucket.

resource "aws_lb" "my-network-load-balancer" {

  depends_on = [aws_s3_bucket.s3_bucket]

  name               = "my-network-load-balancer"
  internal           = false
  load_balancer_type = "network"
  enable_deletion_protection = true

  subnet_mapping {
    subnet_id = data.terraform_remote_state.ec2_instances.outputs.my_foo_instance.subnet-id
    allocation_id = data.terraform_remote_state.elastic_ip.outputs.elastic_ip_allocation_ids[0]
  }

  subnet_mapping {
    subnet_id = data.terraform_remote_state.ec2_instances.outputs.my_bar_instance.subnet-id
    allocation_id = data.terraform_remote_state.elastic_ip.outputs.elastic_ip_allocation_ids[1]
  }

  access_logs {
    bucket  = aws_s3_bucket.s3_bucket.id
    enabled = true
  }

  tags = {
    Environment = "staging"
    Name = "my-network-load-balancer"
  }
}

 

Almost always, you will also:

 

The terraform plan command can be used to see what Terraform will try to do.

terraform plan

 

And the terraform apply command can be used to create the Network Load balancer.

terraform apply

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter e0a318 in the box below so that we can be sure you are a human.