Code Monkey home page Code Monkey logo

ssosync's Introduction

SSO Sync

Github Action gopherbadger-tag-do-not-edit Go Report Card License Apache 2 Taylor Swift

Helping you populate AWS SSO directly with your Google Apps users

SSO Sync will run on any platform that Go can build for. It is available in the AWS Serverless Application Repository

Caution

When using ssosync with an instance of IAM Identity Center integrated with AWS Control Tower. AWS Control Tower creates a number of groups and users (directly via the Identity Store API), when an external identity provider is configured these users and groups are can not be used to log in. However it is important to remember that because ssosync implemements a uni-directional sync it will make the IAM Identity Store match the subset of your Google Workspaces directory you specify, including removing these groups and users created by AWS Control Tower. There is a PFR #179 Configurable handling of 'manually created' Users/Groups in IAM Identity Center to implement an option to ignore these users and groups, hopefully this will be implemented in version 3.x. However, this has a dependancy on PFR #166 Ensure all groups/user creates in IAM Identity Store are via SCIM api and populate externalId field, to be able to reliably and consistently disinguish between SCIM Provisioned users from Manually Created users

Warning

There are breaking changes for versions >= 0.02

Warning

>= 1.0.0-rc.5 groups to do not get deleted in AWS SSO when deleted in the Google Directory, and groups are synced by their email address

Warning

>= 2.0.0 this makes use of the Identity Store API which means:

Warning

>= 2.1.0 make use of named IAM resources, so if deploying via CICD or IaC template will require CAPABILITY_NAMED_IAM to be specified.

Important

>= 2.1.0 switched to using provided.al2 powered by ARM64 instances.

Important

As of v2.2.0 multiple query patterns are supported for both Group and User matching, simply separate each query with a ,. For full sync of groups and/or users specify '*' in the relevant match field. User match and group match can now be used in combination with the sync method of groups. Nested groups will now be flattened into the top level groups. External users are ignored. Group owners are treated as regular group members. User details are now cached to reduce the number of api calls and improve execution times on large directories.

Why?

As per the AWS SSO Homepage:

AWS Single Sign-On (SSO) makes it easy to centrally manage access to multiple AWS accounts and business applications and provide users with single sign-on access to all their assigned accounts and applications from one place.

Key part further down:

With AWS SSO, you can create and manage user identities in AWS SSO’s identity store, or easily connect to your existing identity source including Microsoft Active Directory and Azure Active Directory (Azure AD).

AWS SSO can use other Identity Providers as well... such as Google Apps for Domains. Although AWS SSO supports a subset of the SCIM protocol for populating users, it currently only has support for Azure AD.

This project provides a CLI tool to pull users and groups from Google and push them into AWS SSO. ssosync deals with removing users as well. The heavily commented code provides you with the detail of what it is going to do.

References

Installation

The recommended installation is:

You can also: You can go get github.com/awslabs/ssosync or grab a Release binary from the release page. The binary can be used from your local computer, or you can deploy to AWS Lambda to run on a CloudWatch Event for regular synchronization.

Configuration

You need a few items of configuration. One side from AWS, and the other from Google Cloud to allow for API access to each. You should have configured Google as your Identity Provider for AWS SSO already.

You will need the files produced by these steps for AWS Lambda deployment as well as locally running the ssosync tool.

Google

First, you have to setup your API. In the project you want to use go to the Console and select API & Services > Enable APIs and Services. Search for Admin SDK and Enable the API.

You have to perform this tutorial to create a service account that you use to sync your users. Save the JSON file you create during the process and rename it to credentials.json.

you can also use the --google-credentials parameter to explicitly specify the file with the service credentials. Please, keep this file safe, or store it in the AWS Secrets Manager

In the domain-wide delegation for the Admin API, you have to specify the following scopes for the user.

Back in the Console go to the Dashboard for the API & Services and select "Enable API and Services". In the Search box type Admin and select the Admin SDK option. Click the Enable button.

You will have to specify the email address of an admin via --google-admin to assume this users role in the Directory.

AWS

Go to the AWS Single Sign-On console in the region you have set up AWS SSO and select Settings. Click Enable automatic provisioning.

A pop up will appear with URL and the Access Token. The Access Token will only appear at this stage. You want to copy both of these as a parameter to the ssosync command.

Or you specific these as environment variables.

SSOSYNC_SCIM_ACCESS_TOKEN=<YOUR_TOKEN>
SSOSYNC_SCIM_ENDPOINT=<YOUR_ENDPOINT>

Additionally, authenticate your AWS credentials. Follow this section to create a Shared Credentials File in the home directory or export your Credentials with Environment Variables. Ensure that the default credentials are for the AWS account you intended to be synced.

To obtain your Identity store ID, go to the AWS Identity Center console and select settings. Under the Identity Source section, copy the Identity store ID.

Local Usage

git clone https://github.com/awslabs/ssosync.git
cd ssosync/
make go-build
./ssosync --help
A command line tool to enable you to synchronise your Google
Apps (Google Workspace) users to AWS Single Sign-on (AWS SSO)
Complete documentation is available at https://github.com/awslabs/ssosync

Usage:
  ssosync [flags]

Flags:
  -t, --access-token string         AWS SSO SCIM API Access Token
  -d, --debug                       enable verbose / debug logging
  -e, --endpoint string             AWS SSO SCIM API Endpoint
  -u, --google-admin string         Google Workspace admin user email
  -c, --google-credentials string   path to Google Workspace credentials file (default "credentials.json")
  -g, --group-match string          Google Workspace Groups filter query parameter, a simple '*' denotes sync all groups (and any users that are members of those groups). example: 'name:Admin*,email:aws-*', 'name=Admins' or '*' see: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups, if left empty no groups will be selected.
  -h, --help                        help for ssosync
      --ignore-groups strings       ignores these Google Workspace groups
      --ignore-users strings        ignores these Google Workspace users
      --include-groups strings      include only these Google Workspace groups, NOTE: only works when --sync-method 'users_groups'
      --log-format string           log format (default "text")
      --log-level string            log level (default "info")
  -s, --sync-method string          Sync method to use (users_groups|groups) (default "groups")
  -m, --user-match string           Google Workspace Users filter query parameter, a simple '*' denotes sync all users in the directory. example: 'name:John*,email:admin*', '*' or name=John Doe,email:admin*' see: https://developers.google.com/admin-sdk/directory/v1/guides/search-users, if left empty no users will be selected but if a pattern has been set for GroupMatch users that are members of the groups it matches will still be selected
  -v, --version                     version for ssosync
  -r, --region                      AWS region where identity store exists
  -i, --identity-store-id           AWS Identity Store ID

The function has two behaviour and these are controlled by the --sync-method flag, this behavior could be

  1. groups: (default) The sync procedure work base on Groups, gets the Google Workspace groups and their members, then creates in AWS SSO the users (members of the Google Workspace groups), then the groups and at the end assign the users to their respective groups.
  2. users_groups: (original behavior, previous versions) The sync procedure is simple, gets the Google Workspace users and creates these in AWS SSO Users; then gets Google Workspace groups and creates these in AWS SSO Groups and assigns users to belong to the AWS SSO Groups.

Flags Notes:

Note

  1. Depending on the number of users and groups you have, maybe you can get AWS SSO SCIM API rate limits errors, and more frequently happens if you execute the sync many times in a short time.
  2. Depending on the number of users and groups you have, --debug flag generate too much logs lines in your AWS Lambda function. So test it in locally with the --debug flag enabled and disable it when you use a AWS Lambda function.

AWS Lambda Usage

Tip

Using Lambda may incur costs in your AWS account. Please make sure you have checked the pricing for AWS Lambda and CloudWatch before continuing.

Additionally, before choosing to deploy with Lambda, please ensure that the AWS Lambda SLAs are sufficient for your use cases.

Running ssosync once means that any changes to your Google directory will not appear in AWS SSO. To sync regularly, you can run ssosync via AWS Lambda.

Warning

You find it in the AWS Serverless Application Repository.

Tip

v2.1 Changes

  • user and group selection fields in the Cloudformation template can now be left empty where not required and will not be added as environment variables to the Lambda function, this provides consistency with CLI use of ssosync.
  • Stronger validation of parameters in the Cloudformation template, to improve likelhood of success for new users.
  • Now supports multiple deployment patterns, defaults are consistent with previous versions.

App + secrets This is the default mode and fully backwards compatible with previous versions

App only This mode does not create the secrets but expects you to deployed a separate stack using the Secrets only mode within the same account

Caution

