Skip to content

Commit 2f7135a

Browse files
authored
Fix account map special accounts like dns, identity support dynamic roles (#1087)
1 parent 2198e8e commit 2f7135a

File tree

3 files changed

+51
-39
lines changed

3 files changed

+51
-39
lines changed

modules/account-map/dynamic-roles.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ locals {
6363
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)
6464
} : local.empty
6565

66-
teams_vars = { for k, v in local.teams_stacks : k => v.components.terraform.aws-teams.vars }
66+
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 }
6767
teams_config = local.dynamic_role_enabled ? values(local.teams_vars)[0].teams_config : local.empty
6868
team_names = [for k, v in local.teams_config : k if try(v.enabled, true)]
6969
team_arns = { for team_name in local.team_names : team_name => format(local.iam_role_arn_templates[local.account_role_map.identity], team_name) }
@@ -72,7 +72,7 @@ locals {
7272
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)
7373
} : local.empty
7474

75-
team_roles_vars = { for k, v in local.team_roles_stacks : k => v.components.terraform.aws-team-roles.vars }
75+
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 }
7676

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

modules/account-map/modules/iam-roles/main.tf

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,42 +31,54 @@ module "account_map" {
3131
locals {
3232
profiles_enabled = coalesce(var.profiles_enabled, local.account_map.profiles_enabled)
3333

34-
account_map = module.account_map.outputs
35-
account_name = lookup(module.always.descriptors, "account_name", module.always.stage)
36-
account_org_role_arn = local.account_name == local.account_map.root_account_account_name ? null : format(
37-
"arn:%s:iam::%s:role/OrganizationAccountAccessRole", local.account_map.aws_partition,
38-
local.account_map.full_account_map[local.account_name]
39-
)
40-
4134
dynamic_terraform_role_enabled = try(local.account_map.terraform_dynamic_role_enabled, false)
4235

43-
static_terraform_role = local.account_map.terraform_roles[local.account_name]
44-
dynamic_terraform_role = try(local.dynamic_terraform_role_map[local.dynamic_terraform_role_type], null)
36+
account_map = module.account_map.outputs
37+
account_name = lookup(module.always.descriptors, "account_name", module.always.stage)
38+
root_account_name = local.account_map.root_account_account_name
4539

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

4942
current_identity_account = local.dynamic_terraform_role_enabled ? split(":", local.current_user_role_arn)[4] : ""
50-
is_root_user = local.current_identity_account == local.account_map.full_account_map[local.account_map.root_account_account_name]
51-
is_target_user = local.current_identity_account == local.account_map.full_account_map[local.account_name]
52-
53-
dynamic_terraform_role_map = local.dynamic_terraform_role_enabled ? {
54-
apply = format(local.account_map.iam_role_arn_templates[local.account_name], local.account_map.terraform_role_name_map["apply"])
55-
plan = format(local.account_map.iam_role_arn_templates[local.account_name], local.account_map.terraform_role_name_map["plan"])
56-
# For user without explicit permissions:
57-
# If the current user is a user in the `root` account, assume the `OrganizationAccountAccessRole` role in the target account.
58-
# 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.
59-
# Otherwise, force them into the static Terraform role for the target account,
60-
# to prevent users from accidentally running Terraform in the wrong account.
61-
none = local.is_root_user ? local.account_org_role_arn : (
62-
# null means use current user's role
63-
local.is_target_user ? null : local.static_terraform_role
64-
)
65-
} : {}
6643

67-
final_terraform_role_arn = local.profiles_enabled ? null : (
68-
local.dynamic_terraform_role_enabled ? local.dynamic_terraform_role : local.static_terraform_role
69-
)
44+
terraform_access_map = try(local.account_map.terraform_access_map[local.current_user_role_arn], {})
7045

71-
final_terraform_profile_name = local.profiles_enabled ? local.account_map.profiles[local.account_name] : null
46+
is_root_user = local.current_identity_account == local.account_map.full_account_map[local.root_account_name]
47+
is_target_user = local.current_identity_account == local.account_map.full_account_map[local.account_name]
48+
49+
account_org_role_arns = { for name, id in local.account_map.full_account_map : name =>
50+
name == local.root_account_name ? null : format(
51+
"arn:%s:iam::%s:role/OrganizationAccountAccessRole", local.account_map.aws_partition, id
52+
)
53+
}
54+
55+
static_terraform_roles = local.account_map.terraform_roles
56+
57+
dynamic_terraform_role_maps = {
58+
for account_name in local.account_map.all_accounts : account_name => {
59+
apply = format(local.account_map.iam_role_arn_templates[account_name], local.account_map.terraform_role_name_map["apply"])
60+
plan = format(local.account_map.iam_role_arn_templates[account_name], local.account_map.terraform_role_name_map["plan"])
61+
# For user without explicit permissions:
62+
# If the current user is a user in the `root` account, assume the `OrganizationAccountAccessRole` role in the target account.
63+
# 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.
64+
# Otherwise, force them into the static Terraform role for the target account,
65+
# to prevent users from accidentally running Terraform in the wrong account.
66+
none = local.is_root_user ? local.account_org_role_arns[account_name] : (
67+
# null means use current user's role
68+
local.is_target_user ? null : local.static_terraform_roles[account_name]
69+
)
70+
}
71+
}
72+
73+
dynamic_terraform_role_types = { for account_name in local.account_map.all_accounts :
74+
account_name => try(local.terraform_access_map[account_name], "none")
75+
}
76+
77+
dynamic_terraform_roles = { for account_name in local.account_map.all_accounts :
78+
account_name => local.dynamic_terraform_role_maps[account_name][local.dynamic_terraform_role_types[account_name]]
79+
}
80+
81+
final_terraform_role_arns = { for account_name in local.account_map.all_accounts : account_name =>
82+
local.dynamic_terraform_role_enabled ? local.dynamic_terraform_roles[account_name] : local.static_terraform_roles[account_name]
83+
}
7284
}

modules/account-map/modules/iam-roles/outputs.tf

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
output "terraform_role_arn" {
2-
value = local.profiles_enabled ? null : local.final_terraform_role_arn
2+
value = local.profiles_enabled ? null : local.final_terraform_role_arns[local.account_name]
33
description = "The AWS Role ARN for Terraform to use when provisioning resources in the account, when Role ARNs are in use"
44
}
55

@@ -9,7 +9,7 @@ output "terraform_role_arns" {
99
}
1010

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

@@ -19,7 +19,7 @@ output "aws_partition" {
1919
}
2020

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

@@ -47,7 +47,7 @@ output "current_account_account_name" {
4747
}
4848

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

@@ -57,7 +57,7 @@ output "dns_terraform_profile_name" {
5757
}
5858

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

@@ -72,7 +72,7 @@ output "identity_account_account_name" {
7272
}
7373

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

0 commit comments

Comments
 (0)