# SSO Sync pushes Google Workspace users into IAM Identity Center

> ssosync is a Go CLI and Lambda function that syncs Google Workspace users and groups into AWS IAM Identity Center, with query filters, a dry-run mode and a v2.7 change that deletes and recreates users whose email addresses have been reassigned.

**awslabs/ssosync** — Populate AWS SSO directly with your G Suite users and groups using either a CLI or AWS Lambda

- Repository: https://github.com/awslabs/ssosync
- Stars: 671 · Forks: 214
- Language: Go
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/awslabs-ssosync

## The gap between Google as a directory and AWS as an identity store

AWS IAM Identity Center can hold user identities in its own identity store, or connect to an existing identity source. The README quotes the AWS SSO homepage, which names Microsoft Active Directory and Azure Active Directory as the sources it connects to, and it makes the missing piece explicit: although AWS SSO supports a subset of the SCIM protocol for populating users, that support currently covers Azure AD only. Google Workspace is not on that list, even though AWS SSO can use other identity providers such as Google Apps for Domains in other roles.

That is the problem SSO Sync exists to solve. It is a CLI tool and an AWS Lambda function that pull users and groups from Google and push them into AWS SSO, written in Go and built on AWS SDK v2. The synchronisation is uni-directional, with two sync methods, one for groups and one for users and groups together, and the project is explicit that it also removes users, so it can reflect a departure as well as a join.

The direction of the flow matters for permission, because the tool is doing something AWS will not do for you. It reads the Google directory with the Google API, using a service identity with directory read access, and it writes to the AWS side through the identitystore and ssoadmin services, which is also what lets it set group assignments rather than only create accounts.

For the operator, the appeal is that the whole pipeline fits inside an AWS account. The AWS Serverless Application Repository deployment path is listed as taking about five minutes, the CLI binary about two, and a custom AWS SAM deployment about ten. The quick-start templates are designed to be deployed with the Sync from Git option, which keeps the deployed stack in step with the repository.

## Filtering happens in the Google API query, not after the pull

The filtering model is one of the more useful things in the project, because it decides what gets copied at the source rather than discarding rows after they have been read.

Users and groups are filtered with Google API query parameters, and the README describes this as advanced filtering that is flexible enough to express conditions in the query language the Google Admin SDK already understands. The practical consequence is that a rule such as members of a particular organisational unit, or accounts outside a suspended set, is expressed once and enforced by Google on every run. Nothing has to be filtered out locally, and the dry run and the real run see the same set.

Two supporting mechanisms make that work at directory scale. The README lists support for large directories with user caching and pagination, and the dependency list backs that up: the Google API client and its OAuth2 support, the identitystore and ssoadmin services for the AWS side, and hashicorp's retryablehttp for transient failures on both ends.

The same dependency set also shows how the tool is configured. cobra provides the command line surface and viper handles configuration files, with BurntSushi's toml library for reading them, and logrus provides the structured logging with configurable levels and formats that the feature list mentions. A group and a user are separate objects in both directories, and the two sync methods differ in whether group membership is pushed alongside the group definition or resolved for each user.

One limitation is worth stating up front. Because the sync is uni-directional, a change made inside AWS Identity Center is not pushed back to Google, and the next run can overwrite it. A group membership granted by hand in the AWS console is not a lasting change, and the project does not describe a mechanism for protecting manual edits from the next sync.

## Three deployment shapes, one Go binary

The project is built so that the same code can run in three places, and the repository layout shows how.

The cmd and internal directories hold the Go program, main.go is the entry point, and the Lambda handler is built from the same tree, which the Makefile hints at with a comment that the output binary is the handler referenced in the SAR template. The template.yaml at the top level is the CloudFormation template, and the quick-start directory holds the templates the README points to for simplifying a deployment.

