Auth: Add skip_org_role_sync setting for github (#61673)

* add: skip_org_role_sync setting for github

* fix: frontend

* rearranged tests

* refactor: assignGrafanaAdmin skip also

* Add: tests for allowGrafanaAdmin

- both for the case when both settings are set and the setting for only
  allowGrafanaAdmin

* Apply suggestions from code review

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>

* Update docs/sources/setup-grafana/configure-grafana/_index.md

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>

* Update pkg/login/social/github_oauth.go

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>

* added vairable inside scope

* Update docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md

* Update docs/sources/setup-grafana/configure-security/configure-authentication/github/index.md

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
Eric Leijonmarck
2023-01-25 15:16:08 +01:00
committed by GitHub
co-authored by Christopher Moyer Ieva
parent 529e6c379f
commit 6bd11e0ebf
9 changed files with 103 additions and 7 deletions
+1
View File
@@ -148,6 +148,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
"OAuthSkipOrgRoleUpdateSync": hs.Cfg.OAuthSkipOrgRoleUpdateSync,
"SAMLSkipOrgRoleSync": hs.Cfg.SectionWithEnvOverrides("auth.saml").Key("skip_org_role_sync").MustBool(false),
"LDAPSkipOrgRoleSync": hs.Cfg.LDAPSkipOrgRoleSync,
"GithubSkipOrgRoleSync": hs.Cfg.GithubSkipOrgRoleSync,
"GoogleSkipOrgRoleSync": hs.Cfg.GoogleSkipOrgRoleSync,
"JWTAuthSkipOrgRoleSync": hs.Cfg.JWTAuthSkipOrgRoleSync,
"GrafanaComSkipOrgRoleSync": hs.Cfg.GrafanaComSkipOrgRoleSync,
+20 -6
View File
@@ -8,6 +8,8 @@ import (
"regexp"
"golang.org/x/oauth2"
"github.com/grafana/grafana/pkg/models/roletype"
)
type SocialGithub struct {
@@ -15,6 +17,7 @@ type SocialGithub struct {
allowedOrganizations []string
apiUrl string
teamIds []int
skipOrgRoleSync bool
}
type GithubTeam struct {
@@ -201,14 +204,25 @@ func (s *SocialGithub) UserInfo(client *http.Client, token *oauth2.Token) (*Basi
teams := convertToGroupList(teamMemberships)
role, grafanaAdmin := s.extractRoleAndAdmin(response.Body, teams, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, &InvalidBasicRoleError{idP: "Github", assignedRole: string(role)}
var role roletype.RoleType
var isGrafanaAdmin *bool = nil
if !s.skipOrgRoleSync {
var grafanaAdmin bool
role, grafanaAdmin = s.extractRoleAndAdmin(response.Body, teams, true)
if s.roleAttributeStrict && !role.IsValid() {
return nil, &InvalidBasicRoleError{idP: "Github", assignedRole: string(role)}
}
if s.allowAssignGrafanaAdmin {
isGrafanaAdmin = &grafanaAdmin
}
}
var isGrafanaAdmin *bool = nil
if s.allowAssignGrafanaAdmin {
isGrafanaAdmin = &grafanaAdmin
// we skip allowing assignment of GrafanaAdmin if skipOrgRoleSync is present
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{
+36
View File
@@ -112,11 +112,14 @@ const testGHUserJSON = `{
}`
func TestSocialGitHub_UserInfo(t *testing.T) {
var boolPointer *bool
tests := []struct {
name string
userRawJSON string
userTeamsRawJSON string
settingAutoAssignOrgRole string
settingAllowGrafanaAdmin bool
settingSkipOrgRoleSync bool
roleAttributePath string
autoAssignOrgRole string
want *BasicUserInfo
@@ -167,6 +170,38 @@ func TestSocialGitHub_UserInfo(t *testing.T) {
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "Should be empty role if setting skipOrgRoleSync is set to true",
roleAttributePath: "contains(groups[*], '@github/justice-league') && 'Editor' || 'Viewer'",
settingSkipOrgRoleSync: true,
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
want: &BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
},
},
{
name: "Should return nil pointer if allowGrafanaAdmin and skipOrgRoleSync setting is set to true",
roleAttributePath: "contains(groups[*], '@github/justice-league') && 'Editor' || 'Viewer'",
settingSkipOrgRoleSync: true,
settingAllowGrafanaAdmin: true,
userRawJSON: testGHUserJSON,
userTeamsRawJSON: testGHUserTeamsJSON,
want: &BasicUserInfo{
Id: "1",
Name: "monalisa octocat",
Email: "octocat@github.com",
Login: "octocat",
Role: "",
Groups: []string{"https://github.com/orgs/github/teams/justice-league", "@github/justice-league"},
IsGrafanaAdmin: boolPointer,
},
},
{ // Case that's going to change with Grafana 10
name: "No fallback to default org role (will change in Grafana 10)",
roleAttributePath: "",
@@ -208,6 +243,7 @@ func TestSocialGitHub_UserInfo(t *testing.T) {
allowedOrganizations: []string{},
apiUrl: server.URL + "/user",
teamIds: []int{},
skipOrgRoleSync: tt.settingSkipOrgRoleSync,
}
token := &oauth2.Token{
+1
View File
@@ -146,6 +146,7 @@ func ProvideService(cfg *setting.Cfg, features *featuremgmt.FeatureManager) *Soc
apiUrl: info.ApiUrl,
teamIds: sec.Key("team_ids").Ints(","),
allowedOrganizations: util.SplitString(sec.Key("allowed_organizations").String()),
skipOrgRoleSync: cfg.GithubSkipOrgRoleSync,
}
}
+12
View File
@@ -467,6 +467,9 @@ type Cfg struct {
// then Live uses AppURL as the only allowed origin.
LiveAllowedOrigins []string
// Github OAuth
GithubSkipOrgRoleSync bool
// Grafana.com URL, used for OAuth redirect.
GrafanaComURL string
// Grafana.com API URL. Can be set separately to GrafanaComURL
@@ -1375,6 +1378,11 @@ func readAuthGrafanaComSettings(iniFile *ini.File, cfg *Cfg) {
cfg.GrafanaComSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGithubSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.github")
cfg.GithubSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGoogleSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.google")
cfg.GoogleSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
@@ -1501,7 +1509,11 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
cfg.AuthProxyHeadersEncoded = authProxy.Key("headers_encoded").MustBool(false)
// GrafanaCom
readAuthGrafanaComSettings(iniFile, cfg)
// Github
readAuthGithubSettings(iniFile, cfg)
return nil
}