From 28c1d20ffd2aed0af78b2b8b9d863654788e6453 Mon Sep 17 00:00:00 2001 From: David Tappert Date: Fri, 20 Dec 2024 09:02:13 +0100 Subject: [PATCH 01/10] Adding necessary test files and working to confirm standard terraform code works. --- .../locals.tf | 14 +++++++++++ .../main.tf | 16 +++++++++++++ main.tf | 2 ++ tests/01_mandatory.tftest.hcl | 24 +++++++++---------- tests/02_existing_users_and_groups.tftest.hcl | 24 +++++++++---------- tests/03_inline_policy.tftest.hcl | 24 +++++++++---------- tests/04_google_workspace.tftest.hcl | 24 +++++++++---------- .../05_create_apps_and_assignments.tftest.hcl | 24 +++++++++---------- ...6_existing_user_groups_and_apps.tftest.hcl | 24 +++++++++---------- ...tance_access_control_attributes.tftest.hcl | 13 ++++++++++ 10 files changed, 117 insertions(+), 72 deletions(-) create mode 100644 examples/instance-access-control-attributes/locals.tf create mode 100644 examples/instance-access-control-attributes/main.tf create mode 100644 tests/07_instance_access_control_attributes.tftest.hcl diff --git a/examples/instance-access-control-attributes/locals.tf b/examples/instance-access-control-attributes/locals.tf new file mode 100644 index 0000000..28f6391 --- /dev/null +++ b/examples/instance-access-control-attributes/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" + +} \ No newline at end of file diff --git a/examples/instance-access-control-attributes/main.tf b/examples/instance-access-control-attributes/main.tf new file mode 100644 index 0000000..b10073b --- /dev/null +++ b/examples/instance-access-control-attributes/main.tf @@ -0,0 +1,16 @@ +module "aws-iam-identity-center" { + source = "../.." // local example + +} + +data "aws_ssoadmin_instances" "instances" {} + +resource "aws_ssoadmin_instance_access_control_attributes" "attributes" { + instance_arn = tolist(data.aws_ssoadmin_instances.instances.arns)[0] + attribute { + key = "name" + value { + source = ["$${path:name.givenName}"] + } + } +} \ No newline at end of file diff --git a/main.tf b/main.tf index ad2641c..4a6601f 100644 --- a/main.tf +++ b/main.tf @@ -318,3 +318,5 @@ resource "aws_ssoadmin_application_assignment" "sso_apps_users_assignments" { principal_type = each.value.principal_type } +# SSO Instance Access Control + diff --git a/tests/01_mandatory.tftest.hcl b/tests/01_mandatory.tftest.hcl index 6cbe0fb..23bfd03 100644 --- a/tests/01_mandatory.tftest.hcl +++ b/tests/01_mandatory.tftest.hcl @@ -1,13 +1,13 @@ -run "unit_test" { - command = plan - module { - source = "./examples/create-users-and-groups" - } -} +# run "unit_test" { +# command = plan +# module { +# source = "./examples/create-users-and-groups" +# } +# } -run "e2e_test" { - command = apply - module { - source = "./examples/create-users-and-groups" - } -} +# run "e2e_test" { +# command = apply +# module { +# source = "./examples/create-users-and-groups" +# } +# } diff --git a/tests/02_existing_users_and_groups.tftest.hcl b/tests/02_existing_users_and_groups.tftest.hcl index 4c25514..16d7a3a 100644 --- a/tests/02_existing_users_and_groups.tftest.hcl +++ b/tests/02_existing_users_and_groups.tftest.hcl @@ -1,13 +1,13 @@ -run "unit_test" { - command = plan - module { - source = "./examples/existing-users-and-groups" - } -} +# run "unit_test" { +# command = plan +# module { +# source = "./examples/existing-users-and-groups" +# } +# } -run "e2e_test" { - command = apply - module { - source = "./examples/existing-users-and-groups" - } -} +# run "e2e_test" { +# command = apply +# module { +# source = "./examples/existing-users-and-groups" +# } +# } diff --git a/tests/03_inline_policy.tftest.hcl b/tests/03_inline_policy.tftest.hcl index 1ae4794..f773fd8 100644 --- a/tests/03_inline_policy.tftest.hcl +++ b/tests/03_inline_policy.tftest.hcl @@ -1,13 +1,13 @@ -run "unit_test" { - command = plan - module { - source = "./examples/inline-policy" - } -} +# run "unit_test" { +# command = plan +# module { +# source = "./examples/inline-policy" +# } +# } -run "e2e_test" { - command = apply - module { - source = "./examples/inline-policy" - } -} +# run "e2e_test" { +# command = apply +# module { +# source = "./examples/inline-policy" +# } +# } diff --git a/tests/04_google_workspace.tftest.hcl b/tests/04_google_workspace.tftest.hcl index 9ab39bc..eac4d5f 100644 --- a/tests/04_google_workspace.tftest.hcl +++ b/tests/04_google_workspace.tftest.hcl @@ -1,13 +1,13 @@ -run "unit_test" { - command = plan - module { - source = "./examples/google-workspace" - } -} +# run "unit_test" { +# command = plan +# module { +# source = "./examples/google-workspace" +# } +# } -run "e2e_test" { - command = apply - module { - source = "./examples/google-workspace" - } -} +# run "e2e_test" { +# command = apply +# module { +# source = "./examples/google-workspace" +# } +# } diff --git a/tests/05_create_apps_and_assignments.tftest.hcl b/tests/05_create_apps_and_assignments.tftest.hcl index d53f66e..48d9203 100644 --- a/tests/05_create_apps_and_assignments.tftest.hcl +++ b/tests/05_create_apps_and_assignments.tftest.hcl @@ -1,13 +1,13 @@ -run "unit_test" { - command = plan - module { - source = "./examples/create-apps-and-assignments" - } -} +# run "unit_test" { +# command = plan +# module { +# source = "./examples/create-apps-and-assignments" +# } +# } -run "e2e_test" { - command = apply - module { - source = "./examples/create-apps-and-assignments" - } -} +# run "e2e_test" { +# command = apply +# module { +# source = "./examples/create-apps-and-assignments" +# } +# } diff --git a/tests/06_existing_user_groups_and_apps.tftest.hcl b/tests/06_existing_user_groups_and_apps.tftest.hcl index 1c73e0e..cfb36d9 100644 --- a/tests/06_existing_user_groups_and_apps.tftest.hcl +++ b/tests/06_existing_user_groups_and_apps.tftest.hcl @@ -1,13 +1,13 @@ -run "unit_test" { - command = plan - module { - source = "./examples/existing-users-groups-create-apps" - } -} +# run "unit_test" { +# command = plan +# module { +# source = "./examples/existing-users-groups-create-apps" +# } +# } -run "e2e_test" { - command = apply - module { - source = "./examples/existing-users-groups-create-apps" - } -} +# run "e2e_test" { +# command = apply +# module { +# source = "./examples/existing-users-groups-create-apps" +# } +# } diff --git a/tests/07_instance_access_control_attributes.tftest.hcl b/tests/07_instance_access_control_attributes.tftest.hcl new file mode 100644 index 0000000..af1ffbf --- /dev/null +++ b/tests/07_instance_access_control_attributes.tftest.hcl @@ -0,0 +1,13 @@ +run "unit_test" { + command = plan + module { + source = "./examples/instance-access-control-attributes" + } +} + +run "e2e_test" { + command = apply + module { + source = "./examples/instance-access-control-attributes" + } +} From c2a6435793e1599fdf6a818cb9703405efe5743e Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 26 Dec 2024 14:13:38 +0100 Subject: [PATCH 02/10] Got initial setup working as expected. Need to work through some edge cases and confirm if any other changes are needed. --- .../main.tf | 15 +++++++-------- locals.tf | 13 +++++++++++++ main.tf | 19 +++++++++++++++++-- variables.tf | 9 +++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/examples/instance-access-control-attributes/main.tf b/examples/instance-access-control-attributes/main.tf index b10073b..2164e83 100644 --- a/examples/instance-access-control-attributes/main.tf +++ b/examples/instance-access-control-attributes/main.tf @@ -1,16 +1,15 @@ module "aws-iam-identity-center" { source = "../.." // local example -} -data "aws_ssoadmin_instances" "instances" {} - -resource "aws_ssoadmin_instance_access_control_attributes" "attributes" { - instance_arn = tolist(data.aws_ssoadmin_instances.instances.arns)[0] - attribute { - key = "name" - value { + sso_instance_access_control_attributes = { + FirstName = { + attribute_name = "FirstName" source = ["$${path:name.givenName}"] } + LastName = { + attribute_name = "LastName" + source = ["$${path:name.familyName}"] + } } } \ No newline at end of file diff --git a/locals.tf b/locals.tf index d996c3d..0f04ee5 100644 --- a/locals.tf +++ b/locals.tf @@ -218,3 +218,16 @@ locals { ] ]) } + +# - IAM Access Control Attributes +locals { + # If user provides attributes, use those. If null/empty, provide minimum required + attributes_to_use = ( + var.sso_instance_access_control_attributes != null) ? var.sso_instance_access_control_attributes : { + # This default will only be used during plan phase and resource won't actually be created + Dummy = { + attribute_name = "Dummy" + source = ["dummy"] + } + } +} \ No newline at end of file diff --git a/main.tf b/main.tf index 4a6601f..b1bb5e7 100644 --- a/main.tf +++ b/main.tf @@ -318,5 +318,20 @@ resource "aws_ssoadmin_application_assignment" "sso_apps_users_assignments" { principal_type = each.value.principal_type } -# SSO Instance Access Control - +# SSO Instance Access Control Attributes +resource "aws_ssoadmin_instance_access_control_attributes" "sso_access_control_attributes" { + count = var.sso_instance_access_control_attributes == null ? 0 : 1 + instance_arn = local.ssoadmin_instance_arn + dynamic "attribute" { + for_each = local.attributes_to_use + content { + key = attribute.key + value { + source = attribute.value.source + } + } + } + lifecycle { #TODO: need to check that this is a best practice and/or see if we should allow the user to define and/or override. + create_before_destroy = true + } +} \ No newline at end of file diff --git a/variables.tf b/variables.tf index 395a424..1c53961 100644 --- a/variables.tf +++ b/variables.tf @@ -145,3 +145,12 @@ variable "sso_applications" { error_message = "The application_provider_arn field is mandatory for all applications." } } + +variable "sso_instance_access_control_attributes" { + description = "List of attributes for access control. This is used to create the enable and use attributes for access control." + type = map(object({ + attribute_name = string + source = set(string) + })) + default = null +} \ No newline at end of file From a6c5a0acd9e1c2c383681636ad0397bd66ceba55 Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 26 Dec 2024 14:17:44 +0100 Subject: [PATCH 03/10] Uncommenting the other tests out since I have my test working now. --- tests/01_mandatory.tftest.hcl | 24 +++++++++---------- tests/02_existing_users_and_groups.tftest.hcl | 24 +++++++++---------- tests/03_inline_policy.tftest.hcl | 24 +++++++++---------- tests/04_google_workspace.tftest.hcl | 24 +++++++++---------- .../05_create_apps_and_assignments.tftest.hcl | 24 +++++++++---------- ...6_existing_user_groups_and_apps.tftest.hcl | 24 +++++++++---------- 6 files changed, 72 insertions(+), 72 deletions(-) diff --git a/tests/01_mandatory.tftest.hcl b/tests/01_mandatory.tftest.hcl index 23bfd03..9961135 100644 --- a/tests/01_mandatory.tftest.hcl +++ b/tests/01_mandatory.tftest.hcl @@ -1,13 +1,13 @@ -# run "unit_test" { -# command = plan -# module { -# source = "./examples/create-users-and-groups" -# } -# } +run "unit_test" { + command = plan + module { + source = "./examples/create-users-and-groups" + } +} -# run "e2e_test" { -# command = apply -# module { -# source = "./examples/create-users-and-groups" -# } -# } +run "e2e_test" { + command = apply + module { + source = "./examples/create-users-and-groups" + } +} \ No newline at end of file diff --git a/tests/02_existing_users_and_groups.tftest.hcl b/tests/02_existing_users_and_groups.tftest.hcl index 16d7a3a..4c25514 100644 --- a/tests/02_existing_users_and_groups.tftest.hcl +++ b/tests/02_existing_users_and_groups.tftest.hcl @@ -1,13 +1,13 @@ -# run "unit_test" { -# command = plan -# module { -# source = "./examples/existing-users-and-groups" -# } -# } +run "unit_test" { + command = plan + module { + source = "./examples/existing-users-and-groups" + } +} -# run "e2e_test" { -# command = apply -# module { -# source = "./examples/existing-users-and-groups" -# } -# } +run "e2e_test" { + command = apply + module { + source = "./examples/existing-users-and-groups" + } +} diff --git a/tests/03_inline_policy.tftest.hcl b/tests/03_inline_policy.tftest.hcl index f773fd8..1ae4794 100644 --- a/tests/03_inline_policy.tftest.hcl +++ b/tests/03_inline_policy.tftest.hcl @@ -1,13 +1,13 @@ -# run "unit_test" { -# command = plan -# module { -# source = "./examples/inline-policy" -# } -# } +run "unit_test" { + command = plan + module { + source = "./examples/inline-policy" + } +} -# run "e2e_test" { -# command = apply -# module { -# source = "./examples/inline-policy" -# } -# } +run "e2e_test" { + command = apply + module { + source = "./examples/inline-policy" + } +} diff --git a/tests/04_google_workspace.tftest.hcl b/tests/04_google_workspace.tftest.hcl index eac4d5f..9ab39bc 100644 --- a/tests/04_google_workspace.tftest.hcl +++ b/tests/04_google_workspace.tftest.hcl @@ -1,13 +1,13 @@ -# run "unit_test" { -# command = plan -# module { -# source = "./examples/google-workspace" -# } -# } +run "unit_test" { + command = plan + module { + source = "./examples/google-workspace" + } +} -# run "e2e_test" { -# command = apply -# module { -# source = "./examples/google-workspace" -# } -# } +run "e2e_test" { + command = apply + module { + source = "./examples/google-workspace" + } +} diff --git a/tests/05_create_apps_and_assignments.tftest.hcl b/tests/05_create_apps_and_assignments.tftest.hcl index 48d9203..d53f66e 100644 --- a/tests/05_create_apps_and_assignments.tftest.hcl +++ b/tests/05_create_apps_and_assignments.tftest.hcl @@ -1,13 +1,13 @@ -# run "unit_test" { -# command = plan -# module { -# source = "./examples/create-apps-and-assignments" -# } -# } +run "unit_test" { + command = plan + module { + source = "./examples/create-apps-and-assignments" + } +} -# run "e2e_test" { -# command = apply -# module { -# source = "./examples/create-apps-and-assignments" -# } -# } +run "e2e_test" { + command = apply + module { + source = "./examples/create-apps-and-assignments" + } +} diff --git a/tests/06_existing_user_groups_and_apps.tftest.hcl b/tests/06_existing_user_groups_and_apps.tftest.hcl index cfb36d9..1c73e0e 100644 --- a/tests/06_existing_user_groups_and_apps.tftest.hcl +++ b/tests/06_existing_user_groups_and_apps.tftest.hcl @@ -1,13 +1,13 @@ -# run "unit_test" { -# command = plan -# module { -# source = "./examples/existing-users-groups-create-apps" -# } -# } +run "unit_test" { + command = plan + module { + source = "./examples/existing-users-groups-create-apps" + } +} -# run "e2e_test" { -# command = apply -# module { -# source = "./examples/existing-users-groups-create-apps" -# } -# } +run "e2e_test" { + command = apply + module { + source = "./examples/existing-users-groups-create-apps" + } +} From a7c8f01f305aeaf567c79015615fec8bb30b8606 Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 26 Dec 2024 16:10:48 +0100 Subject: [PATCH 04/10] Adding the readme and the header files - not sure yet what is supposed to update the header file and the rest of the readme file. --- README.md | 2 ++ .../.header.md | 0 .../README.md | 31 +++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 examples/instance-access-control-attributes/.header.md create mode 100644 examples/instance-access-control-attributes/README.md diff --git a/README.md b/README.md index 6217b68..c83598a 100644 --- a/README.md +++ b/README.md @@ -262,6 +262,7 @@ No modules. | [aws_ssoadmin_application_assignment.sso_apps_users_assignments](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_application_assignment) | resource | | [aws_ssoadmin_application_assignment_configuration.sso_apps_assignments_configs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_application_assignment_configuration) | resource | | [aws_ssoadmin_customer_managed_policy_attachment.pset_customer_managed_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_customer_managed_policy_attachment) | resource | +| [aws_ssoadmin_instance_access_control_attributes.sso_access_control_attributes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_instance_access_control_attributes) | resource | | [aws_ssoadmin_managed_policy_attachment.pset_aws_managed_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_managed_policy_attachment) | resource | | [aws_ssoadmin_permission_set.pset](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_permission_set) | resource | | [aws_ssoadmin_permission_set_inline_policy.pset_inline_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssoadmin_permission_set_inline_policy) | resource | @@ -286,6 +287,7 @@ No modules. | [permission\_sets](#input\_permission\_sets) | 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. | `any` | `{}` | no | | [sso\_applications](#input\_sso\_applications) | List of applications to be created in IAM Identity Center |
map(object({
name = string
application_provider_arn = string
description = optional(string)
portal_options = optional(object({
sign_in_options = optional(object({
application_url = optional(string)
origin = string
}))
visibility = optional(string)
}))
status = string # acceptable values are "ENABLED" or "DISABLED"
client_token = optional(string)
tags = optional(map(string))
assignment_required = bool # Resource: aws_ssoadmin_application_assignment_configuration
assignments_access_scope = optional(
list(object({
authorized_targets = optional(list(string)) # List of application names
scope = string
}))
) # Resource: aws_ssoadmin_application_access_scope
group_assignments = optional(list(string)) # Resource aws_ssoadmin_application_assignment, keeping it separated for groups
user_assignments = optional(list(string)) # Resource aws_ssoadmin_application_assignment, keeping it separated for users
}))
| `{}` | no | | [sso\_groups](#input\_sso\_groups) | Names of the groups you wish to create in IAM Identity Center. |
map(object({
group_name = string
group_description = optional(string, null)
}))
| `{}` | no | +| [sso\_instance\_access\_control\_attributes](#input\_sso\_instance\_access\_control\_attributes) | List of attributes for access control. This is used to create the enable and use attributes for access control. |
map(object({
attribute_name = string
source = set(string)
}))
| `null` | no | | [sso\_users](#input\_sso\_users) | Names of the users you wish to create in IAM Identity Center. |
map(object({
display_name = optional(string)
user_name = string
group_membership = list(string)
# Name
given_name = string
middle_name = optional(string, null)
family_name = string
name_formatted = optional(string)
honorific_prefix = optional(string, null)
honorific_suffix = optional(string, null)
# Email
email = string
email_type = optional(string, null)
is_primary_email = optional(bool, true)
# Phone Number
phone_number = optional(string, null)
phone_number_type = optional(string, null)
is_primary_phone_number = optional(bool, true)
# Address
country = optional(string, " ")
locality = optional(string, " ")
address_formatted = optional(string)
postal_code = optional(string, " ")
is_primary_address = optional(bool, true)
region = optional(string, " ")
street_address = optional(string, " ")
address_type = optional(string, null)
# Additional
user_type = optional(string, null)
title = optional(string, null)
locale = optional(string, null)
nickname = optional(string, null)
preferred_language = optional(string, null)
profile_url = optional(string, null)
timezone = optional(string, null)
}))
| `{}` | no | ## Outputs diff --git a/examples/instance-access-control-attributes/.header.md b/examples/instance-access-control-attributes/.header.md new file mode 100644 index 0000000..e69de29 diff --git a/examples/instance-access-control-attributes/README.md b/examples/instance-access-control-attributes/README.md new file mode 100644 index 0000000..13d3990 --- /dev/null +++ b/examples/instance-access-control-attributes/README.md @@ -0,0 +1,31 @@ + +## 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_ssm_parameter.account1_account_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | + +## Inputs + +No inputs. + +## Outputs + +No outputs. + \ No newline at end of file From a876a4f29988f7fa043c6e925ceb0f2c1675baad Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 26 Dec 2024 16:49:43 +0100 Subject: [PATCH 05/10] Adding the missing comments that provide hints as to why your test case is failing - we should really look at a better way to do these tests. --- examples/inline-policy/main.tf | 4 ++-- examples/instance-access-control-attributes/main.tf | 2 +- tests/07_instance_access_control_attributes.tftest.hcl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/inline-policy/main.tf b/examples/inline-policy/main.tf index 54da76e..206602c 100644 --- a/examples/inline-policy/main.tf +++ b/examples/inline-policy/main.tf @@ -52,7 +52,7 @@ module "aws-iam-identity-center" { existing_sso_groups = { AWSControlTowerAdmins : { - group_name = "AWSControlTowerAdmins" + group_name = "AWSControlTowerAdmins" # this must be the name of a sso group that already exists in your AWS account } } @@ -85,7 +85,7 @@ module "aws-iam-identity-center" { existing_permission_sets = { AWSAdministratorAccess : { - permission_set_name = "AWSAdministratorAccess" + permission_set_name = "AWSAdministratorAccess" # this must be the name of a permission set that already exists in your AWS account }, } diff --git a/examples/instance-access-control-attributes/main.tf b/examples/instance-access-control-attributes/main.tf index 2164e83..54b3fd5 100644 --- a/examples/instance-access-control-attributes/main.tf +++ b/examples/instance-access-control-attributes/main.tf @@ -1,7 +1,7 @@ module "aws-iam-identity-center" { source = "../.." // local example - + //Create desired access control attributes sso_instance_access_control_attributes = { FirstName = { attribute_name = "FirstName" diff --git a/tests/07_instance_access_control_attributes.tftest.hcl b/tests/07_instance_access_control_attributes.tftest.hcl index af1ffbf..6b197c7 100644 --- a/tests/07_instance_access_control_attributes.tftest.hcl +++ b/tests/07_instance_access_control_attributes.tftest.hcl @@ -10,4 +10,4 @@ run "e2e_test" { module { source = "./examples/instance-access-control-attributes" } -} +} \ No newline at end of file From b51c1bb3668b001875f6187e626c21046d0dab8f Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 26 Dec 2024 18:01:03 +0100 Subject: [PATCH 06/10] Adding validation and converting to default as empty object, since this appears to be the standard. --- locals.tf | 2 +- main.tf | 2 +- variables.tf | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/locals.tf b/locals.tf index 0f04ee5..4083bbd 100644 --- a/locals.tf +++ b/locals.tf @@ -223,7 +223,7 @@ locals { locals { # If user provides attributes, use those. If null/empty, provide minimum required attributes_to_use = ( - var.sso_instance_access_control_attributes != null) ? var.sso_instance_access_control_attributes : { + var.sso_instance_access_control_attributes != {}) ? var.sso_instance_access_control_attributes : { # This default will only be used during plan phase and resource won't actually be created Dummy = { attribute_name = "Dummy" diff --git a/main.tf b/main.tf index b1bb5e7..6ba6491 100644 --- a/main.tf +++ b/main.tf @@ -320,7 +320,7 @@ resource "aws_ssoadmin_application_assignment" "sso_apps_users_assignments" { # SSO Instance Access Control Attributes resource "aws_ssoadmin_instance_access_control_attributes" "sso_access_control_attributes" { - count = var.sso_instance_access_control_attributes == null ? 0 : 1 + count = length(var.sso_instance_access_control_attributes) <= 0 ? 0 : 1 instance_arn = local.ssoadmin_instance_arn dynamic "attribute" { for_each = local.attributes_to_use diff --git a/variables.tf b/variables.tf index 1c53961..bfd32a6 100644 --- a/variables.tf +++ b/variables.tf @@ -146,11 +146,29 @@ variable "sso_applications" { } } +#Access Control Attributes variable "sso_instance_access_control_attributes" { description = "List of attributes for access control. This is used to create the enable and use attributes for access control." type = map(object({ attribute_name = string source = set(string) })) - default = null + default = {} + validation { + condition = alltrue([ + for attr in values(var.sso_instance_access_control_attributes) : + attr.attribute_name != null && + attr.attribute_name != "" + ]) + error_message = "The attribute_name field is mandatory for all attributes." + } + validation { + condition = alltrue([ + for attr in values(var.sso_instance_access_control_attributes) : + attr.source != null && + length(attr.source) > 0 && # checks if the set is not empty + alltrue([for s in attr.source : s != ""]) # checks no empty strings in set + ]) + error_message = "The attribute source is mandatory and must contain non-empty strings." + } } \ No newline at end of file From 520655933743621142ef923cbc95ee39d32ecd60 Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 26 Dec 2024 21:52:59 +0100 Subject: [PATCH 07/10] Updated the header.md file and re-ran pre-commit. --- README.md | 2 +- .../.header.md | 17 +++++++++++++++++ .../README.md | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c83598a..e758be4 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,7 @@ No modules. | [permission\_sets](#input\_permission\_sets) | 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. | `any` | `{}` | no | | [sso\_applications](#input\_sso\_applications) | List of applications to be created in IAM Identity Center |
map(object({
name = string
application_provider_arn = string
description = optional(string)
portal_options = optional(object({
sign_in_options = optional(object({
application_url = optional(string)
origin = string
}))
visibility = optional(string)
}))
status = string # acceptable values are "ENABLED" or "DISABLED"
client_token = optional(string)
tags = optional(map(string))
assignment_required = bool # Resource: aws_ssoadmin_application_assignment_configuration
assignments_access_scope = optional(
list(object({
authorized_targets = optional(list(string)) # List of application names
scope = string
}))
) # Resource: aws_ssoadmin_application_access_scope
group_assignments = optional(list(string)) # Resource aws_ssoadmin_application_assignment, keeping it separated for groups
user_assignments = optional(list(string)) # Resource aws_ssoadmin_application_assignment, keeping it separated for users
}))
| `{}` | no | | [sso\_groups](#input\_sso\_groups) | Names of the groups you wish to create in IAM Identity Center. |
map(object({
group_name = string
group_description = optional(string, null)
}))
| `{}` | no | -| [sso\_instance\_access\_control\_attributes](#input\_sso\_instance\_access\_control\_attributes) | List of attributes for access control. This is used to create the enable and use attributes for access control. |
map(object({
attribute_name = string
source = set(string)
}))
| `null` | no | +| [sso\_instance\_access\_control\_attributes](#input\_sso\_instance\_access\_control\_attributes) | List of attributes for access control. This is used to create the enable and use attributes for access control. |
map(object({
attribute_name = string
source = set(string)
}))
| `{}` | no | | [sso\_users](#input\_sso\_users) | Names of the users you wish to create in IAM Identity Center. |
map(object({
display_name = optional(string)
user_name = string
group_membership = list(string)
# Name
given_name = string
middle_name = optional(string, null)
family_name = string
name_formatted = optional(string)
honorific_prefix = optional(string, null)
honorific_suffix = optional(string, null)
# Email
email = string
email_type = optional(string, null)
is_primary_email = optional(bool, true)
# Phone Number
phone_number = optional(string, null)
phone_number_type = optional(string, null)
is_primary_phone_number = optional(bool, true)
# Address
country = optional(string, " ")
locality = optional(string, " ")
address_formatted = optional(string)
postal_code = optional(string, " ")
is_primary_address = optional(bool, true)
region = optional(string, " ")
street_address = optional(string, " ")
address_type = optional(string, null)
# Additional
user_type = optional(string, null)
title = optional(string, null)
locale = optional(string, null)
nickname = optional(string, null)
preferred_language = optional(string, null)
profile_url = optional(string, null)
timezone = optional(string, null)
}))
| `{}` | no | ## Outputs diff --git a/examples/instance-access-control-attributes/.header.md b/examples/instance-access-control-attributes/.header.md index e69de29..fddc939 100644 --- a/examples/instance-access-control-attributes/.header.md +++ b/examples/instance-access-control-attributes/.header.md @@ -0,0 +1,17 @@ +This directory contains examples of using the module to **create** instance access control attributes. + +**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 'FirstName' and 'LastName': + +```hcl + sso_instance_access_control_attributes = { + FirstName = { + attribute_name = "FirstName" + source = ["$${path:name.givenName}"] + } + LastName = { + attribute_name = "LastName" + source = ["$${path:name.familyName}"] + } + } + +``` diff --git a/examples/instance-access-control-attributes/README.md b/examples/instance-access-control-attributes/README.md index 13d3990..117ac4b 100644 --- a/examples/instance-access-control-attributes/README.md +++ b/examples/instance-access-control-attributes/README.md @@ -1,4 +1,22 @@ +This directory contains examples of using the module to **create** instance access control attributes. + +**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 'FirstName' and 'LastName': + +```hcl + sso_instance_access_control_attributes = { + FirstName = { + attribute_name = "FirstName" + source = ["$${path:name.givenName}"] + } + LastName = { + attribute_name = "LastName" + source = ["$${path:name.familyName}"] + } + } + +``` + ## Requirements No requirements. From 595dcf540410f359ad996fa399f0d67aeafdc0f3 Mon Sep 17 00:00:00 2001 From: David Tappert Date: Fri, 27 Dec 2024 15:45:48 +0100 Subject: [PATCH 08/10] Switched from using a map to an array - this is simpler and in keeping with the way the resource should be defined. --- README.md | 2 +- .../instance-access-control-attributes/.header.md | 13 +++++-------- .../instance-access-control-attributes/README.md | 13 +++++-------- examples/instance-access-control-attributes/main.tf | 10 +++++----- locals.tf | 13 ------------- main.tf | 5 +---- variables.tf | 10 +++++----- 7 files changed, 22 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index e758be4..2372049 100644 --- a/README.md +++ b/README.md @@ -287,7 +287,7 @@ No modules. | [permission\_sets](#input\_permission\_sets) | 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. | `any` | `{}` | no | | [sso\_applications](#input\_sso\_applications) | List of applications to be created in IAM Identity Center |
map(object({
name = string
application_provider_arn = string
description = optional(string)
portal_options = optional(object({
sign_in_options = optional(object({
application_url = optional(string)
origin = string
}))
visibility = optional(string)
}))
status = string # acceptable values are "ENABLED" or "DISABLED"
client_token = optional(string)
tags = optional(map(string))
assignment_required = bool # Resource: aws_ssoadmin_application_assignment_configuration
assignments_access_scope = optional(
list(object({
authorized_targets = optional(list(string)) # List of application names
scope = string
}))
) # Resource: aws_ssoadmin_application_access_scope
group_assignments = optional(list(string)) # Resource aws_ssoadmin_application_assignment, keeping it separated for groups
user_assignments = optional(list(string)) # Resource aws_ssoadmin_application_assignment, keeping it separated for users
}))
| `{}` | no | | [sso\_groups](#input\_sso\_groups) | Names of the groups you wish to create in IAM Identity Center. |
map(object({
group_name = string
group_description = optional(string, null)
}))
| `{}` | no | -| [sso\_instance\_access\_control\_attributes](#input\_sso\_instance\_access\_control\_attributes) | List of attributes for access control. This is used to create the enable and use attributes for access control. |
map(object({
attribute_name = string
source = set(string)
}))
| `{}` | no | +| [sso\_instance\_access\_control\_attributes](#input\_sso\_instance\_access\_control\_attributes) | List of attributes for access control. This is used to create the enable and use attributes for access control. |
list(object({
attribute_name = string
source = set(string)
}))
| `[]` | no | | [sso\_users](#input\_sso\_users) | Names of the users you wish to create in IAM Identity Center. |
map(object({
display_name = optional(string)
user_name = string
group_membership = list(string)
# Name
given_name = string
middle_name = optional(string, null)
family_name = string
name_formatted = optional(string)
honorific_prefix = optional(string, null)
honorific_suffix = optional(string, null)
# Email
email = string
email_type = optional(string, null)
is_primary_email = optional(bool, true)
# Phone Number
phone_number = optional(string, null)
phone_number_type = optional(string, null)
is_primary_phone_number = optional(bool, true)
# Address
country = optional(string, " ")
locality = optional(string, " ")
address_formatted = optional(string)
postal_code = optional(string, " ")
is_primary_address = optional(bool, true)
region = optional(string, " ")
street_address = optional(string, " ")
address_type = optional(string, null)
# Additional
user_type = optional(string, null)
title = optional(string, null)
locale = optional(string, null)
nickname = optional(string, null)
preferred_language = optional(string, null)
profile_url = optional(string, null)
timezone = optional(string, null)
}))
| `{}` | no | ## Outputs diff --git a/examples/instance-access-control-attributes/.header.md b/examples/instance-access-control-attributes/.header.md index fddc939..010f48a 100644 --- a/examples/instance-access-control-attributes/.header.md +++ b/examples/instance-access-control-attributes/.header.md @@ -1,17 +1,14 @@ This directory contains examples of using the module to **create** instance access control attributes. -**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 'FirstName' and 'LastName': - ```hcl - sso_instance_access_control_attributes = { - FirstName = { + sso_instance_access_control_attributes = [ + { attribute_name = "FirstName" source = ["$${path:name.givenName}"] - } - LastName = { + }, + { attribute_name = "LastName" source = ["$${path:name.familyName}"] } - } - + ] ``` diff --git a/examples/instance-access-control-attributes/README.md b/examples/instance-access-control-attributes/README.md index 117ac4b..fc07e5c 100644 --- a/examples/instance-access-control-attributes/README.md +++ b/examples/instance-access-control-attributes/README.md @@ -1,20 +1,17 @@ This directory contains examples of using the module to **create** instance access control attributes. -**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 'FirstName' and 'LastName': - ```hcl - sso_instance_access_control_attributes = { - FirstName = { + sso_instance_access_control_attributes = [ + { attribute_name = "FirstName" source = ["$${path:name.givenName}"] - } - LastName = { + }, + { attribute_name = "LastName" source = ["$${path:name.familyName}"] } - } - + ] ``` ## Requirements diff --git a/examples/instance-access-control-attributes/main.tf b/examples/instance-access-control-attributes/main.tf index 54b3fd5..cb36249 100644 --- a/examples/instance-access-control-attributes/main.tf +++ b/examples/instance-access-control-attributes/main.tf @@ -2,14 +2,14 @@ module "aws-iam-identity-center" { source = "../.." // local example //Create desired access control attributes - sso_instance_access_control_attributes = { - FirstName = { + sso_instance_access_control_attributes = [ + { attribute_name = "FirstName" source = ["$${path:name.givenName}"] - } - LastName = { + }, + { attribute_name = "LastName" source = ["$${path:name.familyName}"] } - } + ] } \ No newline at end of file diff --git a/locals.tf b/locals.tf index 4083bbd..d996c3d 100644 --- a/locals.tf +++ b/locals.tf @@ -218,16 +218,3 @@ locals { ] ]) } - -# - IAM Access Control Attributes -locals { - # If user provides attributes, use those. If null/empty, provide minimum required - attributes_to_use = ( - var.sso_instance_access_control_attributes != {}) ? var.sso_instance_access_control_attributes : { - # This default will only be used during plan phase and resource won't actually be created - Dummy = { - attribute_name = "Dummy" - source = ["dummy"] - } - } -} \ No newline at end of file diff --git a/main.tf b/main.tf index 6ba6491..9fa2617 100644 --- a/main.tf +++ b/main.tf @@ -323,7 +323,7 @@ resource "aws_ssoadmin_instance_access_control_attributes" "sso_access_control_ count = length(var.sso_instance_access_control_attributes) <= 0 ? 0 : 1 instance_arn = local.ssoadmin_instance_arn dynamic "attribute" { - for_each = local.attributes_to_use + for_each = var.sso_instance_access_control_attributes content { key = attribute.key value { @@ -331,7 +331,4 @@ resource "aws_ssoadmin_instance_access_control_attributes" "sso_access_control_ } } } - lifecycle { #TODO: need to check that this is a best practice and/or see if we should allow the user to define and/or override. - create_before_destroy = true - } } \ No newline at end of file diff --git a/variables.tf b/variables.tf index bfd32a6..5fa4a95 100644 --- a/variables.tf +++ b/variables.tf @@ -149,14 +149,14 @@ variable "sso_applications" { #Access Control Attributes variable "sso_instance_access_control_attributes" { description = "List of attributes for access control. This is used to create the enable and use attributes for access control." - type = map(object({ + type = list(object({ attribute_name = string source = set(string) })) - default = {} + default = [] validation { condition = alltrue([ - for attr in values(var.sso_instance_access_control_attributes) : + for attr in var.sso_instance_access_control_attributes : attr.attribute_name != null && attr.attribute_name != "" ]) @@ -164,11 +164,11 @@ variable "sso_instance_access_control_attributes" { } validation { condition = alltrue([ - for attr in values(var.sso_instance_access_control_attributes) : + for attr in var.sso_instance_access_control_attributes : attr.source != null && length(attr.source) > 0 && # checks if the set is not empty alltrue([for s in attr.source : s != ""]) # checks no empty strings in set ]) error_message = "The attribute source is mandatory and must contain non-empty strings." } -} \ No newline at end of file +} From d21707006aaa4715538c006e31c7a806268d212c Mon Sep 17 00:00:00 2001 From: Kevon Mayers Date: Thu, 9 Jan 2025 13:50:20 -0500 Subject: [PATCH 09/10] bump version, retrigger pipeline --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 95cf410..97e1eac 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ -v1.0.1 +v1.0.2 From 2df38632e37d0dad333c0050c443c6e97846ba47 Mon Sep 17 00:00:00 2001 From: David Tappert Date: Thu, 9 Jan 2025 20:58:28 +0100 Subject: [PATCH 10/10] Removing a trailing space --- examples/instance-access-control-attributes/.header.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/instance-access-control-attributes/.header.md b/examples/instance-access-control-attributes/.header.md index 010f48a..a804d19 100644 --- a/examples/instance-access-control-attributes/.header.md +++ b/examples/instance-access-control-attributes/.header.md @@ -2,7 +2,7 @@ This directory contains examples of using the module to **create** instance acce ```hcl sso_instance_access_control_attributes = [ - { + { attribute_name = "FirstName" source = ["$${path:name.givenName}"] },