Add support for POSIX LDAP schema
In the POSIX LDAP schema, there is no 'memberOf' attribute returned in relation to which groups a person is a member of. Rather, it is necessary to query the group objects which have the people as members. This commit adds an additional filter, which if specified explicitly searches for groups, rather than relying on the 'memberOf' attribute. This enables Grafana to work with LDAP POSIX schema (e.g. OpenLDAP etc.) Signed-off-by: Alex Bligh <alex@alex.org.uk>
This commit is contained in:
+40
-3
@@ -311,18 +311,51 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) {
|
||||
return nil, errors.New("Ldap search matched more than one entry, please review your filter setting")
|
||||
}
|
||||
|
||||
var memberOf []string
|
||||
if a.server.GroupSearchFilter == "" {
|
||||
memberOf = getLdapAttrArray(a.server.Attr.MemberOf, searchResult)
|
||||
} else {
|
||||
// If we are using a POSIX LDAP schema it won't support memberOf, so we manually search the groups
|
||||
var groupSearchResult *ldap.SearchResult
|
||||
for _, groupSearchBase := range a.server.GroupSearchBaseDNs {
|
||||
filter := strings.Replace(a.server.GroupSearchFilter, "%s", username, -1)
|
||||
groupSearchReq := ldap.SearchRequest{
|
||||
BaseDN: groupSearchBase,
|
||||
Scope: ldap.ScopeWholeSubtree,
|
||||
DerefAliases: ldap.NeverDerefAliases,
|
||||
Attributes: []string{
|
||||
// Here MemberOf would be the thing that identifies the group, which is normally 'cn'
|
||||
a.server.Attr.MemberOf,
|
||||
},
|
||||
Filter: filter,
|
||||
}
|
||||
|
||||
groupSearchResult, err = a.conn.Search(&groupSearchReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(groupSearchResult.Entries) > 0 {
|
||||
for i := range groupSearchResult.Entries {
|
||||
memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &ldapUserInfo{
|
||||
DN: searchResult.Entries[0].DN,
|
||||
LastName: getLdapAttr(a.server.Attr.Surname, searchResult),
|
||||
FirstName: getLdapAttr(a.server.Attr.Name, searchResult),
|
||||
Username: getLdapAttr(a.server.Attr.Username, searchResult),
|
||||
Email: getLdapAttr(a.server.Attr.Email, searchResult),
|
||||
MemberOf: getLdapAttrArray(a.server.Attr.MemberOf, searchResult),
|
||||
MemberOf: memberOf,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getLdapAttr(name string, result *ldap.SearchResult) string {
|
||||
for _, attr := range result.Entries[0].Attributes {
|
||||
func getLdapAttrN(name string, result *ldap.SearchResult, n int) string {
|
||||
for _, attr := range result.Entries[n].Attributes {
|
||||
if attr.Name == name {
|
||||
if len(attr.Values) > 0 {
|
||||
return attr.Values[0]
|
||||
@@ -332,6 +365,10 @@ func getLdapAttr(name string, result *ldap.SearchResult) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func getLdapAttr(name string, result *ldap.SearchResult) string {
|
||||
return getLdapAttrN(name, result, 0)
|
||||
}
|
||||
|
||||
func getLdapAttrArray(name string, result *ldap.SearchResult) []string {
|
||||
for _, attr := range result.Entries[0].Attributes {
|
||||
if attr.Name == name {
|
||||
|
||||
@@ -27,6 +27,9 @@ type LdapServerConf struct {
|
||||
SearchFilter string `toml:"search_filter"`
|
||||
SearchBaseDNs []string `toml:"search_base_dns"`
|
||||
|
||||
GroupSearchFilter string `toml:"group_search_filter"`
|
||||
GroupSearchBaseDNs []string `toml:"group_search_base_dns"`
|
||||
|
||||
LdapGroups []*LdapGroupToOrgRole `toml:"group_mappings"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user