Skip to content

Commit

Permalink
feat(identity): create identity-center module (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
p5 authored Sep 8, 2024
1 parent 0af1a81 commit 7e7f290
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 0 deletions.
123 changes: 123 additions & 0 deletions modules/aws/identity/identity-center/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
locals {
# Retrieve the first SSO instance ARN and identity store ID
ssoadmin_instance_arn = tolist(data.aws_ssoadmin_instances.sso_instance.arns)[0]
sso_instance_id = tolist(data.aws_ssoadmin_instances.sso_instance.identity_store_ids)[0]

# Filter permission sets based on the presence of different policy types
aws_managed_permission_sets = {
for pset_name, pset_index in var.permission_sets :
pset_name => pset_index
if length(coalesce(pset_index.aws_managed_policies, [])) > 0
}

inline_policy_permission_sets = {
for pset_name, pset_index in var.permission_sets :
pset_name => pset_index
if can(pset_index.inline_policy)
}

permissions_boundary_aws_managed_permission_sets = {
for pset_name, pset_index in var.permission_sets :
pset_name => pset_index
if can(pset_index.permissions_boundary.managed_policy_arn)
}

permissions_boundary_customer_managed_permission_sets = {
for pset_name, pset_index in var.permission_sets :
pset_name => pset_index
if can(pset_index.permissions_boundary.customer_managed_policy_reference)
}

customer_managed_permission_sets = {
for pset_name, pset_index in var.permission_sets :
pset_name => pset_index
if length(coalesce(pset_index.customer_managed_policies, [])) > 0
}

# Map AWS managed policies to permission sets
pset_aws_managed_policy_maps = flatten([
for pset_name, pset_index in local.aws_managed_permission_sets : [
for policy in pset_index.aws_managed_policies : {
pset_name = pset_name
policy_arn = policy
} if can(policy)
]
])

# Map customer managed policies to permission sets
pset_customer_managed_policy_maps = flatten([
for pset_name, pset_index in local.customer_managed_permission_sets : [
for policy in pset_index.customer_managed_policies : {
pset_name = pset_name
policy_name = policy.name
path = policy.path
} if can(policy)
]
])

# Map inline policies to permission sets
pset_inline_policy_maps = flatten([
for pset_name, pset_index in local.inline_policy_permission_sets : [
{
pset_name = pset_name
inline_policy = pset_index.inline_policy
}
]
])

# Map AWS managed permissions boundaries to permission sets
pset_permissions_boundary_aws_managed_maps = flatten([
for pset_name, pset_index in local.permissions_boundary_aws_managed_permission_sets : [
{
pset_name = pset_name
boundary = {
managed_policy_arn = pset_index.permissions_boundary.managed_policy_arn
}
}
]
])

# Map customer managed permissions boundaries to permission sets
pset_permissions_boundary_customer_managed_maps = flatten([
for pset_name, pset_index in local.permissions_boundary_customer_managed_permission_sets : [
{
pset_name = pset_name
boundary = {
customer_managed_policy_reference = pset_index.permissions_boundary.customer_managed_policy_reference
}
}
]
])

# Filter active accounts from the organization
active_accounts = [
for account in data.aws_organizations_organization.organization.accounts :
account if account.status == "ACTIVE"
]

# Map account names to IDs for active accounts
accounts_ids_maps = {
for account in local.active_accounts :
account.name => account.id
}

# Flatten account assignments data
flatten_account_assignment_data = flatten([
for this_assignment in keys(var.account_assignments) : [
for account in var.account_assignments[this_assignment].account_ids : [
for pset in var.account_assignments[this_assignment].permission_sets : {
permission_set = pset
principal_name = var.account_assignments[this_assignment].principal_name
principal_type = var.account_assignments[this_assignment].principal_type
account_id = length(regexall("[0-9]{12}", account)) > 0 ? account : lookup(local.accounts_ids_maps, account, null)
}
]
]
])

# Map principals and their account assignments
principals_and_their_account_assignments = {
for s in local.flatten_account_assignment_data :
format("Type:%s__Principal:%s__Permission:%s__Account:%s", s.principal_type, s.principal_name, s.permission_set, s.account_id) => s
}
}
23 changes: 23 additions & 0 deletions modules/aws/identity/identity-center/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
data "aws_ssoadmin_instances" "sso_instance" {}
data "aws_organizations_organization" "organization" {}

resource "aws_identitystore_group" "sso_groups" {
for_each = var.sso_groups == null ? {} : var.sso_groups
identity_store_id = local.sso_instance_id
display_name = each.value.group_name
description = each.value.group_description
}

resource "aws_ssoadmin_account_assignment" "account_assignment" {
for_each = local.principals_and_their_account_assignments

instance_arn = local.ssoadmin_instance_arn
permission_set_arn = aws_ssoadmin_permission_set.pset[each.value.permission_set].arn

principal_type = each.value.principal_type

principal_id = aws_identitystore_group.sso_groups[each.value.principal_name].group_id

target_id = each.value.account_id
target_type = "AWS_ACCOUNT"
}
15 changes: 15 additions & 0 deletions modules/aws/identity/identity-center/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "account_assignment_data" {
value = local.flatten_account_assignment_data
description = "Tuple containing account assignment data"

}

output "principals_and_assignments" {
value = local.principals_and_their_account_assignments
description = "Map containing account assignment data"
}

output "sso_groups_ids" {
value = { for k, v in aws_identitystore_group.sso_groups : k => v.group_id }
description = "A map of SSO groups ids created by this module"
}
66 changes: 66 additions & 0 deletions modules/aws/identity/identity-center/permission_set.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
resource "aws_ssoadmin_permission_set" "pset" {
for_each = var.permission_sets
name = each.key

instance_arn = local.ssoadmin_instance_arn
description = lookup(each.value, "description", null)
relay_state = lookup(each.value, "relay_state", null)
session_duration = lookup(each.value, "session_duration", null)
tags = merge(lookup(each.value, "tags", {}), var.tags_all)
}


resource "aws_ssoadmin_managed_policy_attachment" "pset_aws_managed_policy" {
for_each = { for pset in local.pset_aws_managed_policy_maps : "${pset.pset_name}.${pset.policy_arn}" => pset }

instance_arn = local.ssoadmin_instance_arn
managed_policy_arn = each.value.policy_arn
permission_set_arn = aws_ssoadmin_permission_set.pset[each.value.pset_name].arn

depends_on = [aws_ssoadmin_account_assignment.account_assignment]
}


resource "aws_ssoadmin_customer_managed_policy_attachment" "pset_customer_managed_policy" {
for_each = { for pset in local.pset_customer_managed_policy_maps : "${pset.pset_name}.${pset.policy_name}" => pset }

instance_arn = local.ssoadmin_instance_arn
permission_set_arn = aws_ssoadmin_permission_set.pset[each.value.pset_name].arn
customer_managed_policy_reference {
name = each.value.policy_name
path = each.value.path
}

}

resource "aws_ssoadmin_permission_set_inline_policy" "pset_inline_policy" {
for_each = { for pset in local.pset_inline_policy_maps : pset.pset_name => pset if can(pset.inline_policy) }

inline_policy = each.value.inline_policy
instance_arn = local.ssoadmin_instance_arn
permission_set_arn = aws_ssoadmin_permission_set.pset[each.key].arn
}

resource "aws_ssoadmin_permissions_boundary_attachment" "pset_permissions_boundary_aws_managed" {
for_each = { for pset in local.pset_permissions_boundary_aws_managed_maps : pset.pset_name => pset if can(pset.boundary.managed_policy_arn) }

instance_arn = local.ssoadmin_instance_arn
permission_set_arn = aws_ssoadmin_permission_set.pset[each.key].arn
permissions_boundary {
managed_policy_arn = each.value.boundary.managed_policy_arn
}
}

resource "aws_ssoadmin_permissions_boundary_attachment" "pset_permissions_boundary_customer_managed" {
for_each = { for pset in local.pset_permissions_boundary_customer_managed_maps : pset.pset_name => pset if can(pset.boundary.customer_managed_policy_reference) }

instance_arn = local.ssoadmin_instance_arn
permission_set_arn = aws_ssoadmin_permission_set.pset[each.key].arn
permissions_boundary {
customer_managed_policy_reference {
name = each.value.boundary.customer_managed_policy_reference.name
path = can(each.value.boundary.customer_managed_policy_reference.path) ? each.value.boundary.customer_managed_policy_reference.path : "/"
}

}
}
31 changes: 31 additions & 0 deletions modules/aws/identity/identity-center/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
variable "sso_groups" {
description = "Names of the groups you wish to create in IAM Identity Center."
type = map(object({
group_name = string
group_description = optional(string, null)
}))
default = {}
}

variable "permission_sets" {
description = "Permission Sets that you wish to create in IAM Identity Center. This variable is a map of maps containing Permission Set names as keys. See permission_sets description in README for information about map values."
type = any
default = {}
}

variable "account_assignments" {
description = "List of maps containing mapping between user/group, permission set and assigned accounts list. See account_assignments description in README for more information about map values."
type = map(object({
principal_name = string
principal_type = optional(string, "GROUP")
permission_sets = list(string)
account_ids = list(string)
}))
default = {}
}

variable "tags_all" {
description = "A map of tags to add to all resources."
type = map(string)
default = {}
}
10 changes: 10 additions & 0 deletions modules/aws/identity/identity-center/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">=1.3"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">=4.0"
}
}
}

0 comments on commit 7e7f290

Please sign in to comment.