connector/ldap: backward compatibility with single user to group mapping
Signed-off-by: Vitaliy Dmitriev <vi7alya@gmail.com>
This commit is contained in:
parent
f2e7823db9
commit
e20a795a2a
2 changed files with 128 additions and 2 deletions
|
@ -134,6 +134,12 @@ type Config struct {
|
|||
|
||||
Scope string `json:"scope"` // Defaults to "sub"
|
||||
|
||||
// DEPRECATED config options. Those are left for backward compatibility.
|
||||
// See "UserMatchers" below for the current group to user matching implementation
|
||||
// TODO: should be eventually removed from the code
|
||||
UserAttr string `json:"userAttr"`
|
||||
GroupAttr string `json:"groupAttr"`
|
||||
|
||||
// Array of the field pairs used to match a user to a group.
|
||||
// See the "UserMatcher" struct for the exact field names
|
||||
//
|
||||
|
@ -175,6 +181,23 @@ func parseScope(s string) (int, bool) {
|
|||
return 0, false
|
||||
}
|
||||
|
||||
// Build a list of group attr name to user attr value matchers.
|
||||
// Function exists here to allow backward compatibility between old and new
|
||||
// group to user matching implementations.
|
||||
// See "Config.GroupSearch.UserMatchers" comments for the details
|
||||
func (c *ldapConnector) userMatchers() []UserMatcher {
|
||||
if len(c.GroupSearch.UserMatchers) > 0 && c.GroupSearch.UserMatchers[0].UserAttr != "" {
|
||||
return c.GroupSearch.UserMatchers[:]
|
||||
} else {
|
||||
return []UserMatcher{
|
||||
{
|
||||
UserAttr: c.GroupSearch.UserAttr,
|
||||
GroupAttr: c.GroupSearch.GroupAttr,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Open returns an authentication strategy using LDAP.
|
||||
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
|
||||
conn, err := c.OpenConnector(logger)
|
||||
|
@ -392,7 +415,7 @@ func (c *ldapConnector) userEntry(conn *ldap.Conn, username string) (user ldap.E
|
|||
},
|
||||
}
|
||||
|
||||
for _, matcher := range c.GroupSearch.UserMatchers {
|
||||
for _, matcher := range c.userMatchers() {
|
||||
req.Attributes = append(req.Attributes, matcher.UserAttr)
|
||||
}
|
||||
|
||||
|
@ -549,7 +572,7 @@ func (c *ldapConnector) groups(ctx context.Context, user ldap.Entry) ([]string,
|
|||
}
|
||||
|
||||
var groups []*ldap.Entry
|
||||
for _, matcher := range c.GroupSearch.UserMatchers {
|
||||
for _, matcher := range c.userMatchers() {
|
||||
for _, attr := range getAttrs(user, matcher.UserAttr) {
|
||||
filter := fmt.Sprintf("(%s=%s)", matcher.GroupAttr, ldap.EscapeFilter(attr))
|
||||
if c.GroupSearch.Filter != "" {
|
||||
|
|
|
@ -676,6 +676,109 @@ memberUid: janedoe
|
|||
runTests(t, schema, connectLDAP, c, tests)
|
||||
}
|
||||
|
||||
// Test deprecated group to user matching implementation
|
||||
// which was left for backward compatibility.
|
||||
// See "Config.GroupSearch.UserMatchers" comments for the details
|
||||
func TestDeprecatedGroupToUserMatcher(t *testing.T) {
|
||||
schema := `
|
||||
dn: ou=People,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: People
|
||||
|
||||
dn: cn=jane,ou=People,dc=example,dc=org
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
sn: doe
|
||||
cn: jane
|
||||
mail: janedoe@example.com
|
||||
userpassword: foo
|
||||
|
||||
dn: cn=john,ou=People,dc=example,dc=org
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
sn: doe
|
||||
cn: john
|
||||
mail: johndoe@example.com
|
||||
userpassword: bar
|
||||
|
||||
# Group definitions.
|
||||
|
||||
dn: ou=Seattle,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: Seattle
|
||||
|
||||
dn: ou=Portland,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: Portland
|
||||
|
||||
dn: ou=Groups,ou=Seattle,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: Groups
|
||||
|
||||
dn: ou=Groups,ou=Portland,dc=example,dc=org
|
||||
objectClass: organizationalUnit
|
||||
ou: Groups
|
||||
|
||||
dn: cn=qa,ou=Groups,ou=Portland,dc=example,dc=org
|
||||
objectClass: groupOfNames
|
||||
cn: qa
|
||||
member: cn=john,ou=People,dc=example,dc=org
|
||||
|
||||
dn: cn=admins,ou=Groups,ou=Seattle,dc=example,dc=org
|
||||
objectClass: groupOfNames
|
||||
cn: admins
|
||||
member: cn=john,ou=People,dc=example,dc=org
|
||||
member: cn=jane,ou=People,dc=example,dc=org
|
||||
|
||||
dn: cn=developers,ou=Groups,ou=Seattle,dc=example,dc=org
|
||||
objectClass: groupOfNames
|
||||
cn: developers
|
||||
member: cn=jane,ou=People,dc=example,dc=org
|
||||
`
|
||||
c := &Config{}
|
||||
c.UserSearch.BaseDN = "ou=People,dc=example,dc=org"
|
||||
c.UserSearch.NameAttr = "cn"
|
||||
c.UserSearch.EmailAttr = "mail"
|
||||
c.UserSearch.IDAttr = "DN"
|
||||
c.UserSearch.Username = "cn"
|
||||
c.GroupSearch.BaseDN = "dc=example,dc=org"
|
||||
c.GroupSearch.UserAttr = "DN"
|
||||
c.GroupSearch.GroupAttr = "member"
|
||||
c.GroupSearch.NameAttr = "cn"
|
||||
c.GroupSearch.Filter = "(ou:dn:=Seattle)" // ignore other groups
|
||||
|
||||
tests := []subtest{
|
||||
{
|
||||
name: "validpassword",
|
||||
username: "jane",
|
||||
password: "foo",
|
||||
groups: true,
|
||||
want: connector.Identity{
|
||||
UserID: "cn=jane,ou=People,dc=example,dc=org",
|
||||
Username: "jane",
|
||||
Email: "janedoe@example.com",
|
||||
EmailVerified: true,
|
||||
Groups: []string{"admins", "developers"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "validpassword2",
|
||||
username: "john",
|
||||
password: "bar",
|
||||
groups: true,
|
||||
want: connector.Identity{
|
||||
UserID: "cn=john,ou=People,dc=example,dc=org",
|
||||
Username: "john",
|
||||
Email: "johndoe@example.com",
|
||||
EmailVerified: true,
|
||||
Groups: []string{"admins"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runTests(t, schema, connectLDAP, c, tests)
|
||||
}
|
||||
|
||||
func TestStartTLS(t *testing.T) {
|
||||
schema := `
|
||||
dn: ou=People,dc=example,dc=org
|
||||
|
|
Reference in a new issue