By using AWS re:Post, you agree to the Terms of Use

S3 IAM error while "put" ing logs from ALB to S3 bucket

0

s3.tf

resource "aws_iam_role" "iam_role_replication" {
  name = "tf-iam-role-replication-12345"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
POLICY
}

resource "aws_iam_policy" "iam_policy_replication" {
  name = "tf-iam-role-policy-replication-12345"

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:GetReplicationConfiguration",
        "s3:ListBucket"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_s3_bucket.s3_bucket_master.arn}"
      ]
    },
    {
      "Action": [
        "s3:GetObjectVersionForReplication",
        "s3:GetObjectVersionAcl",
         "s3:GetObjectVersionTagging"
      ],
      "Effect": "Allow",
      "Resource": [
        "${aws_s3_bucket.s3_bucket_master.arn}/*"
      ]
    },
    {
      "Action": [
        "s3:ReplicateObject",
        "s3:ReplicateDelete",
        "s3:ReplicateTags"
      ],
      "Effect": "Allow",
      "Resource": "${aws_s3_bucket.s3_bucket_slave.arn}/*"
    }
  ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "replication" {
  role       = aws_iam_role.iam_role_replication.name
  policy_arn = aws_iam_policy.iam_policy_replication.arn
}

resource "aws_s3_bucket" "s3_bucket_slave" {
  bucket_prefix = "s3-bucket-slave-"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "s3_bucket_slave_sse_config" {
  bucket = aws_s3_bucket.s3_bucket_slave.bucket

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.s3_kms_key.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_versioning" "s3_bucket_slave_versioning" {
  bucket = aws_s3_bucket.s3_bucket_slave.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket" "s3_bucket_master" {
  bucket_prefix = "s3-bucket-master-"
}
resource "aws_s3_bucket_policy" "s3_bucket_master_alb_put_policy" {
  bucket = aws_s3_bucket.s3_bucket_master.id
  policy = <<POLICY
{
  "Id": "Policy",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": "${aws_s3_bucket.s3_bucket_master.arn}/access-logs-bucket/*",
      "Principal": {
        "AWS": [
          "${data.aws_elb_service_account.main.arn}"
        ]
      }
    }
  ]
}
POLICY
}


resource "aws_s3_bucket_server_side_encryption_configuration" "s3_bucket_master_sse_config" {
  bucket = aws_s3_bucket.s3_bucket_master.bucket
  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.s3_kms_key.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_versioning" "s3_bucket_master_versioning" {
  bucket = aws_s3_bucket.s3_bucket_master.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_replication_configuration" "s3_bucket_master_replication" {
  # Must have bucket versioning enabled first
  depends_on = [aws_s3_bucket_versioning.s3_bucket_master_versioning]

  role   = aws_iam_role.iam_role_replication.arn
  bucket = aws_s3_bucket.s3_bucket_master.id

  rule {
    id = "foobar"
    delete_marker_replication {
      status = "Disabled"
    }
    filter {
      prefix = "foo"
    }

    status = "Enabled"

    destination {
      bucket        = aws_s3_bucket.s3_bucket_slave.arn
      storage_class = "STANDARD"
    }
  }
}

resource "aws_s3_bucket_acl" "s3_bucket_master_acl" {
  bucket = aws_s3_bucket.s3_bucket_master.id
  acl    = "private"
}

resource "aws_s3_bucket_acl" "s3_bucket_slave_acl" {
  bucket = aws_s3_bucket.s3_bucket_slave.id
  acl    = "log-delivery-write"
}
resource "aws_s3_bucket_public_access_block" "s3_bucket_master_public_access" {
  bucket                  = aws_s3_bucket.s3_bucket_master.id
  restrict_public_buckets = true
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
}
resource "aws_s3_bucket_public_access_block" "s3_bucket_slave_public_access" {
  bucket                  = aws_s3_bucket.s3_bucket_slave.id
  restrict_public_buckets = true
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
}
resource "aws_s3_bucket_logging" "example" {
  bucket = aws_s3_bucket.s3_bucket_master.id

  target_bucket = aws_s3_bucket.s3_bucket_slave.id
  target_prefix = "log/"
}

alb.tf

####################################################
# Target Group Creation
####################################################

resource "aws_lb_target_group" "lb_tg" {
  name        = "alb-target-group"
  port        = 80
  target_type = "instance"
  protocol    = "HTTP"
  vpc_id      = aws_vpc.vpc.id
}

####################################################
# Target Group Attachment with Instance
####################################################

resource "aws_alb_target_group_attachment" "tg_attachment" {
  count            = length(aws_instance.instance.*.id) == 3 ? 3 : 0
  target_group_arn = aws_lb_target_group.lb_tg.arn
  target_id        = element(aws_instance.instance.*.id, count.index)
}

####################################################
# Application Load balancer
####################################################

resource "aws_lb" "lb" {
  name                       = "alb"
  internal                   = true
  load_balancer_type         = "application"
  security_groups            = [aws_security_group.sg.id, ]
  subnets                    = aws_subnet.public_subnet.*.id
  drop_invalid_header_fields = true
  access_logs {
    bucket  = aws_s3_bucket.s3_bucket_master.bucket
    prefix  = "access-logs-bucket"
    enabled = true
  }
  enable_deletion_protection = true
}

####################################################
# Listner
####################################################

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = aws_lb.lb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type = "redirect"

    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}


####################################################
# Listener Rule
####################################################

resource "aws_lb_listener_rule" "static" {
  listener_arn = aws_lb_listener.front_end.arn
  priority     = 100

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.lb_tg.arn

  }

  condition {
    path_pattern {
      values = ["/var/www/html/index.html"]
    }
  }
}

data.tf

# Get user 
data "aws_caller_identity" "current" {}

# Get Account 
data "aws_elb_service_account" "main" {}

Unfortunately, I am getting errors like the below:

╷
│ Error: failure configuring LB attributes: InvalidConfigurationRequest: Access Denied for bucket: s3-bucket-master-20220713230235453200000002. Please check S3bucket permission
│       status code: 400, request id: 17cb8a1b-d914-4fe5-b6cd-5db02f335cc4
│
│   with aws_lb.lb,
│   on alb.tf line 27, in resource "aws_lb" "lb":
│   27: resource "aws_lb" "lb" {
│
╵

I followed the article from https://stackoverflow.com/questions/43366038/terraform-elb-s3-permissions-issue

I am struggling to understand what exactly the issue is and I am kind of blocked.

Any help would be much appreciated.

  • master and slave comes from mysql replication as that is what I worked in past.

1 Answers
0

The only potential issue I can see is that you're using KMS encryption on the S3 buckets. The ALB will not have access to the KMS key to be able to encrypt the logs, which would likely result in the access denied error you're seeing. The docs also mention that you should use S3 managed encryption for this purpose: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions.

Try changing your bucket resources to include the following instead:

rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration#sse_algorithm

answered a month ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions