SSO and Identity Center
Identity and access management are critical foundations of any AWS environment. In the Lab, I immediately implement AWS Identity Center (SSO) to give secure, scalable, and centralised control over access to all accounts in the organisation.
Why Identity Center?
Setting up SSO lets us:
- Centrally manage who has access to what
- Assign fine-grained permissions across environments
- Automate CLI and tool-based access using secure tokens
- Support team workflows like DevOps, networking, and data with the right level of control
This isn’t just about security. Proper configuration allows us to move quickly and safely by using the right tools for the job. In an enterprise environment, where you're operating in a growing environment and onboarding new users, it's paramount to have a clean identity model that makes it easy to scale and maintain.
How it works
With this setup:
- Manage users by group
- Assign broad permissions using managed policies
- Define per-account overrides via custom IAM policies
- You get automatic token vending for CLI and tool access
It scales cleanly and works for everything from sandbox accounts with near-full access to production accounts requiring strict control.
How it's built
In this example, we have the root account, where IAM Identity Center is configured, and a second account, let's call it 'Sandbox,' where we are provisioning access for users to work.
We define two layers of configuration using YAML files in our public repo:
1. Root Account – Org-Level Configuration
This file sets up:
- Groups like DevOpsTeam, NetworkAdmins, DataEngineers
- Permission Sets that include AWS-managed policies (e.g., AmazonEC2FullAccess)
- Custom policy hooks that will enable per-account policies that give us control based on the account usage, e.g. nonprod vs. production
This gives us a consistent, organisation-wide way to manage access while allowing exceptions for specific accounts.
1AWSTemplateFormatVersion: "2010-09-09"2Metadata:3 Author: "ChrisMail"4Description: "Created during the initial formation of the Labs environment"56Parameters:7 SsoInstanceId:8 Type: String9 Description: "The SSO instance id - looks like ssoins-a1a1a1a1a1a1a1a1a"1011 SsoIdentityStoreId:12 Type: String13 Description: "The SSO identity store - looks like d-a1a1a1a1a1"1415 WorkloadName:16 Type: String17 Default: "Labs"18 Description: "The workload name"1920Resources:21 ######################################################################################################22 ################## Labs Network Administrator23 SSOGroupNetworkAdmin:24 Type: AWS::IdentityStore::Group25 Properties:26 Description: !Sub "${WorkloadName} Network Administratiors"27 DisplayName: !Sub "${WorkloadName}.NetworkAdministrator"28 IdentityStoreId: !Sub "${SsoIdentityStoreId}"2930 SSOPermissionSetNetworkAdmin:31 Type: "AWS::SSO::PermissionSet"32 Properties:33 Name: !Sub "${WorkloadName}.NetworkAdministrator"34 Description: "Provides access to the AWS VPC and Cloudformation services"35 SessionDuration: "PT1H"36 InstanceArn: !Sub "arn:${AWS::Partition}:sso:::instance/${SsoInstanceId}"37 ManagedPolicies:38 - !Sub "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess"39 - !Sub "arn:${AWS::Partition}:iam::aws:policy/AmazonVPCFullAccess"40 - !Sub "arn:${AWS::Partition}:iam::aws:policy/AWSCloudFormationFullAccess"41 - !Sub "arn:${AWS::Partition}:iam::aws:policy/AWSResourceAccessManagerFullAccess"42 CustomerManagedPolicyReferences:43 - Name: !Sub "${WorkloadName}.NetworkAdministrator"44 Path: "/SSO/"4546 IAMPolicyNetworkAdministrator:47 Type: "AWS::IAM::ManagedPolicy"48 Properties:49 ManagedPolicyName: !Sub "${WorkloadName}.NetworkAdministrator"50 Path: "/SSO/"51 PolicyDocument:52 Version: "2012-10-17"53 Statement:54 - Sid: "BenignPermForCreate"55 Effect: Allow56 Action:57 - iam:GetPolicy58 Resource:59 - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/SSO/*6061 ######################################################################################################62 ################## ScyneLabs DevOpsTeam63 SSOGroupDevOpsEngineer:64 Type: AWS::IdentityStore::Group65 Properties:66 Description: !Sub "${WorkloadName} DevOps Team"67 DisplayName: !Sub "${WorkloadName}.DevOpsEngineer"68 IdentityStoreId: !Sub "${SsoIdentityStoreId}"6970 SSOPermissionSetDevOpsEngineer:71 Type: "AWS::SSO::PermissionSet"72 Properties:73 Name: !Sub "${WorkloadName}.DevOpsEngineer"74 Description: "Provides access to the AWS VPC and Cloudformation services"75 SessionDuration: "PT1H"76 InstanceArn: !Sub "arn:${AWS::Partition}:sso:::instance/${SsoInstanceId}"77 ManagedPolicies:78 - !Sub "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess"79 CustomerManagedPolicyReferences:80 - Name: !Sub "${WorkloadName}.DevOpsEngineer"81 Path: "/SSO/"8283 IAMPolicyDevOpsEngineer:84 Type: "AWS::IAM::ManagedPolicy"85 Properties:86 ManagedPolicyName: !Sub "${WorkloadName}.DevOpsEngineer"87 Path: "/SSO/"88 PolicyDocument:89 Version: "2012-10-17"90 Statement:91 - Sid: "BenignPermForCreate"92 Effect: Allow93 Action:94 - iam:GetPolicy95 Resource:96 - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/SSO/*"9798 ######################################################################################################99 ################## ScyneLabs BillingTeam100 SSOGroupBilling:101 Type: AWS::IdentityStore::Group102 Properties:103 Description: !Sub "${WorkloadName} Billing"104 DisplayName: !Sub "${WorkloadName}.Billing"105 IdentityStoreId: !Sub "${SsoIdentityStoreId}"106107 SSOPermissionSetBilling:108 Type: "AWS::SSO::PermissionSet"109 Properties:110 Name: !Sub "${WorkloadName}.Billing"111 Description: "Provides access to the AWS billing and admin"112 SessionDuration: "PT1H"113 InstanceArn: !Sub "arn:${AWS::Partition}:sso:::instance/${SsoInstanceId}"114 ManagedPolicies:115 - !Sub "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess"116 - !Sub "arn:${AWS::Partition}:iam::aws:policy/job-function/Billing"117 CustomerManagedPolicyReferences:118 - Name: !Sub "${WorkloadName}.Billing"119 Path: "/SSO/"120121 IAMPolicyBilling:122 Type: "AWS::IAM::ManagedPolicy"123 Properties:124 ManagedPolicyName: !Sub "${WorkloadName}.Billing"125 Path: "/SSO/"126 PolicyDocument:127 Version: "2012-10-17"128 Statement:129 - Sid: "BenignPermForCreate"130 Effect: Allow131 Action:132 - iam:GetPolicy133 Resource:134 - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/SSO/*135136137 ######################################################################################################138 ################## ScyneLabs ReadOnly - Good for things like former2 and other third party tools139 SSOReadOnly:140 Type: AWS::IdentityStore::Group141 Properties:142 Description: !Sub "${WorkloadName} ReadOnly"143 DisplayName: !Sub "${WorkloadName}.ReadOnly"144 IdentityStoreId: !Sub "${SsoIdentityStoreId}"
2. Sandbox Account – Account-Specific Policies
We define any custom policies used by the org-level setup in each account.
Note: The custom policy name and path must exactly match what’s declared in the root account file.
1AWSTemplateFormatVersion: "2010-09-09"2Metadata:3 Author: "ChrisMail"4Description: "Created during the initial formation of the Labs environment"56Parameters:7 WorkloadName:8 Type: String9 Default: "Labs"10 Description: "The workload name"1112Resources:13 ######################################################################################################14 ################## DevOps Engineer15 IAMPolicyLabsDevOpsEngineer:16 Type: "AWS::IAM::ManagedPolicy"17 Properties:18 ManagedPolicyName: !Sub "${WorkloadName}.DevOpsEngineer"19 Path: "/SSO/"20 PolicyDocument:21 Version: "2012-10-17"22 Statement:23 - Sid: "FoundationProtection"24 Effect: Deny25 Action:26 - iam:create*27 - iam:update*28 - iam:delete*29 - lambda:*30 - cloudformation:create*31 - cloudformation:delete*32 - cloudformation:update*33 Resource:34 - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/SSO/*"35 - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:aws-controltower-*"36 - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/StackSet-AWSControlTower*"37 - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/SSO-*"38 - Sid: "DevOpsEngineer"39 Effect: Allow40 Action:41 - SomeApiAccessTo42 Resource: "SomeNamedResources"4344 ######################################################################################################45 ################## DevOps Engineer46 IAMPolicyLabsNetworkAdmin:47 Type: "AWS::IAM::ManagedPolicy"48 Properties:49 ManagedPolicyName: !Sub "${WorkloadName}.NetworkAdministrator"50 Path: "/SSO/"51 PolicyDocument:52 Version: "2012-10-17"53 Statement:54 - Sid: "FoundationProtection"55 Effect: Deny56 Action:57 - iam:create*58 - iam:update*59 - iam:delete*60 - lambda:*61 - cloudformation:create*62 - cloudformation:delete*63 - cloudformation:update*64 Resource:65 - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/SSO/*"66 - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:aws-controltower-*"67 - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/StackSet-AWSControlTower*"68 - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/SSO-*"69 - Sid: "VpcAdmin"70 Effect: Allow71 Action:72 - SomeApiAccessTo73 Resource: "SomeNamedResources"74
3. Account Assignments – Hooking It All Together
Once groups and permission sets are defined, we attach accounts to the groups by:
- Selecting which permission set the group should use in that account
- Letting AWS Identity Center do the magic of provisioning roles, trust relationships, and session access
This is where the environment-level granularity comes in:
- The same group (DevOpsTeam) might get admin access in NonProd, but read-only or limited custom access in Prod.
4. How to Use the CLI with SSO
Once Identity Center is set up, using the AWS CLI becomes secure and straightforward - no more juggling long-lived access keys or copy and pasting from the portal.
Step 1: Configure Your Profile
Add a profile to your ~/.aws/config file like this but with the details for your environment:
1[default]2output = json3region = ap-southeast-245[sso-session labsso]6sso_start_url = https://your-sso-portal.awsapps.com/start7sso_region = ap-southeast-28sso_registration_scopes = sso:account:access910[profile Sandbox_DevOpsEngineer]11sso_session = labsso12sso_account_id = 12345678912313sso_role_name = Labs.DevOpsEngineer1415[profile Sandbox_NetworkAdministrator]16sso_session = labsso17sso_account_id = 12345678912318sso_role_name = Labs.NetworkAdministrator
Step 2: Authenticate with SSO
1aws sso login --sso-session labsso
Step 3: Use the CLI Normally
1aws s3 ls --profile "Sandbox_DevOpsEngineer"