From 7f5d6d9e2d2c16c21e4c0c06bf3f835d6cf15fb7 Mon Sep 17 00:00:00 2001 From: "t.fouchard" Date: Wed, 23 Oct 2019 13:47:21 +0200 Subject: [PATCH] Allow to prefix retrieved by gitlab groups --- connector/gitlab/gitlab.go | 17 ++++++ connector/gitlab/gitlab_test.go | 92 +++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/connector/gitlab/gitlab.go b/connector/gitlab/gitlab.go index a9b0abe2b2..6d6730c801 100644 --- a/connector/gitlab/gitlab.go +++ b/connector/gitlab/gitlab.go @@ -33,6 +33,7 @@ type Config struct { RedirectURI string `json:"redirectURI"` Groups []string `json:"groups"` UseLoginAsID bool `json:"useLoginAsID"` + GroupPrefix string `json:"groupPrefix"` } type gitlabUser struct { @@ -57,6 +58,7 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) logger: logger, groups: c.Groups, useLoginAsID: c.UseLoginAsID, + groupPrefix: c.GroupPrefix, }, nil } @@ -80,6 +82,7 @@ type gitlabConnector struct { httpClient *http.Client // if set to true will use the user's handle rather than their numeric id as the ID useLoginAsID bool + groupPrefix string } func (c *gitlabConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config { @@ -162,6 +165,13 @@ func (c *gitlabConnector) HandleCallback(s connector.Scopes, r *http.Request) (i if err != nil { return identity, fmt.Errorf("gitlab: get groups: %v", err) } + + if c.groupPrefix != "" { + for grpIdx := range groups { + groups[grpIdx] = c.groupPrefix + groups[grpIdx] + } + } + identity.Groups = groups } @@ -206,6 +216,13 @@ func (c *gitlabConnector) Refresh(ctx context.Context, s connector.Scopes, ident if err != nil { return ident, fmt.Errorf("gitlab: get groups: %v", err) } + + if c.groupPrefix != "" { + for grpIdx := range groups { + groups[grpIdx] = c.groupPrefix + groups[grpIdx] + } + } + ident.Groups = groups } return ident, nil diff --git a/connector/gitlab/gitlab_test.go b/connector/gitlab/gitlab_test.go index 331b486ee4..58ef1f7c50 100644 --- a/connector/gitlab/gitlab_test.go +++ b/connector/gitlab/gitlab_test.go @@ -101,6 +101,43 @@ func TestUsernameIncludedInFederatedIdentity(t *testing.T) { expectEquals(t, identity.Groups, []string{"team-1"}) } +func TestUsernameIncludedInFederatedIdentityGroupPrefix(t *testing.T) { + + s := newTestServer(map[string]interface{}{ + "/api/v4/user": gitlabUser{Email: "some@email.com", ID: 12345678}, + "/oauth/token": map[string]interface{}{ + "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9", + "expires_in": "30", + }, + "/oauth/userinfo": userInfo{ + Groups: []string{"team-1"}, + }, + }) + defer s.Close() + + hostURL, err := url.Parse(s.URL) + expectNil(t, err) + + req, err := http.NewRequest("GET", hostURL.String(), nil) + expectNil(t, err) + + c := gitlabConnector{baseURL: s.URL, httpClient: newClient(), groupPrefix: "gl_"} + identity, err := c.HandleCallback(connector.Scopes{Groups: false}, req) + + expectNil(t, err) + expectEquals(t, identity.Username, "some@email.com") + expectEquals(t, identity.UserID, "12345678") + expectEquals(t, 0, len(identity.Groups)) + + c = gitlabConnector{baseURL: s.URL, httpClient: newClient(), groupPrefix: "gl_"} + identity, err = c.HandleCallback(connector.Scopes{Groups: true}, req) + + expectNil(t, err) + expectEquals(t, identity.Username, "some@email.com") + expectEquals(t, identity.UserID, "12345678") + expectEquals(t, identity.Groups, []string{"gl_team-1"}) +} + func TestLoginUsedAsIDWhenConfigured(t *testing.T) { s := newTestServer(map[string]interface{}{ @@ -157,6 +194,34 @@ func TestLoginWithTeamWhitelisted(t *testing.T) { expectEquals(t, identity.Username, "Joe Bloggs") } +func TestLoginWithTeamWhitelistedGroupPrefix(t *testing.T) { + + s := newTestServer(map[string]interface{}{ + "/api/v4/user": gitlabUser{Email: "some@email.com", ID: 12345678, Name: "Joe Bloggs"}, + "/oauth/token": map[string]interface{}{ + "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9", + "expires_in": "30", + }, + "/oauth/userinfo": userInfo{ + Groups: []string{"team-1"}, + }, + }) + defer s.Close() + + hostURL, err := url.Parse(s.URL) + expectNil(t, err) + + req, err := http.NewRequest("GET", hostURL.String(), nil) + expectNil(t, err) + + c := gitlabConnector{baseURL: s.URL, httpClient: newClient(), groups: []string{"team-1"}, groupPrefix: "gl_"} + identity, err := c.HandleCallback(connector.Scopes{Groups: true}, req) + + expectNil(t, err) + expectEquals(t, identity.UserID, "12345678") + expectEquals(t, identity.Username, "Joe Bloggs") +} + func TestLoginWithTeamNonWhitelisted(t *testing.T) { s := newTestServer(map[string]interface{}{ @@ -184,6 +249,33 @@ func TestLoginWithTeamNonWhitelisted(t *testing.T) { expectEquals(t, err.Error(), "gitlab: get groups: gitlab: user \"joebloggs\" is not in any of the required groups") } +func TestLoginWithTeamNonWhitelistedGroupPrefix(t *testing.T) { + + s := newTestServer(map[string]interface{}{ + "/api/v4/user": gitlabUser{Email: "some@email.com", ID: 12345678, Name: "Joe Bloggs", Username: "joebloggs"}, + "/oauth/token": map[string]interface{}{ + "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9", + "expires_in": "30", + }, + "/oauth/userinfo": userInfo{ + Groups: []string{"team-1"}, + }, + }) + defer s.Close() + + hostURL, err := url.Parse(s.URL) + expectNil(t, err) + + req, err := http.NewRequest("GET", hostURL.String(), nil) + expectNil(t, err) + + c := gitlabConnector{baseURL: s.URL, httpClient: newClient(), groups: []string{"team-2"}, groupPrefix: "gl_"} + _, err = c.HandleCallback(connector.Scopes{Groups: true}, req) + + expectNotNil(t, err, "HandleCallback error") + expectEquals(t, err.Error(), "gitlab: get groups: gitlab: user \"joebloggs\" is not in any of the required groups") +} + func newTestServer(responses map[string]interface{}) *httptest.Server { return httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { response := responses[r.RequestURI]