diff --git a/examples/customer-managed-policies/.header.md b/examples/customer-managed-policies/.header.md
new file mode 100644
index 0000000..060e460
--- /dev/null
+++ b/examples/customer-managed-policies/.header.md
@@ -0,0 +1,40 @@
+This directory contains examples of using the module to create users and groups and assign permissions with **Inline Policies**.
+
+**IMPORTANT:** Ensure that the name of your object matches the name of your principal (e.g. user name or group name). See the following example with object/principal names 'Admin' and 'nuzumaki':
+
+```hcl
+ sso_groups = {
+ Admin : {
+ group_name = "Admin"
+ group_description = "Admin IAM Identity Center Group"
+ },
+ }
+
+ // Create desired USERS in IAM Identity Center
+ sso_users = {
+ nuzumaki : {
+ group_membership = ["Admin",]
+ user_name = "nuzumaki"
+ given_name = "Naruto"
+ family_name = "Uzumaki"
+ email = "nuzumaki@hiddenleaf.village"
+ },
+ }
+
+```
+
+These names are referenced throughout the module. Failure to do this may lead to unintentional errors such as the following:
+
+```
+Error: Invalid index
+│
+│ on ../../main.tf line 141, in resource "aws_identitystore_group_membership" "sso_group_membership":
+│ 141: member_id = (contains(local.this_users, each.value.user_name) ? aws_identitystore_user.sso_users[each.value.user_name].user_id : data.aws_identitystore_user.existing_sso_users[each.value.user_name].id)
+│ ├────────────────
+│ │ aws_identitystore_user.sso_users is object with 2 attributes
+│ │ each.value.user_name is "nuzumaki"
+│
+│ The given key does not identify an element in this collection value.
+```
+
+To resolve this, ensure your object and principal names are the same and re-run `terraform plan` and `terraform apply`.
diff --git a/examples/customer-managed-policies/README.md b/examples/customer-managed-policies/README.md
new file mode 100644
index 0000000..8ff95ca
--- /dev/null
+++ b/examples/customer-managed-policies/README.md
@@ -0,0 +1,72 @@
+
+This directory contains examples of using the module to create users and groups and assign permissions with **Inline Policies**.
+
+**IMPORTANT:** Ensure that the name of your object matches the name of your principal (e.g. user name or group name). See the following example with object/principal names 'Admin' and 'nuzumaki':
+
+```hcl
+ sso_groups = {
+ Admin : {
+ group_name = "Admin"
+ group_description = "Admin IAM Identity Center Group"
+ },
+ }
+
+ // Create desired USERS in IAM Identity Center
+ sso_users = {
+ nuzumaki : {
+ group_membership = ["Admin",]
+ user_name = "nuzumaki"
+ given_name = "Naruto"
+ family_name = "Uzumaki"
+ email = "nuzumaki@hiddenleaf.village"
+ },
+ }
+
+```
+
+These names are referenced throughout the module. Failure to do this may lead to unintentional errors such as the following:
+
+```
+Error: Invalid index
+│
+│ on ../../main.tf line 141, in resource "aws_identitystore_group_membership" "sso_group_membership":
+│ 141: member_id = (contains(local.this_users, each.value.user_name) ? aws_identitystore_user.sso_users[each.value.user_name].user_id : data.aws_identitystore_user.existing_sso_users[each.value.user_name].id)
+│ ├────────────────
+│ │ aws_identitystore_user.sso_users is object with 2 attributes
+│ │ each.value.user_name is "nuzumaki"
+│
+│ The given key does not identify an element in this collection value.
+```
+
+To resolve this, ensure your object and principal names are the same and re-run `terraform plan` and `terraform apply`.
+
+## Requirements
+
+No requirements.
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | n/a |
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| [aws-iam-identity-center](#module\_aws-iam-identity-center) | ../.. | n/a |
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_organizations_organization.org](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/organizations_organization) | data source |
+
+## Inputs
+
+No inputs.
+
+## Outputs
+
+No outputs.
+
\ No newline at end of file
diff --git a/examples/customer-managed-policies/locals.tf b/examples/customer-managed-policies/locals.tf
new file mode 100644
index 0000000..922f5e9
--- /dev/null
+++ b/examples/customer-managed-policies/locals.tf
@@ -0,0 +1,14 @@
+# Fetch Account Id from SSM Parameter Store
+data "aws_ssm_parameter" "account1_account_id" {
+ name = "tf-aws-iam-idc-module-testing-account1-account-id" // replace with your SSM Parameter Key
+}
+
+locals {
+ # Account IDs
+ account1_account_id = nonsensitive(data.aws_ssm_parameter.account1_account_id.value)
+ # account1_account_id = "111111111111"
+ # account2_account_id = "222222222222"
+ # account3_account_id = "333333333333"
+ # account4_account_id = "444444444444"
+
+}
diff --git a/examples/customer-managed-policies/main.tf b/examples/customer-managed-policies/main.tf
new file mode 100644
index 0000000..49802ab
--- /dev/null
+++ b/examples/customer-managed-policies/main.tf
@@ -0,0 +1,112 @@
+data "aws_organizations_organization" "org" {}
+
+module "aws-iam-identity-center" {
+ source = "../.." // local example
+ # source = "aws-ia/iam-identity-center/aws" // remote example
+
+ existing_sso_groups = {
+ AWSControlTowerAdmins : {
+ group_name = "AWSControlTowerAdmins" # this must be the name of a sso group that already exists in your AWS account
+ }
+ }
+
+ sso_groups = {
+ Admin : {
+ group_name = "Admin"
+ group_description = "Admin Group"
+ },
+ Dev : {
+ group_name = "Dev"
+ group_description = "Dev Group"
+ },
+ }
+ sso_users = {
+ nuzumaki : {
+ group_membership = ["Admin", "Dev", "AWSControlTowerAdmins"]
+ user_name = "nuzumaki"
+ given_name = "Naruto"
+ family_name = "Uzumaki"
+ email = "nuzumaki@hiddenleaf.village"
+ },
+ suchiha : {
+ group_membership = ["Dev", "AWSControlTowerAdmins"]
+ user_name = "suchiha"
+ given_name = "Sasuke"
+ family_name = "Uchiha"
+ email = "suchiha@hiddenleaf.village"
+ },
+ }
+
+ existing_permission_sets = {
+ AWSAdministratorAccess : {
+ permission_set_name = "AWSAdministratorAccess" # this must be the name of a permission set that already exists in your AWS account
+ },
+ }
+
+ permission_sets = {
+ AdministratorAccess = {
+ description = "Provides full access to AWS services and resources",
+ session_duration = "PT3H",
+ aws_managed_policies = ["arn:aws:iam::aws:policy/AdministratorAccess"]
+
+ customer_managed_policies = [
+ "MyExampleOrgAdminAccess",
+ ]
+
+ tags = { ManagedBy = "Terraform" }
+ },
+ ViewOnlyAccess = {
+ description = "This policy grants permissions to view resources and basic metadata across all AWS services",
+ session_duration = "PT3H",
+ aws_managed_policies = ["arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"]
+ managed_policy_arn = "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
+
+ customer_managed_policies = [
+ {
+ name = "MyExampleOrgViewOnlyAccess"
+ path = "/foo/example/"
+ }
+ ]
+
+ permissions_boundary = {
+ managed_policy_arn = "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
+ }
+ tags = { ManagedBy = "Terraform" }
+ },
+ }
+ account_assignments = {
+ Admin : {
+ principal_name = "Admin"
+ principal_type = "GROUP"
+ principal_idp = "INTERNAL"
+ permission_sets = [
+ "AdministratorAccess",
+ "ViewOnlyAccess",
+ // existing permission set
+ "AWSAdministratorAccess",
+ ]
+ account_ids = [
+ // replace with your own account id
+ local.account1_account_id,
+ # local.account2_account_id
+ # local.account3_account_id
+ # local.account4_account_id
+ ]
+ },
+ Dev : {
+ principal_name = "Dev"
+ principal_type = "GROUP"
+ principal_idp = "INTERNAL"
+ permission_sets = [
+ "ViewOnlyAccess",
+ ]
+ account_ids = [
+ // replace with your own account id
+ local.account1_account_id,
+ # local.account2_account_id
+ # local.account3_account_id
+ # local.account4_account_id
+ ]
+ },
+ }
+}
diff --git a/locals.tf b/locals.tf
index d996c3d..0b5575c 100644
--- a/locals.tf
+++ b/locals.tf
@@ -78,8 +78,8 @@ locals {
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
- # path = path
+ policy_name = try(policy.name, policy)
+ policy_path = try(policy.path, "/")
} if pset_index.customer_managed_policies != null && can(pset_index.customer_managed_policies)
]
])
@@ -207,7 +207,7 @@ locals {
])
# Creating a local variable by flattening the complex type related to Applications to extract a simple structure representing
- # app assignments access scopes
+ # app assignments access scopes
apps_assignments_access_scopes = flatten([
for app in var.sso_applications : [
for ass_acc_scope in app.assignments_access_scope : {
diff --git a/main.tf b/main.tf
index 9fa2617..1588703 100644
--- a/main.tf
+++ b/main.tf
@@ -191,7 +191,7 @@ resource "aws_ssoadmin_customer_managed_policy_attachment" "pset_customer_manage
permission_set_arn = aws_ssoadmin_permission_set.pset[each.value.pset_name].arn
customer_managed_policy_reference {
name = each.value.policy_name
- path = "/"
+ path = each.value.policy_path
}
}
@@ -271,7 +271,7 @@ resource "aws_ssoadmin_application" "sso_apps" {
tags = each.value.tags
}
-# SSO - Applications Assigments Configuration
+# SSO - Applications Assigments Configuration
resource "aws_ssoadmin_application_assignment_configuration" "sso_apps_assignments_configs" {
for_each = {
for idx, assignment_config in local.apps_assignments_configs :
@@ -281,7 +281,7 @@ resource "aws_ssoadmin_application_assignment_configuration" "sso_apps_assignmen
assignment_required = each.value.assignment_required
}
-# SSO - Application Assignments access scope
+# SSO - Application Assignments access scope
resource "aws_ssoadmin_application_access_scope" "sso_apps_assignments_access_scope" {
for_each = {
for idx, app_access_scope in local.apps_assignments_access_scopes :
@@ -289,20 +289,20 @@ resource "aws_ssoadmin_application_access_scope" "sso_apps_assignments_access_sc
}
application_arn = aws_ssoadmin_application.sso_apps[each.value.app_name].application_arn
authorized_targets = [
- for target in each.value.authorized_targets : aws_ssoadmin_application.sso_apps[target].application_arn
+ for target in each.value.authorized_targets : aws_ssoadmin_application.sso_apps[target].application_arn
]
#authorized_targets = each.value.authorized_targets
scope = each.value.scope
}
-# SSO - Applications Assignments
+# SSO - Applications Assignments
# Groups assignments
resource "aws_ssoadmin_application_assignment" "sso_apps_groups_assignments" {
for_each = {
for idx, assignment in local.apps_groups_assignments :
"${assignment.app_name}-${assignment.group_name}" => assignment
}
- application_arn = aws_ssoadmin_application.sso_apps[each.value.app_name].application_arn
+ application_arn = aws_ssoadmin_application.sso_apps[each.value.app_name].application_arn
principal_id = (contains(local.this_groups, each.value.group_name) ? aws_identitystore_group.sso_groups[each.value.group_name].group_id : data.aws_identitystore_group.existing_sso_groups[each.value.group_name].group_id)
principal_type = each.value.principal_type
}
@@ -313,7 +313,7 @@ resource "aws_ssoadmin_application_assignment" "sso_apps_users_assignments" {
for idx, assignment in local.apps_users_assignments :
"${assignment.app_name}-${assignment.user_name}" => assignment
}
- application_arn = aws_ssoadmin_application.sso_apps[each.value.app_name].application_arn
+ application_arn = aws_ssoadmin_application.sso_apps[each.value.app_name].application_arn
principal_id = (contains(local.this_users, each.value.user_name) ? aws_identitystore_user.sso_users[each.value.user_name].user_id : data.aws_identitystore_user.existing_sso_users[each.value.user_name].user_id)
principal_type = each.value.principal_type
}
@@ -331,4 +331,4 @@ resource "aws_ssoadmin_instance_access_control_attributes" "sso_access_control_
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/08_customer_managed_policies.tftest.hcl b/tests/08_customer_managed_policies.tftest.hcl
new file mode 100644
index 0000000..5b55cf4
--- /dev/null
+++ b/tests/08_customer_managed_policies.tftest.hcl
@@ -0,0 +1,13 @@
+run "unit_test" {
+ command = plan
+ module {
+ source = "./examples/customer-managed-policies"
+ }
+}
+
+run "e2e_test" {
+ command = apply
+ module {
+ source = "./examples/customer-managed-policies"
+ }
+}