-
Notifications
You must be signed in to change notification settings - Fork 11.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
Auth: Enforce role sync except if skip org role sync is enabled #70766
Conversation
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.
Mostly looks good, but I added some questions about:
- the behaviour when
roleAttributeStrict
is set for generic OAuth; - the role that we should default to if default org role is not set in the config;
- the use of
errutil
.
I think we should also update the description of auto_assign_org_role
in the config and docs, as it's currently not very accurate ("# Default role new users will be automatically assigned (if auto_assign_org above is set to true)"). I'm happy to handle docs as part of the docs work, but I think we should update the description in config files now.
errRoleAttributePathNotSet = errutil.NewBase(errutil.StatusBadRequest, | ||
"oauth.role_attribute_path_not_set", | ||
errutil.WithPublicMessage("Instance role_attribute_path misconfigured, please contact your administrator")) |
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'm not sure the errors will be parsed correctly, as we seem to use errutil
error where this error is returned: https://github.com/grafana/grafana/blob/main/pkg/services/authn/clients/oauth.go#L125
Maybe it's fine, but worth testing (I can give it a go if you want).
pkg/login/social/social.go
Outdated
if role != "" { | ||
return "", false, errInvalidRole.Errorf("invalid role: %s", role) |
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.
Note: looks like we already check that the role is valid when we read the settings: https://github.com/grafana/grafana/blob/main/pkg/setting/setting.go#L1641 But I guess it doesn't hurt to do it twice.
pkg/login/social/generic_oauth.go
Outdated
} | ||
} | ||
if (userInfo.Role == "" || userInfo.Role == s.defaultRole()) && !s.skipOrgRoleSync { | ||
role, grafanaAdmin, err := s.extractRoleAndAdmin(data.rawJSON, []string{}, 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.
This will fail if we fail to get the role from the token and roleAttributeStrict
, right? I think we should allow for the role to be extracted from the API.
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
} else if role != "" { | ||
return "", false, errInvalidRole.Errorf("invalid role: %s", role) |
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.
question: should we fail if an invalid role is found? Or just if the role is invalid + roleAttributeStrict
is set?
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'll only log and fallthrough to the next method.
After the 2 methods are evaluated we'll set to default role if the role is still "".
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.
Sorry to block this again, but I think that the logic still isn't correct for generic OAuth.
|
||
func (s *SocialBase) extractRoleAndAdmin(rawJSON []byte, groups []string) (org.RoleType, bool, error) { | ||
role, gAdmin, err := s.extractRoleAndAdminOptional(rawJSON, groups) | ||
if role == "" { |
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.
question: should we still set the role to default even if an error is returned?
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.
fixed so it's only handled after the 2 methods
role, grafanaAdmin, err := s.extractRoleAndAdminOptional(data.rawJSON, []string{}) | ||
if err != nil { |
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 still don't think we can return an error here - this would fail if roleAttributeStrict
is set to true
, but the role is being sent through the user info endpoint (it would fail, as the role won't be successfully parsed from the token).
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.
fixed so role attribute strict is only evaluated after the 2 methods
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.
Looks good to me now! Fingers crossed that we haven't missed anything 🤞
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, great job! 🙂
I like how tidy the extractRoleAndAdmin
code is.
Food for thought: Would it be possible to use extractRoleAndAdmin
for AzureAD as well with a default role_attribute_path
correctly set? To have all providers falling back on the same function.
@@ -1645,7 +1646,11 @@ func readUserSettings(iniFile *ini.File, cfg *Cfg) error { | |||
AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true) | |||
cfg.AutoAssignOrg = users.Key("auto_assign_org").MustBool(true) | |||
cfg.AutoAssignOrgId = users.Key("auto_assign_org_id").MustInt(1) | |||
cfg.AutoAssignOrgRole = users.Key("auto_assign_org_role").In("Editor", []string{"Editor", "Admin", "Viewer"}) | |||
cfg.AutoAssignOrgRole = users.Key("auto_assign_org_role").In( | |||
string(roletype.RoleViewer), []string{ |
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.
Seems more logic to be in line with defaults.ini
😄
Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
* enforce role sync except if skip org role sync is enabled * move errors to errors file and set codes * fix docs and defaults * remove legacy parameter * support fall through token-api in generic oauth * fix error handling for generic_oauth * Update pkg/login/social/generic_oauth.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> * Update pkg/login/social/gitlab_oauth_test.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> * Update pkg/login/social/gitlab_oauth_test.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> --------- Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
What is this feature?
If the information provided by the identity provider is empty, make the idP set the default org role.
Use
skip_org_role_sync
to leave it emptyUse
role_attribute_strict
to ensure it gets set by the idPRelease notice breaking change
This change impacts GitHub OAuth, Gitlab OAuth, Okta OAuth and Generic OAuth
Currently if no organization role mapping is found for a user when connecting via OAuth, Grafana doesn’t update the user’s organization role.
With Grafana 10.1, on every login, if the role_attribute_path property does not return a role, then the user is assigned the role specified by the auto_assign_org_role option.
To avoid overriding manually set roles, enable the
skip_org_role_sync
option in the Grafana configuration for your OAuth provider.