Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teamwhitelistsupportonclaims #3

Merged
merged 17 commits into from
Mar 1, 2023
33 changes: 18 additions & 15 deletions handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,26 +139,29 @@ func verifyUser(u interface{}) (bool, error) {
return true, nil

// WhiteList
case len(cfg.Cfg.WhiteList) != 0:
for _, wl := range cfg.Cfg.WhiteList {
if user.Username == wl {
log.Debugf("verifyUser: Success! found user.Username in WhiteList: %s", user.Username)
return true, nil
case len(cfg.Cfg.WhiteList) != 0 || len(cfg.Cfg.TeamWhiteList) != 0:
if len(cfg.Cfg.WhiteList) != 0 {
for _, wl := range cfg.Cfg.WhiteList {
if user.Username == wl {
log.Debugf("verifyUser: Success! found user.Username in WhiteList: %s", user.Username)
return true, nil
}
}
}
return false, fmt.Errorf("verifyUser: user.Username not found in WhiteList: %s", user.Username)

// TeamWhiteList
case len(cfg.Cfg.TeamWhiteList) != 0:
for _, team := range user.TeamMemberships {
for _, wl := range cfg.Cfg.TeamWhiteList {
if team == wl {
log.Debugf("verifyUser: Success! found user.TeamWhiteList in TeamWhiteList: %s for user %s", wl, user.Username)
return true, nil
log.Info("User not in userwhitelist, checking in teamWhiteList")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to debug

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

// TeamWhiteList - first match between user.teammembership and teamwhitelist in config authenticates the user
if len(cfg.Cfg.TeamWhiteList) != 0 {
for _, team := range user.TeamMemberships {
for _, wl := range cfg.Cfg.TeamWhiteList {
if team == wl {
log.Debugf("verifyUser: Success! found user.TeamWhiteList in TeamWhiteList: %s for user %s", wl, user.Username)
return true, nil
}
}
}
log.Warnf("verifyUser: user.TeamMemberships %s not found in TeamWhiteList: %s for user %s", user.TeamMemberships, cfg.Cfg.TeamWhiteList, user.Username)
}
return false, fmt.Errorf("verifyUser: user.TeamMemberships %s not found in TeamWhiteList: %s for user %s", user.TeamMemberships, cfg.Cfg.TeamWhiteList, user.Username)
return false, fmt.Errorf("verifyUser: user.Username not found in WhiteList or TeamWhiteList: %s", user.Username)

// Domains
case len(cfg.Cfg.Domains) != 0:
Expand Down
31 changes: 16 additions & 15 deletions pkg/cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,22 @@ import (
// though most of the time envconfig will use the struct key's name: VOUCH_PORT VOUCH_JWT_MAXAGE
// default values should be set in .defaults.yml
type Config struct {
LogLevel string `mapstructure:"logLevel"`
Listen string `mapstructure:"listen"`
Port int `mapstructure:"port"`
SocketMode int `mapstructure:"socket_mode"`
SocketGroup string `mapstructure:"socket_group"`
DocumentRoot string `mapstructure:"document_root" envconfig:"document_root"`
WriteTimeout int `mapstructure:"writeTimeout"`
ReadTimeout int `mapstructure:"readTimeout"`
IdleTimeout int `mapstructure:"idleTimeout"`
Domains []string `mapstructure:"domains"`
WhiteList []string `mapstructure:"whitelist"`
TeamWhiteList []string `mapstructure:"teamWhitelist"`
AllowAllUsers bool `mapstructure:"allowAllUsers"`
PublicAccess bool `mapstructure:"publicAccess"`
TLS struct {
LogLevel string `mapstructure:"logLevel"`
Listen string `mapstructure:"listen"`
Port int `mapstructure:"port"`
SocketMode int `mapstructure:"socket_mode"`
SocketGroup string `mapstructure:"socket_group"`
DocumentRoot string `mapstructure:"document_root" envconfig:"document_root"`
WriteTimeout int `mapstructure:"writeTimeout"`
ReadTimeout int `mapstructure:"readTimeout"`
IdleTimeout int `mapstructure:"idleTimeout"`
Domains []string `mapstructure:"domains"`
WhiteList []string `mapstructure:"whitelist"`
TeamWhiteList []string `mapstructure:"teamWhitelist"`
TeamWhiteListClaim string `mapstructure:"teamWhitelistclaim"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add description on how this attribute is used

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

AllowAllUsers bool `mapstructure:"allowAllUsers"`
PublicAccess bool `mapstructure:"publicAccess"`
TLS struct {
Cert string `mapstructure:"cert"`
Key string `mapstructure:"key"`
Profile string `mapstructure:"profile"`
Expand Down
43 changes: 39 additions & 4 deletions pkg/providers/openid/openid.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ package openid

import (
"encoding/json"
"golang.org/x/oauth2"
"io/ioutil"
"net/http"

"github.com/vouch/vouch-proxy/pkg/cfg"
"github.com/vouch/vouch-proxy/pkg/providers/common"
"github.com/vouch/vouch-proxy/pkg/structs"
"go.uber.org/zap"
"golang.org/x/oauth2"
"io/ioutil"
"net/http"
)

// Provider provider specific functions
Expand All @@ -39,6 +38,7 @@ func (Provider) GetUserInfo(r *http.Request, user *structs.User, customClaims *s
return err
}
userinfo, err := client.Get(cfg.GenOAuth.UserInfoURL)

if err != nil {
return err
}
Expand All @@ -57,6 +57,41 @@ func (Provider) GetUserInfo(r *http.Request, user *structs.User, customClaims *s
log.Error(err)
return err
}
if err = appendTeamMembershipsFromCustomClaim(data, user); err != nil {
log.Error(err)
return err
}

user.PrepareUserData()
return nil
}

// appendTeamMembershipsFromCustomClaim appends teammembership values in user If

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

// any TeamWhiteListClaim is mentioned in the config file, userinfo body is
// checked for the claim and the claim values are appended to user
// teammemberships. Later, this user data is used for teamwhitelist check in auth.
func appendTeamMembershipsFromCustomClaim(data []byte, user *structs.User) error {
var f interface{}
err := json.Unmarshal(data, &f)
if err != nil {
log.Error(err)
return err
}
if cfg.Cfg.TeamWhiteListClaim != "" {
m := f.(map[string]interface{})
for k := range m {
if k == cfg.Cfg.TeamWhiteListClaim {
claimval, ok := m[k].(string)
if !ok {
log.Error("TeamWhiteList claim sent in openID user body cannot be casted as string")
continue // continue auth with existing teammemberships for user
}

user.TeamMemberships = append(user.TeamMemberships, claimval)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

append only if casting is success

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

break
}
}
log.Infof("team memberships present in user: %+v", user.TeamMemberships)
}
return nil
}
52 changes: 52 additions & 0 deletions pkg/providers/openid/openid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package openid

import (
"github.com/stretchr/testify/assert"
"testing"

"github.com/vouch/vouch-proxy/pkg/cfg"
"github.com/vouch/vouch-proxy/pkg/structs"
)

func TestGetUserInfo(t *testing.T) {
setUp()

user := structs.User{
Username: "test",
CreatedOn: 123,
Email: "[email protected]",
ID: 1,
LastUpdate: 123,
Name: "name",
TeamMemberships: []string{"team1"},
}

// test1
userinfobody := "{\"sub\":\"xx\",\"email\":\"[email protected]\",\"email_address\":\"[email protected]\",\"full_name\":\"ABC DEF\",\"last_name\":\"ABC\",\"CustomClaim1\":\"team2\"}"
data := []byte(userinfobody)
err := appendTeamMembershipsFromCustomClaim(data, &user)
assert.ElementsMatchf(t, err, nil, "Expected error to be nil")
assert.ElementsMatchf(t, user.TeamMemberships, []string{"team1", "team2"}, "Expected team memberships to be appended")

//test2
user.TeamMemberships = nil
userinfobody = "{\"sub\":\"xx\",\"email\":\"[email protected]\",\"email_address\":\"[email protected]\",\"full_name\":\"ABC DEF\",\"last_name\":\"ABC\",\"CustomClaim1\":\"team2\"}"
data = []byte(userinfobody)
err = appendTeamMembershipsFromCustomClaim(data, &user)
assert.ElementsMatchf(t, err, nil, "Expected error to be nil")
assert.ElementsMatchf(t, user.TeamMemberships, []string{"team2"}, "Expected team memberships to be appended")

//test3
user.TeamMemberships = nil
userinfobody = "{\"sub\":\"xx\",\"email\":\"[email protected]\",\"email_address\":\"[email protected]\",\"full_name\":\"ABC DEF\",\"last_name\":\"ABC\",\"CustomClaim1\":[\"team2\",\"team3\"]}"
data = []byte(userinfobody)
err = appendTeamMembershipsFromCustomClaim(data, &user)
assert.ElementsMatchf(t, err, nil, "Expected error to be nil")
assert.ElementsMatchf(t, user.TeamMemberships, nil, "Expected team memberships to be empty due to casting error")

}

func setUp() {
log = cfg.Logging.Logger
cfg.Cfg.TeamWhiteListClaim = "CustomClaim1"
}