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

Time:07-17

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 Terraform ELB S3 Permissions Issue

I am struggling to understand what exactly is the issue!?

P.S Edit 1: Amended the S3 Resource Name as per recommendation but I am still getting the error of access denied.

CodePudding user response:

It seems you have just copy/pasted the example from the documentation [1]:

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": "arn:aws:s3:::my-elb-tf-test-bucket/AWSLogs/*",
      "Principal": {
        "AWS": [
          "${data.aws_elb_service_account.main.arn}"
        ]
      }
    }
  ]
}
POLICY
}

If you look at the ARN it is for a bucket that does not exist:

"arn:aws:s3:::my-elb-tf-test-bucket/AWSLogs/*"

You want the ARN of the master bucket if I am reading this right. So you would use the following ARN and the prefix defined in the prefix argument of the access_logs block in the aws_lb resource:

"${aws_s3_bucket.s3_bucket_master.arn}/access-logs-bucket/AWSLogs/${data.aws_caller_identity.current.id}/*"

EDIT: The prefix has to be there along with the AWSLogs and the AWS account ID as per [2].


[1] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/elb_service_account#example-usage

[2] https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html

CodePudding user response:

The following line needs further correction:

Incorrect:

"Resource": "${aws_s3_bucket.s3_bucket_master.arn}/access-logs-bucket/*",

Correct:

"Resource": "${aws_s3_bucket.s3_bucket_master.arn}/access-logs-bucket/AWSLogs/${data.aws_caller_identity.current.account_id}/*",

I think the .current.account_id on the aws_caller_identity was not considered in previous answer.

  • Related