Skip to content

Commit

Permalink
feat: Enables exclusive IAM policy management of IAM role with manage…
Browse files Browse the repository at this point in the history
…d_policy_arns option
  • Loading branch information
sksmsWKd committed Oct 10, 2024
1 parent 617f4cb commit 7df4893
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 35 deletions.
2 changes: 2 additions & 0 deletions modules/iam-assumable-role/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ No modules.
| <a name="input_custom_role_trust_policy"></a> [custom\_role\_trust\_policy](#input\_custom\_role\_trust\_policy) | A custom role trust policy. (Only valid if create\_custom\_role\_trust\_policy = true) | `string` | `""` | no |
| <a name="input_force_detach_policies"></a> [force\_detach\_policies](#input\_force\_detach\_policies) | Whether policies should be detached from this role when destroying | `bool` | `false` | no |
| <a name="input_inline_policy_statements"></a> [inline\_policy\_statements](#input\_inline\_policy\_statements) | List of inline policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) to attach to IAM role as an inline policy | `any` | `[]` | no |
| <a name="input_managed_policy_arns"></a> [managed\_policy\_arns](#input\_managed\_policy\_arns) | Set of exclusive IAM managed policy ARNs to attach to the IAM role. Configuring an empty set will cause Terraform to remove all managed policy attachments | `list(string)` | `[]` | no |
| <a name="input_max_session_duration"></a> [max\_session\_duration](#input\_max\_session\_duration) | Maximum CLI/API session duration in seconds between 3600 and 43200 | `number` | `3600` | no |
| <a name="input_mfa_age"></a> [mfa\_age](#input\_mfa\_age) | Max age of valid MFA (in seconds) for roles which require MFA | `number` | `86400` | no |
| <a name="input_number_of_custom_role_policy_arns"></a> [number\_of\_custom\_role\_policy\_arns](#input\_number\_of\_custom\_role\_policy\_arns) | Number of IAM policies to attach to IAM role | `number` | `null` | no |
Expand All @@ -73,6 +74,7 @@ No modules.
| <a name="input_trusted_role_actions"></a> [trusted\_role\_actions](#input\_trusted\_role\_actions) | Additional trusted role actions | `list(string)` | <pre>[<br/> "sts:AssumeRole",<br/> "sts:TagSession"<br/>]</pre> | no |
| <a name="input_trusted_role_arns"></a> [trusted\_role\_arns](#input\_trusted\_role\_arns) | ARNs of AWS entities who can assume these roles | `list(string)` | `[]` | no |
| <a name="input_trusted_role_services"></a> [trusted\_role\_services](#input\_trusted\_role\_services) | AWS Services that can assume these roles | `list(string)` | `[]` | no |
| <a name="input_use_managed_policy_arns_on_iam_role"></a> [use\_managed\_policy\_arns\_on\_iam\_role](#input\_use\_managed\_policy\_arns\_on\_iam\_role) | Whether to attach exclusive IAM managed policy to the IAM role. | `bool` | `false` | no |

## Outputs

Expand Down
12 changes: 7 additions & 5 deletions modules/iam-assumable-role/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ locals {
role_sts_externalid = flatten([var.role_sts_externalid])
role_name_condition = var.role_name != null ? var.role_name : "${var.role_name_prefix}*"
custom_role_trust_policy_condition = var.create_custom_role_trust_policy ? var.custom_role_trust_policy : ""
managed_policy_arns = var.use_managed_policy_arns_on_iam_role && length(var.managed_policy_arns) > 0 ? var.managed_policy_arns : null
}

data "aws_iam_policy_document" "assume_role" {
Expand Down Expand Up @@ -150,6 +151,7 @@ resource "aws_iam_role" "this" {

force_detach_policies = var.force_detach_policies
permissions_boundary = var.role_permissions_boundary_arn
managed_policy_arns = local.managed_policy_arns

assume_role_policy = coalesce(
local.custom_role_trust_policy_condition,
Expand All @@ -162,28 +164,28 @@ resource "aws_iam_role" "this" {
}

resource "aws_iam_role_policy_attachment" "custom" {
count = var.create_role ? coalesce(var.number_of_custom_role_policy_arns, length(var.custom_role_policy_arns)) : 0
count = var.create_role && local.managed_policy_arns == null ? coalesce(var.number_of_custom_role_policy_arns, length(var.custom_role_policy_arns)) : 0

role = aws_iam_role.this[0].name
policy_arn = element(var.custom_role_policy_arns, count.index)
}

resource "aws_iam_role_policy_attachment" "admin" {
count = var.create_role && var.attach_admin_policy ? 1 : 0
count = var.create_role && var.attach_admin_policy && local.managed_policy_arns == null ? 1 : 0

role = aws_iam_role.this[0].name
policy_arn = var.admin_role_policy_arn
}

resource "aws_iam_role_policy_attachment" "poweruser" {
count = var.create_role && var.attach_poweruser_policy ? 1 : 0
count = var.create_role && var.attach_poweruser_policy && local.managed_policy_arns == null ? 1 : 0

role = aws_iam_role.this[0].name
policy_arn = var.poweruser_role_policy_arn
}

resource "aws_iam_role_policy_attachment" "readonly" {
count = var.create_role && var.attach_readonly_policy ? 1 : 0
count = var.create_role && var.attach_readonly_policy && local.managed_policy_arns == null ? 1 : 0

role = aws_iam_role.this[0].name
policy_arn = var.readonly_role_policy_arn
Expand Down Expand Up @@ -252,7 +254,7 @@ data "aws_iam_policy_document" "inline" {
}

resource "aws_iam_role_policy" "inline" {
count = local.create_iam_role_inline_policy ? 1 : 0
count = local.create_iam_role_inline_policy && local.managed_policy_arns == null ? 1 : 0

role = aws_iam_role.this[0].name
name_prefix = "${var.role_name}_inline_"
Expand Down
12 changes: 12 additions & 0 deletions modules/iam-assumable-role/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,15 @@ variable "role_session_name" {
type = list(string)
default = ["$${aws:username}"]
}

variable "use_managed_policy_arns_on_iam_role" {
description = "Whether to attach exclusive IAM managed policy to the IAM role."
type = bool
default = false
}

variable "managed_policy_arns" {
description = "Set of exclusive IAM managed policy ARNs to attach to the IAM role. Configuring an empty set will cause Terraform to remove all managed policy attachments"
type = list(string)
default = []
}
62 changes: 32 additions & 30 deletions wrappers/iam-assumable-role/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,36 @@ module "wrapper" {

for_each = var.items

admin_role_policy_arn = try(each.value.admin_role_policy_arn, var.defaults.admin_role_policy_arn, "arn:aws:iam::aws:policy/AdministratorAccess")
allow_self_assume_role = try(each.value.allow_self_assume_role, var.defaults.allow_self_assume_role, false)
attach_admin_policy = try(each.value.attach_admin_policy, var.defaults.attach_admin_policy, false)
attach_poweruser_policy = try(each.value.attach_poweruser_policy, var.defaults.attach_poweruser_policy, false)
attach_readonly_policy = try(each.value.attach_readonly_policy, var.defaults.attach_readonly_policy, false)
create_custom_role_trust_policy = try(each.value.create_custom_role_trust_policy, var.defaults.create_custom_role_trust_policy, false)
create_instance_profile = try(each.value.create_instance_profile, var.defaults.create_instance_profile, false)
create_role = try(each.value.create_role, var.defaults.create_role, false)
custom_role_policy_arns = try(each.value.custom_role_policy_arns, var.defaults.custom_role_policy_arns, [])
custom_role_trust_policy = try(each.value.custom_role_trust_policy, var.defaults.custom_role_trust_policy, "")
force_detach_policies = try(each.value.force_detach_policies, var.defaults.force_detach_policies, false)
inline_policy_statements = try(each.value.inline_policy_statements, var.defaults.inline_policy_statements, [])
max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, 3600)
mfa_age = try(each.value.mfa_age, var.defaults.mfa_age, 86400)
number_of_custom_role_policy_arns = try(each.value.number_of_custom_role_policy_arns, var.defaults.number_of_custom_role_policy_arns, null)
poweruser_role_policy_arn = try(each.value.poweruser_role_policy_arn, var.defaults.poweruser_role_policy_arn, "arn:aws:iam::aws:policy/PowerUserAccess")
readonly_role_policy_arn = try(each.value.readonly_role_policy_arn, var.defaults.readonly_role_policy_arn, "arn:aws:iam::aws:policy/ReadOnlyAccess")
role_description = try(each.value.role_description, var.defaults.role_description, "")
role_name = try(each.value.role_name, var.defaults.role_name, null)
role_name_prefix = try(each.value.role_name_prefix, var.defaults.role_name_prefix, null)
role_path = try(each.value.role_path, var.defaults.role_path, "/")
role_permissions_boundary_arn = try(each.value.role_permissions_boundary_arn, var.defaults.role_permissions_boundary_arn, "")
role_requires_mfa = try(each.value.role_requires_mfa, var.defaults.role_requires_mfa, true)
role_requires_session_name = try(each.value.role_requires_session_name, var.defaults.role_requires_session_name, false)
role_session_name = try(each.value.role_session_name, var.defaults.role_session_name, ["$${aws:username}"])
role_sts_externalid = try(each.value.role_sts_externalid, var.defaults.role_sts_externalid, [])
tags = try(each.value.tags, var.defaults.tags, {})
trusted_role_actions = try(each.value.trusted_role_actions, var.defaults.trusted_role_actions, ["sts:AssumeRole", "sts:TagSession"])
trusted_role_arns = try(each.value.trusted_role_arns, var.defaults.trusted_role_arns, [])
trusted_role_services = try(each.value.trusted_role_services, var.defaults.trusted_role_services, [])
admin_role_policy_arn = try(each.value.admin_role_policy_arn, var.defaults.admin_role_policy_arn, "arn:aws:iam::aws:policy/AdministratorAccess")
allow_self_assume_role = try(each.value.allow_self_assume_role, var.defaults.allow_self_assume_role, false)
attach_admin_policy = try(each.value.attach_admin_policy, var.defaults.attach_admin_policy, false)
attach_poweruser_policy = try(each.value.attach_poweruser_policy, var.defaults.attach_poweruser_policy, false)
attach_readonly_policy = try(each.value.attach_readonly_policy, var.defaults.attach_readonly_policy, false)
create_custom_role_trust_policy = try(each.value.create_custom_role_trust_policy, var.defaults.create_custom_role_trust_policy, false)
create_instance_profile = try(each.value.create_instance_profile, var.defaults.create_instance_profile, false)
create_role = try(each.value.create_role, var.defaults.create_role, false)
custom_role_policy_arns = try(each.value.custom_role_policy_arns, var.defaults.custom_role_policy_arns, [])
custom_role_trust_policy = try(each.value.custom_role_trust_policy, var.defaults.custom_role_trust_policy, "")
force_detach_policies = try(each.value.force_detach_policies, var.defaults.force_detach_policies, false)
inline_policy_statements = try(each.value.inline_policy_statements, var.defaults.inline_policy_statements, [])
managed_policy_arns = try(each.value.managed_policy_arns, var.defaults.managed_policy_arns, [])
max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, 3600)
mfa_age = try(each.value.mfa_age, var.defaults.mfa_age, 86400)
number_of_custom_role_policy_arns = try(each.value.number_of_custom_role_policy_arns, var.defaults.number_of_custom_role_policy_arns, null)
poweruser_role_policy_arn = try(each.value.poweruser_role_policy_arn, var.defaults.poweruser_role_policy_arn, "arn:aws:iam::aws:policy/PowerUserAccess")
readonly_role_policy_arn = try(each.value.readonly_role_policy_arn, var.defaults.readonly_role_policy_arn, "arn:aws:iam::aws:policy/ReadOnlyAccess")
role_description = try(each.value.role_description, var.defaults.role_description, "")
role_name = try(each.value.role_name, var.defaults.role_name, null)
role_name_prefix = try(each.value.role_name_prefix, var.defaults.role_name_prefix, null)
role_path = try(each.value.role_path, var.defaults.role_path, "/")
role_permissions_boundary_arn = try(each.value.role_permissions_boundary_arn, var.defaults.role_permissions_boundary_arn, "")
role_requires_mfa = try(each.value.role_requires_mfa, var.defaults.role_requires_mfa, true)
role_requires_session_name = try(each.value.role_requires_session_name, var.defaults.role_requires_session_name, false)
role_session_name = try(each.value.role_session_name, var.defaults.role_session_name, ["$${aws:username}"])
role_sts_externalid = try(each.value.role_sts_externalid, var.defaults.role_sts_externalid, [])
tags = try(each.value.tags, var.defaults.tags, {})
trusted_role_actions = try(each.value.trusted_role_actions, var.defaults.trusted_role_actions, ["sts:AssumeRole", "sts:TagSession"])
trusted_role_arns = try(each.value.trusted_role_arns, var.defaults.trusted_role_arns, [])
trusted_role_services = try(each.value.trusted_role_services, var.defaults.trusted_role_services, [])
use_managed_policy_arns_on_iam_role = try(each.value.use_managed_policy_arns_on_iam_role, var.defaults.use_managed_policy_arns_on_iam_role, false)
}

0 comments on commit 7df4893

Please sign in to comment.