Skip to content

Commit

Permalink
add role to assume to run terraform
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Apr 27, 2022
1 parent 091293e commit b6a5bef
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 28 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,7 @@
* 1.15.2 -- 2022-04-26
- terraform-state
- add readonly to group inf-terraform w

* 1.15.3 -- 2022-04-27
- terraform-state
- add r-inf-terraform assumable role for TF operations
2 changes: 2 additions & 0 deletions common/defaults.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ locals {
]
"api_interval" = 3600
}
"force_detach_policies" = false
"max_session_duration" = 3600
}
}

Expand Down
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 = "1.15.2"
_module_version = "1.15.3"
}
11 changes: 10 additions & 1 deletion terraform-state/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,25 @@ No modules.
|------|------|
| [aws_dynamodb_table.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource |
| [aws_iam_group.terraform](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group) | resource |
| [aws_iam_group_policy_attachment.terraform_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_group_policy_attachment.terraform_managed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_group_policy_attachment.terraform_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment) | resource |
| [aws_iam_policy.allow_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.tfstate_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.tfstate_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_role.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_kms_alias.tfstate_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
| [aws_kms_key.tfstate_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
| [aws_s3_bucket.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
| [aws_s3_bucket_public_access_block.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | 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.managed_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source |
| [aws_iam_policy.group_managed_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source |
| [aws_iam_policy.role_managed_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source |
| [aws_iam_policy_document.allow_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.allow_sts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.tfstate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.tfstate_kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.tfstate_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
Expand All @@ -93,6 +100,7 @@ No modules.
| <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_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_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 |
Expand All @@ -106,6 +114,7 @@ No modules.

| Name | Description |
|------|-------------|
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | Role ARN for Terraform |
| <a name="output_tfstate_bucket_arn"></a> [tfstate\_bucket\_arn](#output\_tfstate\_bucket\_arn) | Terraform state S3 bucket ARN |
| <a name="output_tfstate_bucket_id"></a> [tfstate\_bucket\_id](#output\_tfstate\_bucket\_id) | Terraform state S3 bucket ID |
| <a name="output_tfstate_dynamodb_arn"></a> [tfstate\_dynamodb\_arn](#output\_tfstate\_dynamodb\_arn) | Terraform state DynamoDB table ARN |
Expand Down
11 changes: 8 additions & 3 deletions terraform-state/group.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
locals {
group_name = format("%v%v", lookup(local._prefixes, "group", ""), "inf-terraform")
group_name = format("%v%v", lookup(local._prefixes, "group", ""), var.name)
group_managed_policies_names = ["ReadOnlyAccess"]
group_managed_policies = [for k, p in data.aws_iam_policy.managed_policies : p.arn]
group_managed_policies = [for k, p in data.aws_iam_policy.group_managed_policies : p.arn]
}

resource "aws_iam_group" "terraform" {
Expand All @@ -20,8 +20,13 @@ resource "aws_iam_group_policy_attachment" "terraform_managed" {
policy_arn = each.value
}

resource "aws_iam_group_policy_attachment" "terraform_assume" {
group = aws_iam_group.terraform.name
policy_arn = aws_iam_policy.allow_assume_role.arn
}


data "aws_iam_policy" "managed_policies" {
data "aws_iam_policy" "group_managed_policies" {
for_each = toset(local.group_managed_policies_names)
name = each.key
}
24 changes: 1 addition & 23 deletions terraform-state/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ locals {
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)
tfstate_policy_name = format("%v%v", lookup(local._prefixes, "policy", ""), var.name)

base_tags = {
"boc:tf_module_version" = local._module_version
Expand Down Expand Up @@ -97,28 +97,6 @@ resource "aws_dynamodb_table" "tfstate" {

}

# create iam policy for it, to apply to roles/groups as needed
resource "aws_iam_policy" "tfstate" {
name = local.tfstate_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")
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")
path = "/"
description = "Access to tfstate resources (write)"
policy = data.aws_iam_policy_document.tfstate_write.json
}

#---
# s3
#---
Expand Down
4 changes: 4 additions & 0 deletions terraform-state/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ output "tfstate_region" {
value = local.tfstate_region
}

output "role_arn" {
description = "Role ARN for Terraform"
value = aws_iam_role.role.arn
}
48 changes: 48 additions & 0 deletions terraform-state/policy_data.tf → terraform-state/policy.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
locals {
iam_arn = format("arn:%v:iam::%v:%%v", data.aws_arn.current.partition, data.aws_caller_identity.current.account_id)
}

# create iam policy for it, to apply to roles/groups as needed
resource "aws_iam_policy" "tfstate" {
name = local.tfstate_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")
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")
path = "/"
description = "Access to tfstate resources (write)"
policy = data.aws_iam_policy_document.tfstate_write.json
}

resource "aws_iam_policy" "allow_assume_role" {
name = format("%v-%v", var.name, "allow-assume")
path = "/"
description = "Assume role for Terraform activity"
policy = data.aws_iam_policy_document.allow_assume_role.json
}

#---
# tfstate s3 bucket
#---
data "aws_iam_policy_document" "tfstate" {
statement {
sid = "TFRemoteStateList"
Expand Down Expand Up @@ -129,3 +165,15 @@ data "aws_iam_policy_document" "tfstate_write" {
resources = [aws_kms_key.tfstate_key.arn]
}
}

#---
# allow assume the role for use by tf, add to a policy to the group
#---
data "aws_iam_policy_document" "allow_assume_role" {
statement {
sid = "AllowSTSAssumeTerraformRole"
effect = "Allow"
actions = ["sts:AssumeRole"]
resources = [aws_iam_role.role.arn]
}
}
60 changes: 60 additions & 0 deletions terraform-state/role.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
locals {
role_name = format("%v%v", lookup(local._prefixes, "role", ""), var.name)
role_description = format("Role to be assumed Terraform execution %v", var.name)
role_managed_policies_names = ["AdministratorAccess"]
role_managed_policies = [for k, p in data.aws_iam_policy.role_managed_policies : p.arn]
}


data "aws_iam_policy" "role_managed_policies" {
for_each = toset(local.role_managed_policies_names)
name = each.key
}

resource "aws_iam_role" "role" {
name = local.role_name
description = local.role_description
force_detach_policies = local._defaults["force_detach_policies"]
max_session_duration = local._defaults["max_session_duration"]
assume_role_policy = data.aws_iam_policy_document.allow_sts.json

# dynamic "inline_policy" {
# for_each = var.inline_policies
# iterator = p
# content {
# name = p.value.name
# policy = p.value.policy
# }
# }

lifecycle {
ignore_changes = [tags["boc:tf_module_version"]]
}

tags = merge(
local.base_tags,
var.tags,
lookup(var.component_tags, "role", {}),
tomap({ Name = local.role_name })
)
}

resource "aws_iam_role_policy_attachment" "role" {
for_each = { for p in local.role_managed_policies : p => p }
role = aws_iam_role.role.name
policy_arn = each.value
}

data "aws_iam_policy_document" "allow_sts" {
statement {
sid = "AllowSTSAssume"
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "AWS"
identifiers = [
format(local.iam_arn, "root"),
]
}
}
}
6 changes: 6 additions & 0 deletions terraform-state/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ variable "component_tags" {
type = map(map(string))
default = { "s3" = {}, "kms" = {}, "ddb" = {} }
}

variable "name" {
description = "Name suffix to use for policies, roles and groups (default: inf-terraform)"
type = string
default = "inf-terraform"
}

0 comments on commit b6a5bef

Please sign in to comment.