For the AWS Serverless Application Repository path, the README links a hands-on lab in the AWS Control Tower Workshop that walks through the complete setup for both AWS and Google Workspace using the recommended Lambda deployment. That lab is the most complete public description of the configuration, and the README also points to a workshop page for the Google Workspace side. The AWS SAM path is for teams who want to own the template, and the repository ships the SAR.md file used for the Serverless Application Repository submission.

The module definition pins the language version explicitly:

```go
module ssosync

go 1.26.9
```

and the direct dependencies are the AWS SDK v2 family, the lambda runtime, the identity store and SSO admin services, Secrets Manager with its caching client, the SSM and CodePipeline clients, the Google API client with OAuth2, cobra, viper, logrus, testify and retryablehttp.

One detail in the README deserves attention for anyone automating the deployment. Region and IdentityStoreID are no longer configurable parameters. The region is extracted programmatically from the SCIM endpoint URL, and the identity store id is resolved through the IAM Identity Center ListInstances API. The parameters are still present in template.yaml so that existing deployment tooling passing a parameter file does not break, and the README states they will be removed.

## Why v2.7 deletes a user instead of updating the external id

The most important behaviour in the project is a security fix, and it is documented at length because it changes what a sync does to existing accounts.

The scenario is a user who is deleted in Google Workspace and then recreated, so the directory user id changes while the email address stays the same. Before v2.4, the existing IAM Identity Store user had its ExternalId field updated to match the new id. Since v2.4 that update was the default behaviour, but the README warns that it is dangerous: where an email address has been reassigned to a different person, updating the ExternalId means the new person silently inherits the permission assignments that were made directly to the previous user.

From v2.7 the default behaviour changed again. Instead of updating the existing user, the tool deletes the existing user and creates a new one. The alternative behaviour is still available through the --force-externalid-update option, so an operator who prefers continuity over the safer default can ask for it explicitly.

The trade-off is real in both directions. Delete and recreate loses any direct permission assignment made to the old identity, which is the point, since inheriting somebody else's permissions is the harm being avoided. The cost is that a group assignment made directly to a user, rather than through a synced group, disappears with the account, and the referenced AWS account or permission set link has to be recreated. Groups synced from Google are unaffected, because the membership lives in Google.

The README describes the code as heavily commented, and says it gives the detail of what is going to be done. That is the first thing to read before the first non-dry run, because the difference between the two behaviours is not visible in a log line until it is too late.

## Dry run, secrets and the log stream

Three features exist to make an unattended sync safe, and they are worth setting up before the first run rather than after a mistake.

The dry-run mode tests the synchronisation without making actual changes, so the same code path that would create, update and delete accounts can be exercised against the real directory and the real AWS account with the writes suppressed. Combined with the detailed logging and the configurable levels and formats, a dry run is the closest thing to a rehearsal the tool offers.

Credentials are handled through AWS Secrets Manager, with a separate caching client in the dependency list, and the Google side uses the service account credentials for the directory API. Nothing about that is unusual, and it is the reason the Lambda deployment is the recommended production path, since the secret can be resolved at runtime without long-lived keys in the environment.

The dependency list also shows the retry and caching posture. hashicorp's retryablehttp covers transient failures against the Google API, the AWS SDK v2 clients handle their own retries, and the caching client avoids re-fetching a secret on every invocation. Pagination is handled on both the Google side, where a directory can be large, and on the AWS side, where the identity store API returns results a page at a time.

What the tool does not do is reconcile. It is a synchroniser with a defined direction, not a reconciliation engine that reports drift and asks what to do. The dry run is the mechanism for seeing the intended changes, and the README's remark that the code is heavily commented is the mechanism for understanding them.

## Release cadence, build tooling and the licence

The project is maintained with a visible release rhythm. The recent tags are v2.9.2 on 2026-10-19, v2.9.1 on 2026-10-16 and v2.9.0 on 2026-09-28, and the last push to the repository was on 2026-10-22. Patch releases appearing days apart is what you would expect from a project that ships behaviour changes like the v2.7 default, and the CHANGELOG.md at the top of the repository is the file to read before each upgrade.

