-
Notifications
You must be signed in to change notification settings - Fork 48
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
AUTH-8: Add group synchronization from OIDC providers #87
Conversation
/cc @s-urbaniak @ibihim |
/hold |
/hold cancel |
e4c60b0
to
a8b4672
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.
Great PR. I can't yet understand everything, but I hope my comments help you nevertheless.
pkg/cmd/oauth-server/server.go
Outdated
@@ -33,7 +33,7 @@ func RunOsinServer(osinConfig *osinv1.OsinServerConfig, stopCh <-chan struct{}) | |||
return errors.New("osin server requires non-empty oauthConfig") | |||
} | |||
|
|||
oauthServerConfig, err := newOAuthServerConfig(osinConfig) | |||
oauthServerConfig, postStartHooks, err := newOAuthServerConfig(osinConfig) |
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.
Wouldn't it be better, if postStartHooks
would be returned from a dedicated function or being part of the oauthServerConfig
(if they config something)?
I wouldn't anticipate to retrieve hooks, when calling for a config.
The main point, as far as I can tell (and this is not much, as I am a newbie and I am looking from an abstract and not holistic view), we are handing the definition of the hooks down to reach the informer. So I would assume that we could create the informer on this level and hand it down to the config and a dedicated make-hooks 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.
This is the same how the postStartHooks
are being passed through the other apiservers (oauth-, openshift- and kube-apiservers).
I don't think return of postStartHooks
is actually that surprising here. You're generating configuration for the apiserver, and you want the apiserver to run certain actions that make the configuration work properly.
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.
If it is idiomatic, let keep doing it that way 😄
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.
In order to understand the idiomatic attempt to handling postStartHooks I looked into kubernetes/apiserver
and openshift/openshift-apiserver
, but couldn't find a similar pattern. In the former it is part of the Server
and injected and in the later it is part of the Config
.
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.
Hmm, I think my point was more about delivering the postStartHooks
to the inner GenericAPIServer
of the server object,
I can hide the hooks in the config structure if you want, and use it while setting up the OAuthServer
struct in the completedOAuthConfig.New
method if you want.
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.
moved the postStartHooks to the config
pkg/groupmapper/groupmapper.go
Outdated
// FIXME: add retries | ||
// FIXME: use idpName | ||
func (m *UserGroupsMapper) removeUserFromGroupWithRetries(idpName, username, group string) error { | ||
updatedGroup, err := m.groupsClient.Get(context.TODO(), group, metav1.GetOptions{}) |
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.
Shouldn't we bubble up the ctx?
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.
the context is unfortunately not wired through the oauth-server, and I fear that to really do it properly we would have to also implement openshift/osin#82
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.
on Sep 18, 2015
👀
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.
Ok, I would mark the suggestion as too big for the issue.
Do we have refactoring opportunities?
74983be
to
81db104
Compare
/test verify |
/hold |
userIdentityMapping userclient.UserIdentityMappingInterface, | ||
method identitymapper.MappingMethodType, | ||
) (api.UserIdentityMapper, error) { | ||
userMapper, err := identitymapper.NewIdentityUserMapper( |
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.
as far as i see NewIdentityUserMapper
is unused, is there any reason to keep this separate constructor? I think we are instanciating with groups only, no?
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.
We are wrapping the UserIdentityWrapper
result of the NewIdentityUserMapper
with a groups mapper. I think it's worth having it separate to keep the logical wrapper -> wrapped
relationship as each of these mappers are serving a slightly different purpose.
now with real bumps! |
groups userclient.GroupInterface, | ||
groupsLister userlisterv1.GroupLister, | ||
userIdentityMapping userclient.UserIdentityMappingInterface, | ||
method identitymapper.MappingMethodType, |
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.
Nit: quite some amount of params. At some point we should consider switching to a config / functional options.
pkg/cmd/oauth-server/server.go
Outdated
@@ -33,7 +33,7 @@ func RunOsinServer(osinConfig *osinv1.OsinServerConfig, stopCh <-chan struct{}) | |||
return errors.New("osin server requires non-empty oauthConfig") | |||
} | |||
|
|||
oauthServerConfig, err := newOAuthServerConfig(osinConfig) | |||
oauthServerConfig, postStartHooks, err := newOAuthServerConfig(osinConfig) |
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.
In order to understand the idiomatic attempt to handling postStartHooks I looked into kubernetes/apiserver
and openshift/openshift-apiserver
, but couldn't find a similar pattern. In the former it is part of the Server
and injected and in the later it is part of the Config
.
pkg/oauthserver/oauth_apiserver.go
Outdated
@@ -43,7 +49,7 @@ func init() { | |||
|
|||
// TODO we need to switch the oauth server to an external type, but that can be done after we get our externally facing flag values fixed | |||
// TODO remaining bits involve the session file, LDAP util code, validation, ... | |||
func NewOAuthServerConfig(oauthConfig osinv1.OAuthConfig, userClientConfig *rest.Config, genericConfig *genericapiserver.RecommendedConfig) (*OAuthServerConfig, error) { | |||
func NewOAuthServerConfig(oauthConfig osinv1.OAuthConfig, userClientConfig *rest.Config, genericConfig *genericapiserver.RecommendedConfig) (*OAuthServerConfig, map[string]genericapiserver.PostStartHookFunc, error) { |
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.
It would be cool if we could at some point trim down the function 😄
pkg/oauthserver/oauth_apiserver.go
Outdated
return ret, nil | ||
postStartHooks := map[string]genericapiserver.PostStartHookFunc{ | ||
"openshift.io-StartUserInformer": func(ctx genericapiserver.PostStartHookContext) error { | ||
go userInformer.Start(ctx.StopCh) |
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.
Do we need to start it as a Go routine? The Start
method seems to iterate over the internal informers and start a Go routine too.
https://github.com/kubernetes/apiserver/blob/master/pkg/server/config.go#L664
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 think it might be better to make sure the call is non-blocking if we don't own the implementation, but I can change it to not use the goroutine if you want.
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.
It would be interesting to know if this Go routines will stay alive for as long as the child-Go routines are alive.
If the minimal blocking, while iterating through the for-loop could be more problematic than an additional Go-routine, then I am fine 😄
Wrap usermappers with a groupmapper that attempts to add a user to groups that they are not a part of or remove them from groups for the specific provider.
/hold cancel |
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.
/lgtm
Name: group, | ||
Annotations: map[string]string{ | ||
fmt.Sprintf(groupSyncedKeyFmt, idpName): "synced", | ||
groupGeneratedKey: "true", |
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.
Nit:
Sorry, I just now realized this. Would it make sense to make "synced"
and "true"
constants?
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ibihim, stlaz The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/retest-required Please review the full test history for this PR and help us cut down flakes. |
1 similar comment
/retest-required Please review the full test history for this PR and help us cut down flakes. |
This PR adds group synchronization for OIDC providers as described in the Synchronizing User Groups on Login enhancement.
The usermappers normally used to create users are wrapped by a delegator that first attempts to perform the usermapping strategy and only after its success it attempts to add/remove the user in appropriate groups.