If you want to use your own existing secrets then provide them as a comma separated list in the ##CrossStackConfigI## field in the following order: GoogleCredentials ARN,GoogleAdminEmail ARN,SCIMEndpoint ARN,SCIMAccessToken ARN,Region ARN,IdentityStoreID ARN

App for cross-account This mode is used where you have deployed the secrets in a separate account, the arns of the KMS key and secrets need to be passed into the CrossStackConfig field, It is easiest to have created the secrets in the other account using the ** Secrest for cross-account** mode, as the output can simply copied and pasted into the above field.

Caution

If you want to use your own existing secrets then provide them as a comma separated list in the CrossStackConfig field in the following order: GoogleCredentials ARN,GoogleAdminEmail ARN,SCIMEndpoint ARN,SCIMAccessToken ARN,Region ARN,IdentityStoreID ARN,KMS Key ARN

Important

Be sure to allow access to the key and secrets in their respective policies to the role SSOSyncAppRole in the app account.

Secrets only This mode creates a set of secrets but does not deploy the app itself, it requires the app is deployed in that same account using the App only mode. This allows for decoupling of the secrets and the app.

Secrets for cross-account This mode creates a set of secrets and KMS key but does not deploy the app itself, this is for use with an app stack, deployed using the App for cross-account mode. This allows for a single set of secrets to be shared with multipl app instance for testing, and improve secrets security.

SAM

You can use the AWS Serverless Application Model (SAM) to deploy this to your account.

Please, install the AWS SAM CLI and GoReleaser.

Specify an Amazon S3 Bucket for the upload with export S3_BUCKET=<YOUR_BUCKET> and an S3 prefix with export S3_PREFIX=<YOUR_PREFIX>.

Execute make package in the console. Which will package and upload the function to the bucket. You can then use the packaged.yaml to configure and deploy the stack in AWS CloudFormation Console.

Example

Build

aws cloudformation validate-template --template-body  file://template.yaml 1>/dev/null &&
sam validate &&
sam build

Deploy

sam deploy --guided

License

Apache-2.0

ssosync's People

Contributors

amazon-auto avatar chris-bateman avatar chrispates avatar christiangda avatar cmbrehm avatar da3mon-01 avatar dependabot[bot] avatar dermah avatar fredericbarthelet avatar grugnog avatar hristo-ganekov-sumup avatar jferris avatar johnkeates avatar joshloke avatar joshuachong avatar jverhoeks avatar katallaxie avatar leepa avatar midu-git avatar mike-carey avatar nason avatar tim-hutchinson avatar troyready avatar waigel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ssosync's Issues

Error when syncing groups that contain external users

Describe the bug
When syncing a group that contains external users, an exception is thrown

To Reproduce
Steps to reproduce the behavior:

  1. Create a Google Group that has a mix of internal and external users (i.e., a slack channel)
  2. Run the code
  3. See error
START RequestId: 7178a6cd-fde1-4e96-9269-0836561644e0 Version: $LATEST
time="2021-08-11T17:49:12Z" level=info msg="Syncing AWS users and groups from Google Workspace SAML Application"
time="2021-08-11T17:49:12Z" level=info msg=syncing sync_method=groups
time="2021-08-11T17:49:12Z" level=debug msg="get google groups" query="name:AWS-*"
time="2021-08-11T17:49:12Z" level=debug msg="get google users and groups and its users"
time="2021-08-11T17:49:12Z" level=debug msg="get group members from google" group=AWS-SSO-BillingAdmin
time="2021-08-11T17:49:12Z" level=debug msg="get users" group=AWS-SSO-BillingAdmin
time="2021-08-11T17:49:12Z" level=debug msg="get user" group=AWS-SSO-BillingAdmin [email protected]
time="2021-08-11T17:49:13Z" level=debug msg="get group members from google" group=AWS
time="2021-08-11T17:49:13Z" level=debug msg="get users" group=AWS
time="2021-08-11T17:49:13Z" level=debug msg="get user" group=AWS [email protected]
time="2021-08-11T17:49:13Z" level=debug msg="get user" group=AWS [email protected]
time="2021-08-11T17:49:13Z" level=debug msg="get user" group=AWS [email protected]
runtime error: index out of range [0] with length 0: boundsError
[{"path":"github.com/aws/[email protected]/lambda/errors.go","line":39,"label":"lambdaPanicResponse"},{"path":"github.com/aws/[email protected]/lambda/function.go","line":36,"label":"(*Function).Invoke.func1"},{"path":"runtime/panic.go","line":965,"label":"gopanic"},{"path":"runtime/panic.go","line":88,"label":"goPanicIndex"},{"path":"work/ssosync/ssosync/internal/sync.go","line":490,"label":"(*syncGSuite).getGoogleGroupsAndUsers"},{"path":"work/ssosync/ssosync/internal/sync.go","line":279,"label":"(*syncGSuite).SyncGroupsUsers"},{"path":"work/ssosync/ssosync/internal/sync.go","line":685,"label":"DoSync"},{"path":"work/ssosync/ssosync/cmd/root.go","line":55,"label":"glob..func1"},{"path":"github.com/spf13/[email protected]/command.go","line":852,"label":"(*Command).execute"},{"path":"github.com/spf13/[email protected]/command.go","line":960,"label":"(*Command).ExecuteC"},{"path":"github.com/spf13/[email protected]/command.go","line":897,"label":"(*Command).Execute"},{"path":"reflect/value.go","line":476,"label":"Value.call"},{"path":"reflect/value.go","line":337,"label":"Value.Call"},{"path":"github.com/aws/[email protected]/lambda/handler.go","line":124,"label":"NewHandler.func1"},{"path":"github.com/aws/[email protected]/lambda/handler.go","line":24,"label":"lambdaHandler.Invoke"},{"path":"github.com/aws/[email protected]/lambda/function.go","line":64,"label":"(*Function).Invoke"},{"path":"reflect/value.go","line":476,"label":"Value.call"},{"path":"reflect/value.go","line":337,"label":"Value.Call"},{"path":"net/rpc/server.go","line":377,"label":"(*service).call"},{"path":"runtime/asm_amd64.s","line":1371,"label":"goexit"}]
END RequestId: 7178a6cd-fde1-4e96-9269-0836561644e0
REPORT RequestId: 7178a6cd-fde1-4e96-9269-0836561644e0	Duration: 2862.59 ms	Billed Duration: 2863 ms	Memory Size: 128 MB	Max Memory Used: 52 MB	Init Duration: 159.38 ms	
runtime error: index out of range [0] with length 0
boundsError

Expected behavior

Expected all internal Google users to be synced without an error and external users skipped

Additional context

Also tried using the UserMatch filter, but as you can see here it is not respected when using the default (sync_method=groups) sync method.

Error when deploy lambda error after sam application manually

Describe the bug
Trying to deploy sam application manually after deploy the lambda crash

To Reproduce
Steps to reproduce the behavior:
Environment Vars:

SSOSYNC_GOOGLE_ADMIN | arn:aws:secretsmanager:us-east-1:㊙️
SSOSYNC_GOOGLE_CREDENTIALS | arn:aws:secretsmanager:us-east-1::
SSOSYNC_GROUP_MATCH | email:somePrefix*
SSOSYNC_LOG_FORMAT | text
SSOSYNC_LOG_LEVEL | info
SSOSYNC_SCIM_ACCESS_TOKEN | arn:aws:secretsmanager:us-east-1::
SSOSYNC_SCIM_ENDPOINT | arn:aws:secretsmanager:us-east-1::
SSOSYNC_SYNC_METHOD | groups

Error:

