diff --git a/providers.tf b/providers.tf index 34b7e5c..d2f4929 100644 --- a/providers.tf +++ b/providers.tf @@ -47,3 +47,23 @@ provider "aws" { } region = var.aws_region } + +# The provider used to create the role allowing read-only access to this +# project's Terraform state in the Terraform account. +provider "aws" { + alias = "terraformprovisionaccount" + assume_role { + role_arn = data.terraform_remote_state.terraform.outputs.provisionaccount_role.arn + session_name = local.caller_user_name + } + default_tags { + # It makes no sense to associate a "Workspace" tag with the + # Terraform read role, since it can read the state from any + # workspace. + # + # Such a tag will also flip flop as one switched from staging to + # production or vice versa, which is highly annoying. + tags = { for k, v in var.tags : k => v if k != "Workspace" } + } + region = var.aws_region +} diff --git a/read_terraform_state_role.tf b/read_terraform_state_role.tf new file mode 100644 index 0000000..7d623be --- /dev/null +++ b/read_terraform_state_role.tf @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------------------ +# Create the IAM policy and role that allows read-only access to the Terraform +# state for this project in the S3 bucket where Terraform remote state is +# stored. +# ------------------------------------------------------------------------------ + +module "read_terraform_state" { + source = "github.com/cisagov/terraform-state-read-role-tf-module" + + providers = { + aws = aws.terraformprovisionaccount + # This provider isn't used because of the create_assume_role = + # false below. + aws.users = aws + } + + account_ids = distinct(concat([ + local.users_account_id + ], var.additional_remote_state_account_ids)) + # Don't create the assume role policy + create_assume_role = false + role_name = var.read_terraform_state_role_name + terraform_state_bucket_name = "cisa-cool-terraform-state" + terraform_state_path = "cool-dns-cyber.dhs.gov/*.tfstate" +} diff --git a/remote_state.tf b/remote_state.tf index 2b63191..76e0c65 100644 --- a/remote_state.tf +++ b/remote_state.tf @@ -62,3 +62,20 @@ data "terraform_remote_state" "pca_staging" { workspace = "staging" } + +data "terraform_remote_state" "terraform" { + backend = "s3" + + config = { + encrypt = true + bucket = "cisa-cool-terraform-state" + dynamodb_table = "terraform-state-lock" + profile = "cool-terraform-backend" + region = "us-east-1" + key = "cool-accounts/terraform.tfstate" + } + + # There is only one environment for this account, so there is + # no need to match the current Terraform workspace. + workspace = "production" +} diff --git a/variables.tf b/variables.tf index 04ba5a0..79efb54 100644 --- a/variables.tf +++ b/variables.tf @@ -15,6 +15,12 @@ variable "cyhy_account_id" { # These parameters have reasonable defaults. # ------------------------------------------------------------------------------ +variable "additional_remote_state_account_ids" { + type = list(string) + description = "A list of accound IDs corresponding to additional accounts that should have permission to assume the role to read this root module's remote state (e.g. [\"123456789012\"])." + default = [] +} + variable "aws_region" { type = string description = "The AWS region to communicate with." @@ -27,6 +33,12 @@ variable "cloudfront_zone_id" { default = "Z2FDTNDATAQYW2" } +variable "read_terraform_state_role_name" { + type = string + description = "The name to assign the IAM role and policy that allows read-only access to the cool-dns.cyber.dhs.gov state in the S3 bucket where Terraform state is stored." + default = "ReadCyberDhsGovTerraformState" +} + variable "route53resourcechange_role_description" { type = string description = "The description to associate with the IAM role (as well as the corresponding policy) that allows sufficient permissions to modify resource records in the DNS zone."