Skip to main content

AWS Identity Center (SSO)

This guide provides an overview of setting up AWS Identity Center (SSO) with ClickOps, detailing prerequisites and supported external identity providers. It explains how to integrate AWS SSO with providers like Okta, Azure AD, JumpCloud, and Google Workspace, including specific steps for configuring each.

How it Works​

AWS Single Sign-On (AWS SSO) is a service that simplifies access management for AWS accounts and applications for managing your organization's workforce identity at scale across a multi-account AWS deployment. It enables users to sign in to AWS once and access multiple AWS accounts and applications without the need to re-enter credentials. To use it with an identity provider (e.g. such as Okta) for AWS SSO, administrators typically need to configure the integration within the AWS Management Console. This involves setting up a new AWS SSO instance, connecting it the IdP, and specifying the users or groups that should have access to AWS resources. AWS SSO provides logging and auditing capabilities, allowing organizations to track user access to AWS resources and monitor security-related events

  1. SAML-Based Authentication

    The integration between the IdP and AWS SSO relies on the Security Assertion Markup Language (SAML) for authentication and authorization. SAML enables the exchange of authentication and authorization data between Okta and AWS, allowing users to log in once to Okta and gain access to AWS resources without additional logins.

  2. User Provisioning

    AWS SSO can be configured to automatically provision and de-provision user accounts based on changes in the IdP directory. This helps keep user access in sync with changes made in the Okta environment.

  3. AWS SSO Permission Sets

    AWS SSO allows administrators to define fine-grained access policies, specifying which AWS accounts and services users from the IdP can access

  4. Multi-Factor Authentication (MFA)

    Organizations using Okta for authentication with AWS SSO can enhance security by enforcing multi-factor authentication (MFA) for added identity verification.

Once configured, users can experience single sign-on when accessing AWS resources. They log in to their IdP account and seamlessly gain access to AWS without needing to provide credentials again.

It's important to note that the specifics of the integration process may be subject to updates or changes, so it's recommended to refer to the official AWS documentation and Okta documentation for the most accurate and up-to-date information based on your current date.

Prerequisites​

First, enable the AWS IAM Identity Center (successor to AWS Single Sign-On) service in the aws-admin account. This is the account where the aws-sso component will be deployed.

Precondition-0: Minimum-Clickops Bootstrap

  1. Root Console Access (READONLY)

    • Sign in to the management account using root credentials (console only β€” DO NOT create root access keys)
    • This is your starting point; permissions to enable Identity Center are root-only
  2. Enable AWS Organizations (one-time setup)

    • Navigate to AWS Organizations in the AWS Web Console
    • Click Enable
    • This creates the organizational structure needed for IAM Identity Center
  3. Enable IAM Identity Center (one-time setup)

    • Navigate to IAM Identity Center (successor to AWS Single Sign-On)
    • Select your deployment region β€” e.g. ap-southeast-2 for Sydney (OceanSoft), or your enterprise's primary region
    • Click Enable to activate the service
    • Once enabled, IAM Identity Center creates service-linked roles in all AWS accounts within the organization
  4. Create Admin Permission Set (one-time setup)

    • In the Identity Center console, go to Permission sets
    • Click Create permission set
    • Select Predefined permission set and choose AdministratorAccess
    • Click Next, then Create
  5. Assign Your Identity Center User

    • In Identity Center β†’ Users and groups, confirm your Identity Center user exists (created during initial setup)
    • Go to AWS accounts β†’ management account β†’ Assign users or groups
    • Assign your user/group to the Admin permission set
    • Wait for provisioning to complete
  6. Configure Short-Lived SSO Credentials

    • On your local machine, run: aws configure sso
    • When prompted:
      • SSO session name: sso (or your preferred name)
      • SSO start URL: https://<your-identity-center-id>.awsapps.com/start (found in Identity Center β†’ Settings)
      • SSO region: ap-southeast-2 (for OceanSoft) or your enterprise's home region (e.g. us-east-1)
      • SSO registration scopes: leave default (OIDC consent scopes)
    • Run: aws sso login --profile sso
    • You will be redirected to a browser window to authenticate with your Identity Center credentials
    • After successful auth, your profile will have temporary credentials (~12-hour session)

Why this approach:

  • Root credentials are short-lived (console sessions expire) and audit-logged
  • No long-lived IAM user or access keys are created, eliminating static credential risk
  • Permission sets enforce least-privilege access per user/group/account
  • Short-lived Identity Center credentials (12h default, configurable) are automatically rotated by AWS
  • SCIM provisioning (next step) automatically syncs users and groups from your external IdP into AWS, so you never manually create IAM users again