[{"path":"github.com/aws/[email protected]/lambda/errors.go","line":39,"label":"lambdaPanicResponse"},{"path":"github.com/aws/[email protected]/lambda/function.go","line":36,"label":"(*Function).Invoke.func1"},{"path":"runtime/panic.go","line":965,"label":"gopanic"},{"path":"runtime/panic.go","line":212,"label":"panicmem"},{"path":"runtime/signal_unix.go","line":734,"label":"sigpanic"},{"path":"cfir/git/ssosync/internal/google/client.go","line":45,"label":"NewClient"},{"path":"cfir/git/ssosync/internal/sync.go","line":687,"label":"DoSync"},{"path":"cfir/git/ssosync/cmd/root.go","line":55,"label":"glob..func1"},{"path":"github.com/spf13/[email protected]/command.go","line":852,"label":"(*Command).execute"},{"path":"github.com/spf13/[email protected]/command.go","line":960,"label":"(*Command).ExecuteC"},{"path":"github.com/spf13/[email protected]/command.go","line":897,"label":"(*Command).Execute"},{"path":"reflect/value.go","line":476,"label":"Value.call"},{"path":"reflect/value.go","line":337,"label":"Value.Call"},{"path":"github.com/aws/[email protected]/lambda/handler.go","line":124,"label":"NewHandler.func1"},{"path":"github.com/aws/[email protected]/lambda/handler.go","line":24,"label":"lambdaHandler.Invoke"},{"path":"github.com/aws/[email protected]/lambda/function.go","line":64,"label":"(*Function).Invoke"},{"path":"reflect/value.go","line":476,"label":"Value.call"},{"path":"reflect/value.go","line":337,"label":"Value.Call"},{"path":"net/rpc/server.go","line":377,"label":"(*service).call"},{"path":"runtime/asm_amd64.s","line":1371,"label":"goexit"}] END RequestId: ab43f97f-ab0f-4292-a001-53529de7b2fc REPORT RequestId: ab43f97f-ab0f-4292-a001-53529de7b2fc Duration: 1110.06 ms Billed Duration: 1111 ms Memory Size: 128 MB Max Memory Used: 53 MB Init Duration: 147.93 ms runtime error: invalid memory address or nil pointer dereference errorString
Sam properties
SemanticVersion: 1.0.0-rc.9
SourceCodeUrl: https://github.com/awslabs/ssosync/tree/1.0.0-rc.9

golint failures

Describe the bug

internal/aws/client.go:31:2: exported var ErrUserNotFound should have comment or be unexported
--
992 | internal/aws/http.go:20:6: type HttpClient should be HTTPClient
993 | internal/aws/mock/mock_http.go:25:6: type name will be used as mock.MockIHttpClient by other packages, and that stutters; consider calling this IHttpClient
994 | internal/aws/mock/mock_http.go:31:6: type name will be used as mock.MockIHttpClientMockRecorder by other packages, and that stutters; consider calling this IHttpClientMockRecorder
995 | internal/config/secrets.go:33:19: method SCIMEndpointUrl should be SCIMEndpointURL

To Reproduce
Steps to reproduce the behavior:

golint -set_exit_status ./...

Expected behavior
Clean run from golint

Additional context
Add any other context about the problem here.

The active/disabled status isn't synced from Google to AWS SSO

Is your feature request related to a problem? Please describe.
When a user is relieved of duty this is done by disabling the User in GSuite. It's important that the access in Aws is also removed. Deleting a user is done after a period.

Describe the solution you'd like
I created a PR that sync the the flag to the user. In SSO the flag is called Active, in GSuite Disable.
The added logic is
At Create: Pass the Active Flag for the user object
At Update: The Active state is retrieved from AWS and verified with the Gsuite Disabled Flag. Is this is changed the user is updated. Herefor a new function UpdateUser is created.

Additional context
Add any other context or screenshots about the feature request here.

Breaking change on v1.0.0-rc.9 (from v1.0.0-rc.8)

Describe the bug

When running ssosync v1.0.0-rc.8, the process works fine. When running v1.0.0-rc.9 with the exact same set of parameters, it exits with an error.

To Reproduce
Steps to reproduce the behavior:

  1. Download v1.0.0-rc.8
  2. Run with:
./ssosync \
  --debug \
  --access-token "REDACTED" \
  --endpoint "REDACTED" \
  --google-admin "REDACTED" \
  --google-credentials "credentials.json"
  1. See the correct output running the sync.

  2. Download v1.0.0-rc.9

  3. Run with the exact same commands as before

  4. See the error:

INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application 
INFO[0000] syncing                                       sync_method=groups
DEBU[0000] get google groups                             query=
FATA[0000] googleapi: Error 400: Invalid Input: query, invalid

Expected behavior
Expected v1.0.0-rc.9 to not have any breaking changes from v1.0.0-rc.8, as none are documented, and this is not a major version bump.

To be very clear: a bump such as rc.8 -> rc.9 should have absolutely identical behavior for a valid set of parameters. Anything different than that makes it a breaking change, which doesn't belong to something like rc.8 -> rc.9.

Additional context
Running on Mac OS 11.2.3.

Support for subgroups?

It appears that the program doesn't support subgroups on the Google side.

We have a group of [email protected] that's made up of several direct members and a few subgroups -- things like [email protected] and [email protected]. Google allows you to add groups to groups in this way.

Unfortunately, these subgroups are not flattened out and included when running a sync. I am unsure if this is by design (to prevent infinite loops) or if the program is unaware of the subgroups. Has anyone else run into this?

The workaround is to directly use the subgroups when assigning permissions, but it would be significantly more convenient to use the "ubergroup" instead. I'm hoping for some insight from someone familiar with the program/APIs before diving in myself to see.

Default value for sync-method flag breaks previous behaviour

Describe the bug
I noticed after upgrading to v1.0.0-rc.9 from v1.0.0-rc.8 that our SSO sync started failing with the following message:

time="2021-03-29T12:07:40Z" level=info msg="Syncing AWS users and groups from Google Workspace SAML Application"
time="2021-03-29T12:07:40Z" level=info msg=syncing sync_method=groups
time="2021-03-29T12:07:40Z" level=debug msg=get google groups query=
time="2021-03-29T12:07:40Z" level=fatal msg="googleapi: Error 400: Invalid Input: query, invalid"

The default value for the new sync-method flag is groups and I believe the empty query is not accepted by the Google API.

To Reproduce
Steps to reproduce the behaviour:

  1. Run ssosync only with the minimum set of flags, for example:
ssosync \
          --debug \
          --access-token REDACTED \
          --endpoint REDACTED \
          --google-admin REDACTED \
          --google-credentials credentials.json
  1. Check output

Expected behavior
The sync should happen with no errors.

Additionaal context
Even when setting the sync-method to users_groups, it yields the same result as the query to fetch groups is invalid.

Permission error when creating ssosync Lambda function

Describe the bug

Error:
You are not authorized to perform: serverlessrepo:GetApplication

Error is thrown when attempting to create the ssosync function in AWS via the create url https://console.aws.amazon.com/lambda/home#/create/app?applicationId=arn:aws:serverlessrepo:eu-west-1:084703771460:applications/ssosync

To Reproduce
Steps to reproduce the behavior:

  1. Go to README
  2. Click on AWS Serverless Application Repository.
  3. See error
    image

Expected behavior
I would expect access to be able to create the function as per the lab.

Additional context
Add any other context about the problem here.

Is is no longer available in AWS Serverless Application Repository.

Describe the bug
Following the link AWS Serverless Application Repository from the readme results in an error You are not authorized to perform: serverlessrepo:GetApplication.

I think it is no longer available in the repository. Is this something intended ?

To Reproduce
Steps to reproduce the behavior:

  1. Login to an was account with admin privileges
  2. Click AWS Serverless Application Repository
  3. See error You are not authorized to perform: serverlessrepo:GetApplication.

Expected behavior
I was expanding to find the app and be able to create a stack out of it.

Additional context
We figure this out by trying to update an existing stack

Unsupported Protocol Scheme

Running ./ssosync -c ~/credentials.json --google-admin "[email protected]" --group-match 'name:aws-admin*' --debug

Results:
NFO[0000] Syncing AWS users and groups from Google Workspace SAML Application
INFO[0000] syncing sync_method=groups
DEBU[0000] get google groups query="name:aws-admin*"
DEBU[0000] get google users and groups and its users
DEBU[0000] get group members from google group=aws-administrators
DEBU[0001] get users group=aws-administrators
DEBU[0001] get user group=aws-administrators id=[email protected]
DEBU[0001] get user group=aws-administrators id=[email protected]
DEBU[0002] get aws groups
INFO[0002] [DEBUG] GET /Groups
INFO[0002] [ERR] GET /Groups request failed: Get "/Groups": unsupported protocol scheme ""
ERRO[0002] error getting aws groups
FATA[0002] Get "/Groups": GET /Groups giving up after 1 attempt(s): Get "/Groups": unsupported protocol scheme ""

Any info would be appreciated.

Thank you,
Akash

User creation fails. status of http response was 400

Describe the bug
User creation fails with errors:

error creating user
status of http response was 400

Raw server response reports an error:

Request is unparsable, syntactically incorrect, or violates schema.","status":"400"

Steps to reproduce the behavior:

1.Add raw response debug line to: https://github.com/awslabs/ssosync/blob/master/internal/aws/client.go#L126

log.Error("[RESPONSE] ", string(response))
  1. Compile & Run ssosync with debug
./ssosync -d \
  --access-token $SSOSYNC_SCIM_ACCESS_TOKEN \
  --endpoint $SSOSYNC_SCIM_ENDPOINT \
  --google-admin [email protected] \
  --google-credentials myorganization.json \
  --group-match 'Name:org_team.support*'

