Browse Source

new config option for source of %s in group_search_filter, useful for nested LDAP groups

David Warden 9 years ago
parent
commit
87aca5bf1b
3 changed files with 26 additions and 14 deletions
  1. 17 11
      conf/ldap.toml
  2. 6 1
      pkg/login/ldap.go
  3. 3 2
      pkg/login/settings.go

+ 17 - 11
conf/ldap.toml

@@ -28,25 +28,31 @@ search_base_dns = ["dc=grafana,dc=org"]
 # This is done by enabling group_search_filter below. You must also set member_of= "cn"
 # This is done by enabling group_search_filter below. You must also set member_of= "cn"
 # in [servers.attributes] below.
 # in [servers.attributes] below.
 
 
-# Users with nested/recursive group membership must have an LDAP server that supports LDAP_MATCHING_RULE_IN_CHAIN
-# and set group_search_filter below in such a way that it returns the groups the submitted username is a member of.
+# Users with nested/recursive group membership and an LDAP server that supports LDAP_MATCHING_RULE_IN_CHAIN
+# can set group_search_filter, group_search_filter_user_attribute, group_search_base_dns and member_of
+# below in such a way that the user's recursive group membership is considered.
 #
 #
 # Nested Groups + Active Directory (AD) Example:
 # Nested Groups + Active Directory (AD) Example:
 #
 #
-#   AD groups store the Distinguished Names (DNs) of members, so your filter will need to know the DN
-#   for the user based only on the submitted username. Multiple DN templates can be
-#   searched by combining filters with the LDAP or operator.
+#   AD groups store the Distinguished Names (DNs) of members, so your filter must
+#   recursively search your groups for the authenticating user's DN. For example:
 #
 #
-#   Some examples:
-#     group_search_filter = "(member:1.2.840.113556.1.4.1941:=CN=%s,[user container/OU])"
-#     group_search_filter = "(|(member:1.2.840.113556.1.4.1941:=CN=%s,[user container/OU])(member:1.2.840.113556.1.4.1941:=CN=%s,[another user container/OU]))"
+#     group_search_filter = "(member:1.2.840.113556.1.4.1941:=%s)"
+#     group_search_filter_user_attribute = "distinguishedName"
+#     group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
 #
 #
-#   You might also want to change member_of in [servers.attributes] to "distinguishedName". This
-#   does not appear to be necessary but it will show you more accurate group membership if
-#   verbose_logging is enabled.
+#     [servers.attributes]
+#     ...
+#     member_of = "distinguishedName"
 
 
 ## Group search filter, to retrieve the groups of which the user is a member (only set if memberOf attribute is not available)
 ## Group search filter, to retrieve the groups of which the user is a member (only set if memberOf attribute is not available)
 # group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))"
 # group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))"
+## Group search filter user attribute defines what user attribute gets substituted for %s in group_search_filter.
+## Defaults to the value of username in [server.attributes]
+## Valid options are any of your values in [servers.attributes]
+## If you are using nested groups you probably want to set this and member_of in
+## [servers.attributes] to "distinguishedName"
+# group_search_filter_user_attribute = "distinguishedName"
 ## An array of the base DNs to search through for groups. Typically uses ou=groups
 ## An array of the base DNs to search through for groups. Typically uses ou=groups
 # group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
 # group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
 
 

+ 6 - 1
pkg/login/ldap.go

@@ -318,7 +318,12 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) {
 		// If we are using a POSIX LDAP schema it won't support memberOf, so we manually search the groups
 		// If we are using a POSIX LDAP schema it won't support memberOf, so we manually search the groups
 		var groupSearchResult *ldap.SearchResult
 		var groupSearchResult *ldap.SearchResult
 		for _, groupSearchBase := range a.server.GroupSearchBaseDNs {
 		for _, groupSearchBase := range a.server.GroupSearchBaseDNs {
-			filter := strings.Replace(a.server.GroupSearchFilter, "%s", username, -1)
+			var filter_replace string
+			filter_replace = getLdapAttr(a.server.GroupSearchFilterUserAttribute, searchResult)
+			if a.server.GroupSearchFilterUserAttribute == "" {
+				filter_replace = getLdapAttr(a.server.Attr.Username, searchResult)
+			}
+			filter := strings.Replace(a.server.GroupSearchFilter, "%s", filter_replace, -1)
 
 
 			if ldapCfg.VerboseLogging {
 			if ldapCfg.VerboseLogging {
 				log.Info("LDAP: Searching for user's groups: %s", filter)
 				log.Info("LDAP: Searching for user's groups: %s", filter)

+ 3 - 2
pkg/login/settings.go

@@ -27,8 +27,9 @@ type LdapServerConf struct {
 	SearchFilter  string   `toml:"search_filter"`
 	SearchFilter  string   `toml:"search_filter"`
 	SearchBaseDNs []string `toml:"search_base_dns"`
 	SearchBaseDNs []string `toml:"search_base_dns"`
 
 
-	GroupSearchFilter  string   `toml:"group_search_filter"`
-	GroupSearchBaseDNs []string `toml:"group_search_base_dns"`
+	GroupSearchFilter              string   `toml:"group_search_filter"`
+	GroupSearchFilterUserAttribute string   `toml:"group_search_filter_user_attribute"`
+	GroupSearchBaseDNs             []string `toml:"group_search_base_dns"`
 
 
 	LdapGroups []*LdapGroupToOrgRole `toml:"group_mappings"`
 	LdapGroups []*LdapGroupToOrgRole `toml:"group_mappings"`
 }
 }