Skip to content

Commit

Permalink
fix(iam_sso): order changes of inputs does not lead to unwanted resou…
Browse files Browse the repository at this point in the history
…rce changes anymore

BREAKING CHANGE: The introduction of for_each instead of count for the
iam_sso resources will lead to resource desctructions and re-creations
if the existing states are not moved manually. It's not possible to do
this automatically because we don't know the group and user names which
are now used as identifiers.
  • Loading branch information
Claus-Theodor Riegg authored and crigertg committed Mar 29, 2023
1 parent 0a657f4 commit b7c2392
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 37 deletions.
61 changes: 39 additions & 22 deletions modules/iam_sso/locals.tf
Original file line number Diff line number Diff line change
@@ -1,47 +1,64 @@
locals {
# build a list of all group memberships for the users.
group_memberships = flatten([
for user, user_config in var.users : [
for group in user_config.group_memberships : {
# we rely on terraforms grouping mode to pass list contents as arguments to the merge function.
# see https://makandracards.com/operations/541333-use-terraform-grouping-mode-like-golang-s-ellipsis-expression

# build a map of all group memberships for the users.
group_memberships = merge([
for user, user_config in var.users : {
for group in user_config.group_memberships :
"${user}_${group}" => {
user_id = aws_identitystore_user.this[user].user_id
group_id = aws_identitystore_group.this[group].group_id
}
] if user_config.group_memberships != null
])
} if user_config.group_memberships != null
]...)

# build a list of all groups to assign to the given accounts
group_assignments = flatten([
for group, group_config in var.groups : [
for assignment in group_config.account_assignments : {
# build a map of all groups to assign to the given accounts
group_assignments = merge([
for group, group_config in var.groups : {
for assignment in group_config.account_assignments :
"${group}_${assignment.account_number}" => {
group_id = aws_identitystore_group.this[group].group_id
permission_set_arn = module.permission_sets.permission_sets[assignment.permission_set_name].arn
account_number = assignment.account_number
} if assignment != null && assignment.account_number != "ALL"
] if group_config.account_assignments != null
])
} if group_config.account_assignments != null
]...)

# build a list of all groups which should be assigned to all accounts in the organization
# build a list of all group assignemnts and permission sets which should be assigned to all accounts in the organization
groups_to_assign_to_all_accounts = flatten([
for group, group_config in var.groups : [
for assignment in group_config.account_assignments : {
group_name = group
group_id = aws_identitystore_group.this[group].group_id
permission_set_arn = module.permission_sets.permission_sets[assignment.permission_set_name].arn
} if assignment != null && assignment.account_number == "ALL"
] if group_config.account_assignments != null
])

# for the group assignments to all accounts we create a list of the combinations of group/permissionset and account IDs of active accounts
list_of_active_account_ids = [for account in data.aws_organizations_organization.this.accounts : account.id if account.status == "ACTIVE"]
groups_for_all_accounts = length(local.groups_to_assign_to_all_accounts) > 0 ? setproduct(local.groups_to_assign_to_all_accounts, local.list_of_active_account_ids) : []
# for the group assignments to all accounts we create a map of the combinations of group/permissionset and account IDs of active accounts
list_of_active_account_ids = [for account in data.aws_organizations_organization.this.accounts : account.id if account.status == "ACTIVE"]
all_account_groups_account_id_assocations = length(local.groups_to_assign_to_all_accounts) > 0 ? setproduct(local.groups_to_assign_to_all_accounts, local.list_of_active_account_ids) : []

# build a list of all user assignments to the given accounts
user_assignments = flatten([
for user, user_config in var.users : [
for assignment in user_config.account_assignments : {
# lastly we create a map of all group assignments to all accounts with the key being the group name and account ID
# This way we can use a for_each instead of count
group_all_account_assignments = {
for group in local.all_account_groups_account_id_assocations : "${group[0].group_name}_${group[1]}" => {
group_id = group[0].group_id
permission_set_arn = group[0].permission_set_arn
account_number = group[1]
}
}

# build a map of all user assignments to the given accounts
user_assignments = merge([
for user, user_config in var.users : {
for assignment in user_config.account_assignments :
"${user}_${assignment.account_number}" => {
user_id = aws_identitystore_user.this[user].user_id
permission_set_arn = module.permission_sets.permission_sets[assignment.permission_set_name].arn
account_number = assignment.account_number
} if assignment != null && assignment.account_number != "ALL"
] if user_config.account_assignments != null
])
} if user_config.account_assignments != null
]...)
}
30 changes: 15 additions & 15 deletions modules/iam_sso/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,47 +33,47 @@ resource "aws_identitystore_user" "this" {
}

resource "aws_identitystore_group_membership" "this" {
count = length(local.group_memberships)
for_each = local.group_memberships
identity_store_id = tolist(data.aws_ssoadmin_instances.this.identity_store_ids)[0]
group_id = local.group_memberships[count.index].group_id
member_id = local.group_memberships[count.index].user_id
group_id = each.value.group_id
member_id = each.value.user_id
}

resource "aws_ssoadmin_account_assignment" "groups" {
count = length(local.group_assignments)
for_each = local.group_assignments
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]

permission_set_arn = local.group_assignments[count.index].permission_set_arn
permission_set_arn = each.value.permission_set_arn

principal_id = local.group_assignments[count.index].group_id
principal_id = each.value.group_id
principal_type = "GROUP"

target_id = local.group_assignments[count.index].account_number
target_id = each.value.account_number
target_type = "AWS_ACCOUNT"
}

resource "aws_ssoadmin_account_assignment" "groups_all_accounts" {
count = length(local.groups_for_all_accounts)
for_each = local.group_all_account_assignments
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]

permission_set_arn = local.groups_for_all_accounts[count.index][0].permission_set_arn
permission_set_arn = each.value.permission_set_arn

principal_id = local.groups_for_all_accounts[count.index][0].group_id
principal_id = each.value.group_id
principal_type = "GROUP"

target_id = local.groups_for_all_accounts[count.index][1]
target_id = each.value.account_number
target_type = "AWS_ACCOUNT"
}

resource "aws_ssoadmin_account_assignment" "users" {
count = length(local.user_assignments)
for_each = local.user_assignments
instance_arn = tolist(data.aws_ssoadmin_instances.this.arns)[0]

permission_set_arn = local.user_assignments[count.index].permission_set_arn
permission_set_arn = each.value.permission_set_arn

principal_id = local.user_assignments[count.index].user_id
principal_id = each.value.user_id
principal_type = "USER"

target_id = local.user_assignments[count.index].account_number
target_id = each.value.account_number
target_type = "AWS_ACCOUNT"
}

0 comments on commit b7c2392

Please sign in to comment.