Skip to content

Commit

Permalink
Fix account map special accounts like dns, identity support dynamic r…
Browse files Browse the repository at this point in the history
…oles (#1087)
  • Loading branch information
goruha authored Aug 1, 2024
1 parent 2198e8e commit 2f7135a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 39 deletions.
4 changes: 2 additions & 2 deletions modules/account-map/dynamic-roles.tf
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ locals {
for k, v in yamldecode(data.utils_describe_stacks.teams[0].output) : k => v if !local.stack_has_namespace || try(split(module.this.delimiter, k)[local.stack_namespace_index] == module.this.namespace, false)
} : local.empty

teams_vars = { for k, v in local.teams_stacks : k => v.components.terraform.aws-teams.vars }
teams_vars = { for k, v in local.teams_stacks : k => v.components.terraform.aws-teams.vars if try(v.components.terraform.aws-teams.vars, null) != null }
teams_config = local.dynamic_role_enabled ? values(local.teams_vars)[0].teams_config : local.empty
team_names = [for k, v in local.teams_config : k if try(v.enabled, true)]
team_arns = { for team_name in local.team_names : team_name => format(local.iam_role_arn_templates[local.account_role_map.identity], team_name) }
Expand All @@ -72,7 +72,7 @@ locals {
for k, v in yamldecode(data.utils_describe_stacks.team_roles[0].output) : k => v if !local.stack_has_namespace || try(split(module.this.delimiter, k)[local.stack_namespace_index] == module.this.namespace, false)
} : local.empty

team_roles_vars = { for k, v in local.team_roles_stacks : k => v.components.terraform.aws-team-roles.vars }
team_roles_vars = { for k, v in local.team_roles_stacks : k => v.components.terraform.aws-team-roles.vars if try(v.components.terraform.aws-team-roles.vars, null) != null }

all_team_vars = merge(local.teams_vars, local.team_roles_vars)

Expand Down
74 changes: 43 additions & 31 deletions modules/account-map/modules/iam-roles/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,42 +31,54 @@ module "account_map" {
locals {
profiles_enabled = coalesce(var.profiles_enabled, local.account_map.profiles_enabled)

account_map = module.account_map.outputs
account_name = lookup(module.always.descriptors, "account_name", module.always.stage)
account_org_role_arn = local.account_name == local.account_map.root_account_account_name ? null : format(
"arn:%s:iam::%s:role/OrganizationAccountAccessRole", local.account_map.aws_partition,
local.account_map.full_account_map[local.account_name]
)

dynamic_terraform_role_enabled = try(local.account_map.terraform_dynamic_role_enabled, false)

static_terraform_role = local.account_map.terraform_roles[local.account_name]
dynamic_terraform_role = try(local.dynamic_terraform_role_map[local.dynamic_terraform_role_type], null)
account_map = module.account_map.outputs
account_name = lookup(module.always.descriptors, "account_name", module.always.stage)
root_account_name = local.account_map.root_account_account_name

current_user_role_arn = coalesce(one(data.awsutils_caller_identity.current[*].eks_role_arn), one(data.awsutils_caller_identity.current[*].arn), "disabled")
dynamic_terraform_role_type = try(local.account_map.terraform_access_map[local.current_user_role_arn][local.account_name], "none")
current_user_role_arn = coalesce(one(data.awsutils_caller_identity.current[*].eks_role_arn), one(data.awsutils_caller_identity.current[*].arn), "disabled")

current_identity_account = local.dynamic_terraform_role_enabled ? split(":", local.current_user_role_arn)[4] : ""
is_root_user = local.current_identity_account == local.account_map.full_account_map[local.account_map.root_account_account_name]
is_target_user = local.current_identity_account == local.account_map.full_account_map[local.account_name]

dynamic_terraform_role_map = local.dynamic_terraform_role_enabled ? {
apply = format(local.account_map.iam_role_arn_templates[local.account_name], local.account_map.terraform_role_name_map["apply"])
plan = format(local.account_map.iam_role_arn_templates[local.account_name], local.account_map.terraform_role_name_map["plan"])
# For user without explicit permissions:
# If the current user is a user in the `root` account, assume the `OrganizationAccountAccessRole` role in the target account.
# If the current user is a user in the target account, do not assume a role at all, let them do what their role allows.
# Otherwise, force them into the static Terraform role for the target account,
# to prevent users from accidentally running Terraform in the wrong account.
none = local.is_root_user ? local.account_org_role_arn : (
# null means use current user's role
local.is_target_user ? null : local.static_terraform_role
)
} : {}

final_terraform_role_arn = local.profiles_enabled ? null : (
local.dynamic_terraform_role_enabled ? local.dynamic_terraform_role : local.static_terraform_role
)
terraform_access_map = try(local.account_map.terraform_access_map[local.current_user_role_arn], {})

final_terraform_profile_name = local.profiles_enabled ? local.account_map.profiles[local.account_name] : null
is_root_user = local.current_identity_account == local.account_map.full_account_map[local.root_account_name]
is_target_user = local.current_identity_account == local.account_map.full_account_map[local.account_name]

account_org_role_arns = { for name, id in local.account_map.full_account_map : name =>
name == local.root_account_name ? null : format(
"arn:%s:iam::%s:role/OrganizationAccountAccessRole", local.account_map.aws_partition, id
)
}

static_terraform_roles = local.account_map.terraform_roles

dynamic_terraform_role_maps = {
for account_name in local.account_map.all_accounts : account_name => {
apply = format(local.account_map.iam_role_arn_templates[account_name], local.account_map.terraform_role_name_map["apply"])
plan = format(local.account_map.iam_role_arn_templates[account_name], local.account_map.terraform_role_name_map["plan"])
# For user without explicit permissions:
# If the current user is a user in the `root` account, assume the `OrganizationAccountAccessRole` role in the target account.
# If the current user is a user in the target account, do not assume a role at all, let them do what their role allows.
# Otherwise, force them into the static Terraform role for the target account,
# to prevent users from accidentally running Terraform in the wrong account.
none = local.is_root_user ? local.account_org_role_arns[account_name] : (
# null means use current user's role
local.is_target_user ? null : local.static_terraform_roles[account_name]
)
}
}

dynamic_terraform_role_types = { for account_name in local.account_map.all_accounts :
account_name => try(local.terraform_access_map[account_name], "none")
}

dynamic_terraform_roles = { for account_name in local.account_map.all_accounts :
account_name => local.dynamic_terraform_role_maps[account_name][local.dynamic_terraform_role_types[account_name]]
}

final_terraform_role_arns = { for account_name in local.account_map.all_accounts : account_name =>
local.dynamic_terraform_role_enabled ? local.dynamic_terraform_roles[account_name] : local.static_terraform_roles[account_name]
}
}
12 changes: 6 additions & 6 deletions modules/account-map/modules/iam-roles/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
output "terraform_role_arn" {
value = local.profiles_enabled ? null : local.final_terraform_role_arn
value = local.profiles_enabled ? null : local.final_terraform_role_arns[local.account_name]
description = "The AWS Role ARN for Terraform to use when provisioning resources in the account, when Role ARNs are in use"
}

Expand All @@ -9,7 +9,7 @@ output "terraform_role_arns" {
}

output "terraform_profile_name" {
value = local.profiles_enabled ? local.final_terraform_profile_name : null
value = local.profiles_enabled ? local.account_map.profiles[local.account_name] : null
description = "The AWS config profile name for Terraform to use when provisioning resources in the account, when profiles are in use"
}

Expand All @@ -19,7 +19,7 @@ output "aws_partition" {
}

output "org_role_arn" {
value = local.account_org_role_arn
value = local.account_org_role_arns[local.account_name]
description = "The AWS Role ARN for Terraform to use when SuperAdmin is provisioning resources in the account"
}

Expand Down Expand Up @@ -47,7 +47,7 @@ output "current_account_account_name" {
}

output "dns_terraform_role_arn" {
value = local.profiles_enabled ? null : local.account_map.terraform_roles[local.account_map.dns_account_account_name]
value = local.profiles_enabled ? null : local.final_terraform_role_arns[local.account_map.dns_account_account_name]
description = "The AWS Role ARN for Terraform to use to provision DNS Zone delegations, when Role ARNs are in use"
}

Expand All @@ -57,7 +57,7 @@ output "dns_terraform_profile_name" {
}

output "audit_terraform_role_arn" {
value = local.profiles_enabled ? null : local.account_map.terraform_roles[local.account_map.audit_account_account_name]
value = local.profiles_enabled ? null : local.final_terraform_role_arns[local.account_map.audit_account_account_name]
description = "The AWS Role ARN for Terraform to use to provision resources in the \"audit\" role account, when Role ARNs are in use"
}

Expand All @@ -72,7 +72,7 @@ output "identity_account_account_name" {
}

output "identity_terraform_role_arn" {
value = local.profiles_enabled ? null : local.account_map.terraform_roles[local.account_map.identity_account_account_name]
value = local.profiles_enabled ? null : local.final_terraform_role_arns[local.account_map.identity_account_account_name]
description = "The AWS Role ARN for Terraform to use to provision resources in the \"identity\" role account, when Role ARNs are in use"
}

Expand Down

0 comments on commit 2f7135a

Please sign in to comment.