The build tooling is pinned with care, which is visible in the Makefile. The development dependencies are installed into a local.bin directory at specific versions:

```make
MOCKERY_VERSION ?= v3.7.1
GOLANGCI_LINT_VERSION ?= v2.12.2
GORELEASER_VERSION ?= v2.17.0
UPX_VERSION ?= v4.2.4
```

Mockery generates the mocks for the interfaces, golangci-lint is the linter, goreleaser produces the release binaries, and UPX compresses them. The Makefile also supports a VERBOSE=1 flag that turns on verbose output for tests, builds and curl, which is a small thing that saves time when a build step fails silently. The presence of a.mockery.yml file and the testify dependency in go.mod indicates that the code is written to be unit tested against generated mocks.

The licence is Apache 2.0, with the LICENSE and NOTICE files in the repository. That is a permissive licence with an explicit patent grant, and a NOTICE file means a downstream distributor has to carry attribution for the bundled components. There is a CODE_OF_CONDUCT.md, a CONTRIBUTING.md and an SAR.md, so the project has some of the governance documents an organisation would want to see before adopting something that writes to an identity store.

The remaining caveat is scale of operation rather than of the code. A sync that deletes and recreates identities is a privileged action, and the licence says nothing about whether the person running it should.

## Conclusion

ssosync fits an organisation that has standardised on Google Workspace and wants those accounts to appear in IAM Identity Center without paying for a directory sync product, and it is the fastest route when a team already runs Lambda and Secrets Manager. It is the wrong tool if you need bidirectional change, since the sync is uni-directional, and it is the wrong tool if your identity source is Azure AD, because AWS supports SCIM for that directory natively. Before running it against a real identity store, run the dry-run mode, read the CHANGELOG entry for v2.7 and decide whether the delete and recreate default is what you want or whether --force-externalid-update is safer, and confirm that the identity store id and region resolve correctly in your account before the first real sync.

## FAQ

### What does ssosync do and which directories does it connect?

SSO Sync pulls users and groups from Google Workspace and pushes them into AWS IAM Identity Center, previously AWS SSO, using the identitystore and ssoadmin APIs. The sync is uni-directional, and the tool also removes users that no longer exist in Google.

### How do I install and run ssosync?

There are three paths. The AWS Serverless Application Repository deployment is listed as about five minutes, a CLI binary for local testing and CI/CD as about two minutes, and an AWS SAM deployment for custom setups as about ten minutes. The README also points to a hands-on lab in the AWS Control Tower Workshop that walks through the full setup for AWS and Google Workspace.

### What changed in ssosync v2.7 for users whose email was reassigned?

From v2.7 the default is to delete the existing identity store user and create a new one, because updating the ExternalId would let a new person silently inherit permissions assigned to the previous user. The old behaviour can be restored with the --force-externalid-update option, and the README recommends caution before using it.

### Can I still set the region and IdentityStoreID for ssosync?

Not as configurable parameters. The region is extracted from the SCIM endpoint URL and the identity store id is resolved through the IAM Identity Center ListInstances API. The parameters remain in template.yaml so existing deployment tooling does not break, and the README says they will be removed.

### Is there a dry run mode in ssosync?

Yes, the feature list includes a dry-run mode that tests the synchronisation without making actual changes, alongside structured logging with configurable levels and formats. Credentials for the Google side are handled through AWS Secrets Manager.

## Sources

- [awslabs/ssosync on GitHub](https://github.com/awslabs/ssosync)
- [Issues](https://github.com/awslabs/ssosync/issues)
- [License: Apache-2.0](https://github.com/awslabs/ssosync/blob/master/LICENSE)
- [README](https://github.com/awslabs/ssosync/blob/master/README.md)
- [Releases](https://github.com/awslabs/ssosync/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/awslabs-ssosync
