Auth: Add skip_org_role_sync to GitLab OAuth (#62055)

* Auth: Add skip_org_role_sync to GitLab OAuth

- add: tests
- docs added

* Update pkg/login/social/gitlab_oauth.go

Co-authored-by: Karl Persson <kalle.persson@grafana.com>

* fix: for import

Co-authored-by: Karl Persson <kalle.persson@grafana.com>
This commit is contained in:
Eric Leijonmarck
2023-01-25 13:39:54 +01:00
committed by GitHub
co-authored by Karl Persson
parent 5f6616ff3e
commit 143ee0c49f
11 changed files with 85 additions and 13 deletions
+1
View File
@@ -151,6 +151,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
"GoogleSkipOrgRoleSync": hs.Cfg.GoogleSkipOrgRoleSync,
"JWTAuthSkipOrgRoleSync": hs.Cfg.JWTAuthSkipOrgRoleSync,
"GrafanaComSkipOrgRoleSync": hs.Cfg.GrafanaComSkipOrgRoleSync,
"GitLabSkipOrgRoleSync": hs.Cfg.GitLabSkipOrgRoleSync,
"AzureADSkipOrgRoleSync": hs.Cfg.AzureADSkipOrgRoleSync,
"DisableSyncLock": hs.Cfg.DisableSyncLock,
},
+19 -9
View File
@@ -7,12 +7,15 @@ import (
"regexp"
"golang.org/x/oauth2"
"github.com/grafana/grafana/pkg/models/roletype"
)
type SocialGitlab struct {
*SocialBase
allowedGroups []string
apiUrl string
allowedGroups []string
apiUrl string
skipOrgRoleSync bool
}
func (s *SocialGitlab) IsGroupMember(groups []string) bool {
@@ -107,14 +110,21 @@ func (s *SocialGitlab) UserInfo(client *http.Client, _ *oauth2.Token) (*BasicUse
groups := s.GetGroups(client)
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, groups, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, &InvalidBasicRoleError{idP: "Gitlab", assignedRole: string(role)}
}
var role roletype.RoleType
var isGrafanaAdmin *bool = nil
if s.allowAssignGrafanaAdmin {
isGrafanaAdmin = &grafanaAdmin
if !s.skipOrgRoleSync {
var grafanaAdmin bool
role, grafanaAdmin = s.extractRoleAndAdmin(response.Body, groups, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, &InvalidBasicRoleError{idP: "Gitlab", assignedRole: string(role)}
}
if s.allowAssignGrafanaAdmin {
isGrafanaAdmin = &grafanaAdmin
}
}
if s.allowAssignGrafanaAdmin && s.skipOrgRoleSync {
s.log.Debug("allowAssignGrafanaAdmin and skipOrgRoleSync are both set, Grafana Admin role will not be synced, consider setting one or the other")
}
userInfo := &BasicUserInfo{
+15
View File
@@ -27,16 +27,19 @@ const (
)
func TestSocialGitlab_UserInfo(t *testing.T) {
var nilPointer *bool
provider := SocialGitlab{
SocialBase: &SocialBase{
log: newLogger("gitlab_oauth_test", "debug"),
},
skipOrgRoleSync: false,
}
type conf struct {
AllowAssignGrafanaAdmin bool
RoleAttributeStrict bool
AutoAssignOrgRole org.RoleType
SkipOrgRoleSync bool
}
tests := []struct {
@@ -83,6 +86,17 @@ func TestSocialGitlab_UserInfo(t *testing.T) {
ExpectedRole: "Editor",
ExpectedGrafanaAdmin: falseBoolPtr(),
},
{
Name: "Should not sync role, return empty role and nil pointer for GrafanaAdmin for skip org role sync set to true",
Cfg: conf{SkipOrgRoleSync: true},
UserRespBody: editorUserRespBody,
GroupsRespBody: "[" + strings.Join([]string{viewerGroup, editorGroup}, ",") + "]",
RoleAttributePath: gitlabAttrPath,
ExpectedLogin: "gitlab-editor",
ExpectedEmail: "gitlab-editor@example.org",
ExpectedRole: "",
ExpectedGrafanaAdmin: nilPointer,
},
{ // Case that's going to change with Grafana 10
Name: "No fallback to default org role (will change in Grafana 10)",
Cfg: conf{AutoAssignOrgRole: org.RoleViewer},
@@ -126,6 +140,7 @@ func TestSocialGitlab_UserInfo(t *testing.T) {
provider.allowAssignGrafanaAdmin = test.Cfg.AllowAssignGrafanaAdmin
provider.autoAssignOrgRole = string(test.Cfg.AutoAssignOrgRole)
provider.roleAttributeStrict = test.Cfg.RoleAttributeStrict
provider.skipOrgRoleSync = test.Cfg.SkipOrgRoleSync
t.Run(test.Name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+4 -3
View File
@@ -152,9 +152,10 @@ func ProvideService(cfg *setting.Cfg, features *featuremgmt.FeatureManager) *Soc
// GitLab.
if name == "gitlab" {
ss.socialMap["gitlab"] = &SocialGitlab{
SocialBase: newSocialBase(name, &config, info, cfg.AutoAssignOrgRole, cfg.OAuthSkipOrgRoleUpdateSync, *features),
apiUrl: info.ApiUrl,
allowedGroups: util.SplitString(sec.Key("allowed_groups").String()),
SocialBase: newSocialBase(name, &config, info, cfg.AutoAssignOrgRole, cfg.OAuthSkipOrgRoleUpdateSync, *features),
apiUrl: info.ApiUrl,
allowedGroups: util.SplitString(sec.Key("allowed_groups").String()),
skipOrgRoleSync: cfg.GitLabSkipOrgRoleSync,
}
}
+11
View File
@@ -430,6 +430,9 @@ type Cfg struct {
// Google
GoogleSkipOrgRoleSync bool
// Gitlab
GitLabSkipOrgRoleSync bool
// LDAP
LDAPEnabled bool
LDAPSkipOrgRoleSync bool
@@ -1377,6 +1380,11 @@ func readAuthGoogleSettings(iniFile *ini.File, cfg *Cfg) {
cfg.GoogleSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGitlabSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.gitlab")
cfg.GitLabSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
auth := iniFile.Section("auth")
@@ -1434,6 +1442,9 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
// Google Auth
readAuthGoogleSettings(iniFile, cfg)
// GitLab Auth
readAuthGitlabSettings(iniFile, cfg)
// anonymous access
AnonymousEnabled = iniFile.Section("auth.anonymous").Key("enabled").MustBool(false)
cfg.AnonymousEnabled = AnonymousEnabled