Hi all,
I hope someone can point me in the right direction.
I am trying to build a KMS key policy. In this policy I need to allow several GuardDuty detector IDs from different regions. So my desired policy should look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGuardDutyKey",
"Effect": "Allow",
"Principal": {
"Service": "guardduty.amazonaws.com"
},
"Action": "kms:GenerateDataKey",
"Resource": "arn:${aws_partition}:kms:${kms_key_region}:${source_account}:key/${kms_key_id}",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "${source_account}",
"aws:SourceArn": [
"arn:${aws_partition}:guardduty:${guardduty_detector_region}:${source_account}:detector/${guardduty_detector_id_1}",
"arn:${aws_partition}:guardduty:${guardduty_detector_region}:${source_account}:detector/${guardduty_detector_id_2}",
"arn:${aws_partition}:guardduty:${guardduty_detector_region}:${source_account}:detector/${guardduty_detector_id_N}"
]
}
}
}
]
}
I need to build the aws:SourceArn
condition key, which is a list, dynamically depending on the number of GuardDuty connector IDs that I am passing.
So far this is the configuration I have:
In main.tf
:
locals {
guardduty_detector_ids = [
{"eu-west-1" = data.aws_guardduty_detector.ireland_guardduty_detector.id}, # returns a detector ID - works fine
{"us-east-1" = data.aws_guardduty_detector.virginia_guardduty_detector.id},
{"eu-central-1" = data.aws_guardduty_detector.frankfurt_guardduty_detector.id},
{"eu-west-2" = data.aws_guardduty_detector.london_guardduty_detector.id},
{"eu-west-3" = data.aws_guardduty_detector.paris_guardduty_detector.id},
{"eu-north-1" = data.aws_guardduty_detector.stockholm_guardduty_detector.id},
{"us-east-2" = data.aws_guardduty_detector.ohio_guardduty_detector.id},
{"us-west-1" = data.aws_guardduty_detector.north_california_guardduty_detector.id},
{"us-west-2" = data.aws_guardduty_detector.oregon_guardduty_detector.id},
{"ca-central-1" = data.aws_guardduty_detector.central_guardduty_detector.id},
{"ap-south-1" = data.aws_guardduty_detector.mumbai_guardduty_detector.id},
{"ap-northeast-3" = data.aws_guardduty_detector.osaka_guardduty_detector.id},
{"ap-northeast-2" = data.aws_guardduty_detector.seoul_guardduty_detector.id},
{"ap-southeast-1" = data.aws_guardduty_detector.singapore_guardduty_detector.id},
{"ap-southeast-2" = data.aws_guardduty_detector.sydney_guardduty_detector.id},
{"ap-northeast-1" = data.aws_guardduty_detector.tokyo_guardduty_detector.id},
{"sa-east-1" = data.aws_guardduty_detector.sao_paulo_guardduty_detector.id}
]
}
module "aws_guardduty_findings_kms_key" {
source = "./kms-key"
description = "This is used to encrypt GuardDuty exported findings"
policy = templatefile("policy/aws_guardduty_findings_kms_key_policy.json", {
source_account = var.account_id
kms_key_region = var.aws_region
kms_key_id = "*"
guardduty_detector_ids = local.guardduty_detector_ids
aws_partition = "aws"
})
}
In policy/aws_guardduty_findings_kms_key_policy.json
file I have:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGuardDutyKey",
"Effect": "Allow",
"Principal": {
"Service": "guardduty.amazonaws.com"
},
"Action": "kms:GenerateDataKey",
"Resource": "arn:${aws_partition}:kms:${kms_key_region}:${source_account}:key/${kms_key_id}",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "${source_account}",
"aws:SourceArn": [
%{ for guardduty_detector_id_info in guardduty_detector_ids }
%{ for guardduty_detector_region, guardduty_detector_id in guardduty_detector_id_info }
"arn:${aws_partition}:guardduty:${guardduty_detector_region}:${source_account}:detector/${guardduty_detector_id}"
%{ endfor }
%{ endfor }
]
}
}
}
]
}
As you can see, I am using the templatefile()
function to build a template policy where I can dynamically construct the list value of the aws:SourceArn
condition key, so I can get my desired policy as shown above.
But when I apply
the above configuration, I get an error:
Error: "policy" contains an invalid JSON: invalid character '"' after array element
│
│ with module.aws_guardduty_findings_kms_key.aws_kms_key.kms_key,
│ on ./kms-key/main.tf line 5, in resource "aws_kms_key" "kms_key":
│ 5: policy = var.policy
Can someone please point out what am I doing wrong here? I don’t understand why this is failing and what is should I be doing differently. It seems that it doesn’t like something about the double quotes that the ARN value is wrapped in.
If I put the entire statement inside the two for
loops, then it works fine. But that will increase a lot the size of the policy as it will create the statement for each item in the local guardduty_detector_ids
variable, which is not ideal.
I would appreciate very much some guidance.
Thank you very much in advance!