Instead of ClickOps, use the iam-identity-center Terraform module to manage IAM Identity Center resources as code. The module covers groups, users, permission sets, account assignments, and ABAC attributes.

Key Facts

  • IAM Identity Center can be enabled in any region β€” not only us-east-1. Our reference setup uses ap-southeast-2.
  • Since November 2023, IAM Identity Center works on standalone accounts without AWS Organizations. Permission sets, groups, and account assignments all function on a single account.
  • If you need account-name-to-ID resolution (referencing accounts by name instead of 12-digit ID), you need org-level SSO (enable_organizations_lookup = true). For standalone accounts, set enable_organizations_lookup = false.

Module Source​

Choose one source depending on your context:

# Production β€” Pinned SHA (recommended)
source = "git::https://github.com/nnthanh101/terraform-aws.git//modules/sso?ref=978f8fc70e0c54975fd0ff6c19ae7dd972cad0ce"

# Development β€” Local path (monorepo development ONLY)
# source = "../../../terraform-aws/modules/sso" # DEV ONLY

# Option 3 β€” Terraform Registry (after registry publish)
source = "oceansoft/sso/aws"
version = "~> 2.0"

Standalone Account Setup​

For a standalone account (no AWS Organizations). Example: OceanSoft management account in Sydney region.

terraform {
required_version = ">= 1.11.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 6.28, < 7.0"
}
}

# S3 native locking, no DynamoDB (Terraform 1.10+)
backend "s3" {
region = "ap-southeast-2" # or $AWS_DEFAULT_REGION
bucket = "<ACCOUNT_ID>-tfstate-<REGION>"
key = "identity/terraform.tfstate"
use_lockfile = true
encrypt = true
skip_credentials_validation = false
}
}