Expected behavior
Users and groups should have been created at AWS SSO side.

Additional context

Effect at AWS SSO side:

Operation Logs:

INFO[0009] creating user                                 [email protected]
DEBU[0009] INIT BODY{ [urn:ietf:params:scim:schemas:core:2.0:User] [email protected] {Dee John} John Dee true [{[email protected] work true}] [{work}]}
INFO[0009] [DEBUG] POST https://scim.us-east-1.amazonaws.com/xxx/scim/v2/Users
DEBU[0009] RESPONSE{"id":"xxx-yyy","meta":{"resourceType":"User","created":"2021-11-04T14:59:11Z","lastModified":"2021-11-04T14:59:11Z"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"userName":"[email protected]","name":{"familyName":"Dee","givenName":"John"},"displayName":"John Dee","active":true,"emails":[{"value":"[email protected]","type":"work","primary":true}],"addresses":[{"type":"work"}]}
...
...
INFO[0009] [DEBUG] GET https://scim.us-east-1.amazonaws.com/xxx/scim/v2/Users?filter=userName+eq+%joe.k%myorganization.com%22
INFO[0009] creating user                                 [email protected]
DEBU[0009] INIT BODY{ [urn:ietf:params:scim:schemas:core:2.0:User] [email protected] {Kane Joe} Joe Kane true [{[email protected] work true}] [{work}]}
INFO[0009] [DEBUG] POST https://scim.us-east-1.amazonaws.com/xxx/scim/v2/Users
DEBU[0009] RESPONSE{"schema":["urn:ietf:params:scim:api:messages:2.0:Error"],"detail":"Request is unparsable, syntactically incorrect, or violates schema.","status":"400","exceptionRequestId":"xxx-yyy-zzz","timeStamp":"2021-11-04 14:59:11.864"}
ERRO[0009] error creating user                           [email protected]
DEBU[0009] status of http response was 400               [email protected]
FATA[0009] status of http response was 400

getGroupUsersOperations should return the delete and equals arrays - but does not

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. this code expects a return value from getGroupUsersOperations:
    deleteUsersFromGroup, _ := getGroupUsersOperations(googleGroupsUsers, awsGroupsUsers)
  2. but there clearly isn't one:
    return

Expected behavior
The function getGroupUsersOperations should return the delete and equals arrays - but it does not.

Additional context
internal/sync.go line 661 should read return delete, equals

Thanks!

Groups with colons fail to be created

Describe the bug
Groups with colons fail to be created

To Reproduce
Steps to reproduce the behavior:

  1. Create a group in GSuite containing a colon in the display name - e.g. Hello: there
  2. Run ssosync as you normally would, with the --debug flag
  3. You get error FATA[0019] status of http response was 400

Expected behavior

The group is created!

Additional context

There are various approaches that could resolve this - for example:

  • AWS SSO is updated to accept colons
  • The colons are filtered out by awssso
  • The group system name (i.e. the e-mail address name) is used instead of the display name
  • Improved docs and error messages to call this out, so that people can update their display names in GSuite

ssosync and control tower preconfigured groups

Hi, This is more of a question i think than a request. (Just could not find this anywhere)

Is your feature request related to a problem? Please describe.

I am using ssosync in combination with control tower.
Now control tower comes with some aws sso preconfigured groups.
If i run ssosync it was always delete the preconfigured groups from aws sso which are linked to the control tower setup.

it seems like ssosync only takes in account the groups it can find in its filter per unique run.

Describe the solution you'd like

I would like to sync users/groups with or without a filter from G suite to aws sso without deleting the preconfigured groups that control tower creates.

Describe alternatives you've considered

none i would just like to know if this is possible to do with ssosync.

How to format multiple groups under groupmatch

Not sure if this is the proper forum to ask, but how does one format launch.json to have multiple entries for groups under the --group-match section? Running out of ideas after reviewing documentation in readme as well as links to google api pages. Also what is the format for command line execution would help. This is my first time golang experience, so debuging has been challenging for me. Thanks in advance.

409 conflict response from AWS SCIM API when syncing large number of users

Describe the bug
I've got this issue where I keep getting 409 conflict response from AWS SCIM API when syncing ~100 users

I did some reading to the code and AWS SCIM API reference, and found this on the ListUsers page:

https://docs.aws.amazon.com/singlesignon/latest/developerguide/listusers.html#constraints-listusers

At this time, the ListUsers API is only capable of returning up to 50 results

I think this is causing the issue. The current implementation uses ListUsers to fetch AWS users, but since its only capable of returning only 50 users, it will only compare the 50 AWS users against the ~100 from Google Workspace API. This is causing 409 conflicts to AWS SCIM when ssosync attempts to create an already existing AWS user.

Is there anything I miss when configuring ssosync?

v1.0.0-rc.9: How to use --include-groups

Describe the bug
This might be a misunderstanding of how to use --include-groups on my part, a code bug, or a problem w/ the objects in my GSuite External IdP. I'm not sure.

I've got something like 5 groups, containing around 100 users, that I want to ssosync. Importing all of my GSuite users/groups isn't an option as I have thousands of those, most of whom don't need access to AWS.

What is the syntax to use --include-groups? I've not been able to get it to work.

When I try 1 or more comma separated values like officetech or officetech,webops I receive a Error 400: Invalid Input: query, invalid response. Eg.,

./ssosync --debug --access-token "REDACTED" --endpoint "REDACTED" --google-admin "redacted@redacted" --google-credentials "~/Documents/ssosync.google.credentials.json" --include-groups "officetech"
INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application
INFO[0000] syncing                                       sync_method=groups
DEBU[0000] get google groups                             query=
FATA[0000] googleapi: Error 400: Invalid Input: query, invalid

However, I am able to import my officetech Group and it's users with --group-match "name:officetec*", and the Group and it's users are properly imported to AWS SSO.

I don't think --group-match meets my use case, however, since only the last incidence of that switch appears to be respected. For example, If I do --group-match "name:webop*" --group-match "name:officetec*" , ssosync appears to only attempt to import the *officetech Group/users.

Expected behavior
The following would import exactly 3 Groups, and their users (officetech, webops & thirdgroup):

./ssosync --debug --access-token "REDACTED" --endpoint "REDACTED" --google-admin "redacted@redacted" --google-credentials "~/Documents/ssosync.google.credentials.json" --include-groups "officetech,webops,thirdgroup"

Users are not synced when there is a deleted user

Describe the bug
When a user is deleted from GSuite after it's been already synced the SyncUser loop fails.

To Reproduce
Steps to reproduce the behavior:

  1. Sync Users from Gsuite -> SSO
  2. Delete User in Gsuite
  3. run the sync command. The users aren't synced.
INFO[0000] Creating the Google and AWS Clients needed
DEBU[0000] get deleted users
DEBU[0001] get google groups

Expected behavior
Ignore the delete user and continue with the rest of the users.

Additional context
I created already a PR with a fix

SSO Sync not working for google workspaces user to SSO

Describe the bug
when you run the function it is not populating the user on AWS site , and when you check the lambda function error that we are getting is

"runtime error: invalid memory address or nil pointer dereference: errorString [{"path":"github.com/aws/[email protected]/lambda/errors.go","line":39,"label":"lambdaPanicResponse"},{"path":"github.com/aws/[email protected]/lambda/function.go","line":36,"label":"(*Function).Invoke.func1"},{"path":"runtime/panic.go","line":838,"label":"gopanic"},{"path":"runtime/panic.go","line":220,"label":"panicmem"},{"path":"runtime/signal_unix.go","line":818,"label":"sigpanic"},{"path":"output/src608454744/src/internal/google/client.go","line":45,"label":"NewClient"},{"path":"output/src608454744/src/internal/sync.go","line":687,"label":"DoSync"},{"path":"output/src608454744/src/cmd/root.go","line":55,"label":"glob..func1"},{"path":"github.com/spf13/[email protected]/command.go","line":852,"label":"(*Command).execute"},{"path":"github.com/spf13/[email protected]/command.go","line":960,"label":"(*Command).ExecuteC"},{"path":"github.com/spf13/[email protected]/command.go","line":897,"label":"(*Command).Execute"},{"path":"reflect/value.go","line":556,"label":"Value.call"},{"path":"reflect/value.go","line":339,"label":"Value.Call"},{"path":"github.com/aws/[email protected]/lambda/handler.go","line":124,"label":"NewHandler.func1"},{"path":"github.com/aws/[email protected]/lambda/handler.go","line":24,"label":"lambdaHandler.Invoke"},{"path":"github.com/aws/[email protected]/lambda/function.go","line":64,"label":"(*Function).Invoke"},{"path":"reflect/value.go","line":556,"label":"Value.call"},{"path":"reflect/value.go","line":339,"label":"Value.Call"},{"path":"net/rpc/server.go","line":381,"label":"(*service).call"},{"path":"runtime/asm_amd64.s","line":1571,"label":"goexit"}]"

To Reproduce
Steps to reproduce the behavior follow the steps mentioned in the link below.
https://github.com/awslabs/ssosync#readme

Lack of support for nest groups

Describe the bug
When running SSO Sync receive error message:
Exception has occurred: panic
"runtime error: index out of range [0] with length 0"
Stack:
3 0x0000000000eca5d3 in github.com/awslabs/ssosync/internal.(*syncGSuite).getGoogleGroupsAndUsers
at C:/Users/matth/Desktop/Stuff/AWS SSO/SSOSYNC/ssosync/internal/sync.go:511
4 0x0000000000ec6ae7 in github.com/awslabs/ssosync/internal.(*syncGSuite).SyncGroupsUsers
at C:/Users/matth/Desktop/Stuff/AWS SSO/SSOSYNC/ssosync/internal/sync.go:291
5 0x0000000000ecceec in github.com/awslabs/ssosync/internal.DoSync
at C:/Users/matth/Desktop/Stuff/AWS SSO/SSOSYNC/ssosync/internal/sync.go:706
6 0x0000000000fee6ab in github.com/awslabs/ssosync/cmd.glob..func1
at C:/Users/matth/Desktop/Stuff/AWS SSO/SSOSYNC/ssosync/cmd/root.go:55
7 0x0000000000fb2f70 in github.com/spf13/cobra.(*Command).execute
at C:/Users/matth/go/pkg/mod/github.com/spf13/[email protected]/command.go:852
8 0x0000000000fb3ce6 in github.com/spf13/cobra.(*Command).ExecuteC
at C:/Users/matth/go/pkg/mod/github.com/spf13/[email protected]/command.go:960
9 0x0000000000fb33ef in github.com/spf13/cobra.(*Command).Execute
at C:/Users/matth/go/pkg/mod/github.com/spf13/[email protected]/command.go:897
10 0x0000000000fecec5 in github.com/awslabs/ssosync/cmd.Execute
at C:/Users/matth/Desktop/Stuff/AWS SSO/SSOSYNC/ssosync/cmd/root.go:72
11 0x0000000000fee877 in main.main
at C:/Users/matth/Desktop/Stuff/AWS SSO/SSOSYNC/ssosync/main.go:29

Error hits sync.go line 511: membersUsers = append(membersUsers, u[0])

u evaluates to "[]*google.golang.org/api/admin/directory/v1.User len: 0, cap: 0, []"

I am trying to sync a small subset of groups and about 40-80 users from Gsuite to AWS SSO. I cannot sync all user accounts and groups, it has to be a subset.

To Reproduce
Steps to reproduce the behavior:

  1. Debug mode with VSCode
  2. Ran with args using launch.json (sanitized here) to pass args.
    "args": [
    ...
    "--google-admin",
    "[email protected]",
    "--sync-method",
    "groups",
    "--ignore-users",
    "email:*",
    "--include-groups",
    "name:[email protected]"
    ]
  3. See error

Expected behavior
Expect it to continue and finish process.

Additional context
https://alegiovanardi.medium.com/go-slices-explained-part-1-1f1143b568fc seems to indicate that the array (or slice) is too small. I'm not sure why because it appears to be dynamically assigned. I've spent several hours trying to fix it, but I have no experience with GOLang and can't get over that hurdle.
This gsuite domain has thousands of user accounts.

Thanks for your attention

googleapi: Error 400: Invalid Input, invalid

Describe the bug
ssosync fails with error 400

INFO[0000] Creating the Google and AWS Clients needed
DEBU[0000] get deleted users
WARN[0000] Error Getting Deleted Users
FATA[0000] googleapi: Error 400: Invalid Input, invalid

To Reproduce
Steps to reproduce the behavior:
I just did all the steps, described in the readme.
Enabled Admin api, created service account, added it to the domain wide delegation with 3 scopes, created key,
started ssosync.

Expected behavior
A clear and concise description of what you expected to happen.

Additional context
Add any other context about the problem here.

User and group syncing results in scim request throttling error 429

Describe the bug
User and group syncing can abruptly end due to AWS SSO SCIM request throttling. This results in either a HTTP error 429 or 409. The 409 conflict can occur when the initial HTTP 429 error is dropped by the tool and ssosync attempts to create either a user or group which already exists. This only seems to occur on low latency connections (instance in a vpc in the same region as the sso scim endpoint) on systems with more resources and a medium number of users, groups, and memberships (~200 users and ~200 groups).

To Reproduce
Steps to reproduce the behavior:

  1. Run ssosync in a kubernetes cluster as a cronjob. The node executing the container is in the same region as the AWS SSO scim provisioning endpoint.
  2. Attempt to sync around 200 users with 200 groups.
  3. Container runs for around 10 - 15 seconds before exiting with either of the following errors:
{"level":"fatal","msg":"status of http response was 409","time":"2020-08-13T16:48:06Z"}
{"level":"fatal","msg":"status of http response was 429","time":"2020-08-13T16:48:06Z"}

Expected behavior
The ssosync tool should back-off and retry requests several times when a HTTP 429 is returned from the scim endpoint. Resulting in the sync completing.

Additional context
In the case of an HTTP 409 conflict I added additional logging and found an AWS throttling exception is returned for the last object lookup. The 429 is silently dropped and the sync tool attempts to create the object which already exists. This results in the fatal 409 which causes the tool to exit.

{
  "level": "debug",
  "msg": "&{429 Too Many Requests 429 HTTP/2.0 2 0 map[Content-Length:[0] Content-Type:[application/json] Date:[Thu, 13 Aug 2020 21:19:21 GMT] X-Amzn-Errortype:[ThrottlingException] X-Amzn-Requestid:[11111-22222-33333-aaaaa]]}",
  "time": "2020-08-13T21:19:21Z"
}

Allow use of Systems Manager Parameters instead of Secrets Manager Secrets

Is your feature request related to a problem? Please describe.
This application currently only supports Secrets Manager for remote secret storage. Secrets Manager is $0.40/secret/month.

Systems Manager Parameters are equally secure (can be KMS encrypted) and are free. Since none of the other Secrets Manager features are necessary for this application (rotation, replication), use of Secrets Manager is not strictly required.

Therefore, Systems Manager Parameters would be a preferred secret store for some users.

Describe the solution you'd like
Allow specifying Systems Manager parameter names/ARNs instead of only allowing hard-coded Secret names.

Describe alternatives you've considered
Keep using secrets.

Having issues sync Gsuite email groups to AWS SSO

So I was able to sync all Gsuite users via the "users_groups" but I am not seeing any Google Workspaces groups in AWS SSO Console.

Ideally I just want to sync all GSuite groups with AWS SSO and then deploy an AWS SSO permission set for GSuite group, I am using the following command:

./ssosync -t $SSOSYNC_SCIM_ACCESS_TOKEN -e $SSOSYNC_SCIM_ENDPOINT -u -c <key.json>
-g 'name:Fuel* email:all*' --sync-method 'groups'

and I am getting this

INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application 
INFO[0000] syncing                                       sync_method=groups
INFO[0000] get google groups                             query="name:Fuel* email:all*"
FATA[0001] googleapi: Error 400: Invalid Input: query, invalid 

what i am doing wrong to sync the GSuite email groups to AWS SSO Groups?

Add users without groups

Users that do not belong to any groups should be synced in as well. Right now they're ignored.

Doesn't support more than 50 users

Describe the bug

func (c *client) GetUsers() ([]*User, error) {

GetUsers call doesn't support pagination and according to your docs here https://docs.aws.amazon.com/singlesignon/latest/developerguide/listusers.html the max results returned is 50. This means only 50 existing users will ever be returned and diffed with the users in gsuite resulting in users that already exist trying to be re-created and the entire sync process failing on 409 errors on user creation of a user that already exits

To Reproduce
Have more than 50 users being synced and watch the 409s pour in

Expected behavior
Support more than 50 users

Additional context

timestamp message
1646431741449 START RequestId: ccb39549-b4d2-4a8a-b5e8-89071d8eaac4 Version: $LATEST
1646431742502 {"level":"info","msg":"Syncing AWS users and groups from Google Workspace SAML Application","time":"2022-03-04T22:09:02Z"}
1646431742502 {"level":"info","msg":"syncing","sync_method":"groups","time":"2022-03-04T22:09:02Z"}
1646431742502 {"level":"info","msg":"get google groups","query":"name:aws-* email:aws-*","time":"2022-03-04T22:09:02Z"}
1646431778089 {"level":"info","msg":"get existing aws groups","time":"2022-03-04T22:09:38Z"}
1646431778153 {"level":"info","msg":"get existing aws users","time":"2022-03-04T22:09:38Z"}
1646431823124 {"level":"info","msg":"syncing changes","time":"2022-03-04T22:10:23Z"}
1646431823160 {"level":"warning","msg":"deleting user","time":"2022-03-04T22:10:23Z","user":"a@***********"}
1646431823406 {"level":"info","msg":"creating user","time":"2022-03-04T22:10:23Z","user":"t@*************"}
1646431823470 {"level":"error","msg":"error creating user","time":"2022-03-04T22:10:23Z","user":"t@************"}
1646431823471 status of http response was 409: errorString null
1646431823472 END RequestId: ccb39549-b4d2-4a8a-b5e8-89071d8eaac4
1646431823472 REPORT RequestId: ccb39549-b4d2-4a8a-b5e8-89071d8eaac4 Duration: 82020.83 ms Billed Duration: 82021 ms Memory Size: 128 MB Max Memory Used: 51 MB Init Duration: 191.18 ms

email addresses redacted

Valid Groups name, compatibility between --sync-method groups and users_groups

Is your feature request related to a problem? Please describe.

Since I introduced the flag --sync-method to implement a different way to sync Groups and their members I noticed the negative impact of it. Trying to figure out what happened and why the impact was bad, and basically reading the project reported issues I noticed the following.

I broke the groups mapping's fields with the new --sync-method "groups", what I mean:

1) if you use --sync-method "users_groups", which was the original behavior

Users Fields
AWS SSO SCIM Schema Google Workspace Notes
userName <-- primaryEmail
name <-- {givenName, familyName }
displayName <-- givenName + " " + familyName
active: <-- !suspended
emails: <-- [ primaryEmail ] ignored from google, used primaryEmail
addresses: <-- [ {type: "work"} ] ignored from google, Fixed

Go code for AWS SSO SCIM Schema

type User struct {
	ID       string   `json:"id,omitempty"`
	Schemas  []string `json:"schemas"`
	Username string   `json:"userName"`
	Name     struct {
		FamilyName string `json:"familyName"`
		GivenName  string `json:"givenName"`
	} `json:"name"`
	DisplayName string        `json:"displayName"`
	Active      bool          `json:"active"`
	Emails      []UserEmail   `json:"emails"`
	Addresses   []UserAddress `json:"addresses"`
}
Groups Fields
AWS SSO SCIM Schema Google Workspace Notes
displayName <-- email Group email

Go code for AWS SSO SCIM Schema

type Group struct {
	ID          string   `json:"id,omitempty"`
	Schemas     []string `json:"schemas"`
	DisplayName string   `json:"displayName"`
	Members     []string `json:"members"`
}

2) if you use --sync-method "groups", my introduced behavior

