From 19eaf7de8524226817414e1e712d7e7a148c3e77 Mon Sep 17 00:00:00 2001 From: Jacob Aae Mikkelsen Date: Fri, 21 Oct 2016 10:47:59 +0200 Subject: [PATCH 1/5] Allow gitlab-group as input parameter --- main.go | 1 + options.go | 3 +++ providers/gitlab.go | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/main.go b/main.go index ba3366876..c017cef16 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,7 @@ func main() { flagSet.String("azure-tenant", "common", "go to a tenant-specific or common (tenant-independent) endpoint.") flagSet.String("github-org", "", "restrict logins to members of this organisation") flagSet.String("github-team", "", "restrict logins to members of this team") + flagSet.String("gitlab-group", "", "restrict logins to members of this group") flagSet.Var(&googleGroups, "google-group", "restrict logins to members of this google group (may be given multiple times).") flagSet.String("google-admin-email", "", "the google admin to impersonate for api calls") flagSet.String("google-service-account-json", "", "the path to the service account json credentials") diff --git a/options.go b/options.go index 4777d9d1e..03f66c3a1 100644 --- a/options.go +++ b/options.go @@ -31,6 +31,7 @@ type Options struct { EmailDomains []string `flag:"email-domain" cfg:"email_domains"` GitHubOrg string `flag:"github-org" cfg:"github_org"` GitHubTeam string `flag:"github-team" cfg:"github_team"` + GitLabGroup string `flag:"gitlab-group" cfg:"gitlab_group"` GoogleGroups []string `flag:"google-group" cfg:"google_group"` GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email"` GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json"` @@ -229,6 +230,8 @@ func parseProviderInfo(o *Options, msgs []string) []string { p.Configure(o.AzureTenant) case *providers.GitHubProvider: p.SetOrgTeam(o.GitHubOrg, o.GitHubTeam) + case *providers.GitLabProvider: + p.SetGroup(o.GitLabGroup) case *providers.GoogleProvider: if o.GoogleServiceAccountJSON != "" { file, err := os.Open(o.GoogleServiceAccountJSON) diff --git a/providers/gitlab.go b/providers/gitlab.go index 708283add..4e1180cfb 100644 --- a/providers/gitlab.go +++ b/providers/gitlab.go @@ -10,6 +10,7 @@ import ( type GitLabProvider struct { *ProviderData + Group string } func NewGitLabProvider(p *ProviderData) *GitLabProvider { @@ -41,6 +42,10 @@ func NewGitLabProvider(p *ProviderData) *GitLabProvider { return &GitLabProvider{ProviderData: p} } +func (p *GitLabProvider) SetGroup(group string) { + p.Group = group +} + func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) { req, err := http.NewRequest("GET", From d4297228a59a858ff5e2dd97f87d01799968ecda Mon Sep 17 00:00:00 2001 From: Jacob Aae Mikkelsen Date: Fri, 21 Oct 2016 10:48:53 +0200 Subject: [PATCH 2/5] Respect gitlab-group in provider --- providers/gitlab.go | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/providers/gitlab.go b/providers/gitlab.go index 4e1180cfb..8c89239c6 100644 --- a/providers/gitlab.go +++ b/providers/gitlab.go @@ -6,6 +6,9 @@ import ( "net/url" "github.com/bitly/oauth2_proxy/api" + "fmt" + "io/ioutil" + "encoding/json" ) type GitLabProvider struct { @@ -46,8 +49,53 @@ func (p *GitLabProvider) SetGroup(group string) { p.Group = group } +func (p *GitLabProvider) hasGroup(accessToken string) (bool, error) { + + var groups []struct { + Group string `json:"name"` + } + + endpoint := p.ValidateURL.Scheme + "://" + p.ValidateURL.Host + "/api/v3/groups?access_token="+accessToken + req, _ := http.NewRequest("GET", endpoint, nil) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false, err + } + + body, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return false, err + } + if resp.StatusCode != 200 { + return false, fmt.Errorf("got %d from %q %s", resp.StatusCode, endpoint, body) + } + + if err := json.Unmarshal(body, &groups); err != nil { + return false, err + } + + for _, group := range groups { + if( p.Group == group.Group) { + // Found the group + return true, nil + } + } + + log.Printf("Group %s not found in %s", p.Group, groups) + return false, nil +} + + func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) { + // if we require a group, check that first + if p.Group != "" { + if ok, err := p.hasGroup(s.AccessToken); err != nil || !ok { + return "", err + } + } + req, err := http.NewRequest("GET", p.ValidateURL.String()+"?access_token="+s.AccessToken, nil) if err != nil { From 4f637a0bfdd613222e04a492b3b555d00dc42136 Mon Sep 17 00:00:00 2001 From: Jacob Aae Mikkelsen Date: Fri, 21 Oct 2016 10:49:17 +0200 Subject: [PATCH 3/5] Add documentation for gitlab-group configuration --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2e6e4c964..5c6b6240f 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,10 @@ If you are using GitHub enterprise, make sure you set the following to the appro Whether you are using GitLab.com or self-hosting GitLab, follow [these steps to add an application](http://doc.gitlab.com/ce/integration/oauth_provider.html) +The GitLab auth provider supports one additional parameters to restrict authentication to a specific group. Restricting by group is normally accompanied with `--email-domain=*` + + -gitlab-group="": restrict logins to members of this group + If you are using self-hosted GitLab, make sure you set the following to the appropriate URL: -login-url="/oauth/authorize" From 6b5a334c294656bb02b28d6d5d11367dd42cf111 Mon Sep 17 00:00:00 2001 From: Jacob Aae Mikkelsen Date: Wed, 15 Mar 2017 15:59:57 +0100 Subject: [PATCH 4/5] Minor updates based on review comments and gofmt --- README.md | 2 +- providers/gitlab.go | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5c6b6240f..07d2f0a96 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ If you are using GitHub enterprise, make sure you set the following to the appro Whether you are using GitLab.com or self-hosting GitLab, follow [these steps to add an application](http://doc.gitlab.com/ce/integration/oauth_provider.html) -The GitLab auth provider supports one additional parameters to restrict authentication to a specific group. Restricting by group is normally accompanied with `--email-domain=*` +The GitLab auth provider supports one additional parameter to restrict authentication to a specific group. Restricting by group is normally accompanied with `--email-domain=*` -gitlab-group="": restrict logins to members of this group diff --git a/providers/gitlab.go b/providers/gitlab.go index 8c89239c6..1e9c83293 100644 --- a/providers/gitlab.go +++ b/providers/gitlab.go @@ -5,10 +5,10 @@ import ( "net/http" "net/url" - "github.com/bitly/oauth2_proxy/api" + "encoding/json" "fmt" + "github.com/bitly/oauth2_proxy/api" "io/ioutil" - "encoding/json" ) type GitLabProvider struct { @@ -55,7 +55,7 @@ func (p *GitLabProvider) hasGroup(accessToken string) (bool, error) { Group string `json:"name"` } - endpoint := p.ValidateURL.Scheme + "://" + p.ValidateURL.Host + "/api/v3/groups?access_token="+accessToken + endpoint := p.ValidateURL.Scheme + "://" + p.ValidateURL.Host + "/api/v3/groups?access_token=" + accessToken req, _ := http.NewRequest("GET", endpoint, nil) resp, err := http.DefaultClient.Do(req) if err != nil { @@ -76,7 +76,7 @@ func (p *GitLabProvider) hasGroup(accessToken string) (bool, error) { } for _, group := range groups { - if( p.Group == group.Group) { + if p.Group == group.Group { // Found the group return true, nil } @@ -86,7 +86,6 @@ func (p *GitLabProvider) hasGroup(accessToken string) (bool, error) { return false, nil } - func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) { // if we require a group, check that first From 27643bc80f95abdf281257adc993d8c6efe83e35 Mon Sep 17 00:00:00 2001 From: Jacob Aae Mikkelsen Date: Sat, 24 Mar 2018 12:07:13 +0100 Subject: [PATCH 5/5] providers: gitlab: support pagination for groups Patch from BenoitKnecht: https://github.com/bitly/oauth2_proxy/commit/c141ff8da3ce7d865db38ccd4e5c157727a6b0d5 --- providers/gitlab.go | 57 ++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/providers/gitlab.go b/providers/gitlab.go index 1e9c83293..627ae8d70 100644 --- a/providers/gitlab.go +++ b/providers/gitlab.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/bitly/oauth2_proxy/api" "io/ioutil" + "strconv" ) type GitLabProvider struct { @@ -55,30 +56,44 @@ func (p *GitLabProvider) hasGroup(accessToken string) (bool, error) { Group string `json:"name"` } - endpoint := p.ValidateURL.Scheme + "://" + p.ValidateURL.Host + "/api/v3/groups?access_token=" + accessToken - req, _ := http.NewRequest("GET", endpoint, nil) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return false, err - } + endpoint := p.ValidateURL.Scheme + "://" + p.ValidateURL.Host + "/api/v3/groups" + for page := 1; page != 0; { + req, _ := http.NewRequest("GET", endpoint, nil) + query := req.URL.Query() + query.Add("access_token", accessToken) + query.Add("page", strconv.Itoa(page)) + req.URL.RawQuery = query.Encode() + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false, err + } - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - return false, err - } - if resp.StatusCode != 200 { - return false, fmt.Errorf("got %d from %q %s", resp.StatusCode, endpoint, body) - } + next := resp.Header["X-Next-Page"] + if len(next) == 1 { + page, _ = strconv.Atoi(next[0]) + } else { + // Last iteration + page = 0 + } - if err := json.Unmarshal(body, &groups); err != nil { - return false, err - } + body, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return false, err + } + if resp.StatusCode != 200 { + return false, fmt.Errorf("got %d from %q %s", resp.StatusCode, endpoint, body) + } + + if err := json.Unmarshal(body, &groups); err != nil { + return false, err + } - for _, group := range groups { - if p.Group == group.Group { - // Found the group - return true, nil + for _, group := range groups { + if p.Group == group.Group { + // Found the group + return true, nil + } } }