Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

account-map Documentation for Dynamic Roles #870

Merged
merged 12 commits into from
Oct 12, 2023
2 changes: 1 addition & 1 deletion modules/account-map/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ components:
| <a name="output_profiles_enabled"></a> [profiles\_enabled](#output\_profiles\_enabled) | Whether or not to enable profiles instead of roles for the backend |
| <a name="output_root_account_account_name"></a> [root\_account\_account\_name](#output\_root\_account\_account\_name) | The short name for the root account |
| <a name="output_root_account_aws_name"></a> [root\_account\_aws\_name](#output\_root\_account\_aws\_name) | The name of the root account as reported by AWS |
| <a name="output_terraform_access_map"></a> [terraform\_access\_map](#output\_terraform\_access\_map) | Mapping of team Role ARN to map of account name to terraform action role ARN to assume |
| <a name="output_terraform_access_map"></a> [terraform\_access\_map](#output\_terraform\_access\_map) | Mapping of team Role ARN to map of account name to terraform action role ARN to assume<br><br>For each team in `aws-teams`, look at every account and see if that team has access to the designated "apply" role.<br> If so, add an entry `<account-name> = "apply"` to the `terraform_access_map` entry for that team.<br> If not, see if it has access to the "plan" role, and if so, add a "plan" entry.<br> Otherwise, no entry is added. |
| <a name="output_terraform_dynamic_role_enabled"></a> [terraform\_dynamic\_role\_enabled](#output\_terraform\_dynamic\_role\_enabled) | True if dynamic role for Terraform is enabled |
| <a name="output_terraform_profiles"></a> [terraform\_profiles](#output\_terraform\_profiles) | A list of all SSO profiles used to run terraform updates |
| <a name="output_terraform_role_name_map"></a> [terraform\_role\_name\_map](#output\_terraform\_role\_name\_map) | Mapping of Terraform action (plan or apply) to aws-team-role name to assume for that action |
Expand Down
27 changes: 24 additions & 3 deletions modules/account-map/dynamic-roles.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@

# The `utils_describe_stacks` data resources use the Cloud Posse Utils provider to describe Atmos stacks, and then
# we merge the results into `local.all_team_vars`. This is the same as running the following locally:
# ```
# atmos describe stacks --components=aws-teams,aws-team-roles --component-types=terraform --sections=vars
# ```
# The result of these stack descriptions includes all metadata for the given components. For example, we now
# can filter the result to find all stacks where either `aws-teams` or `aws-team-roles` are deployed.
#
# In particular, we can use this data to find the name of the account (defined by `descriptor_formats.account_name`)
# where team roles are deployed and the values for those descriptors (typically `tenant` and `stage`).
# We then determine which roles are provisioned and which teams can access any given role in any particular account.
milldr marked this conversation as resolved.
Show resolved Hide resolved
#
# `descriptor_formats.account_name` is typically defined in `stacks/orgs/NAMESPACE/_defaults.yaml`, and if not
# defined, the stack name will default to `stage`.`
#
# If `namespace` is included in `descriptor_formats.account_name`, then we additionally filter to only stacks with
# the same `namespace` as `module.this.namespace`. See `local.stack_namespace_index` and `local.stack_namespace_index`
#
# https://atmos.tools/cli/commands/describe/stacks/
# https://registry.terraform.io/providers/cloudposse/utils/latest/docs/data-sources/describe_stacks
data "utils_describe_stacks" "teams" {
count = local.dynamic_role_enabled ? 1 : 0

Expand All @@ -18,9 +37,11 @@ data "utils_describe_stacks" "team_roles" {
locals {
dynamic_role_enabled = module.this.enabled && var.terraform_dynamic_role_enabled

# `var.terraform_role_name_map` maps some team role in the `aws-team-roles` configuration to "plan" and some other team to "apply".
apply_role = var.terraform_role_name_map.apply
plan_role = var.terraform_role_name_map.plan

# If a namespace is included with the stack name, only loop through stacks in the same namespace
# zero-based index showing position of the namespace in the stack name
stack_namespace_index = try(index(module.this.normalized_context.descriptor_formats.stack.labels, "namespace"), -1)
stack_has_namespace = local.stack_namespace_index >= 0
Expand Down Expand Up @@ -53,11 +74,11 @@ locals {

team_roles_vars = { for k, v in local.team_roles_stacks : k => v.components.terraform.aws-team-roles.vars }

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

stack_planners = { for k, v in local.team_roles_vars : k => v.roles[local.plan_role].trusted_teams if try(length(v.roles[local.plan_role].trusted_teams), 0) > 0 && try(v.roles[local.plan_role].enabled, true) }
stack_terraformers = { for k, v in local.team_roles_vars : k => v.roles[local.apply_role].trusted_teams if try(length(v.roles[local.apply_role].trusted_teams), 0) > 0 && try(v.roles[local.apply_role].enabled, true) }

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

team_planners = { for team in local.team_names : team => {
for stack, trusted in local.stack_planners : local.stack_account_map[stack] => "plan" if contains(trusted, team)
} }
Expand Down
9 changes: 8 additions & 1 deletion modules/account-map/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,14 @@ output "terraform_dynamic_role_enabled" {

output "terraform_access_map" {
value = local.dynamic_role_enabled ? local.role_arn_terraform_access : null
description = "Mapping of team Role ARN to map of account name to terraform action role ARN to assume"
description = <<-EOT
Mapping of team Role ARN to map of account name to terraform action role ARN to assume

For each team in `aws-teams`, look at every account and see if that team has access to the designated "apply" role.
If so, add an entry `<account-name> = "apply"` to the `terraform_access_map` entry for that team.
If not, see if it has access to the "plan" role, and if so, add a "plan" entry.
Otherwise, no entry is added.
EOT
}

output "terraform_role_name_map" {
Expand Down
Loading