Users Fields

Users mapping still the same that --sync-method "users_groups"

Groups Fields
AWS SSO SCIM Schema Google Workspace Notes
displayName <-- name Group name

The Problem

1. As you see, the original behavior (--sync-method "users_groups") is using Google group email as AWS SSO group name and I implemented (--sync-method "groups") using Google group name as AWS SSO group name.

Additionally exist the following aspect

Group Names as a displayName
  • Could be duplicated, not unique
  • Could be empty
  • May not follow AWS SSO Group Names pattern (see notes below)
Group Email as a displayName
  • Looks like a user instead of a group, I.M.H.O: ugly group name
  • May not follow AWS SSO Group Names pattern (see notes below)

2. When the code fills the internal structure to store the Google Groups and their members, I used the Google Group Name as a key

Go code

func getGroupOperations(awsGroups []*aws.Group, googleGroups []*admin.Group) (add []*aws.Group, delete []*aws.Group, equals []*aws.Group) {

	awsMap := make(map[string]*aws.Group)
	googleMap := make(map[string]struct{})

	for _, awsGroup := range awsGroups {
		awsMap[awsGroup.DisplayName] = awsGroup
	}

	for _, gGroup := range googleGroups {
		googleMap[gGroup.Name] = struct{}{} // --> HERE
	}

	// AWS Groups found and not found in google
	for _, gGroup := range googleGroups {
		if _, found := awsMap[gGroup.Name]; found {
			equals = append(equals, awsMap[gGroup.Name])
		} else {
			add = append(add, aws.NewGroup(gGroup.Name))
		}
	}

	// Google Groups founds and not in aws
	for _, awsGroup := range awsGroups {
		if _, found := googleMap[awsGroup.DisplayName]; !found {
			delete = append(delete, aws.NewGroup(awsGroup.DisplayName))
		}
	}

	return add, delete, equals
}
NOTES
  • I didn't find the name restrictions or name convention over the field displayName (Group Name in Web Console) on AWS SSO SCIM API, but the weird is that using the AWS Web Console for AWS SSO service with SCIM off, this shows the following message "Can contain only alphanumeric characters, or any of the following: ._- Maximum of 128 characters". But is you use AWS SSO SCIM APIto create a group, White spaces and @ are allowed, so?

