github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/server/oauth_gitlab.go (about) 1 package server 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" 8 9 "github.com/pyroscope-io/pyroscope/pkg/config" 10 "github.com/sirupsen/logrus" 11 "golang.org/x/oauth2" 12 ) 13 14 type oauthHandlerGitlab struct { 15 oauthBase 16 allowedGroups []string 17 } 18 19 func newOauthGitlabHandler(cfg config.GitlabOauth, baseURL string, log *logrus.Logger) (*oauthHandlerGitlab, error) { 20 authURL, err := url.Parse(cfg.AuthURL) 21 if err != nil { 22 return nil, err 23 } 24 25 h := &oauthHandlerGitlab{ 26 oauthBase: oauthBase{ 27 config: &oauth2.Config{ 28 ClientID: cfg.ClientID, 29 ClientSecret: cfg.ClientSecret, 30 Scopes: []string{"read_api"}, 31 Endpoint: oauth2.Endpoint{AuthURL: cfg.AuthURL, TokenURL: cfg.TokenURL}, 32 }, 33 authURL: authURL, 34 log: log, 35 callbackRoute: "/auth/gitlab/callback", 36 redirectRoute: "/auth/gitlab/redirect", 37 apiURL: cfg.APIURL, 38 baseURL: baseURL, 39 }, 40 allowedGroups: cfg.AllowedGroups, 41 } 42 43 if cfg.RedirectURL != "" { 44 h.config.RedirectURL = cfg.RedirectURL 45 } 46 47 return h, nil 48 } 49 50 type gitlabGroups struct { 51 Path string 52 } 53 54 func (o oauthHandlerGitlab) userAuth(client *http.Client) (extUserInfo, error) { 55 type userProfileResponse struct { 56 ID int64 57 Email string 58 Username string 59 AvatarURL string 60 } 61 62 resp, err := client.Get(o.oauthBase.apiURL + "/user") 63 if err != nil { 64 return extUserInfo{}, fmt.Errorf("failed to get oauth user info: %w", err) 65 } 66 defer resp.Body.Close() 67 68 var userProfile userProfileResponse 69 err = json.NewDecoder(resp.Body).Decode(&userProfile) 70 if err != nil { 71 return extUserInfo{}, fmt.Errorf("failed to decode user profile response: %w", err) 72 } 73 u := extUserInfo{ 74 Name: userProfile.Username, 75 Email: userProfile.Email, 76 } 77 if len(o.allowedGroups) == 0 { 78 return u, nil 79 } 80 81 groups, err := o.fetchGroups(client) 82 if err != nil { 83 return extUserInfo{}, fmt.Errorf("failed to get groups: %w", err) 84 } 85 86 for _, allowed := range o.allowedGroups { 87 for _, member := range groups { 88 if member.Path == allowed { 89 return u, nil 90 } 91 } 92 } 93 94 return extUserInfo{}, errForbidden 95 } 96 97 func (o oauthHandlerGitlab) fetchGroups(client *http.Client) ([]gitlabGroups, error) { 98 groupsURL := o.apiURL + "/groups" 99 more := true 100 groups := make([]gitlabGroups, 0) 101 102 for more { 103 resp, err := client.Get(groupsURL) 104 if err != nil { 105 return nil, err 106 } 107 defer resp.Body.Close() 108 109 var grp []gitlabGroups 110 err = json.NewDecoder(resp.Body).Decode(&grp) 111 if err != nil { 112 return nil, err 113 } 114 115 groups = append(groups, grp...) 116 117 groupsURL, more = hasMoreLinkResults(resp.Header) 118 if err != nil { 119 return nil, err 120 } 121 } 122 123 return groups, nil 124 } 125 126 func (o oauthHandlerGitlab) getOauthBase() oauthBase { 127 return o.oauthBase 128 }