Reputation: 469
I need to deploy AWS GuardDuty across all accounts/regions in my AWS Organization. My first step is to delegate GuardDuty's administration to a designated account. Since, GuardDuty is a regional resource, I need to perform such delegation across all regions. Note that we are operating in pretty much every region of AWS.
Here is a brute-force approach for accomplishing this task:
provider "aws" {
region = "us-east-1"
alias = "us-east-1"
}
provider "aws" {
region = "us-east-2"
alias = "us-east-2"
}
# Do the same for the remaining regions
resource "aws_guardduty_organization_admin_account" "us-east-1" {
provider = aws.us-east-1
admin_account_id = "123456789..."
}
resource "aws_guardduty_organization_admin_account" "us-east-2" {
provider = aws.us-east-2
admin_account_id = "123456789..."
}
# Do the same for the remaining regions
This works, but has several disadvantages:
Question: Is there a better way of doing this? There is an old thread on this scenario here: https://github.com/hashicorp/terraform/issues/451
However, it does not appear that a good options existed at that time, so I want to see if better options are available now.
Ideally, I want to leverage data "aws_regions" "all" {}
to loop over the existing regions and dynamically create the delegation resources and providers.
I tried the approach suggested by @Matt Schuchard:
Given this resource:
resource "aws_guardduty_organization_admin_account" "us-east-1" {
# interpolate in for expression here since not allowed in provider argument
for_each = toset([for region in data.aws_regions.this.names : "aws.${region}"])
provider = each.value
admin_account_id = "123456789..."
}
Terraform 1.0.10, produces the following error:
Error: Failed to query available provider packages
Could not retrieve the list of available versions for provider hashicorp/each: ...
Upvotes: 4
Views: 2647
Reputation: 28854
You would need the for_each
meta-argument for both the provider
and the resource
blocks to iterate over all AWS regions within a single block. If one attempts to use the for_each
meta-argument with the provider
block, then the error message displays:
The provider argument name "for_each" is reserved for use by Terraform in a future version.
and this is on the roadmap for future development.
However, one can do this with the for_each
meta-argument in the resource block. First, you suggested retrieving all available regions with the data aws_regions
to always truly target all regions:
data "aws_regions" "this" {}
where the all_regions
and filters
arguments can down-select the desired regions. The exported resource attribute names
of type list(string)
would store the desired regions.
Assuming you are configuring providers and their aliases as described in the question, you would then use this list
within the resource block:
resource "aws_guardduty_organization_admin_account" "us-east-1" {
# interpolate in for expression here since not allowed in provider argument
for_each = toset([for region in data.aws_regions.this.names : "aws.${region}"])
provider = each.value
admin_account_id = "123456789..."
}
and this would manage the resource in all desired AWS regions.
Upvotes: 2