References:

Describe the solution you'd like

Options:

  1. I can make a PR with the necessary changes to use Google group email as AWS SSO group name for (--sync-method "groups"), but this is going to broke the people that have implemented the method --sync-method "groups"
  2. I can implement a new flag --groups-name-field with possible values [name|email] to maintain compatibility, but this could be confusing, I think.
  3. In all cases validate the value of displayName before call the AWS SSO SCIM API to avoid errors and log the warning message ignoring group, bad name or something else

Describe alternatives you've considered

Just the above, or somebody has a better idea?

SSOSYNC_IGNORE_GROUPS not working in lambda

Describe the bug
Added lambda environment var SSOSYNC_IGNORE_GROUPS and pointed it at a secret in secret manager but its not ignoring said groups

To Reproduce
Steps to reproduce the behaviour:

  1. Add secret to secret manager with [email protected],[email protected]
  2. add env var to lambda called SSOSYNC_IGNORE_GROUPS and point it at the ARN of the above
  3. run the function
  4. check logs in cloud watch and see that groups are being synced

Expected behavior
run the function and check logs and see that groups are not being synced

Additional context
Won't be an issue when PR16 is merged as we have over 300 groups and only need to sync 3.

Limit groups by schema

Is your feature request related to a problem? Please describe.
We are using groups in gsuite not only as a real set of user groups, but also as internal mailing lists for projects or as alerting hubs for several topics. Thus we have a lot of groups. From our 100 Groups (and rising) only around 5-10 are related to actual groups in AWS.

Describe the solution you'd like
Add a filter to allow only groups whose emails match the filter. (e.g. aws.*@mydomain.com or *@department.mydomain.com)

Describe alternatives you've considered
None

ssosync deletes Control Tower groups

Describe the bug

A recent run of ssosync deleted a bunch of Control Tower accounts. I don't know why this didn't happen in prior runs. (Perhaps they were added in a recent Control Tower release?)

To Reproduce
Steps to reproduce the behavior:

  1. Example session:
snafu$ ./ssosync -u [email protected] -g 'email:aws-*'
INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application 
INFO[0000] syncing                                       sync_method=groups
INFO[0000] get google groups                             query="email:aws-*"
INFO[0006] get existing aws groups                      
INFO[0006] get existing aws users                       
INFO[0034] syncing changes                              
WARN[0034] deleting user                                 [email protected]
INFO[0035] creating user                                 [email protected]
WARN[0037] removing user from group                      group="AWS Admins" [email protected]
INFO[0038] adding user to group                          group="AWS Engineering" [email protected]
WARN[0038] removing user from group                      group="AWS Engineering" [email protected]
WARN[0041] deleting group                                group=AWSServiceCatalogAdmins
WARN[0041] deleting group                                group=AWSAuditAccountAdmins
WARN[0041] deleting group                                group=AWSControlTowerAdmins
WARN[0042] deleting group                                group=AWSSecurityAuditors
WARN[0042] deleting group                                group=AWSLogArchiveViewers
WARN[0042] deleting group                                group=AWSLogArchiveAdmins
WARN[0042] deleting group                                group=AWSSecurityAuditPowerUsers
WARN[0043] deleting group                                group=AWSAccountFactory
INFO[0043] sync completed                               

