Add support for a simple group filter
This commit is contained in:
parent
5e5717ded7
commit
2fd6f02cd8
3
main.go
3
main.go
|
|
@ -34,7 +34,8 @@ func main() {
|
|||
flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint or file:// paths for static files. Routing is based on the path")
|
||||
flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream")
|
||||
flagSet.Bool("pass-user-headers", true, "pass X-Forwarded-User and X-Forwarded-Email information to upstream")
|
||||
flagSet.Bool("pass-groups", false, "pass user group information along with basic auth to upstream")
|
||||
flagSet.Bool("pass-groups", false, "pass user group information in the X-Forwarded-Groups header to upstream (Azure only)")
|
||||
flagSet.String("filter-groups", "", "exclude groups that do not contain this value in its 'displayName' (Azure only)")
|
||||
flagSet.String("basic-auth-password", "", "the password to set when passing the HTTP Basic Auth header")
|
||||
flagSet.Bool("pass-access-token", false, "pass OAuth access_token to upstream via X-Forwarded-Access-Token header")
|
||||
flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream")
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ type OAuthProxy struct {
|
|||
SetXAuthRequest bool
|
||||
PassBasicAuth bool
|
||||
PassGroups bool
|
||||
FilterGroups string
|
||||
SkipProviderButton bool
|
||||
PassUserHeaders bool
|
||||
BasicAuthPassword string
|
||||
|
|
@ -208,6 +209,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
|
|||
PassBasicAuth: opts.PassBasicAuth,
|
||||
PassUserHeaders: opts.PassUserHeaders,
|
||||
PassGroups: opts.PassGroups,
|
||||
FilterGroups: opts.FilterGroups,
|
||||
BasicAuthPassword: opts.BasicAuthPassword,
|
||||
PassAccessToken: opts.PassAccessToken,
|
||||
SkipProviderButton: opts.SkipProviderButton,
|
||||
|
|
@ -551,7 +553,7 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
|
|||
|
||||
session.IDToken = req.Form.Get("id_token")
|
||||
if p.PassGroups && session.IDToken != "" {
|
||||
session.Groups, err = p.provider.GetGroups(session)
|
||||
session.Groups, err = p.provider.GetGroups(session, p.FilterGroups)
|
||||
if err != nil {
|
||||
p.ErrorPage(rw, 500, "Internal Error", "Internal Error")
|
||||
return
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ type Options struct {
|
|||
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
|
||||
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
|
||||
PassGroups bool `flag:"pass-groups" cfg:"pass_groups"`
|
||||
FilterGroups string `flag:"filter-groups" cfg:"filter_groups"`
|
||||
BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"`
|
||||
PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"`
|
||||
PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`
|
||||
|
|
@ -103,6 +104,7 @@ func NewOptions() *Options {
|
|||
PassBasicAuth: true,
|
||||
PassUserHeaders: true,
|
||||
PassGroups: false,
|
||||
FilterGroups: "",
|
||||
PassAccessToken: false,
|
||||
PassHostHeader: true,
|
||||
ApprovalPrompt: "force",
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ func (p *AzureProvider) GetEmailAddress(s *SessionState) (string, error) {
|
|||
return email, err
|
||||
}
|
||||
|
||||
func (p *AzureProvider) GetGroups(s *SessionState) (string, error) {
|
||||
// Get list of groups user belong to. Filter the desired names of groups (in case of huge group set)
|
||||
func (p *AzureProvider) GetGroups(s *SessionState, f string) (string, error) {
|
||||
if s.AccessToken == "" {
|
||||
return "", errors.New("missing access token")
|
||||
}
|
||||
|
|
@ -136,36 +137,51 @@ func (p *AzureProvider) GetGroups(s *SessionState) (string, error) {
|
|||
return "", errors.New("missing id token")
|
||||
}
|
||||
|
||||
// parse token, check if it has groups
|
||||
// if groups, return "|".join(groups_list)
|
||||
// else
|
||||
// look for claim source
|
||||
// GET source
|
||||
// parse response
|
||||
// return "|".join(response.groups_list)
|
||||
// For future use. Right now microsoft graph don't support filter
|
||||
// http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part2-url-conventions/odata-v4.0-errata02-os-part2-url-conventions-complete.html#_Toc406398116
|
||||
|
||||
req, err := http.NewRequest("GET", "https://graph.microsoft.com/v1.0/me/memberOf/", nil)
|
||||
//req, err := http.NewRequest("POST", "https://graph.microsoft.com/v1.0/me/getMemberGroups", strings.NewReader("{\"securityEnabledOnly\":true}"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header = getAzureHeader(s.AccessToken)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
groupData, err := api.Request(req)
|
||||
|
||||
groups := make([]string, 0)
|
||||
for _, groupInfo := range groupData.Get("value").MustArray() {
|
||||
//v, ok := groupInfo.(string)
|
||||
v, ok := groupInfo.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
/*
|
||||
var request string = "https://graph.microsoft.com/v1.0/me/memberOf?$select=id,displayName,groupTypes,securityEnabled,description,mailEnabled&$top=999"
|
||||
if f != "" {
|
||||
request += "?$filter=contains(displayName, '"+f+"')"
|
||||
}
|
||||
dname := v["displayName"].(string)
|
||||
secen := v["securityEnabled"].(bool)
|
||||
mailen := v["mailEnabled"].(bool)
|
||||
if secen == true && mailen == false {
|
||||
groups = append(groups, dname)
|
||||
*/
|
||||
//
|
||||
// Filters that will be possible to use:
|
||||
// contains - unknown function | "https://graph.microsoft.com/v1.0/me/memberOf?$filter=contains(displayName,%27olm%27)"
|
||||
// startswith - not supported | "https://graph.microsoft.com/v1.0/me/memberOf?$filter=startswith(displayName,%27olm%27)"
|
||||
// substring - not supported | "https://graph.microsoft.com/v1.0/me/memberOf?$filter=substring(displayName,0,2)%20eq%20%27olm%27"
|
||||
|
||||
requestUrl := "https://graph.microsoft.com/v1.0/me/memberOf?$select=displayName"
|
||||
groups := make([]string, 0)
|
||||
|
||||
for {
|
||||
req, err := http.NewRequest("GET", requestUrl, nil)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header = getAzureHeader(s.AccessToken)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
groupData, err := api.Request(req)
|
||||
|
||||
for _, groupInfo := range groupData.Get("value").MustArray() {
|
||||
v, ok := groupInfo.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
dname := v["displayName"].(string)
|
||||
if strings.Contains(dname, f) {
|
||||
groups = append(groups, dname)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if nextlink := groupData.Get("@odata.nextLink").MustString(); nextlink != "" {
|
||||
requestUrl = nextlink
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) {
|
|||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (p *ProviderData) GetGroups(s *SessionState) (string, error) {
|
||||
func (p *ProviderData) GetGroups(s *SessionState, f string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
type Provider interface {
|
||||
Data() *ProviderData
|
||||
GetEmailAddress(*SessionState) (string, error)
|
||||
GetGroups(*SessionState) (string, error)
|
||||
GetGroups(*SessionState, string) (string, error)
|
||||
Redeem(string, string) (*SessionState, error)
|
||||
ValidateGroup(string) bool
|
||||
ValidateSessionState(*SessionState) bool
|
||||
|
|
|
|||
Loading…
Reference in New Issue