LDAP: Fix debug view to display the actual computed mapping in ldap.go (#48103)

* LDAP debug fix with Org role inheritance

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* ldap debug coherent with ldap.go

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

Co-authored-by: Jguer <joao.guerreiro@grafana.com>
pull/48127/head
Gabriel MABILLE 3 years ago committed by GitHub
parent 1566fa2ede
commit 94fd03f44f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 54
      pkg/api/ldap_debug.go
  2. 2
      pkg/services/ldap/helpers.go
  3. 2
      pkg/services/ldap/ldap.go
  4. 2
      pkg/services/ldap/ldap_helpers_test.go

@ -241,7 +241,7 @@ func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration", err)
}
ldap := newLDAP(ldapConfig.Servers)
multiLDAP := newLDAP(ldapConfig.Servers)
username := web.Params(c.Req)[":username"]
@ -249,9 +249,8 @@ func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "Validation error. You must specify an username", nil)
}
user, serverConfig, err := ldap.User(username)
if user == nil {
user, serverConfig, err := multiLDAP.User(username)
if user == nil || err != nil {
return response.Error(http.StatusNotFound, "No user was found in the LDAP server(s) with that username", err)
}
@ -268,45 +267,32 @@ func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) response.Response {
IsDisabled: user.IsDisabled,
}
orgRoles := []LDAPRoleDTO{}
// Need to iterate based on the config groups as only the first match for an org is used
// We are showing all matches as that should help in understanding why one match wins out
// over another.
for _, configGroup := range serverConfig.Groups {
for _, userGroup := range user.Groups {
if strings.EqualFold(configGroup.GroupDN, userGroup) {
r := &LDAPRoleDTO{GroupDN: configGroup.GroupDN, OrgId: configGroup.OrgId, OrgRole: configGroup.OrgRole}
orgRoles = append(orgRoles, *r)
break
}
}
//}
}
// Then, we find what we did not match by inspecting the list of groups returned from
// LDAP against what we have already matched above.
unmappedUserGroups := map[string]struct{}{}
for _, userGroup := range user.Groups {
var matched bool
unmappedUserGroups[strings.ToLower(userGroup)] = struct{}{}
}
for _, orgRole := range orgRoles {
if strings.EqualFold(orgRole.GroupDN, userGroup) { // we already matched it
matched = true
break
}
orgRolesMap := map[int64]models.RoleType{}
for _, group := range serverConfig.Groups {
// only use the first match for each org
if orgRolesMap[group.OrgId] != "" {
continue
}
if !matched {
r := &LDAPRoleDTO{GroupDN: userGroup}
orgRoles = append(orgRoles, *r)
if ldap.IsMemberOf(user.Groups, group.GroupDN) {
orgRolesMap[group.OrgId] = group.OrgRole
u.OrgRoles = append(u.OrgRoles, LDAPRoleDTO{GroupDN: group.GroupDN,
OrgId: group.OrgId, OrgRole: group.OrgRole})
delete(unmappedUserGroups, strings.ToLower(group.GroupDN))
}
}
u.OrgRoles = orgRoles
for userGroup := range unmappedUserGroups {
u.OrgRoles = append(u.OrgRoles, LDAPRoleDTO{GroupDN: userGroup})
}
ldapLogger.Debug("mapping org roles", "orgsRoles", u.OrgRoles)
err = u.FetchOrgs(c.Req.Context(), hs.SQLStore)
if err != nil {
if err := u.FetchOrgs(c.Req.Context(), hs.SQLStore); err != nil {
return response.Error(http.StatusBadRequest, "An organization was not found - Please verify your LDAP configuration", err)
}

@ -6,7 +6,7 @@ import (
"gopkg.in/ldap.v3"
)
func isMemberOf(memberOf []string, group string) bool {
func IsMemberOf(memberOf []string, group string) bool {
if group == "*" {
return true
}

@ -422,7 +422,7 @@ func (server *Server) buildGrafanaUser(user *ldap.Entry) (*models.ExternalUserIn
continue
}
if isMemberOf(memberOf, group.GroupDN) {
if IsMemberOf(memberOf, group.GroupDN) {
extUser.OrgRoles[group.OrgId] = group.OrgRole
if extUser.IsGrafanaAdmin == nil || !*extUser.IsGrafanaAdmin {
extUser.IsGrafanaAdmin = group.IsGrafanaAdmin

@ -21,7 +21,7 @@ func TestIsMemberOf(t *testing.T) {
for _, tc := range tests {
t.Run(fmt.Sprintf("isMemberOf(%v, \"%s\") = %v", tc.memberOf, tc.group, tc.expected), func(t *testing.T) {
assert.Equal(t, tc.expected, isMemberOf(tc.memberOf, tc.group))
assert.Equal(t, tc.expected, IsMemberOf(tc.memberOf, tc.group))
})
}
}

Loading…
Cancel
Save