provider "aws" {
alias = "identity_center"
region = "ap-southeast-2" # Set to $AWS_DEFAULT_REGION (e.g., ap-southeast-2 for Sydney, us-east-1 for N. Virginia)

module "identity_center" {
source = "../../modules/iam-identity-center"

providers = {
aws = aws.identity_center
}

# Standalone: no Organizations lookup needed
enable_organizations_lookup = false

sso_groups = {
PlatformTeam = {
group_name = "PlatformTeam"
group_description = "Platform engineering team"
}
AuditTeam = {
group_name = "AuditTeam"
group_description = "Audit and compliance team with read-only access"
}
}

permission_sets = {
Admin = {
description = "Full administrator access"
session_duration = "PT4H"
aws_managed_policies = ["arn:aws:iam::aws:policy/AdministratorAccess"]
tags = { ManagedBy = "Terraform" }
}
ReadOnly = {
description = "Read-only access across all services"
session_duration = "PT8H"
aws_managed_policies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"]
tags = { ManagedBy = "Terraform" }
}
}

account_assignments = {
PlatformAdmins = {
principal_name = "PlatformTeam"
principal_type = "GROUP"
principal_idp = "INTERNAL"
permission_sets = ["Admin"]
account_ids = ["<MANAGEMENT_ACCOUNT_ID>"] # e.g., 111111111111
}
AuditReadOnly = {
principal_name = "AuditTeam"
principal_type = "GROUP"
principal_idp = "INTERNAL"
permission_sets = ["ReadOnly"]
account_ids = ["<MANAGEMENT_ACCOUNT_ID>"] # e.g., 111111111111
}
}
}

Multi-Account Landing Zone​

For org-level SSO with multiple accounts (enable_organizations_lookup = true). Requires AWS Organizations to be created first, then IAM Identity Center enabled via Console ("Enable with AWS Organizations"):

module "aws-iam-identity-center" {
source = "../../modules/iam-identity-center"

# Org-level: resolves account names to IDs
enable_organizations_lookup = true

sso_groups = {
LZAdministrators = {
group_name = "LZAdministrators"
group_description = "Landing Zone administrators β€” full access"
}
LZPowerUsers = {
group_name = "LZPowerUsers"
group_description = "Power users β€” deploy workloads, no IAM/billing"
}
LZReadOnly = {
group_name = "LZReadOnly"
group_description = "Read-only access for compliance and audit"
}
LZSecurityAudit = {
group_name = "LZSecurityAudit"
group_description = "Security audit β€” CloudTrail, GuardDuty, Config"
}
}

permission_sets = {
LZAdministratorAccess = {
description = "Full admin access (break-glass only)"
session_duration = "PT1H"
aws_managed_policies = ["arn:aws:iam::aws:policy/AdministratorAccess"]
tags = { ManagedBy = "Terraform", Tier = "admin" }
}
LZPowerUserAccess = {
description = "Power user β€” deploy workloads, no IAM mutation"
session_duration = "PT4H"
aws_managed_policies = ["arn:aws:iam::aws:policy/PowerUserAccess"]
tags = { ManagedBy = "Terraform", Tier = "power-user" }
}
LZReadOnlyAccess = {
description = "Read-only access for all accounts"
session_duration = "PT8H"
aws_managed_policies = ["arn:aws:iam::aws:policy/ReadOnlyAccess"]
tags = { ManagedBy = "Terraform", Tier = "read-only" }
}
}

account_assignments = {
LZAdmins_Management = {
principal_name = "LZAdministrators"
principal_type = "GROUP"
principal_idp = "INTERNAL"
permission_sets = ["LZAdministratorAccess"]
account_ids = ["111111111111"] # management account
}
LZReadOnly_AllAccounts = {
principal_name = "LZReadOnly"
principal_type = "GROUP"
principal_idp = "INTERNAL"
permission_sets = ["LZReadOnlyAccess"]
account_ids = ["111111111111", "222222222222", "333333333333"]
}
}

# ABAC: Environment-scoped access control
sso_instance_access_control_attributes = [
{
attribute_name = "Environment"
source = ["$${path:enterprise.Environment}"]
},
{
attribute_name = "CostCenter"
source = ["$${path:enterprise.CostCenter}"]
},
]
}

Deploy Commands​

# Step 1: Tier 1 snapshot tests β€” no AWS credentials required (2-3s)
task test:tier1 MODULE=iam-identity-center

# Step 2: Validate format and syntax
task build:validate

# Step 3: Deploy
terraform -chdir=projects/iam-identity-center init
terraform -chdir=projects/iam-identity-center plan
terraform -chdir=projects/iam-identity-center apply

# Step 4: Cross-validate deployed resources
# Instance: ssoins-82591e7bc2548c18 | Identity store: d-97679527f0
aws sso-admin list-permission-sets \
--instance-arn arn:aws:sso:::instance/ssoins-82591e7bc2548c18 \
--region ap-southeast-2

aws identitystore list-groups \
--identity-store-id d-97679527f0 \
--region ap-southeast-2

# Step 5: Tear down (sandbox only)
terraform -chdir=projects/iam-identity-center destroy
Setup Sequence

Standalone account: Enable IAM Identity Center via Console first, then run Terraform.

Org-level SSO: Create AWS Organization first, then enable IAM Identity Center via Console ("Enable with AWS Organizations"), then run Terraform. Reversing this order requires re-enabling Identity Center from scratch.

Configure your Identity Provider​

Terraform vs. ClickOps Boundary (Critical)​

ClickOps only (irreducible manual steps):

  1. Switch IAM Identity Center identity source from internal to external IdP (one-time AWS console operation)
  2. Complete the SAML handshake: download metadata from IdP, upload to AWS Identity Center
  3. Enable SCIM provisioning: retrieve SCIM endpoint + access token from AWS, paste into IdP

Terraform fully automates (after ClickOps steps above):

  • Groups (create in internal directory, or sync from external IdP via SCIM)
  • Permission sets (define fine-grained access policies)
  • Account assignments (bind groups + permission sets to AWS accounts)

This distinction prevents manual drift. Once SCIM is enabled, IdP users/groups automatically sync into AWS; Terraform then assigns permissions to those synced groups.

Supported IdPs & Setup Instructions​

Instructions below cover the most common identity providers. For others (CyberArk, OneLogin, Ping Identity), refer to AWS documentation for additional IdP integrations.

Internal Identity Center Directory (no external IdP): Use this if your organization does not have a centralized identity provider. Create users/groups directly in AWS Identity Center, and Terraform manages permission sets and account assignments.

Microsoft Entra ID (formerly Azure AD) is a cloud-based directory service that integrates with AWS Identity Center via SAML authentication and SCIM provisioning. Users and groups in Entra sync automatically into AWS Identity Center, where Terraform manages permission sets and account assignments.

Setup Entra AD with AWS Identity Center​

Phase 1: Enable SAML + SCIM Handshake (ClickOps Only)​

  1. In AWS Identity Center Console (ap-southeast-2)

    • Navigate to Settings β†’ Identity source β†’ Change identity source
    • Select External identity provider
    • Copy the IAM Identity Center Assertion Consumer Service (ACS) URL and issuer URL β€” you will need these in Entra
    • In the IdP SAML metadata section: you will upload Entra metadata here after exporting it
  2. In Microsoft Entra Admin Center (aad.portal.azure.com) β€” Use the Gallery App

    • Go to Enterprise Applications β†’ + New application β†’ Search the gallery
    • Search for AWS IAM Identity Center (the pre-integrated gallery app)
    • Click Create to add the app
    • The gallery app automatically populates SAML metadata and supports SCIM provisioning, which eliminates manual Identifier/ACS/metadata entry and reduces misconfiguration risk
    • Navigate to Single sign-on β†’ SAML
    • The Service provider metadata section should already contain:
      • Identifier (Entity ID): pre-populated with IAM Identity Center issuer URL
      • Reply URL (Assertion Consumer Service URL): pre-populated with IAM Identity Center ACS URL
    • Verify these values match the AWS URLs you copied in Step 1; if they differ, you may have selected a non-gallery app by mistake β€” delete it and search for AWS IAM Identity Center in the gallery again
    • Download the Federation Metadata XML from the SAML Signing Certificates section
    • Save this as entra-metadata.xml

    If the gallery app is unavailable (rare): follow the non-gallery fallback steps to manually enter Entity ID, ACS URL, and download metadata XML. However, gallery is preferred because it supports SCIM auto-provisioning of users and groups.

  3. Back in AWS Identity Center Console

    • In Change identity source β†’ Identity provider metadata: upload the entra-metadata.xml file
    • Confirm the change (type ACCEPT in the dialog)
  4. In Microsoft Entra Admin Center

    • Navigate to Users and groups β†’ + New group
    • Create groups that match your permission-set names (e.g., PlatformTeam, PowerUsers, AuditTeam, SecurityTeam)
    • Assign users to these groups
  5. Enable SCIM Provisioning in AWS Identity Center Console

    • Go to Settings β†’ Automatic provisioning β†’ Enable
    • Copy the SCIM endpoint and Access token from the dialog
    • Save these securely (1Password)
  6. In Microsoft Entra Admin Center

    • Return to AWS Identity Center application β†’ Provisioning
    • Click Get started
    • Set Provisioning Mode to Automatic
    • Under Admin Credentials:
      • Tenant URL: paste the SCIM endpoint from Step 5
      • Secret Token: paste the access token from Step 5
    • Click Test Connection β†’ verify green success message
    • Enable Provision users and Provision groups
    • Save
  7. Verify Sync

    • In AWS Identity Center Console: go to Groups and verify that Entra groups now appear with Created by: SCIM source
    • Wait 5-15 minutes for users to sync (initial sync may take longer)

Phase 2: Assign Permission Sets (Terraform)​

Once groups sync into AWS Identity Center, Terraform (infra/terraform/aws/identity/) manages permission sets and account assignments:

  1. In infra/terraform/aws/identity/config/, define account assignments that reference the synced Entra groups:

    account_assignments:
    PlatformAdmins:
    principal_name: "PlatformTeam" # Must match the Entra group name
    principal_type: "GROUP"
    principal_idp: "EXTERNAL" # External = Entra-synced group
    permission_sets:
    - "LZAdministratorAccess"
    account_ids:
    - "111111111111" # management account
  2. Run terraform plan and terraform apply in infra/terraform/aws/identity/

  3. Verify in AWS Identity Center Console: go to AWS accounts β†’ select an account β†’ Users and groups β†’ confirm that Entra groups now have permission-set assignments

Testing Access​

Verify Entra user can log in to AWS
  1. Assign an Entra user to one of your permission-set groups
  2. Wait for SCIM sync (usually instant)
  3. In AWS Identity Center: go to Settings and copy the AWS access portal URL (format: https://d-xxxxxxxxxx.awsapps.com/start)
  4. Open the URL in a private browser window
  5. You should see the Entra login page
  6. Log in with an Entra user account
  7. On successful auth, you should see the AWS access portal with available roles corresponding to the permission sets assigned to that user's groups

Learn more: AWS documentation: Use Microsoft Entra ID as an external IdP for IAM Identity Center