Automatic Provisioning of AWS IAM Identity Center Users and Groups from Google Workspace Directory using SSO Sync
Introduction
AWS IAM Identity Center supports automatic provisioning from various providers, including OneLogin, Microsoft Azure Active Directory, on-premise MS Active Directory, and other supported identity providers via the System for Cross-domain Identity Management (SCIM) implementation.
Google Workspace custom Security Assertion Markup Language (SAML) applications, on the other hand, don’t support automatic provisioning yet. On the other hand, AWS and Google are working with Fast Federation (FastFed) Working Group to make this feature available.
In the meantime, to automate the process of synchronizing users and groups from the Google Workspace Directory to the AWS IAM Identity Center, we will use the SSOSYNC project provided by AWSLABS.
In this post, we will walk you through the process of how the synchronization works and set up of SSOSYNC, running it locally for testing/debugging and deploying it as a serverless application.
Identity Synchronization Diagram
Created with mermaid.js
Google GCP, Google Workspace, and AWS IAM IC Setup
We will set up the Google GCP Service Account, Google Workspace for Domain wide delegation, and AWS IAM Identity Center SCIM Credentials as required settings and parameters for our SSO Sync.
Google GCP
First create an isolated GCP project only for AWS IAM Identity Center purpose. Then create or Enable the API Services for Admin SDK API.
Create a Project
Enable API and Services
Admin SDK API
Enable Admin SDK API
Service Account and Client ID
Create a Service Account this serves as our credentials to access the Google Workspace Directory resources.
Select Service Account Credential
Provide Service Account Credential Details
Select Service Account Create New Key
Service Account Create JSON Type Private Key
A
JSON
file will automatically be downloaded by the browser with a filename format namedaws-iam-identity-center-xxxxxx-xxxxxxxxxxxx.json
. Save it in a safe place for ourSSO Sync
CLI tool and for serverless application to log into Google.
To identify and used it easily, just rename the file
aws-iam-identity-center-xxxxxx-xxxxxxxxxxxx.json
tocredentials.json
1
mv aws-iam-identity-center-xxxxxx-xxxxxxxxxxxx.json credentials.json
Service Account Credential Client ID
Copy the 21 digit
Unique ID
this will be our Client ID
for Google Workspace Domain Wide Delegation
Google Workspace Domain Wide Delegation
Domain wide delegation settings provides a linkage from our service account to access the Google Workspace Directory based on the scopes we set, for what only the SSO Sync able to obtain.
Manage Domain Wide Delegation
Domain Wide Delegation Add Client
Add the Client ID
we copied from the Service Account
details form IAM and Admin (GCP)
and add the list of OAuth Scopes
.
1
2
3
https://www.googleapis.com/auth/admin.directory.group.readonly
https://www.googleapis.com/auth/admin.directory.group.member.readonly
https://www.googleapis.com/auth/admin.directory.user.readonly
AWS IAM Identity Center Automatic provisioning
On AWS IAM Identity Center enable the automatic provisioning to complete the coordination from Google Workspace Directory
Please take note of the SCIM credentials right after we enable them.
Enable Automatic provisioning
Automatic provisioning SCIM Configuration
Copy the details from the
SCIM endpoint
to theSSOSYNC_SCIM_ENDPOINT.txt
file and theAccess token
to theSSOSYNC_SCIM_ACCESS_TOKEN.txt
file.
Save these in a safe place for our
SSO Sync
CLI tool and for serverless application.
Setup the SSO Sync (from AWS Labs)
Clone and Build the SSO Sync from the Source Repository
AWS Labs provided the tool to complete the process, and it serves as a pipeline for users and groups from Google Workspace Directory to AWS IAM Identity Center. The project source requires building, and a compiled distributed binary is created.
Clone SSO Sync Repository
Copy the source from the AWS Github repository.
1
2
3
git clone https://github.com/awslabs/ssosync.git
cd ssosync
code .
Build the SSO Sync
Make sure you have the GO installed in your system.
If you are on macOS and want to test the applications, use this command line option to build the specific binary for macOS
1
2
GOOS=darwin GOARCH=amd64 make go-build
GOOS=darwin GOARCH=arm64 make go-build
For Linux and serverless applications, use this command line option.
1
GOOS=linux GOARCH=amd64 make go-build
Once a build is successfully run, a binary file
./ssosync
is created.
Manually Sync through CLI (Testing or Debugging)
Using environment variables, we have provided the least required parameter for our SSO Sync.
credentials.json
is a file from the Service Account Create JSON Type Private Key.SSOSYNC_SCIM_ENDPOINT.txt
andSSOSYNC_SCIM_ACCESS_TOKEN.txt
are files from the Automatic provisioning SCIM Configuration.d-xxxxxxxxxx
is theIdentity store ID
found in AWS Console > IAM Identity Center> Settings > Identity source
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SSOSYNC_LOG_LEVEL=debug
SSOSYNC_LOG_FORMAT=text
SSOSYNC_GOOGLE_CREDENTIALS=credentials.json
SSOSYNC_GOOGLE_ADMIN=[email protected]
SSOSYNC_SCIM_ENDPOINT=`cat SSOSYNC_SCIM_ENDPOINT.txt`
SSOSYNC_SCIM_ACCESS_TOKEN=`cat SSOSYNC_SCIM_ACCESS_TOKEN.txt`
SSOSYNC_REGION=us-east-1
SSOSYNC_IDENTITY_STORE_ID=d-xxxxxxxxxx
SSOSYNC_USER_MATCH=
SSOSYNC_GROUP_MATCH=
SSOSYNC_SYNC_METHOD=groups
SSOSYNC_IGNORE_GROUPS=
SSOSYNC_IGNORE_USERS=
SSOSYNC_INCLUDE_GROUPS=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
Load the environment variables on your shell session.
1
2
$ set -a && source .env && set +a
Run the SSO Sync binary
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ ./ssosync
# INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application
# INFO[0000] syncing sync_method=groups
# INFO[0000] get google groups query=
# DEBU[0001] preparing list of google users and then google groups and their members
# DEBU[0001] get group members from google group=administrator
# DEBU[0001] get users group=administrator
# DEBU[0001] get user group=administrator [email protected]
# INFO[0002] get existing aws groups
# INFO[0003] get existing aws users
# INFO[0003] get active status for aws users
# INFO[0004] preparing map of user id's to user
# DEBU[0004] preparing list of aws groups and their members
# INFO[0004] syncing changes
# DEBU[0004] deleting aws users deleted in google
# DEBU[0004] updating aws users updated in google
# DEBU[0004] creating aws users added in google
# DEBU[0004] creating aws groups added in google
# DEBU[0004] validating groups members, equals in aws and google
# DEBU[0004] finding user group=administrator [email protected]
# DEBU[0005] checking user is in group already group=administrator [email protected]
# DEBU[0005] delete aws groups deleted in google
# INFO[0005] sync completed
As you have seen, the SSO Sync STDOUT shows the expected results. Users and Groups from Google Workspace Directory sync perfectly to our AWS IAM Identity Center.
Periodically Sync through AWS SAM (Production)
Build the SAM to deployable template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ sam build
# Building codeuri: /path/to/awslabs/ssosync runtime: go1.x metadata: {} architecture: x86_64 functions: SSOSyncFunction
# Running GoModulesBuilder:Build
# Build Succeeded
# Built Artifacts : .aws-sam/build
# Built Template : .aws-sam/build/template.yaml
# Commands you can use next
# =========================
# [*] Validate SAM template: sam validate
# [*] Invoke Function: sam local invoke
# [*] Test Function in the Cloud: sam sync --stack-name --watch
# [*] Deploy: sam deploy --guided
Deploy the SSO Sync SAM Application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
$ sam deploy --guided
# Configuring SAM deploy
# ======================
# Looking for config file [samconfig.toml] : Not found
# Setting default arguments for 'sam deploy'
# =========================================
# Stack Name [sam-app]: SSOSync
# AWS Region [us-east-1]:
# Parameter ScheduleExpression [rate(15 minutes)]:
# Parameter LogLevel [warn]:
# Parameter LogFormat [json]:
# Parameter GoogleCredentials:
# Parameter GoogleAdminEmail:
# Parameter SCIMEndpointUrl:
# Parameter SCIMEndpointAccessToken:
# Parameter Region:
# Parameter IdentityStoreID:
# Parameter GoogleUserMatch []:
# Parameter GoogleGroupMatch []:
# Parameter IgnoreGroups []:
# Parameter IgnoreUsers []:
# Parameter IncludeGroups []:
# Parameter SyncMethod [groups]:
# #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
# Confirm changes before deploy [y/N]:
# #SAM needs permission to be able to create roles to connect to the resources in your template
# Allow SAM CLI IAM role creation [Y/n]:
# #Preserves the state of previously provisioned resources when an operation fails
# Disable rollback [y/N]:
# Save arguments to configuration file [Y/n]:
# SAM configuration file [samconfig.toml]:
# SAM configuration environment [default]:
# **** TRUNCATED DETAILS ****
# Deploying with following values
# ===============================
# Stack name : SSOSync
# Region : us-east-1
# Confirm changeset : False
# Disable rollback : False
# Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-*************
# Capabilities : ["CAPABILITY_IAM"]
# Parameter overrides : {"ScheduleExpression": "rate(15 minutes)", "LogLevel": "warn", "LogFormat": "json", "GoogleCredentials": "*****", "GoogleAdminEmail": "*****", "SCIMEndpointUrl": "*****", "SCIMEndpointAccessToken": "*****", "Region": "*****", "IdentityStoreID": "*****", "GoogleUserMatch": "", "GoogleGroupMatch": "", "IgnoreGroups": "", "IgnoreUsers": "", "IncludeGroups": "", "SyncMethod": "groups"}
# Signing Profiles : {}
# Initiating deployment
# =====================
# File with same data already exists at SSOSync/*************.template, skipping upload
# Waiting for changeset to be created..
# CloudFormation stack changeset
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Operation LogicalResourceId ResourceType Replacement
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# + Add AWSGoogleAdminEmail AWS::SecretsManager::Secret N/A
# + Add AWSGoogleCredentialsSecret AWS::SecretsManager::Secret N/A
# + Add AWSIdentityStoreIDSecret AWS::SecretsManager::Secret N/A
# + Add AWSRegionSecret AWS::SecretsManager::Secret N/A
# + Add AWSSCIMAccessTokenSecret AWS::SecretsManager::Secret N/A
# + Add AWSSCIMEndpointSecret AWS::SecretsManager::Secret N/A
# + Add SSOSyncFunctionRole AWS::IAM::Role N/A
# + Add SSOSyncFunctionSyncScheduledEventPermission AWS::Lambda::Permission N/A
# + Add SSOSyncFunctionSyncScheduledEvent AWS::Events::Rule N/A
# + Add SSOSyncFunction AWS::Lambda::Function N/A
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Changeset created successfully. arn:aws:cloudformation:us-east-1:*************:changeSet/samcli-deploy*************/*************
# 2023-02-13 00:52:57 - Waiting for stack create/update to complete
# CloudFormation events from stack operations (refresh every 0.5 seconds)
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSCIMEndpointSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSCIMAccessTokenSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSGoogleCredentialsSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSRegionSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSIdentityStoreIDSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSCIMEndpointSecret Resource creation Initiated
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSRegionSecret Resource creation Initiated
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSSCIMAccessTokenSecret Resource creation Initiated
# CREATE_COMPLETE AWS::SecretsManager::Secret AWSSCIMEndpointSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSIdentityStoreIDSecret Resource creation Initiated
# CREATE_COMPLETE AWS::SecretsManager::Secret AWSSCIMAccessTokenSecret -
# CREATE_IN_PROGRESS AWS::SecretsManager::Secret AWSGoogleAdminEmail Resource creation Initiated
# CREATE_COMPLETE AWS::SecretsManager::Secret AWSRegionSecret -
# CREATE_COMPLETE AWS::SecretsManager::Secret AWSIdentityStoreIDSecret -
# CREATE_COMPLETE AWS::SecretsManager::Secret AWSGoogleCredentialsSecret -
# CREATE_COMPLETE AWS::SecretsManager::Secret AWSGoogleAdminEmail -
# CREATE_IN_PROGRESS AWS::IAM::Role SSOSyncFunctionRole -
# CREATE_IN_PROGRESS AWS::IAM::Role SSOSyncFunctionRole Resource creation Initiated
# CREATE_COMPLETE AWS::IAM::Role SSOSyncFunctionRole -
# CREATE_IN_PROGRESS AWS::Lambda::Function SSOSyncFunction -
# CREATE_IN_PROGRESS AWS::Lambda::Function SSOSyncFunction Resource creation Initiated
# CREATE_COMPLETE AWS::Lambda::Function SSOSyncFunction -
# CREATE_IN_PROGRESS AWS::Events::Rule SSOSyncFunctionSyncScheduledEvent -
# CREATE_IN_PROGRESS AWS::Events::Rule SSOSyncFunctionSyncScheduledEvent Resource creation Initiated
# CREATE_COMPLETE AWS::Events::Rule SSOSyncFunctionSyncScheduledEvent -
# CREATE_IN_PROGRESS AWS::Lambda::Permission SSOSyncFunctionSyncScheduledEventPermission -
# CREATE_IN_PROGRESS AWS::Lambda::Permission SSOSyncFunctionSyncScheduledEventPermission Resource creation Initiated
# CREATE_COMPLETE AWS::Lambda::Permission SSOSyncFunctionSyncScheduledEventPermission -
# CREATE_COMPLETE AWS::CloudFormation::Stack SSOSync -
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Successfully created/updated stack - SSOSync in us-east-1
Test the SSOSync
Lambda Application (Lambda Function Stack)
Testing locally if deployed parameters are properly configured.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ echo '{}' | sam local invoke --event - "SSOSyncFunction"
# Reading invoke payload from stdin (you can also pass it from file with --event)
# Invoking dist/ssosync_linux_amd64_v1/ssosync (go1.x)
# Local image was not found.
# Removing rapid images for repo public.ecr.aws/sam/emulation-go1.x
# Building image.............................................................
# Using local image: public.ecr.aws/lambda/go:1-rapid-x86_64.
# Mounting /path/to/awslabs/ssosync/.aws-sam/build/SSOSyncFunction as /var/task:ro,delegated inside runtime container
# START RequestId: **************************** Version: $LATEST
# time="2023-02-12T17:39:35Z" level=info msg="Executing as Lambda"
# time="2023-02-12T17:39:38Z" level=info msg="Syncing AWS users and groups from Google Workspace SAML Application"
# time="2023-02-12T17:39:38Z" level=info msg=syncing sync_method=groups
# time="2023-02-12T17:39:38Z" level=info msg="get google groups" query=
# time="2023-02-12T17:39:39Z" level=debug msg="preparing list of google users and then google groups and their members"
# time="2023-02-12T17:39:39Z" level=debug msg="get group members from google" group=administrator
# time="2023-02-12T17:39:39Z" level=debug msg="get users" group=administrator
# time="2023-02-12T17:39:39Z" level=debug msg="get user" group=administrator [email protected]
# time="2023-02-12T17:39:40Z" level=info msg="get existing aws groups"
# time="2023-02-12T17:39:41Z" level=info msg="get existing aws users"
# time="2023-02-12T17:39:42Z" level=info msg="get active status for aws users"
# time="2023-02-12T17:39:43Z" level=info msg="preparing map of user id's to user"
# time="2023-02-12T17:39:43Z" level=debug msg="preparing list of aws groups and their members"
# time="2023-02-12T17:39:43Z" level=info msg="syncing changes"
# time="2023-02-12T17:39:43Z" level=debug msg="deleting aws users deleted in google"
# time="2023-02-12T17:39:43Z" level=debug msg="updating aws users updated in google"
# time="2023-02-12T17:39:43Z" level=debug msg="creating aws users added in google"
# time="2023-02-12T17:39:43Z" level=debug msg="creating aws groups added in google"
# time="2023-02-12T17:39:43Z" level=debug msg="validating groups members, equals in aws and google"
# time="2023-02-12T17:39:43Z" level=debug msg="finding user" group=administrator [email protected]
# time="2023-02-12T17:39:44Z" level=debug msg="checking user is in group already" group=administrator [email protected]
# time="2023-02-12T17:39:44Z" level=debug msg="delete aws groups deleted in google"
# time="2023-02-12T17:39:44Z" level=info msg="sync completed"
# "Success"END RequestId: ****************************
# REPORT RequestId: **************************** Init Duration: 0.16 ms Duration: 8748.82 ms Billed Duration: 8749 ms Memory Size: 128 MB Max Memory Used: 128 MB
Test the production deployed Lambda Application and check the rest of the events in the AWS Cloudwatch log groups application streams.
1
2
3
4
5
6
7
8
9
$ aws lambda invoke --function-name SSOSync-SSOSyncFunction-************ --payload '{}' response.json
# {
# "StatusCode": 200,
# "ExecutedVersion": "$LATEST"
# }
# $ cat response.json
# "Success"
Let the Lambda Application
and its EventBridge
periodic settings execute the syncing from the Google Workspace Directory to AWS IAM Identity Center do the rest.
Other Deployment Options
You can also deploy the SSO Sync Lambda Application through AWS Console using the AWS Serverless Application Repository. Just fill in the required parameters and deploy. Then Wait for the AWS Cloudformation to automate the deployment process.