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:
Alex Bligh
2015-10-13 19:51:59 +01:00
parent 458e6da700
commit e8256f0ad7
3 changed files with 64 additions and 3 deletions
+40 -3
View File
@@ -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 {
+3
View File
@@ -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"`
}