Expected behavior
While I'm aware that ssosync will delete groups that don't exist in Google, ssosync should never delete groups or accounts that are created by Control Tower (or otherwise part of AWS administration). I have filed this as a bug because, in my opinion, this is a serious deviation from expectations.

Additional context
The current experience for using Google as an identity provider for AWS is pretty poor. This command line tool should not be needed at all. I expect more from AWS, and I think it is in AWS's best interests to provide production-grade SSO integration with Google.

Need to specify users and groups to include rather than ignore

I need to specify users/groups to include rather than ignore.

Is your feature request related to a problem? Please describe.
The problem I have is that the tool currently assumes that every user or group in Google should also exist in AWS SSO. This doesn't work for my organization. Only a very small list of users that exist in a single Google group should be synced to AWS SSO and I'd rather control which SSO group is used according to user attributes on the Google side. This allows for much easier management on the Google side. Furthermore as it is now the list to ignore would equal N-1; if another Google admin were to add a new group I would have to update the ignore list to avoid adding unauthorized users to AWS SSO. It would be far too easy for a group to be added without my knowledge and therefore unauthorized users would be granted access by mistake.

Describe the solution you'd like
I'd like to see the tool offer at least --include-groups and perhaps --include-users which would allow me to specify a shorter list of the only group(s) to sync. The --include-groups and --ignore-groups flags would of course be mutually exclusive; an error would be raised if both were used together.

Describe alternatives you've considered
Write my own tool or continue managing users manually.

Additional context
Our organization includes many people in many departments besides engineering. It makes absolutely no sense to sync every person in every group when only a small subset of users actually need access to AWS. As it is, the tool forces me to ignore a very long and growing list of groups that have no relation to AWS at all. Only 1 (maybe 2) group(s) need to be synced and this would be more easily and plainly achieved via --include-groups

Nested google groups are not synchronised correctly in AWS

We have nested groups in google . For example group A contains group B . The group B has a user Y.

In this scenario, In thew AWS SSO we expect to see that the group A will have the Group B inside or the user Y directly.

Seems AWS SSO doesn"t support nested groups and the ssosync script doesn"t expand nested group recursively

Googleapi: Error 404: Domain not found., notFound

I have deployed the solution via SAM, the deployment went well but running the lambda function results in the following error:

FATA[0000] googleapi: Error 404: Domain not found., notFound

Please advise,
Thanks

Pagination does not work (maybe incorrect use of count parameter)

I have more than 10 users and the code only fetches the first ten. Inside getUserPage you have

       q.Add("count", "10")

I think this means "only return 10 total" not "return 10 at a time".

I removed that line and the code worked fine for me.

