### Install SSOSync via Go Get Source: https://github.com/awslabs/ssosync/blob/master/README.md Use 'go get' to install the SSOSync tool. This is an alternative to downloading release binaries. ```bash go get github.com/awslabs/ssosync ``` -------------------------------- ### Setup Development Environment Source: https://github.com/awslabs/ssosync/blob/master/README.md Commands to clone the repository, install dependencies, and build the application locally. Ensure Go 1.24+ and Make are installed. ```bash # Clone repository git clone https://github.com/awslabs/ssosync.git cd ssosync/ # Install development dependencies make setup # Run tests make test # Build locally make go-build # Run with development configuration make dev ``` -------------------------------- ### Available Make Targets Source: https://github.com/awslabs/ssosync/blob/master/README.md List of available `make` commands for managing the development workflow, including setup, testing, linting, and building. ```bash make help # Show all available targets make setup # Install all dependencies make test # Run tests with coverage make test-verbose # Run tests with verbose output make test-coverage # Generate HTML coverage report make lint # Run linters make fmt # Format code make go-build # Build application make clean # Clean build artifacts make ci # Run CI pipeline (fmt, vet, test) ``` -------------------------------- ### CLI Usage Source: https://context7.com/awslabs/ssosync/llms.txt Demonstrates how to use the `ssosync` command-line interface for performing synchronization tasks, with examples of common flags and environment variable equivalents. ```APIDOC ## CLI Usage — `ssosync` command The `ssosync` binary wraps `DoSync` via a Cobra CLI. All flags have `SSOSYNC_`-prefixed environment variable equivalents, enabling configuration without exposing secrets in command history. ```bash # Basic sync — groups matching "AWS*" and their member users ./ssosync \ --google-admin admin@company.com \ --google-credentials ./credentials.json \ --endpoint "https://scim.us-east-1.amazonaws.com/.../scim/v2/" \ --access-token "AQoDYXdzEJr..." \ --region us-east-1 \ --identity-store-id d-1234567890 \ --group-match "name:AWS*" \ --sync-method groups ``` ``` -------------------------------- ### AWS SAM Deployment: App + Secrets Source: https://context7.com/awslabs/ssosync/llms.txt Build and deploy SSO Sync as an AWS Lambda function using AWS SAM for a single-account setup with the 'App + secrets' pattern. Use --guided for interactive deployment. ```bash sam build sam deploy --guided \ --stack-name ssosync \ --capabilities CAPABILITY_NAMED_IAM \ --parameter-overrides \ DeployPattern="App + secrets" \ GoogleAdminEmail="admin@company.com" \ GoogleCredentials='{"type":"service_account",...}' \ SCIMEndpointUrl="https://scim.us-east-1.amazonaws.com/.../scim/v2/" \ SCIMEndpointAccessToken="AQoDYXdzEJr..." \ Region="us-east-1" \ IdentityStoreID="d-1234567890" \ GoogleGroupMatch="name:AWS*" \ SyncMethod="groups" \ ScheduleExpression="rate(15 minutes)" \ LogLevel="warn" \ LogFormat="json" \ DryRun="live" ``` -------------------------------- ### Advanced SSOSync CLI Usage: Ignore Specific Users/Groups Source: https://github.com/awslabs/ssosync/blob/master/README.md This example shows how to synchronize all groups while excluding specific users and groups by providing their email addresses or names. ```bash # Ignore specific users/groups ./ssosync \ --group-match "*" \ --ignore-users "service@company.com,bot@company.com" \ --ignore-groups "temp-group@company.com" ``` -------------------------------- ### Manual SAM Deployment Source: https://github.com/awslabs/ssosync/blob/master/README.md Commands for deploying the SSOSync application using AWS SAM. Supports guided deployment or deployment with predefined parameters. ```bash # Build sam build # Deploy with guided setup sam deploy --guided # Or deploy with parameters sam deploy \ --stack-name ssosync \ --capabilities CAPABILITY_NAMED_IAM \ --parameter-overrides \ GoogleAdminEmail=admin@company.com \ ScheduleExpression="rate(15 minutes)" ``` -------------------------------- ### Advanced SSOSync CLI Usage: Sync Specific Groups with Dry-Run Source: https://github.com/awslabs/ssosync/blob/master/README.md This example demonstrates syncing specific groups based on name and email patterns, using a dry-run to preview changes without applying them. Debug logging is enabled. ```bash # Sync specific groups with dry-run ./ssosync \ --group-match "name:Engineering*,email:aws-*" \ --sync-method groups \ --dry-run \ --log-level debug ``` -------------------------------- ### Group Filtering Examples Source: https://github.com/awslabs/ssosync/blob/master/README.md Use the `--group-match` flag to filter which Google Groups are synced. Supports wildcard and exact matching, as well as multiple patterns. ```bash # Sync groups starting with "AWS" --group-match "name:AWS*" ``` ```bash # Sync multiple patterns --group-match "name:Admin*,email:aws-*" ``` ```bash # Sync specific group --group-match "name=Administrators" ``` ```bash # Sync all groups --group-match "*" ``` -------------------------------- ### User Filtering Examples Source: https://github.com/awslabs/ssosync/blob/master/README.md Use the `--user-match` flag to filter which Google Users are synced. Supports wildcard and exact matching, as well as complex queries combining name, email, and organization. ```bash # Sync users with specific name pattern --user-match "name:John*" ``` ```bash # Sync users with email pattern --user-match "email:admin*" ``` ```bash # Sync all users --user-match "*" ``` ```bash # Complex query --user-match "name:John*,email:admin*,orgName=Engineering" ``` -------------------------------- ### AWS SAM Deployment: Cross-Account App Source: https://context7.com/awslabs/ssosync/llms.txt Deploy the application stack in account B for a cross-account setup, using the output values from the secrets stack deployed in account A. ```bash # Step 2 — deploy app stack in account B sam deploy \ --stack-name ssosync-app \ --parameter-overrides \ DeployPattern="App for cross-account" \ CrossStackConfig="arn:aws:secretsmanager:...,arn:aws:kms:..." # from step 1 output ``` -------------------------------- ### AWS SAM Deployment: Cross-Account Secrets Source: https://context7.com/awslabs/ssosync/llms.txt Deploy the secrets stack in account A for a cross-account setup. This step outputs configuration values needed for deploying the app stack in account B. ```bash # Step 1 — deploy secrets stack in account A sam deploy \ --stack-name ssosync-secrets \ --parameter-overrides \ DeployPattern="Secrets for cross-account" \ CrossStackConfig="123456789012" \ # account B's AWS account ID [... credential params ...] # Copy "AppConfigRemote" output value ``` -------------------------------- ### Sync Google Users to AWS Identity Center Source: https://context7.com/awslabs/ssosync/llms.txt Handles the full user lifecycle: removes deleted Google users from AWS, and creates or updates active Google users in AWS. Suspended users are filtered unless SyncSuspended is enabled. Check Google service account permissions for errors getting deleted users, and SCIM endpoint/token for errors creating users. ```go syncer := internal.New(cfg, awsScimClient, googleClient, identityStoreClient) // query syntax: Google Admin SDK search — https://developers.google.com/admin-sdk/directory/v1/guides/search-users // Examples: "*", "email:admin*", "name:John*,orgName=Engineering" err := syncer.SyncUsers("*") if err != nil { // Error Getting Deleted Users — check Google service account permissions // Error creating user — check SCIM endpoint and token log.Fatal(err) } // Output (logrus structured logs): // INFO deleting google user email=departed@company.com // INFO creating user email=newjoin@company.com // DEBUG Mismatch active/suspended, updating user ``` -------------------------------- ### Initialize and Run SSO Sync Configuration Source: https://context7.com/awslabs/ssosync/llms.txt Demonstrates the main entry point `DoSync` for orchestrating the full synchronization pipeline. It initializes clients, validates connectivity, and dispatches to the selected sync method. Ensure the configuration struct is populated with valid credentials and endpoints. ```go package main import ( "context" "github.com/awslabs/ssosync/internal" "github.com/awslabs/ssosync/internal/config" ) func main() { cfg := &config.Config{ GoogleAdmin: "admin@company.com", GoogleCredentials: "./credentials.json", // path to service account JSON SCIMEndpoint: "https://scim.us-east-1.amazonaws.com/abcd1234-.../scim/v2/", SCIMAccessToken: "AQoDYXdzEJr...", Region: "us-east-1", IdentityStoreID: "d-1234567890", SyncMethod: "groups", // or "users_groups" GroupMatch: "name:AWS*", UserMatch: "", DryRun: false, LogLevel: "info", LogFormat: "text", } ctx := context.Background() if err := internal.DoSync(ctx, cfg); err != nil { // Error: problem establishing Google/AWS connection, or sync failure panic(err) } // Output: INFO Syncing AWS users and groups from Google Workspace SAML Application // INFO Test call for groups successful Groups=[...] // INFO syncing sync_method=groups // INFO sync completed } ``` -------------------------------- ### Display SSOSync CLI Help Source: https://github.com/awslabs/ssosync/blob/master/README.md Run the ssosync command with the --help flag to see all available options and commands. ```bash ./ssosync --help ``` -------------------------------- ### Basic SSOSync CLI Usage Source: https://github.com/awslabs/ssosync/blob/master/README.md Perform a basic synchronization using essential parameters like Google admin email, credentials path, SCIM endpoint, access token, region, and identity store ID. The group-match flag filters which groups to sync. ```bash ./ssosync \ --google-admin admin@company.com \ --google-credentials ./credentials.json \ --scim-endpoint https://scim.us-east-1.amazonaws.com/... \ --scim-access-token AQoDYXdzE... \ --region us-east-1 \ --identity-store-id d-1234567890 \ --group-match "name:AWS*" ``` -------------------------------- ### Configure and Validate ssosync Settings Source: https://context7.com/awslabs/ssosync/llms.txt Initialize and configure the `Config` struct for ssosync. Settings can be loaded from CLI flags, environment variables, or AWS Secrets Manager. Always validate the configuration before use. ```go import "github.com/awslabs/ssosync/internal/config" cfg := config.New() // returns defaults: LogLevel=info, LogFormat=text, SyncMethod=groups // Override with specific values cfg.GoogleAdmin = "admin@company.com" cfg.GoogleCredentials = "./credentials.json" cfg.SCIMEndpoint = "https://scim.us-east-1.amazonaws.com/.../scim/v2/" cfg.SCIMAccessToken = "AQoDYXdzEJr..." cfg.Region = "us-east-1" cfg.IdentityStoreID = "d-1234567890" cfg.SyncMethod = "groups" // "groups" or "users_groups" cfg.GroupMatch = "name:AWS*" // Google groups query; "*" = all groups cfg.UserMatch = "" // Google users query; "" = skip direct user fetch cfg.IgnoreUsers = []string{"svc-account@company.com"} cfg.IgnoreGroups = []string{"temp-group@company.com"} cfg.IncludeGroups = []string{} // only applies with users_groups method cfg.DryRun = false cfg.SyncSuspended = false // true = include suspended users cfg.PrecacheOrgUnits = []string{"/"} // nil = disable precaching; "/" = whole directory if err := cfg.Validate(); err != nil { // Returns errors for: missing GoogleAdmin, SCIMEndpoint, SCIMAccessToken, Region, // IdentityStoreID, or invalid SyncMethod value log.Fatal(err) } ``` -------------------------------- ### google.NewClient Source: https://context7.com/awslabs/ssosync/llms.txt Creates an authenticated Google Admin SDK client using a service account JSON key with domain-wide delegation. Required scopes are specified for proper authorization. ```APIDOC ## google.NewClient — Create Google Workspace Directory API client Creates an authenticated Google Admin SDK client using a service account JSON key with domain-wide delegation. Required scopes: `admin.directory.group.readonly`, `admin.directory.group.member.readonly`, `admin.directory.user.readonly`. ```go import ( "context" "os" "github.com/awslabs/ssosync/internal/google" ) ctx := context.Background() // Read service account JSON (domain-wide delegation must be configured in Google Admin) creds, err := os.ReadFile("credentials.json") if err != nil { log.Fatal(err) } googleClient, err := google.NewClient(ctx, "admin@company.com", creds) if err != nil { // Invalid credentials JSON, or missing scopes in Google Admin Console log.Fatal(err) } // Use the client: users, err := googleClient.GetUsers("name:Jane*", " isSuspended=false isArchived=false") groups, err := googleClient.GetGroups("email:aws-*") members, err := googleClient.GetGroupMembers(groups[0]) deleted, err := googleClient.GetDeletedUsers() ``` ``` -------------------------------- ### Run ssosync via CLI Source: https://context7.com/awslabs/ssosync/llms.txt Execute the ssosync binary with command-line flags. Environment variables with the `SSOSYNC_` prefix can be used as alternatives to flags. ```bash # Basic sync — groups matching "AWS*" and their member users ./ssosync \ --google-admin admin@company.com \ --google-credentials ./credentials.json \ --endpoint "https://scim.us-east-1.amazonaws.com/.../scim/v2/" \ --access-token "AQoDYXdzEJr..." \ --region us-east-1 \ --identity-store-id d-1234567890 \ --group-match "name:AWS*" \ --sync-method groups ``` -------------------------------- ### Create Google Workspace Directory API Client Source: https://context7.com/awslabs/ssosync/llms.txt Creates an authenticated Google Admin SDK client using a service account JSON key with domain-wide delegation. Requires specific scopes: admin.directory.group.readonly, admin.directory.group.member.readonly, admin.directory.user.readonly. Ensure domain-wide delegation is configured in Google Admin Console. ```go import ( "context" "os" "github.com/awslabs/ssosync/internal/google" ) ctx := context.Background() // Read service account JSON (domain-wide delegation must be configured in Google Admin) creds, err := os.ReadFile("credentials.json") if err != nil { log.Fatal(err) } googleClient, err := google.NewClient(ctx, "admin@company.com", creds) if err != nil { // Invalid credentials JSON, or missing scopes in Google Admin Console log.Fatal(err) } // Use the client: users, err := googleClient.GetUsers("name:Jane*", " isSuspended=false isArchived=false") groups, err := googleClient.GetGroups("email:aws-*") members, err := googleClient.GetGroupMembers(groups[0]) deleted, err := googleClient.GetDeletedUsers() ``` -------------------------------- ### Environment Variable Configuration Source: https://context7.com/awslabs/ssosync/llms.txt Configure SSO Sync using environment variables, which is recommended for CI/CD and Lambda deployments. The CLI tool reads these variables automatically. ```bash export SSOSYNC_GOOGLE_ADMIN="admin@company.com" export SSOSYNC_GOOGLE_CREDENTIALS="./credentials.json" export SSOSYNC_SCIM_ENDPOINT="https://scim.us-east-1.amazonaws.com/.../scim/v2/" export SSOSYNC_SCIM_ACCESS_TOKEN="AQoDYXdzEJr..." export SSOSYNC_REGION="us-east-1" export SSOSYNC_IDENTITY_STORE_ID="d-1234567890" export SSOSYNC_GROUP_MATCH="name:AWS*" export SSOSYNC_DRY_RUN="false" ./ssosync ``` -------------------------------- ### SSOSync Configuration via Environment Variables Source: https://github.com/awslabs/ssosync/blob/master/README.md Set SSOSync configuration parameters using environment variables. This is an alternative to using CLI flags. ```bash export SSOSYNC_GOOGLE_ADMIN="admin@company.com" export SSOSYNC_GOOGLE_CREDENTIALS="./credentials.json" export SSOSYNC_SCIM_ENDPOINT="https://scim.us-east-1.amazonaws.com/..." export SSOSYNC_SCIM_ACCESS_TOKEN="AQoDYXdzE..." export SSOSYNC_REGION="us-east-1" export SSOSYNC_IDENTITY_STORE_ID="d-1234567890" export SSOSYNC_GROUP_MATCH="name:AWS*" export SSOSYNC_DRY_RUN="true" ``` -------------------------------- ### View Lambda Execution Logs Source: https://context7.com/awslabs/ssosync/llms.txt Monitor the execution of the SSO Sync Lambda function by tailing its logs in CloudWatch. ```bash aws logs tail /aws/lambda/ssosync --follow ``` -------------------------------- ### Fetch Google Workspace Groups Source: https://context7.com/awslabs/ssosync/llms.txt Lists Google Workspace groups matching a query with automatic pagination. Wildcard "*" fetches all groups; comma-separated patterns are executed as separate API calls. Returns an error if the query returns zero groups. ```go // Wildcard: all groups groups, err := googleClient.GetGroups("*") ``` ```go // Name prefix pattern groups, err = googleClient.GetGroups("name:AWS*") ``` ```go // Multiple patterns (2 API calls merged) groups, err = googleClient.GetGroups("name:Admin*,email:aws-*") ``` ```go // Exact name match groups, err = googleClient.GetGroups("name=Administrators") ``` ```go for _, g := range groups { fmt.Printf("Group: %s Email: %s Members: %d\n", g.Name, g.Email, g.DirectMembersCount) } ``` ```go // Error: "google api return 0 groups?" if query matches nothing ``` -------------------------------- ### Advanced SSOSync CLI Usage: Sync All Users and Groups Source: https://github.com/awslabs/ssosync/blob/master/README.md This command synchronizes all users and groups by using wildcard matches for both user and group filtering. ```bash # Sync all users and groups ./ssosync \ --user-match "*" \ --group-match "*" \ --sync-method users_groups ``` -------------------------------- ### Dry Run with Debug Logging Source: https://context7.com/awslabs/ssosync/llms.txt Preview changes without applying them by using the --dry-run and --log-level debug flags. Logs are formatted as JSON. ```bash ./ssosync \ --google-admin admin@company.com \ --google-credentials ./credentials.json \ --endpoint "https://scim.us-east-1.amazonaws.com/.../scim/v2/" \ --access-token "AQoDYXdzEJr..." \ --region us-east-1 \ --identity-store-id d-1234567890 \ --group-match "*" \ --dry-run \ --log-level debug \ --log-format json ``` -------------------------------- ### Configuration Struct and Validation Source: https://context7.com/awslabs/ssosync/llms.txt Details the `Config` struct used for application settings, populated from various sources and validated before use. ```APIDOC ## `config.Config` — Configuration struct and validation The central configuration object populated from CLI flags, environment variables (with `SSOSYNC_` prefix), or AWS Secrets Manager (Lambda mode). All fields map to `mapstructure` tags for Viper-based binding. ```go import "github.com/awslabs/ssosync/internal/config" cfg := config.New() // returns defaults: LogLevel=info, LogFormat=text, SyncMethod=groups // Override with specific values cfg.GoogleAdmin = "admin@company.com" cfg.GoogleCredentials = "./credentials.json" cfg.SCIMEndpoint = "https://scim.us-east-1.amazonaws.com/.../scim/v2/" cfg.SCIMAccessToken = "AQoDYXdzEJr..." cfg.Region = "us-east-1" cfg.IdentityStoreID = "d-1234567890" cfg.SyncMethod = "groups" // "groups" or "users_groups" cfg.GroupMatch = "name:AWS*" // Google groups query; "*" = all groups cfg.UserMatch = "" // Google users query; "" = skip direct user fetch cfg.IgnoreUsers = []string{"svc-account@company.com"} cfg.IgnoreGroups = []string{"temp-group@company.com"} cfg.IncludeGroups = []string{} // only applies with users_groups method cfg.DryRun = false cfg.SyncSuspended = false // true = include suspended users cfg.PrecacheOrgUnits = []string{"/"} // nil = disable precaching; "/" = whole directory if err := cfg.Validate(); err != nil { // Returns errors for: missing GoogleAdmin, SCIMEndpoint, SCIMAccessToken, Region, // IdentityStoreID, or invalid SyncMethod value log.Fatal(err) } ``` ``` -------------------------------- ### Testing Commands Source: https://github.com/awslabs/ssosync/blob/master/README.md Commands for running tests, including verbose output and coverage reports. Integration tests require valid AWS credentials. ```bash # Run all tests make test # Run tests with verbose output make test-verbose # Generate coverage report make test-coverage # Run integration tests (requires valid credentials) go test -tags=integration ./internal -v ``` -------------------------------- ### Run CI Pipeline Source: https://github.com/awslabs/ssosync/blob/master/README.md Execute the continuous integration pipeline, which includes running tests and checks. This command is typically used during development to ensure code quality. ```bash make ci ``` -------------------------------- ### Sync Specific Groups and Users Source: https://context7.com/awslabs/ssosync/llms.txt Synchronize specific groups using name and email patterns, match explicit users by organization, and exclude certain users and groups. ```bash ./ssosync \ --sync-method users_groups \ --group-match "name:Admin*,email:aws-*" \ --user-match "orgName=Engineering" \ --ignore-users "svc@company.com,bot@company.com" \ --ignore-groups "temp-group@company.com" \ --include-groups "aws-admins@company.com,aws-devs@company.com" \ [... auth flags ...] ``` -------------------------------- ### Create and Manage Identity Store Groups and Memberships Source: https://context7.com/awslabs/ssosync/llms.txt Use these functions to create groups, add users to groups, and check membership status in AWS Identity Store. Ensure you have initialized the Identity Store client. ```go import ( "context" "github.com/awslabs/ssosync/internal/aws/identitystore" "github.com/aws/aws-sdk-go-v2/aws" ) ctx := context.Background() identityStoreID := "d-1234567890" groupDisplayName := "aws-admins@company.com" // Create a group output, err := identitystore.CreateGroup(ctx, identityStoreClient, aws.String(identityStoreID), aws.String(groupDisplayName), ) if err != nil { log.Fatal(err) } groupID := *output.GroupId // Add a user to the group _, err = identitystore.CreateGroupMembership(ctx, identityStoreClient, aws.String(identityStoreID), aws.String(groupID), aws.String("userId-abcd-1234"), // user's Identity Store ID ) // Check if user is already a member (avoids duplicate membership errors) isMember, err := identitystore.IsMemberInGroups(ctx, identityStoreClient, aws.String(identityStoreID), []string{groupID}, aws.String("userId-abcd-1234"), ) fmt.Printf("Is member: %v\n", *isMember) // true or false ``` -------------------------------- ### Tail CloudWatch Logs Source: https://github.com/awslabs/ssosync/blob/master/README.md Use this AWS CLI command to follow logs in real-time. Replace 'ssosync-function' with your actual Lambda function name. ```bash aws logs tail /aws/lambda/ssosync-function --follow ``` -------------------------------- ### View CloudWatch Logs Source: https://github.com/awslabs/ssosync/blob/master/README.md Use this AWS CLI command to list log groups associated with the Lambda function. Ensure the function name prefix matches your deployment. ```bash aws logs describe-log-groups --log-group-name-prefix /aws/lambda/ssosync ``` -------------------------------- ### aws.NewDryClient / aws.NewDryIdentityStore Source: https://context7.com/awslabs/ssosync/llms.txt Provides drop-in replacements for SCIM and Identity Store clients that log operations without making actual API calls, used in dry-run mode. ```APIDOC ## `aws.NewDryClient` / `aws.NewDryIdentityStore` — Dry-run mode clients Drop-in replacements for the real SCIM and Identity Store clients that log all intended operations without making actual API calls. Used when `--dry-run` flag or `DRY_RUN=true` environment variable is set. ### Usage Examples ```go // CLI: ssosync --dry-run ... // Env: DRY_RUN=true // In code (from DoSync): mkAwsScimClient := aws.NewClient if cfg.DryRun { mkAwsScimClient = aws.NewDryClient // SCIM operations become no-ops with logging } awsScimClient, _ := mkAwsScimClient(httpClient, &aws.Config{...}) if cfg.DryRun { finalIdentityStoreClient = aws.NewDryIdentityStore(identityStoreClient) // Identity Store operations (CreateGroup, DeleteUser, etc.) become no-ops } // Output when dry-run is active: // WARN This is a DRY RUN - actions will *not* be actually performed // INFO creating user email=newuser@company.com [no API call made] // WARN This was a DRY RUN - actions were *not* actually performed ``` ``` -------------------------------- ### Paginate Through Identity Store Groups and Users Source: https://context7.com/awslabs/ssosync/llms.txt Helper functions for paginating through all groups or users in an AWS Identity Store. Requires an initialized Identity Store client and a converter function to transform SDK types. ```go import ( "context" aws_identitystore "github.com/aws/aws-sdk-go-v2/service/identitystore" "github.com/awslabs/ssosync/internal/aws/identitystore" "github.com/awslabs/ssosync/internal/interfaces" identitystore_types "github.com/aws/aws-sdk-go-v2/service/identitystore/types" ) ctx := context.Background() storeID := "d-1234567890" // List all groups with pagination groups, err := identitystore.ListGroupsPager( ctx, aws_identitystore.NewListGroupsPaginator(identityStoreClient, &aws_identitystore.ListGroupsInput{IdentityStoreId: &storeID}, ), func(g identitystore_types.Group) *interfaces.Group { return internal.ConvertIdentityStoreGroupToAWSGroup(g) // returns nil for invalid groups }, ) // List all users with pagination users, err := identitystore.ListUsersPager( ctx, aws_identitystore.NewListUsersPaginator(identityStoreClient, &aws_identitystore.ListUsersInput{IdentityStoreId: &storeID}, ), internal.ConvertSdkUserObjToNative, // skips users with nil emails (AWS Control Tower users) ) fmt.Printf("Groups: %d, Users: %d\n", len(groups), len(users)) ``` -------------------------------- ### Fetch Google Workspace Users with Query Source: https://context7.com/awslabs/ssosync/llms.txt Lists active or suspended Google Workspace users matching a query. Supports multiple comma-separated query patterns executed as separate API calls and merged. Returns up to MaxRetries=5 attempts on failure. Zero-width spaces in names are normalized to regular spaces for Identity Store compatibility. ```go // query: "" returns nil (no users); "*" returns all users; comma-separated for multi-pattern // filter: appended to every sub-query — typically " isSuspended=false isArchived=false" // or " isArchived=false" when SyncSuspended=true // Sync all users users, err := googleClient.GetUsers("*", " isSuspended=false isArchived=false") // Multi-pattern query (executed as 2 separate API calls, results merged) users, err = googleClient.GetUsers("email:admin*,orgName=Engineering", " isSuspended=false isArchived=false") // Lookup by specific email (resolves aliases to primary email) users, err = googleClient.GetUsers("email=alice@company.com", " isSuspended=false isArchived=false") for _, u := range users { fmt.Printf("User: %s %s <%s> suspended=%v\n", u.Name.GivenName, u.Name.FamilyName, u.PrimaryEmail, u.Suspended) } // Note: zero-width spaces in names are normalized to regular spaces for Identity Store compatibility ``` -------------------------------- ### google.Client.GetGroups Source: https://context7.com/awslabs/ssosync/llms.txt Fetches Google Workspace groups matching a query with automatic pagination. Supports wildcard '*' for all groups and comma-separated patterns for multiple queries. Returns an error if the query returns zero groups. ```APIDOC ## `google.Client.GetGroups` — Fetch groups from Google Workspace Lists Google Workspace groups matching a query with automatic pagination. Wildcard `"*"` fetches all groups; comma-separated patterns are executed as separate API calls. Returns an error if the query returns zero groups (likely a misconfiguration). ### Usage Examples ```go // Wildcard: all groups groups, err := googleClient.GetGroups("*") // Name prefix pattern groups, err = googleClient.GetGroups("name:AWS*") // Multiple patterns (2 API calls merged) groups, err = googleClient.GetGroups("name:Admin*,email:aws-*") // Exact name match groups, err = googleClient.GetGroups("name=Administrators") for _, g := range groups { fmt.Printf("Group: %s Email: %s Members: %d\n", g.Name, g.Email, g.DirectMembersCount) } // Error: "google api return 0 groups?" if query matches nothing ``` ``` -------------------------------- ### Paginated Listing Helpers for Groups and Users Source: https://context7.com/awslabs/ssosync/llms.txt Helper functions for paginating through all groups or users in an AWS Identity Store, converting SDK types to internal objects. ```APIDOC ## `identitystore.ListGroupsPager` / `ListUsersPager` — Paginated listing helpers Paginate through all groups or users in an AWS Identity Store, converting SDK types to internal `interfaces.Group` / `interfaces.User` objects using a provided converter function. ```go import ( "context" aws_identitystore "github.com/aws/aws-sdk-go-v2/service/identitystore" "github.com/awslabs/ssosync/internal/aws/identitystore" "github.com/awslabs/ssosync/internal/interfaces" identitystore_types "github.com/aws/aws-sdk-go-v2/service/identitystore/types" ) ctx := context.Background() storeID := "d-1234567890" // List all groups with pagination groups, err := identitystore.ListGroupsPager( ctx, aws_identitystore.NewListGroupsPaginator(identityStoreClient, &aws_identitystore.ListGroupsInput{IdentityStoreId: &storeID}, ), func(g identitystore_types.Group) *interfaces.Group { return internal.ConvertIdentityStoreGroupToAWSGroup(g) // returns nil for invalid groups }, ) // List all users with pagination users, err := identitystore.ListUsersPager( ctx, aws_identitystore.NewListUsersPaginator(identityStoreClient, &aws_identitystore.ListUsersInput{IdentityStoreId: &storeID}, ), internal.ConvertSdkUserObjToNative, // skips users with nil emails (AWS Control Tower users) ) fmt.Printf("Groups: %d, Users: %d\n", len(groups), len(users)) ``` ``` -------------------------------- ### aws.NewClient Source: https://context7.com/awslabs/ssosync/llms.txt Creates an HTTP client for the AWS IAM Identity Center SCIM v2 endpoint, validating HTTPS. Used for user CRUD operations via the SCIM protocol. ```APIDOC ## `aws.NewClient` — Create AWS SCIM API client Creates an HTTP client for the AWS IAM Identity Center SCIM v2 endpoint. Validates that the endpoint URL uses HTTPS. Used for user CRUD operations via the SCIM protocol. In dry-run mode, use `aws.NewDryClient` instead. ### Usage Examples ```go import ( "net/http" "github.com/awslabs/ssosync/internal/aws" "github.com/hashicorp/go-retryablehttp" ) retryClient := retryablehttp.NewClient() retryClient.Logger = nil // suppress debug output in production httpClient := retryClient.StandardClient() scimClient, err := aws.NewClient(httpClient, &aws.Config{ Endpoint: "https://scim.us-east-1.amazonaws.com/abcd1234-ef56-7890-abcd-ef1234567890/scim/v2/", Token: "AQoDYXdzEJr...", // SCIM access token from IAM Identity Center console }) if err != nil { // "invalid URL" — endpoint must start with https:// log.Fatal(err) } // Available methods: user, err := scimClient.FindUserByEmail("alice@company.com") // ErrUserNotFound if not present user, err = scimClient.CreateUser(aws.NewUser("Alice", "Smith", "alice@company.com", true)) user, err = scimClient.UpdateUser(aws.UpdateUser(user.ID, "Alice", "Smith", "alice@company.com", false)) group, err := scimClient.FindGroupByDisplayName("aws-admins@company.com") // ErrGroupNotFound if missing ``` ``` -------------------------------- ### AWS SCIM and Identity Store Dry-Run Clients Source: https://context7.com/awslabs/ssosync/llms.txt Drop-in replacements for the real SCIM and Identity Store clients that log all intended operations without making actual API calls. Used when `--dry-run` flag or `DRY_RUN=true` environment variable is set. ```go // CLI: ssosync --dry-run ... // Env: DRY_RUN=true ``` ```go // In code (from DoSync): mkAwsScimClient := aws.NewClient if cfg.DryRun { mkAwsScimClient = aws.NewDryClient // SCIM operations become no-ops with logging } awsScimClient, _ := mkAwsScimClient(httpClient, &aws.Config{...}) ``` ```go if cfg.DryRun { finalIdentityStoreClient = aws.NewDryIdentityStore(identityStoreClient) // Identity Store operations (CreateGroup, DeleteUser, etc.) become no-ops } ``` ```go // Output when dry-run is active: // WARN This is a DRY RUN - actions will *not* be actually performed // INFO creating user email=newuser@company.com [no API call made] // WARN This was a DRY RUN - actions were *not* actually performed ``` -------------------------------- ### SyncUsers Source: https://context7.com/awslabs/ssosync/llms.txt Handles the full user lifecycle: fetches recently deleted Google users and removes them from AWS, then fetches active Google users matching the query and creates or updates them in AWS. Suspended users are filtered unless SyncSuspended is enabled. ```APIDOC ## SyncUsers — Sync individual users (groups method) Handles the full user lifecycle: fetches recently deleted Google users and removes them from AWS, then fetches active Google users matching the query and creates or updates them in AWS. Suspended users are filtered unless `SyncSuspended` is enabled. ```go syncer := internal.New(cfg, awsScimClient, googleClient, identityStoreClient) // query syntax: Google Admin SDK search — https://developers.google.com/admin-sdk/directory/v1/guides/search-users // Examples: "*", "email:admin*", "name:John*,orgName=Engineering" err := syncer.SyncUsers("*") if err != nil { // Error Getting Deleted Users — check Google service account permissions // Error creating user — check SCIM endpoint and token log.Fatal(err) } // Output (logrus structured logs): // INFO deleting google user email=departed@company.com // INFO creating user email=newjoin@company.com // DEBUG Mismatch active/suspended, updating user ``` ``` -------------------------------- ### SyncGroups Source: https://context7.com/awslabs/ssosync/llms.txt Fetches Google groups matching a query, creates missing groups in AWS Identity Center, and reconciles group membership for all previously synced users. It relies on a prior SyncUsers call to populate the user cache. ```APIDOC ## SyncGroups — Sync only groups (groups method) Fetches Google groups matching a query, creates missing groups in AWS Identity Center, and reconciles group membership for all previously synced users. Does not independently create or delete users — relies on a prior `SyncUsers` call to populate the user cache. ```go syncer := internal.New(cfg, awsScimClient, googleClient, identityStoreClient) // First sync users to populate the internal user cache err := syncer.SyncUsers("*") if err != nil { log.Fatal(err) } // Then sync groups — members are matched against the cached users err = syncer.SyncGroups("name:Admin*,email:aws-*") if err != nil { log.Fatal(err) } // For each matched Google group: // - Creates group in AWS if not found (by email address as DisplayName) // - For each cached AWS user: adds to group if Google member, removes if not // NOTE: groups are NOT deleted from AWS when removed from Google in this mode ``` ``` -------------------------------- ### Create AWS SCIM API Client Source: https://context7.com/awslabs/ssosync/llms.txt Creates an HTTP client for the AWS IAM Identity Center SCIM v2 endpoint. Validates that the endpoint URL uses HTTPS. Used for user CRUD operations via the SCIM protocol. In dry-run mode, use `aws.NewDryClient` instead. ```go import ( "net/http" "github.com/awslabs/ssosync/internal/aws" "github.com/hashicorp/go-retryablehttp" ) ``` ```go retryClient := retryablehttp.NewClient() retryClient.Logger = nil // suppress debug output in production httpClient := retryClient.StandardClient() ``` ```go scimClient, err := aws.NewClient(httpClient, &aws.Config{ Endpoint: "https://scim.us-east-1.amazonaws.com/abcd1234-ef56-7890-abcd-ef1234567890/scim/v2/", Token: "AQoDYXdzEJr...", // SCIM access token from IAM Identity Center console }) ``` ```go if err != nil { // "invalid URL" — endpoint must start with https:// log.Fatal(err) } ``` ```go // Available methods: user, err := scimClient.FindUserByEmail("alice@company.com") // ErrUserNotFound if not present user, err = scimClient.CreateUser(aws.NewUser("Alice", "Smith", "alice@company.com", true)) user, err = scimClient.UpdateUser(aws.UpdateUser(user.ID, "Alice", "Smith", "alice@company.com", false)) group, err := scimClient.FindGroupByDisplayName("aws-admins@company.com") // ErrGroupNotFound if missing ``` -------------------------------- ### Sync Google Groups to AWS Identity Center Source: https://context7.com/awslabs/ssosync/llms.txt Fetches Google groups, creates missing groups in AWS, and reconciles group membership. Relies on a prior SyncUsers call to populate the user cache. Groups are not deleted from AWS when removed from Google in this mode. ```go syncer := internal.New(cfg, awsScimClient, googleClient, identityStoreClient) // First sync users to populate the internal user cache err := syncer.SyncUsers("*") if err != nil { log.Fatal(err) } // Then sync groups — members are matched against the cached users err = syncer.SyncGroups("name:Admin*,email:aws-*") if err != nil { log.Fatal(err) } // For each matched Google group: // - Creates group in AWS if not found (by email address as DisplayName) // - For each cached AWS user: adds to group if Google member, removes if not // NOTE: groups are NOT deleted from AWS when removed from Google in this mode ``` -------------------------------- ### google.Client.GetUsers Source: https://context7.com/awslabs/ssosync/llms.txt Lists active (or suspended, if filter allows) Google Workspace users matching a query. Supports multiple comma-separated query patterns which are executed as separate API calls and merged. Returns up to `MaxRetries=5` attempts on failure. ```APIDOC ## google.Client.GetUsers — Fetch users from Google Workspace Lists active (or suspended, if filter allows) Google Workspace users matching a query. Supports multiple comma-separated query patterns which are executed as separate API calls and merged. Returns up to `MaxRetries=5` attempts on failure. ```go // query: "" returns nil (no users); "*" returns all users; comma-separated for multi-pattern // filter: appended to every sub-query — typically " isSuspended=false isArchived=false" // or " isArchived=false" when SyncSuspended=true // Sync all users users, err := googleClient.GetUsers("*", " isSuspended=false isArchived=false") // Multi-pattern query (executed as 2 separate API calls, results merged) users, err = googleClient.GetUsers("email:admin*,orgName=Engineering", " isSuspended=false isArchived=false") // Lookup by specific email (resolves aliases to primary email) users, err = googleClient.GetUsers("email=alice@company.com", " isSuspended=false isArchived=false") for _, u := range users { fmt.Printf("User: %s %s <%s> suspended=%v\n", u.Name.GivenName, u.Name.FamilyName, u.PrimaryEmail, u.Suspended) } // Note: zero-width spaces in names are normalized to regular spaces for Identity Store compatibility ``` ``` -------------------------------- ### Identity Store Group and Membership Operations Source: https://context7.com/awslabs/ssosync/llms.txt Provides functions to create and manage groups and their memberships within AWS IAM Identity Center using the Identity Store API. ```APIDOC ## `identitystore.CreateGroup` / `CreateGroupMembership` — Identity Store group operations Thin wrappers around AWS SDK v2 Identity Store API calls for group and membership management. Used internally by the sync engine when reconciling Google groups with AWS IAM Identity Center. ```go import ( "context" "github.com/awslabs/ssosync/internal/aws/identitystore" "github.com/aws/aws-sdk-go-v2/aws" ) ctx := context.Background() identityStoreID := "d-1234567890" groupDisplayName := "aws-admins@company.com" // Create a group output, err := identitystore.CreateGroup(ctx, identityStoreClient, aws.String(identityStoreID), aws.String(groupDisplayName), ) if err != nil { log.Fatal(err) } groupID := *output.GroupId // Add a user to the group _, err = identitystore.CreateGroupMembership(ctx, identityStoreClient, aws.String(identityStoreID), aws.String(groupID), aws.String("userId-abcd-1234"), // user's Identity Store ID ) // Check if user is already a member (avoids duplicate membership errors) isMember, err := identitystore.IsMemberInGroups(ctx, identityStoreClient, aws.String(identityStoreID), []string{groupID}, aws.String("userId-abcd-1234"), ) fmt.Printf("Is member: %v\n", *isMember) // true or false ``` ``` -------------------------------- ### google.Client.GetGroupMembers Source: https://context7.com/awslabs/ssosync/llms.txt Fetches all direct and derived members of a Google group. External members and users without email are filtered later by the sync engine. ```APIDOC ## `google.Client.GetGroupMembers` — Fetch members of a Google group Returns all direct and derived (nested) members of a group using `IncludeDerivedMembership(true)`. External members, users without email, and non-USER type members are later filtered by the sync engine during processing. ### Usage Examples ```go groups, _ := googleClient.GetGroups("name=AWS-Admins") members, err := googleClient.GetGroupMembers(groups[0]) if err != nil { log.Fatal(err) // retry up to MaxRetries=5 } for _, m := range members { fmt.Printf("Member: %s Type: %s Status: %s\n", m.Email, m.Type, m.Status) } // Types: USER, GROUP (nested groups are expanded due to IncludeDerivedMembership) // Status: ACTIVE, SUSPENDED, or empty (external members — skipped during sync) ``` ``` -------------------------------- ### Perform Bidirectional Sync of Groups and Users Source: https://context7.com/awslabs/ssosync/llms.txt Utilizes the `SyncGroupsUsers` method for full bidirectional reconciliation of groups and their members. This method handles nested group flattening, caching, and computes add/update/delete operations for both users and groups in AWS IAM Identity Center. Ensure `queryGroups` and `queryUsers` are appropriately filtered. ```go // internal/sync.go — called via DoSync when SyncMethod == "users_groups" (DefaultSyncMethod) // Direct usage via the SyncGSuite interface: syncer := internal.New(cfg, awsScimClient, googleClient, identityStoreClient) // queryGroups: Google groups filter — empty string skips group fetch // queryUsers: Google users filter — empty string skips direct user fetch err := syncer.SyncGroupsUsers("name:AWS*", "orgName=Engineering") if err != nil { // Handles: Google API errors, Identity Store API errors, HTTP errors log.Fatal(err) } // Process: // 1. Precache all Google groups for nested group resolution // 2. Fetch matching Google users (queryUsers) // 3. Fetch matching Google groups + their members (queryGroups), flattening nested groups // 4. List existing AWS users and groups from Identity Store // 5. Compute: addAWSUsers, delAWSUsers, updateAWSUsers from diff // 6. Compute: addAWSGroups, delAWSGroups, equalAWSGroups from diff // 7. Apply: update users → create users → create groups+members → reconcile members → delete groups → delete users ``` -------------------------------- ### Fetch Google Group Members Source: https://context7.com/awslabs/ssosync/llms.txt Returns all direct and derived members of a group using `IncludeDerivedMembership(true)`. External members, users without email, and non-USER type members are later filtered by the sync engine. ```go groups, _ := googleClient.GetGroups("name=AWS-Admins") members, err := googleClient.GetGroupMembers(groups[0]) if err != nil { log.Fatal(err) // retry up to MaxRetries=5 } ``` ```go for _, m := range members { fmt.Printf("Member: %s Type: %s Status: %s\n", m.Email, m.Type, m.Status) } ``` ```go // Types: USER, GROUP (nested groups are expanded due to IncludeDerivedMembership) // Status: ACTIVE, SUSPENDED, or empty (external members — skipped during sync) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.