gitlab: support for group whitelist
This commit is contained in:
		@@ -26,10 +26,11 @@ const (
 | 
			
		||||
 | 
			
		||||
// Config holds configuration options for gilab logins.
 | 
			
		||||
type Config struct {
 | 
			
		||||
	BaseURL      string `json:"baseURL"`
 | 
			
		||||
	ClientID     string `json:"clientID"`
 | 
			
		||||
	ClientSecret string `json:"clientSecret"`
 | 
			
		||||
	RedirectURI  string `json:"redirectURI"`
 | 
			
		||||
	BaseURL      string   `json:"baseURL"`
 | 
			
		||||
	ClientID     string   `json:"clientID"`
 | 
			
		||||
	ClientSecret string   `json:"clientSecret"`
 | 
			
		||||
	RedirectURI  string   `json:"redirectURI"`
 | 
			
		||||
	Groups       []string `json:"groups"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type gitlabUser struct {
 | 
			
		||||
@@ -52,6 +53,7 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
 | 
			
		||||
		clientID:     c.ClientID,
 | 
			
		||||
		clientSecret: c.ClientSecret,
 | 
			
		||||
		logger:       logger,
 | 
			
		||||
		groups:       c.Groups,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -68,7 +70,7 @@ var (
 | 
			
		||||
type gitlabConnector struct {
 | 
			
		||||
	baseURL      string
 | 
			
		||||
	redirectURI  string
 | 
			
		||||
	org          string
 | 
			
		||||
	groups       []string
 | 
			
		||||
	clientID     string
 | 
			
		||||
	clientSecret string
 | 
			
		||||
	logger       log.Logger
 | 
			
		||||
@@ -142,7 +144,7 @@ func (c *gitlabConnector) HandleCallback(s connector.Scopes, r *http.Request) (i
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if s.Groups {
 | 
			
		||||
		groups, err := c.groups(ctx, client)
 | 
			
		||||
		groups, err := c.getGroups(ctx, client, s.Groups, user.Username)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return identity, fmt.Errorf("gitlab: get groups: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -185,7 +187,7 @@ func (c *gitlabConnector) Refresh(ctx context.Context, s connector.Scopes, ident
 | 
			
		||||
	ident.Email = user.Email
 | 
			
		||||
 | 
			
		||||
	if s.Groups {
 | 
			
		||||
		groups, err := c.groups(ctx, client)
 | 
			
		||||
		groups, err := c.getGroups(ctx, client, s.Groups, user.Username)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return ident, fmt.Errorf("gitlab: get groups: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -224,11 +226,11 @@ func (c *gitlabConnector) user(ctx context.Context, client *http.Client) (gitlab
 | 
			
		||||
	return u, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// groups queries the GitLab API for group membership.
 | 
			
		||||
// userGroups queries the GitLab API for group membership.
 | 
			
		||||
//
 | 
			
		||||
// The HTTP passed client is expected to be constructed by the golang.org/x/oauth2 package,
 | 
			
		||||
// which inserts a bearer token as part of the request.
 | 
			
		||||
func (c *gitlabConnector) groups(ctx context.Context, client *http.Client) ([]string, error) {
 | 
			
		||||
func (c *gitlabConnector) userGroups(ctx context.Context, client *http.Client) ([]string, error) {
 | 
			
		||||
	req, err := http.NewRequest("GET", c.baseURL+"/oauth/userinfo", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("gitlab: new req: %v", err)
 | 
			
		||||
@@ -256,3 +258,37 @@ func (c *gitlabConnector) groups(ctx context.Context, client *http.Client) ([]st
 | 
			
		||||
 | 
			
		||||
	return u.Groups, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *gitlabConnector) getGroups(ctx context.Context, client *http.Client, groupScope bool, userLogin string) ([]string, error) {
 | 
			
		||||
	gitlabGroups, err := c.userGroups(ctx, client)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(c.groups) > 0 {
 | 
			
		||||
		filteredGroups := filterGroups(gitlabGroups, c.groups)
 | 
			
		||||
		if len(filteredGroups) == 0 {
 | 
			
		||||
			return nil, fmt.Errorf("gitlab: user %q is not in any of the required groups", userLogin)
 | 
			
		||||
		}
 | 
			
		||||
		return filteredGroups, nil
 | 
			
		||||
	} else if groupScope {
 | 
			
		||||
		return gitlabGroups, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Filter the users' group memberships by 'groups' from config.
 | 
			
		||||
func filterGroups(userGroups, configGroups []string) []string {
 | 
			
		||||
	groups := []string{}
 | 
			
		||||
	groupFilter := make(map[string]struct{})
 | 
			
		||||
	for _, group := range configGroups {
 | 
			
		||||
		groupFilter[group] = struct{}{}
 | 
			
		||||
	}
 | 
			
		||||
	for _, group := range userGroups {
 | 
			
		||||
		if _, ok := groupFilter[group]; ok {
 | 
			
		||||
			groups = append(groups, group)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return groups
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user