From 4a0feaf589606fce80a3a10ae600dbd841227bef Mon Sep 17 00:00:00 2001 From: Stephan Renatus Date: Mon, 11 May 2020 11:42:26 +0200 Subject: [PATCH] connector/saml: add 'FilterGroups' setting This should make AllowedGroups equivalent to an LDAP group filter: When set to true, only the groups from AllowedGroups will be included in the user's identity. Signed-off-by: Stephan Renatus --- Documentation/connectors/saml.md | 2 ++ connector/saml/saml.go | 7 +++++++ connector/saml/saml_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/Documentation/connectors/saml.md b/Documentation/connectors/saml.md index c9af0995..5c542490 100644 --- a/Documentation/connectors/saml.md +++ b/Documentation/connectors/saml.md @@ -18,6 +18,8 @@ The connector doesn't support signed AuthnRequests or encrypted attributes. The SAML Connector supports providing a whitelist of SAML Groups to filter access based on, and when the `groupsattr` is set with a scope including groups, Dex will check for membership based on configured groups in the `allowedGroups` config setting for the SAML connector. +If `filterGroups` is set to true, any groups _not_ part of `allowedGroups` will be excluded. + ## Configuration ```yaml diff --git a/connector/saml/saml.go b/connector/saml/saml.go index 1c1cb460..e0f3f933 100644 --- a/connector/saml/saml.go +++ b/connector/saml/saml.go @@ -101,6 +101,7 @@ type Config struct { // used split the groups string. GroupsDelim string `json:"groupsDelim"` AllowedGroups []string `json:"allowedGroups"` + FilterGroups bool `json:"filterGroups"` RedirectURI string `json:"redirectURI"` // Requested format of the NameID. The NameID value is is mapped to the ID Token @@ -165,6 +166,7 @@ func (c *Config) openConnector(logger log.Logger) (*provider, error) { groupsAttr: c.GroupsAttr, groupsDelim: c.GroupsDelim, allowedGroups: c.AllowedGroups, + filterGroups: c.FilterGroups, redirectURI: c.RedirectURI, logger: logger, @@ -240,6 +242,7 @@ type provider struct { groupsAttr string groupsDelim string allowedGroups []string + filterGroups bool redirectURI string @@ -430,6 +433,10 @@ func (p *provider) HandlePOST(s connector.Scopes, samlResponse, inResponseTo str return ident, fmt.Errorf("user not a member of allowed groups") } + if p.filterGroups { + ident.Groups = groupMatches + } + // Otherwise, we're good return ident, nil } diff --git a/connector/saml/saml_test.go b/connector/saml/saml_test.go index 4d28e33a..aa07aae7 100644 --- a/connector/saml/saml_test.go +++ b/connector/saml/saml_test.go @@ -53,6 +53,7 @@ type responseTest struct { emailAttr string groupsAttr string allowedGroups []string + filterGroups bool // Expected outcome of the test. wantErr bool @@ -121,6 +122,29 @@ func TestGroupsWhitelist(t *testing.T) { test.run(t) } +func TestGroupsWhitelistWithFiltering(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/good-resp.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + groupsAttr: "groups", + allowedGroups: []string{"Admins"}, + filterGroups: true, + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantIdent: connector.Identity{ + UserID: "eric.chiang+okta@coreos.com", + Username: "Eric", + Email: "eric.chiang+okta@coreos.com", + EmailVerified: true, + Groups: []string{"Admins"}, // "Everyone" is filtered + }, + } + test.run(t) +} + func TestGroupsWhitelistEmpty(t *testing.T) { test := responseTest{ caFile: "testdata/ca.crt", @@ -388,6 +412,7 @@ func (r responseTest) run(t *testing.T) { RedirectURI: r.redirectURI, EntityIssuer: r.entityIssuer, AllowedGroups: r.allowedGroups, + FilterGroups: r.filterGroups, // Never logging in, don't need this. SSOURL: "http://foo.bar/", }