How to refer conditional resources on another resource in terraform

I created 2 buckets. One will create always and one will create when env is QA.

resource "aws_s3_bucket" "bucket_always" {
  bucket_prefix = format("bucket.always")
  acl           = "private"

  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "aws:kms"
      }
    }
  }
} 

resource "aws_s3_bucket" "bucket_conditional" {
  count = var.name == "qa" ? 1 : 0
  bucket_prefix = format("bucket.conditional")
  acl           = "private"

  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "aws:kms"
      }
    }
  }
} 

Now how can I create an IAM and add both buckets arn? The below policy won’t work because of conditional bucket

data "aws_iam_policy_document" "test_policy_document" {
  statement {
    actions = [
      "s3:ListBucket",
    ]

    resources = [
      aws_s3_bucket.bucket_always.arn,
      aws_s3_bucket.bucket_conditional.arn,
    ]
  }

  statement {
    actions = [
      "s3:PutObject",
      "s3:GetObject",
      "s3:DeleteObject",
    ]

    resources = [
      "${aws_s3_bucket.bucket_always.arn}/*",
      "${aws_s3_bucket.bucket_conditional.arn}/*",
    ]
  }
}

You need to add the conditional where you are using it too. So only try to reference the QA bucket if the environment is set to QA.

If you’ll be frequently using “all of the buckets” in expressions and want to factor out the conditional handling then you could declare a local value like this;

locals {
  s3_buckets = concat(
    [aws_s3_bucket.bucket_always],
    aws_s3_bucket.bucket_conditional,
  )
}

Because aws_s3_bucket.bucket_always doesn’t have count set we need to construct a single-element sequence to concatenate here, but concat then concatenates them together to make a single flat sequence of bucket objects, which will have either one or two elements. (Another way to go here would be to set unconditional count = 1 on that first resource so that they’ll both appear as lists of objects, but I think that would probably be surprising for future readers.)

You can then use local.s3_buckets in all of the ways you might typically use to work with all instances of a resource with count set. For example:

  resources = local.s3_buckets[*].arn
  resources = [for b in local.s3_buckets : "${b.arn}/*"]