Aws application load balancer cannot enable access logs via terraform only via console even after applying policies

I have an application load balancer and I’m trying to enable logging, terraform code below:


resource "aws_s3_bucket" "lb-logs" {
  bucket = "yeo-messaging-${var.environment}-lb-logs"
}

resource "aws_s3_bucket_acl" "lb-logs-acl" {
  bucket = aws_s3_bucket.lb-logs.id
  acl    = "private"
}


resource "aws_lb" "main" {
  name                       = "main"
  internal                   = false
  load_balancer_type         = "application"
  security_groups            = [aws_security_group.public.id]
  enable_deletion_protection = false
  subnets                    = [aws_subnet.public.id, aws_subnet.public-backup.id]

  access_logs {
    bucket  = aws_s3_bucket.lb-logs.bucket
    prefix  = "main-lb"
    enabled = true
  }
}

unfortunately I can’t apply this due to:

Error: failure configuring LB attributes: InvalidConfigurationRequest: Access Denied for bucket: xxx-lb-logs. Please check S3bucket permission
│       status code: 400, request id: xx

I’ve seen a few SO threads and documentation but unfortunately it all applies to the classic load balancer, particularly the ‘data’ that allows you to get the service account of the laod balancer.

I have found some policy info on how to apply the right permissions to a SA but I can’t seem to find how to apply the service account to the LB itself.

Example:

data "aws_iam_policy_document" "allow-lb" {
  statement {
    principals {
      type        = "AWS"
      identifiers = [data.aws_elb_service_account.main.arn]
    }

    actions = [
      "s3:GetObject",
      "s3:ListBucket",
      "s3:PutObject"
    ]

    resources = [
      aws_s3_bucket.lb-logs.arn,
      "${aws_s3_bucket.lb-logs.arn}/*",
    ]
  }
}


resource "aws_s3_bucket_policy" "allow-lb" {
  bucket = aws_s3_bucket.lb-logs.id
  policy = data.aws_iam_policy_document.allow-lb.json
}

But this is all moot because data.aws_elb_service_account.main.arn is only for classic LB.


EDIT:

Full code with attempt from answer below:


resource "aws_s3_bucket" "lb-logs" {
  bucket = "yeo-messaging-${var.environment}-lb-logs"
}

resource "aws_s3_bucket_acl" "lb-logs-acl" {
  bucket = aws_s3_bucket.lb-logs.id
  acl    = "private"
}

data "aws_iam_policy_document" "allow-lb" {
  statement {
    principals {
      type        = "Service"
      identifiers = ["logdelivery.elb.amazonaws.com"]
    }

    actions = [
      "s3:PutObject"
    ]

    resources = [
      "${aws_s3_bucket.lb-logs.arn}/*"
    ]

    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"

      values = [
        "bucket-owner-full-control"
      ]
    }
  }
}

resource "aws_s3_bucket_policy" "allow-lb" {
  bucket = aws_s3_bucket.lb-logs.id
  policy = data.aws_iam_policy_document.allow-lb.json
}


resource "aws_lb" "main" {
  name                       = "main"
  internal                   = false
  load_balancer_type         = "application"
  security_groups            = [aws_security_group.public.id]
  enable_deletion_protection = false
  subnets                    = [aws_subnet.public.id, aws_subnet.public-backup.id]

  access_logs {
    bucket  = aws_s3_bucket.lb-logs.bucket
    prefix  = "main-lb"
    enabled = true
  }
}