Edit: Nope removing the line did not resolve the problem :(

Allow specifying secret ARNs

Is your feature request related to a problem? Please describe.
My secrets (SSOSyncGoogleAdminEmail, SSOSyncSCIMAccessToken, SSOSyncSCIMEndpointUrl, SSOSyncGoogleCredentials) are stored in a separate AWS account (in the same Organization). Cross-account sharing is correctly set up.

However, since the secret names are hardcoded in this application, there's no way to configure it to load secrets from a different account.

Describe the solution you'd like
As command line parameters and/or environment variables, allow specifying full ARNs for the secrets that should be used.

Performance issue with large number of users and groups

Bug description

Consider a G Suite organization with 200 users and 200 groups.
In order to sync (add or remove users from this group) AWS SSO group members with G Suite group members, one separate HTTP call to SCIM endpoint is made for every user, for each group, to check wether this user is already in the group or not. This allows building of current AWS SSO users-groups mapping and ensure proper addUserToGroup or removeUserFromGroup operation to match the desired target mapping retrieved from G Suite.

for _, g := range googleGroups {

ssosync/internal/sync.go

Lines 201 to 203 in 5c7c352

for _, u := range s.users {
log.WithField("user", u.Username).Debug("Checking user is in group already")
b, err := s.aws.IsUserInGroup(u, group)

With our 200 users and 200 groups, this results in 40.000 HTTP requests made to SCIM, just to get current group-member mapping.

This causes my SAM application to continuously timeout after 5min of HTTP calls.

IMHO, there are 2 options here to improve the situation :

  • add a disable-group-sync option to the command to disable group syncing all together for organizations not using group provisioning from G Suite or for large use cases like mine
  • check if there is an efficient way to build existing users in AWS SSO groups other than specifically requesting wether one specific user is in one specific group. I'm not familiar with SCIM protocol so I don't know if this is an actual limitation of the protocol or not

WDYT ?

Avoid deleting users on AWS SSO that were recreated on Google

Problem
Noticed that if we delete a user on the Google side and then recreate it with the exact same details the following occurs:

  1. ssosync will consider that user as inactive based on the API response, hence deleting it from AWS SSO
    https://github.com/awslabs/ssosync/blob/master/internal/sync.go#L70-L103
    https://github.com/awslabs/ssosync/blob/master/internal/google/client.go#L64-L73

  2. ssosync will then list all the active users and it will see that it needs to add again the user that has just been deleted in the previous step.
    https://github.com/awslabs/ssosync/blob/master/internal/sync.go#L105-L152

  3. At this stage user will have no permission sets assigned on AWS SSO, and this will happen every time we run ssosync.

Possible Solution
I believe that it would be beneficial to change the SyncUsers function so it checks that all of the API returned deleted users are in fact inactive, and for the ones that are now active it just ignores them by building a new list of deleted users which we can iterate over just like its being done atm.

v1.0.0-rc9: Initial Import Of Users And Group Fails With 404

Describe the bug
Starting with an empty SSO directory running the below command to sync our AWS Power Users group:

❯ ./ssosync \
    --endpoint REDACTED \
    --access-token REDACTED \
    -c creds.json \
    -g 'email:aws-power-users*' \
    --google-admin [email protected] \
    --debug

INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application
INFO[0000] syncing                                       sync_method=groups
DEBU[0000] get google groups                             query="email:aws-power-users*"
DEBU[0000] get google users and groups and its users
DEBU[0000] get group members from google                 group="AWS Power Users"
DEBU[0000] get users                                     group="AWS Power Users"
DEBU[0000] get user                                      group="AWS Power Users" [email protected]
...
DEBU[0016] get aws groups
INFO[0016] [DEBUG] GET REDACTED/scim/v2/Groups
DEBU[0016] get aws users
INFO[0016] [DEBUG] GET REDACTED/scim/v2/Users
DEBU[0016] get aws groups and its users
INFO[0016] creating user                                 [email protected]
INFO[0016] [DEBUG] POST REDACTED/scim/v2/Users
...
INFO[0023] creating group                                group="AWS Power Users"
INFO[0023] [DEBUG] POST REDACTED/scim/v2/Groups
DEBU[0023] finding user                                  group="AWS Power Users"
INFO[0023] [DEBUG] GET REDACTED/scim/v2/Users?filter=userName+eq+%22redacted%redacted.com%22
INFO[0023] adding user to group                          group="AWS Power Users" [email protected]
DEBU[0023] Group Change                                  group="AWS Power Users" operations=add [email protected]
INFO[0023] [DEBUG] PATCH REDACTED/scim/v2/Groups
FATA[0023] status of http response was 404

Checking in the AWS SSO console shows the group is created. A subsequent rerun of the same command yields a new error.

❯ ./ssosync \
    --endpoint REDACTED \
    --access-token REDACTED \
    -c creds.json \
    -g 'email:aws-power-users*' \
    --google-admin [email protected] \
    --debug

INFO[0000] Syncing AWS users and groups from Google Workspace SAML Application
INFO[0000] syncing                                       sync_method=groups
DEBU[0000] get google groups                             query="email:aws-power-users*"
DEBU[0000] get google users and groups and its users
DEBU[0000] get group members from google                 group="AWS Power Users"
DEBU[0000] get users                                     group="AWS Power Users"
DEBU[0000] get user                                      group="AWS Power Users" [email protected]
...
DEBU[0016] get aws groups
INFO[0016] [DEBUG] GET REDACTED/scim/v2/Groups
DEBU[0016] get aws users
INFO[0016] [DEBUG] GET REDACTED/scim/v2/Users
DEBU[0019] get group members from aws                    group="AWS Power Users"
DEBU[0019] checking if user is member of                 group="AWS Power Users"
INFO[0019] [DEBUG] GET REDACTED/scim/v2/Groups?filter=id+eq+%229a672df75b-0f856220-1288-46dc-b610-99ea77ef12eb%22+and+members+eq+%229a672df75b-12f494c8-893d-40f0-9fc0-cfc93e415ff2%22
...
INFO[0024] creating user                                 [email protected]
INFO[0024] [DEBUG] POST REDACTED/scim/v2/Users
ERRO[0024] error creating user                           [email protected]
FATA[0024] status of http response was 409

After checking the directory in the console, the group is empty.

Expected behavior
A group and its users should be created in a single pass.

Additional context
This does not happen consistently with all groups. I am able to sync another group without issues without problems.

segmentation violation

Hey,

just installed the tool via go and getting the following error on a Linux machine:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0xa80b25]

goroutine 1 [running]:
github.com/awslabs/ssosync/internal/google.NewClient(0x100be40, 0xc0003a26c0, 0x0, 0x0, 0xc0003f8000, 0x1a2, 0x3a2, 0x0, 0x0, 0x15876e0, ...)
	/home/runner/work/ssosync/ssosync/internal/google/client.go:44 +0xd5
github.com/awslabs/ssosync/internal.DoSync(0x100be40, 0xc0003a26c0, 0xc0003c0780, 0xc0003a26c0, 0xc00039e9c0)
	/home/runner/work/ssosync/ssosync/internal/sync.go:251 +0x1e1
github.com/awslabs/ssosync/cmd.glob..func1(0x157b340, 0xc0003a2600, 0x0, 0x4, 0x0, 0x0)
	/home/runner/work/ssosync/ssosync/cmd/root.go:54 +0x89
github.com/spf13/cobra.(*Command).execute(0x157b340, 0xc00001e0b0, 0x4, 0x4, 0x157b340, 0xc00001e0b0)
	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:842 +0x453
github.com/spf13/cobra.(*Command).ExecuteC(0x157b340, 0x405cff, 0xc000076058, 0x0)
	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:950 +0x349
github.com/spf13/cobra.(*Command).Execute(...)
	/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:887
github.com/awslabs/ssosync/cmd.Execute()
	/home/runner/work/ssosync/ssosync/cmd/root.go:71 +0x3e
main.main()
	/home/runner/work/ssosync/ssosync/main.go:29 +0x20
go version go1.15.2 linux/amd64

Please let me know what other information you require from me.

Deploying to GCP Cloud Functions

Is your feature request related to a problem? Please describe.
Sometimes it makes more sense to deploy this synchronization to GCP Cloud Functions. Since there is no need to export credentials out of GCP and in terms of more correct architecture - the parent provider (GCP) will be responsible to delegate the security to the undergoing provider (AWS)

Describe the solution you'd like
Provide instructions on how to deploy ssosync to GCP Cloud Functions and periodically call it with scheduler

Lambda Deployment - ssosync: no such file or directory: PathError

Describe the bug
I am using ssosync using a CloudFormation StackSet template, and deployed via terraform resources - a "aws_cloudformation_stack_set" resource to mount the template and an "aws_cloudformation_stack_set_instance" to deploy the application. After some configuration this setup has worked, and I have the application deployed.

Upon a first run of the Lambda function I have been receiving PathError errors from the function.

To Reproduce
Steps to reproduce the behavior:

  1. Deploy the application via the CloudFormation StackSet template
  2. Lambda Function is triggered by the Event rule
  3. fork/exec /var/task/dist/ssosync_linux_amd64/ssosync: no such file or directory: PathError null is logged in the Lambda function log stream.

Expected behavior
The application runs, Users and Groups are populated in the SSO console.

Additional context
I've also tried deprecating the version of the source code used by the function and the same occurs. I'm wondering if due to the way I'm deploying the application there have been some configuration issues, but the infrastructure seems fine and I don't see how my setup would affect the file system of the function.

Addition of a dry run flag

@ChrisPates glad to see this project finally getting some much needed attention

Is your feature request related to a problem? Please describe.
This tool has been broken for quite a while and some of us have been running it with our own set of patches. However, now that there is a renewed focus on this, I expect people would want to get back to using the upstream version.

Describe the solution you'd like
In order to minimise the risk when switching sync tool or after version updates a --dry-run option would be very helpful.

Unclear required --include-groups with --sync-method ‘users_groups’

Describe the bug
Reading the documentation, when using the --sync-method ‘users_groups’, my understanding is that --include-groups should be optional and include every groups by default. However when not using the option every groups are silently ignored.
Indeed when looking at

ssosync/internal/sync.go

Lines 178 to 181 in 6220679

for _, g := range googleGroups {
if s.ignoreGroup(g.Email) || !s.includeGroup(g.Email) {
continue
}

we can see that if s.includeGroup return false, the group is ignored. And s.includeGroup will return false if the group is not in --include-groups (so every single groups if --include-groups is empty).

ssosync/internal/sync.go

Lines 745 to 753 in 6220679

func (s *syncGSuite) includeGroup(name string) bool {
for _, g := range s.cfg.IncludeGroups {
if g == name {
return true
}
}
return false
}

To Reproduce
Steps to reproduce the behavior:

  1. Run sso sync with --sync-method ‘users_groups’ and no --include-groups
  2. See no group created

Expected behavior
Every groups should be included

Lambda Environment Variables are not actually used

Describe the bug
The template.yaml files contains the following environment variables:

SSOSYNC_GOOGLE_CREDENTIALS: !Ref AWSGoogleCredentialsSecret
SSOSYNC_GOOGLE_ADMIN: !Ref AWSGoogleAdminEamil
SSOSYNC_SCIM_ENDPOINT: !Ref AWSSCIMEndpointSecret
SSOSYNC_SCIM_ACCESS_TOKEN: !Ref AWSSCIMAccessTokenSecret

These variables, however, are not actually used in the source code. Instead secrets.go contains hard coded values.

Expected behavior
Environment Variables should be used to allow configuration of the ssosync app.

SSOSYNC_GROUP_MATCH not filtering groups in Lambda

Describe the bug
Trying to configure ssosync to filter using either name or email prefix. All groups (and thus effectively all Users) are synced to AWS rather than just those matching the filter.

As a side-issue, all groups created in AWS SSO are named based on the email from the Google Workspace Group, where I'd expect the name to match name.

To Reproduce
Steps to reproduce the behavior:

  1. Installed SAM Application using https://console.aws.amazon.com/lambda/home#/create/app?applicationId=arn:aws:serverlessrepo:eu-west-1:084703771460:applications/ssosync

Using version 1.0.0-rc.8 based on inspecting the CloudFormation Template, Code URI: ############/arn:aws:serverlessrepo:eu-west-1:084703771460:applications-ssosync-versions-1.0.0-rc.8/110db7d7-a2bc-4f0a-9072-8e7fd347c160

  1. Ran with args '...'
Key Value
SSOSYNC_GOOGLE_ADMIN arn:aws:secretsmanager:us-east-2:############:secret:SSOSyncGoogleAdminEmail-...
SSOSYNC_GOOGLE_CREDENTIALS arn:aws:secretsmanager:us-east-2:############:secret:SSOSyncGoogleCredentials-...
SSOSYNC_LOG_FORMAT json
SSOSYNC_LOG_LEVEL info
SSOSYNC_SCIM_ACCESS_TOKEN arn:aws:secretsmanager:us-east-2:############:secret:SSOSyncSCIMAccessToken-...
SSOSYNC_SCIM_ENDPOINT arn:aws:secretsmanager:us-east-2:############:secret:SSOSyncSCIMEndpointUrl-...
SSOSYNC_SYNC_METHOD groups
SSOSYNC_GROUP_MATCH name:'My Company Access Group - AWS*' (also tried email:aws-*, name:aws-*, name:aws, and email:aws
  1. Inspect logs and see all groups being synced.

Expected behavior
Expect only those Groups matching the filter defined by SSOSYNC_GROUP_MATCH to sync from Google Workspace. I would think if it was just a bad filter, I would get 0 groups/users synced, but the fact that everything syncs makes it seem like the variable isn't being read.

Additional context
Found the instructions for set-up of this from: https://controltower.aws-management.tools/aa/sso/google/.

SSO syns failed: error creating user (it tried to create existing user and fails)

Hi, I use the latest 1.0.0-rc.10 version of ssosync and it fails for the last 2 week and I don't undestand what is the root cause.
The sync process fails on the random user which is already exists. What should I do to fix this issue ?

{
    "level": "debug",
    "msg": "updating aws users updated in google",
    "time": "2022-11-03T11:45:39Z"
}
{
    "level": "info",
    "msg": "creating user",
    "time": "2022-11-03T11:45:39Z",
    "user": "[email protected]"
}
{
    "level": "error",
    "msg": "error creating user",
    "time": "2022-11-03T11:45:39Z",
    "user": "[email protected]"
}
status of http response was 409: errorString
null

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.