-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved Google OIDC connector #9697
Conversation
a8f4359
to
751b125
Compare
751b125
to
50a0369
Compare
9dbb4f2
to
fa0e2ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add test coverage?
Either of the following would allow you to test with out needing to talk to google:
- Migrating the
groupsFromGsuite*
functions to an interface would allow you to mock the client - Utilizing WithEndpoint or WithGRPCConn would allow you to mock google
52dda21
to
544c2e6
Compare
dce94e7
to
b324fe3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let a few small comments. Looks good otherwise.
b324fe3
to
1eb37e2
Compare
1eb37e2
to
2e5b33a
Compare
lib/auth/oidc_google.go
Outdated
// actual docs for the API call are at | ||
// https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/searchTransitiveGroups . | ||
err = service.Groups.Memberships.SearchTransitiveGroups("groups/-"). | ||
Query(fmt.Sprintf("member_key_id == '%s' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels", email)). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this query language work? Does it have the equivalent of parameterized queries?
I'm wondering if you can do something like SQL injection with it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried looking for a "proper" way to do this, but the only library to handle this (https://github.com/google/cel-go) is apparently only for evaluating CEL expressions in text form, not for building them; I don't think it's a problem here, because the email
parameter we use to format the string is the email
that came as part of the OIDC claims, so it's something that Google considers to be a valid email address - which I don't believe can include any '
s.
@espadolini Just to make sure I understand this correctly, this PR solves two problems.
For (1), the issue is resolved by no longer filtering on a particular domain when we make the groups.list query. However, this does entail a change in default behavior as you will get all domains a user is part of. For (2), from what I can tell the main issue is that to support getting transitive group membership, we have to call different API endpoints that not all users may have access to due to needing to be on a Google Workspace Enterprise plan. Is there any other way to solve (2) or is the Enterprise plan the only way to get transitive group membership for a user? |
That's correct. The change in default behavior could be mitigated by putting the groups that don't match the domain of the user into a separate claim ( I don't think there's a reasonable way to get transitive group memberships without using the intended API - anything ad-hoc that we build ourselves would be too spammy and fragile. |
@espadolini For (1), let's bump the version of the connector to For (2), can we update the logic to always call |
fa75539
to
c49bdb3
Compare
@espadolini Please add documentation the two changes in behavior for |
c49bdb3
to
2e342c9
Compare
return nil, trace.Wrap(err) | ||
} | ||
} else { | ||
credentials, err := getGoogleWorkspaceCredentials(ctx, connector, directory.AdminDirectoryGroupReadonlyScope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar logic to the V2 logic below, consider parameterizing into a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had tried refactoring it a bit but this is still the clearest way to write it that I've found, I'm afraid. 😢
@@ -102,8 +102,8 @@ func UnmarshalOIDCConnector(bytes []byte, opts ...MarshalOption) (types.OIDCConn | |||
return nil, trace.Wrap(err) | |||
} | |||
switch h.Version { | |||
case types.V2: | |||
var c types.OIDCConnectorV2 | |||
case types.V2, types.V3: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this is standard practice elsewhere in the codebase, in which case ignore this comment, however if not then it may be confusing why we are using an OIDCConnectorV3
for case V2
and worthy of a clarifying comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a comment in (*OIDCConnectorV3).CheckAndSetDefaults()
already, but it's probably useful to restate it here as well.
f709b35
to
2353bb6
Compare
go get: upgraded cloud.google.com/go v0.60.0 => v0.100.2 go get: upgraded github.com/golang/snappy v0.0.1 => v0.0.3 go get: upgraded github.com/googleapis/gax-go/v2 v2.0.5 => v2.1.1 go get: upgraded go.opencensus.io v0.22.5 => v0.23.0 go get: upgraded golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d => v0.0.0-20211104180415-d3ed0bb246c8 go get: upgraded google.golang.org/api v0.29.0 => v0.65.0
This undoes the user account impersonation changes, and always requires an admin account again.
This also removes the extra boolean flag that was added previously.
Enterprise builds will break unless gravitational/teleport.e#385 is included.
2353bb6
to
c463543
Compare
* go get google.golang.org/api go get: upgraded cloud.google.com/go v0.60.0 => v0.100.2 go get: upgraded github.com/golang/snappy v0.0.1 => v0.0.3 go get: upgraded github.com/googleapis/gax-go/v2 v2.0.5 => v2.1.1 go get: upgraded go.opencensus.io v0.22.5 => v0.23.0 go get: upgraded golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d => v0.0.0-20211104180415-d3ed0bb246c8 go get: upgraded golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 => v0.0.0-20211216021012-1d35b9e2eb4e go get: upgraded google.golang.org/api v0.29.0 => v0.65.0 go get: upgraded google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c => v0.0.0-20220107163113-42d7afdf6368 go get: upgraded google.golang.org/protobuf v1.26.0 => v1.27.1 * Optionally fetch transitive groups in the Google OIDC connector * Refactor the google workspace parts of the OIDC code * Further refactoring This undoes the user account impersonation changes, and always requires an admin account again. * Test coverage * Address review comments * Minor refactor and name changes * Allow domain filtering, tests now bypass addGoogleWorkspaceClaims * Update `OIDCConnectorV2` to `OIDCConnectorV3` * Backwards compatibility for OIDCConnector v2 This also removes the extra boolean flag that was added previously. * Update e-ref Enterprise builds will break unless gravitational/teleport.e#387 is included.
Optional Google Cloud Identity support to fetch transitive groups (i.e. groups that a user belongs to both directly and indirectly through nested groups) for SSO.
This bumps the version of the
oidc
resources fromv2
tov3
, supporting both versions, with no change to the actual spec for the resource; the behavior ofv2
connectors will stay the same, whilev3
connectors will not filter the returned groups by domain name, and (depending on the permissions of the configured service account) will attempt to fetch both direct and indirect groups.Fixes #8122.
Fixes #5521.