Context
So I am upgrading terraform AWS provider so I can take advantage of python 3.11 lambda. The biggest issue is that I have to change aws_iam_policy_document.policy to aws_iam_policy_document.source_policy_documents which is a list of strings and not a string. ( I am using --
and ++
to show changes)
data "aws_iam_policy_document" "bucket" {
count = local.policy_enabled ? 1 : 0
-- source_json = var.policy
++ source_policy_documents = var.policy
I then changed variable policy to a list of strings:
variable "policy" {
description = "A bucket policy in JSON format."
-- type = string
-- default = null
++ type = list(string)
++ default = []
}
Added a bracket around policy
on this loggin bucket module
module "ehl_telemetry_access_logging_s3_bucket" {
source = "./modules/infra/s3bucket"
count = var.ehl_telemetry_access_logging_s3_bucket.create ? 1 : 0
bucket = local.ehl_telemetry_access_logging_s3_bucket_name
versioning = var.ehl_telemetry_access_logging_s3_bucket.versioning
block_public_acls = var.ehl_telemetry_access_logging_s3_bucket.block_public_acls
block_public_policy = var.ehl_telemetry_access_logging_s3_bucket.block_public_policy
ignore_public_acls = var.ehl_telemetry_access_logging_s3_bucket.ignore_public_acls
restrict_public_buckets = var.ehl_telemetry_access_logging_s3_bucket.restrict_public_buckets
policy = [replace(replace(replace(jsonencode(var.ehl_telemetry_access_logging_s3_bucket.policy), "VAR_S3_BUCKET", local.ehl_telemetry_access_logging_s3_bucket_name), "VAR_ACCOUNT_ID", data.aws_caller_identity.current.account_id), "VAR_REGION", var.aws_region)]
apply_server_side_encryption_by_default = {kms_master_key_id: module.kms_key.keyarn, sse_algorithm: "aws:kms"}
lifecycle_rules = var.ehl_telemetry_access_logging_s3_bucket.lifecycle_rules
tags = merge(local.common_tags, var.ehl_telemetry_access_logging_s3_bucket.tags)
}
The main issue is on this resource (original with just string type as policy):
resource "aws_s3_bucket_policy" "bucket" {
count = local.policy_enabled ? 1 : 0
bucket = local.bucket_id
# Debugging outputs
original_policy = local.original_policy
policy_string = local.policy_string
encoded_policy = local.encoded_policy
# remove whitespaces by decoding and encoding again to suppress terrform output whitespace cahnges
policy = try(jsonencode(jsondecode(data.aws_iam_policy_document.bucket[0].json)), null)
depends_on = [
var.module_depends_on,
aws_s3_bucket_public_access_block.bucket,
]
}
It is trying to use this iam_policy_document.
data "aws_iam_policy_document" "bucket" {
count = local.policy_enabled ? 1 : 0
source_policy_documents = var.policy
dynamic "statement" {
for_each = local.cross_account_bucket_actions_enabled ? [1] : []
content {
actions = var.cross_account_bucket_actions
resources = [local.bucket_arn]
principals {
type = "AWS"
identifiers = var.cross_account_identifiers
}
}
}
dynamic "statement" {
for_each = local.cross_account_object_actions_enabled ? [1] : []
content {
actions = var.cross_account_object_actions
resources = ["${local.bucket_arn}/*"]
principals {
type = "AWS"
identifiers = var.cross_account_identifiers
}
}
}
dynamic "statement" {
for_each = local.cross_account_object_actions_with_forced_acl_enabled ? [1] : []
content {
actions = var.cross_account_object_actions_with_forced_acl
resources = ["${local.bucket_arn}/*"]
principals {
type = "AWS"
identifiers = var.cross_account_identifiers
}
dynamic "condition" {
for_each = length(var.cross_account_forced_acls) == 0 ? [] : [1]
content {
test = "StringEquals"
variable = "s3:x-amz-acl"
values = var.cross_account_forced_acls
}
}
}
}
dynamic "statement" {
for_each = local.origin_access_identities_enabled ? [{
actions = ["s3:GetObject"]
resources = ["${local.bucket_arn}/*"]
}, {
actions = ["s3:ListBucket"]
resources = [local.bucket_arn]
}] : []
content {
actions = statement.value.actions
resources = statement.value.resources
principals {
type = "AWS"
identifiers = local.oai_identities
}
}
}
dynamic "statement" {
for_each = local.elb_log_delivery ? [1] : []
content {
actions = ["s3:PutObject"]
resources = ["${local.bucket_arn}/*"]
principals {
type = "AWS"
identifiers = sort(local.elb_accounts)
}
}
}
}
Attempts
-
policy = try(jsonencode(jsondecode(data.aws_iam_policy_document.bucket[0][0].json)), null)
Error:Only attribute access is allowed here, using the dot operator.
-
policy = local.policy_enabled ? jsonencode(tolist(data.aws_iam_policy_document.bucket[0])) : null
Error: data.aws_iam_policy_document.bucket[0] is object with 7 attributes
Invalid value for “v” parameter: cannot convert object to list of any single -
policy = data.aws_iam_policy_document.bucket[0].json
Error: MalformedPolicy: Missing required field Statement -
policy = data.aws_iam_policy_document.bucket.json
Error:
Missing resource instance key
│
│ on modules/infra/s3bucket/main.tf line 202, in resource "aws_s3_bucket_policy" "bucket":
│ 202: policy = data.aws_iam_policy_document.bucket.json
│
│ Because data.aws_iam_policy_document.bucket has "count" set, its attributes
│ must be accessed on specific instances.
│
│ For example, to correlate with indices of a referring resource, use:
│ data.aws_iam_policy_document.bucket[count.index]
policy = try(data.aws_iam_policy_document.bucket.json, null)
Error:
Missing resource instance key
│
│ on modules/infra/s3bucket/main.tf line 202, in resource "aws_s3_bucket_policy" "bucket":
│ 202: policy = try(data.aws_iam_policy_document.bucket.json, null)
│
│ Because data.aws_iam_policy_document.bucket has "count" set, its attributes
│ must be accessed on specific instances.
│
│ For example, to correlate with indices of a referring resource, use:
│ data.aws_iam_policy_document.bucket[count.index]
policy = local.policy_enabled ? data.aws_iam_policy_document.bucket[count.index].json : null
Error: putting S3 policy: MalformedPolicy: Missing required field Statement
Any Ideas on what to try