Skip to content

Commit

Permalink
* 2.12.0 -- 2025-05-06
Browse files Browse the repository at this point in the history
  - 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
  • Loading branch information
badra001 committed May 6, 2025
1 parent d0b7586 commit 5aaf039
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion common/version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "2.11.0"
_module_version = "2.12.0"
}
8 changes: 6 additions & 2 deletions terraform-state/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ No requirements.
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a |
| <a name="provider_terraform"></a> [terraform](#provider\_terraform) | n/a |

## Modules

Expand Down Expand Up @@ -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 |
Expand All @@ -241,12 +243,14 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_account_alias"></a> [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no |
| <a name="input_account_id"></a> [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no |
| <a name="input_application_assume_roles"></a> [application\_assume\_roles](#input\_application\_assume\_roles) | Additional role ARNs allowed to assume the Terraform State role | `list(string)` | `[]` | no |
| <a name="input_application_mode"></a> [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 |
| <a name="input_bucket_key_enabled"></a> [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 |
| <a name="input_component_tags"></a> [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` | <pre>{<br> "ddb": {},<br> "kms": {},<br> "s3": {}<br>}</pre> | no |
| <a name="input_component_tags"></a> [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` | <pre>{<br/> "ddb": {},<br/> "kms": {},<br/> "s3": {}<br/>}</pre> | no |
| <a name="input_kms_tfstate_key"></a> [kms\_tfstate\_key](#input\_kms\_tfstate\_key) | Terraform remote state KMS key alias | `string` | `"k-kms-inf-tfstate"` | no |
| <a name="input_name"></a> [name](#input\_name) | Name suffix to use for policies, roles and groups (default: inf-terraform) | `string` | `"inf-terraform"` | no |
| <a name="input_override_prefixes"></a> [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 |
| <a name="input_sso_permissionset_names"></a> [sso\_permissionset\_names](#input\_sso\_permissionset\_names) | List of SSO Permissionset Names (aka, SSO roles) to allow to assume the role | `list(string)` | <pre>[<br> "inf-terraform"<br>]</pre> | no |
| <a name="input_sso_permissionset_names"></a> [sso\_permissionset\_names](#input\_sso\_permissionset\_names) | List of SSO Permissionset Names (aka, SSO roles) to allow to assume the role | `list(string)` | <pre>[<br/> "inf-terraform"<br/>]</pre> | no |
| <a name="input_tags"></a> [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 |
| <a name="input_tfstate_bucket"></a> [tfstate\_bucket](#input\_tfstate\_bucket) | Terraform remote state S3 bucket | `string` | `""` | no |
| <a name="input_tfstate_bucket_prefix"></a> [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 |
Expand Down
34 changes: 29 additions & 5 deletions terraform-state/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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 }
)

}
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}
7 changes: 4 additions & 3 deletions terraform-state/policy.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions terraform-state/role.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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)))
}
}
}
12 changes: 12 additions & 0 deletions terraform-state/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
}

0 comments on commit 5aaf039

Please sign in to comment.