From 5aaf039ee74667fcc70207369fb950d6a1c8ffd3 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 6 May 2025 16:17:12 -0400 Subject: [PATCH] * 2.12.0 -- 2025-05-06 - terraform-state - add application_mode, application_assume_roles - when application_mode is _true_, it creates tfstate and ddb for `name` to be used by application areas, not for infrastructure --- CHANGELOG.md | 5 +++++ common/version.tf | 2 +- terraform-state/README.md | 8 ++++++-- terraform-state/main.tf | 34 +++++++++++++++++++++++++++++----- terraform-state/policy.tf | 7 ++++--- terraform-state/role.tf | 4 ++-- terraform-state/variables.tf | 12 ++++++++++++ 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f346a3..1a122c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -403,3 +403,8 @@ * 2.11.0 -- 2025-03-18 - s3-logs - copy s3-flow-logs to s3-logs to normalize names (to reuse for other stuff) + +* 2.12.0 -- 2025-05-06 + - terraform-state + - add application_mode, application_assume_roles + - when application_mode is _true_, it creates tfstate and ddb for `name` to be used by application areas, not for infrastructure diff --git a/common/version.tf b/common/version.tf index ac684e2..c80a418 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,3 +1,3 @@ locals { - _module_version = "2.11.0" + _module_version = "2.12.0" } diff --git a/terraform-state/README.md b/terraform-state/README.md index 3278b8b..e9351d3 100644 --- a/terraform-state/README.md +++ b/terraform-state/README.md @@ -194,6 +194,7 @@ No requirements. | Name | Version | |------|---------| | [aws](#provider\_aws) | n/a | +| [terraform](#provider\_terraform) | n/a | ## Modules @@ -221,6 +222,7 @@ No modules. | [aws_s3_bucket_public_access_block.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_server_side_encryption_configuration.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_s3_bucket_versioning.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | +| [terraform_data.application_mode](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource | | [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy.group_managed_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source | @@ -241,12 +243,14 @@ No modules. |------|-------------|------|---------|:--------:| | [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no | | [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no | +| [application\_assume\_roles](#input\_application\_assume\_roles) | Additional role ARNs allowed to assume the Terraform State role | `list(string)` | `[]` | no | +| [application\_mode](#input\_application\_mode) | Enable application mode, which will set appropriate names based on the name variable, including the bucket prefix v-s3- | `bool` | `false` | no | | [bucket\_key\_enabled](#input\_bucket\_key\_enabled) | Enable or disable the use of S3 Bucket Keys (see AWS documetnation at https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-key.html). | `bool` | `false` | no | -| [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | +| [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | | [kms\_tfstate\_key](#input\_kms\_tfstate\_key) | Terraform remote state KMS key alias | `string` | `"k-kms-inf-tfstate"` | no | | [name](#input\_name) | Name suffix to use for policies, roles and groups (default: inf-terraform) | `string` | `"inf-terraform"` | no | | [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | -| [sso\_permissionset\_names](#input\_sso\_permissionset\_names) | List of SSO Permissionset Names (aka, SSO roles) to allow to assume the role | `list(string)` |
[
"inf-terraform"
]
| no | +| [sso\_permissionset\_names](#input\_sso\_permissionset\_names) | List of SSO Permissionset Names (aka, SSO roles) to allow to assume the role | `list(string)` |
[
"inf-terraform"
]
| no | | [tags](#input\_tags) | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no | | [tfstate\_bucket](#input\_tfstate\_bucket) | Terraform remote state S3 bucket | `string` | `""` | no | | [tfstate\_bucket\_prefix](#input\_tfstate\_bucket\_prefix) | Terraform remote state S3 bucket prefix, prepended to the AWS account ID to make the bucket name. | `string` | `"inf-tfstate"` | no | diff --git a/terraform-state/main.tf b/terraform-state/main.tf index ed12ff3..84d4282 100644 --- a/terraform-state/main.tf +++ b/terraform-state/main.tf @@ -56,18 +56,38 @@ locals { account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id tfstate_region = data.aws_region.current.name + region_short = join("", [for c in split("-", local.tfstate_region) : substr(c, 0, 1)]) tfstate_key_arn = aws_kms_key.tfstate_key.arn tfstate_bucket = var.tfstate_bucket != "" ? var.tfstate_bucket : format("%v-%v", var.tfstate_bucket_prefix, local.account_id) tfstate_policy_name = format("%v%v", lookup(local._prefixes, "policy", ""), var.tfstate_bucket_prefix) + settings = { + bucket_name = var.application_mode ? format("%v%v-%v-%v", lookup(local._prefixes, "s3", ""), var.name, local.account_id, local.region_short) : local.tfstate_bucket + kms_key_name = var.application_mode ? format("%v%v", lookup(local._prefixes, "kms", ""), var.name) : var.kms_tfstate_key + policy_name = var.application_mode ? format("%v%v", lookup(local._prefixes, "policy", ""), var.name) : format("%v%v", lookup(local._prefixes, "policy", ""), var.tfstate_bucket_prefix) + } + base_tags = { "boc:tf_module_version" = local._module_version "boc:created_by" = "terraform" } } +resource "terraform_data" "application_mode" { + count = var.application_mode ? 1 : 0 + input = var.name + + lifecycle { + precondition { + condition = var.name != "inf-tfstate" + error_message = "Application mode var.name cannot be inf-tfstate." + } + } +} + + # this pre-loads the key so that it is ready when the DDB table create happens data "aws_kms_key" "kms_dynamodb" { key_id = "alias/aws/dynamodb" @@ -109,7 +129,8 @@ resource "aws_dynamodb_table" "tfstate" { # s3 #--- resource "aws_s3_bucket" "tfstate" { - bucket = local.tfstate_bucket + # bucket = local.tfstate_bucket + bucket = local.settings.bucket_name # acl = "private" lifecycle { @@ -121,7 +142,7 @@ resource "aws_s3_bucket" "tfstate" { var.tags, local.base_tags, lookup(var.component_tags, "s3", {}), - tomap({ Name = local.tfstate_bucket }), + { Name = local.settings.bucket_name } ) } @@ -177,14 +198,16 @@ resource "aws_s3_bucket_ownership_controls" "tfstate" { # kms #--- resource "aws_kms_key" "tfstate_key" { - description = "inf-tfstate encryption key" + # description = format("%v encryption key",var.kms_tfstate_key) + description = format("%v encryption key", var.name) enable_key_rotation = true tags = merge( var.tags, local.base_tags, lookup(var.component_tags, "kms", {}), - tomap({ Name = var.kms_tfstate_key }), + # { Name = var.kms_tfstate_key }, + { Name = local.settings.kms_key_name }, ) lifecycle { @@ -194,6 +217,7 @@ resource "aws_kms_key" "tfstate_key" { } resource "aws_kms_alias" "tfstate_key" { - name = "alias/${var.kms_tfstate_key}" + # name = "alias/${var.kms_tfstate_key}" + name = format("alias/%v", local.settings.kms_key_name) target_key_id = aws_kms_key.tfstate_key.key_id } diff --git a/terraform-state/policy.tf b/terraform-state/policy.tf index 58dd84c..b59575a 100644 --- a/terraform-state/policy.tf +++ b/terraform-state/policy.tf @@ -4,21 +4,22 @@ locals { # create iam policy for it, to apply to roles/groups as needed resource "aws_iam_policy" "tfstate" { - name = local.tfstate_policy_name + # name = local.tfstate_policy_name + name = local.settings.policy_name path = "/" description = "Access to tfstate resources" policy = data.aws_iam_policy_document.tfstate.json } resource "aws_iam_policy" "tfstate_read" { - name = format("%v-%v", local.tfstate_policy_name, "read") + name = format("%v-%v", local.settings.policy_name, "read") path = "/" description = "Access to tfstate resources (read)" policy = data.aws_iam_policy_document.tfstate_read.json } resource "aws_iam_policy" "tfstate_write" { - name = format("%v-%v", local.tfstate_policy_name, "write") + name = format("%v-%v", local.settings.policy_name, "write") path = "/" description = "Access to tfstate resources (write)" policy = data.aws_iam_policy_document.tfstate_write.json diff --git a/terraform-state/role.tf b/terraform-state/role.tf index 50b9cb5..18a3735 100644 --- a/terraform-state/role.tf +++ b/terraform-state/role.tf @@ -43,7 +43,7 @@ resource "aws_iam_role" "role" { } resource "aws_iam_role_policy_attachment" "role" { - for_each = { for p in local.role_managed_policies : p => p } + for_each = !var.application_mode ? { for p in local.role_managed_policies : p => p } : {} role = aws_iam_role.role.name policy_arn = each.value } @@ -69,7 +69,7 @@ data "aws_iam_policy_document" "allow_sts" { condition { test = "ArnLike" variable = "aws:PrincipalArn" - values = flatten([for p in var.sso_permissionset_names : [for f in local.sso_role_arn_formats : format(f, p)]]) + values = distinct(compact(concat(flatten([for p in var.sso_permissionset_names : [for f in local.sso_role_arn_formats : format(f, p)]]), var.application_assume_roles))) } } } diff --git a/terraform-state/variables.tf b/terraform-state/variables.tf index 7c24353..06c1fff 100644 --- a/terraform-state/variables.tf +++ b/terraform-state/variables.tf @@ -66,3 +66,15 @@ variable "sso_permissionset_names" { type = list(string) default = ["inf-terraform"] } + +variable "application_mode" { + description = "Enable application mode, which will set appropriate names based on the name variable, including the bucket prefix v-s3-" + type = bool + default = false +} + +variable "application_assume_roles" { + description = "Additional role ARNs allowed to assume the Terraform State role" + type = list(string) + default = [] +}