Cannot get Grafana LDAP Authentication to work

Hi all,

I’ve been using Grafana for a while now just using a local login. I now want to deploy it to multiple other users using Active Directory (LDAP) but I can’t seem to get the config right. See below for my ldap.toml

# To troubleshoot and get more log info enable ldap debug logging in grafana.ini
# [log]
# filters = ldap:debug
[[servers]]
# Ldap server host (specify multiple hosts space separated)
host = "obfuscated.obfuscated.obfuscated.co.uk"
# Default port is 389 or 636 if use_ssl = true
port = 389
# Set to true if ldap server supports TLS
use_ssl = false
# Set to true if connect ldap server with STARTTLS pattern (create connection in insecure, then upgrade to secure connection with TLS)
start_tls = false
# set to true if you want to skip ssl cert validation
ssl_skip_verify = false
# set to the path to your root CA certificate or leave unset to use system defaults
# root_ca_cert = /path/to/certificate.crt

# Search user bind dn
bind_dn = "CN=ICINGA2,OU=obfuscated,OU=obufscated,OU=Application,OU=SYSTEM,OU=Users,OU=Standard,OU=Business,DC=obfuscated,DC=obfuscated,DC=obfuscated,DC=co,DC=uk"
# Search user bind password
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
bind_password = 'obfuscated'

# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
search_filter = "(&(objectClass=user)(memberOf=CN=ICINGA2-USERS,OU=obfuscated,OU=Application,OU=Groups,OU=obfuscated,OU=Bespoke,OU=Business,DC=obfuscated,DC=obfuscated,DC=obfuscated,DC=obfuscated,DC=obfuscated))"

# An array of base dns to search through
search_base_dns = ["OU=Roaming,OU=Interactive,OU=Users,OU=Standard,OU=Business,DC=obfuscated,DC=obfuscated,DC=obfuscated,DC=obfuscatedDC=obfuscated]

# In POSIX LDAP schemas, without memberOf attribute a secondary query must be made for groups.
# This is done by enabling group_search_filter below. You must also set member_of= "cn"
# in [servers.attributes] below.

# 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:
#
#   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:
#
#     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"]
#
#     [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 = "(&(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
# group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]

# Specify names of the ldap attributes your ldap uses
[servers.attributes]
name = "givenName"
surname = "SN"
username = "sAMAccountName"
member_of = "memberOf"
email =  "email"

# Map ldap groups to grafana org roles
[[servers.group_mappings]]
group_dn = "cn=admins,dc=grafana,dc=org"
org_role = "Admin"
# The Grafana organization database id, optional, if left out the default org (id 1) will be used
# org_id = 1

[[servers.group_mappings]]
group_dn = "cn=users,dc=grafana,dc=org"
org_role = "Editor"

[[servers.group_mappings]]
# If you want to match all (or no ldap groups) then you can use wildcard
group_dn = "*"
org_role = "Viewer"

When a user tries to login the following log is generated:
“Error while trying to authenticate user” logger=context userId=0 orgId=0 uname= error=“Ldap search matched more than one entry, please review your filter setting”

Any idea what could be the issue?

Many thanks in advance!

Enable logging via ‘filters = ldap:debug’ in Grafana.ini log section

Then check you grafana log file

I think as per your error. please look at your ldap configuration and you have enabled too many filters. It will work fine, when you fix the filters.

That’s what I can’t figure out. I use the same query in two other pieces of software and it works fine.

I don’t see how this query can return more than one result.

(&(objectClass=user)(memberOf=CN=ICINGA2-USERS,OU=obfuscated,OU=Application,OU=Groups,OU=obfuscated,OU=Bespoke,OU=Business,DC=obfuscated,DC=obfuscated,DC=obfuscated,DC=obfuscated,DC=obfuscated))

The user you are trying to login as is either a part of that group or it isn’t.

Debug log for ldap is already turned on. I don’t seem to be getting particularly verbose logs though. Only one liners.

Where do you match on username? Not seeing the %s that will be replaced with the username entered by the user on login screen

Doh! Knew it would be something really simple. Thank you.

Hi Andrew,

What did you do to fix it ?
I am going through the same problem.

Below is the error message I get in log file .

t=2017-12-24T08:13:54+0000 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=POST path=/login status=401 remote_addr=10.232.111.21 time_ms=3121 size=41 referer=http://servername:3000/login

I can’t speak for Andrew, but I came across this thread while trying to solve the same problem.

Here is what my search filter had been when I was getting this error:
search_filter = “(&(objectCategory=user)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(sAMAccountName=*)(memberOf=CN=Grafana_Users,OU=Grafana,OU=Corporate_Groups,DC=corp,DC=local))”

I changed it to:
search_filter = “(&(objectCategory=user)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(sAMAccountName=%s)(memberOf=CN=Grafana_Users,OU=Grafana,OU=Corporate_Groups,DC=corp,DC=local))”

It’s updating sAMAccountName from star to percentstring that turns the search from show me all the users in those groups to show me all of the users in those groups with the name given at the login page.