Commit 6cdfff52 by Torkel Ödegaard

Merge branch 'master' of github.com:grafana/grafana

parents 462b5d93 f2833bfd
...@@ -31,37 +31,11 @@ search_filter = "(cn=%s)" ...@@ -31,37 +31,11 @@ search_filter = "(cn=%s)"
# An array of base dns to search through # An array of base dns to search through
search_base_dns = ["dc=grafana,dc=org"] search_base_dns = ["dc=grafana,dc=org"]
# In POSIX LDAP schemas, without memberOf attribute a secondary query must be made for groups. ## For Posix or LDAP setups that does not support member_of attribute you can define the below settings
# This is done by enabling group_search_filter below. You must also set member_of= "cn" ## Please check grafana LDAP docs for examples
# 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 = "(&(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"] # group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
# group_search_filter_user_attribute = "uid"
# Specify names of the ldap attributes your ldap uses # Specify names of the ldap attributes your ldap uses
[servers.attributes] [servers.attributes]
......
+++ +++
title = "LDAP Authentication" title = "LDAP Authentication"
description = "Grafana LDAP Authentication Guide " description = "Grafana LDAP Authentication Guide "
keywords = ["grafana", "configuration", "documentation", "ldap"] keywords = ["grafana", "configuration", "documentation", "ldap", "active directory"]
type = "docs" type = "docs"
[menu.docs] [menu.docs]
name = "LDAP" name = "LDAP"
...@@ -10,35 +10,42 @@ parent = "authentication" ...@@ -10,35 +10,42 @@ parent = "authentication"
weight = 2 weight = 2
+++ +++
# LDAP # LDAP Authentication
The LDAP integration in Grafana allows your Grafana users to login with their LDAP credentials. You can also specify mappings between LDAP The LDAP integration in Grafana allows your Grafana users to login with their LDAP credentials. You can also specify mappings between LDAP
group memberships and Grafana Organization user roles. Below we detail grafana.ini config file group memberships and Grafana Organization user roles.
settings and ldap.toml config file options.
## Supported LDAP Servers
Grafana uses a [third-party LDAP library](https://github.com/go-ldap/ldap) under the hood that supports basic LDAP v3 functionality.
This means that you should be able to configure LDAP integration using any compliant LDAPv3 server, for example [OpenLDAP](#openldap) or
[Active Directory](#active-directory) among [others](https://en.wikipedia.org/wiki/Directory_service#LDAP_implementations).
## Enable LDAP ## Enable LDAP
You turn on LDAP in the [main config file]({{< relref "installation/configuration.md" >}}) as well as specify the path to the LDAP In order to use LDAP integration you'll first need to enable LDAP in the [main config file]({{< relref "installation/configuration.md" >}}) as well as specify the path to the LDAP
specific configuration file (default: `/etc/grafana/ldap.toml`). specific configuration file (default: `/etc/grafana/ldap.toml`).
```bash ```bash
[auth.ldap] [auth.ldap]
# Set to `true` to enable LDAP integration (default: `false`) # Set to `true` to enable LDAP integration (default: `false`)
enabled = true enabled = true
# Path to the LDAP specific configuration file (default: `/etc/grafana/ldap.toml`) # Path to the LDAP specific configuration file (default: `/etc/grafana/ldap.toml`)
config_file = /etc/grafana/ldap.toml` config_file = /etc/grafana/ldap.toml
# Allow sign up should almost always be true (default) to allow new Grafana users to be created (if ldap authentication is ok). If set to # Allow sign up should almost always be true (default) to allow new Grafana users to be created (if ldap authentication is ok). If set to
# false only pre-existing Grafana users will be able to login (if ldap authentication is ok). # false only pre-existing Grafana users will be able to login (if ldap authentication is ok).
allow_sign_up = true allow_sign_up = true
``` ```
## LDAP Configuration ## Grafana LDAP Configuration
```bash Depending on which LDAP server you're using and how that's configured your Grafana LDAP configuration may vary.
# To troubleshoot and get more log info enable ldap debug logging in grafana.ini See [configuration examples](#configuration-examples) for more information.
# [log]
# filters = ldap:debug
**LDAP specific configuration file (ldap.toml) example:**
```bash
[[servers]] [[servers]]
# Ldap server host (specify multiple hosts space separated) # Ldap server host (specify multiple hosts space separated)
host = "127.0.0.1" host = "127.0.0.1"
...@@ -69,13 +76,8 @@ search_filter = "(cn=%s)" ...@@ -69,13 +76,8 @@ search_filter = "(cn=%s)"
# An array of base dns to search through # An array of base dns to search through
search_base_dns = ["dc=grafana,dc=org"] search_base_dns = ["dc=grafana,dc=org"]
# 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.
## 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))"
## An array of the base DNs to search through for groups. Typically uses ou=groups # group_search_filter_user_attribute = "distinguishedName"
# group_search_base_dns = ["ou=groups,dc=grafana,dc=org"] # group_search_base_dns = ["ou=groups,dc=grafana,dc=org"]
# Specify names of the ldap attributes your ldap uses # Specify names of the ldap attributes your ldap uses
...@@ -85,28 +87,11 @@ surname = "sn" ...@@ -85,28 +87,11 @@ surname = "sn"
username = "cn" username = "cn"
member_of = "memberOf" member_of = "memberOf"
email = "email" email = "email"
# Map ldap groups to grafana org roles
[[servers.group_mappings]]
group_dn = "cn=admins,dc=grafana,dc=org"
org_role = "Admin"
# To make user an instance admin (Grafana Admin) uncomment line below
# grafana_admin = true
# The Grafana organization database id, optional, if left out the default org (id 1) will be used. Setting this allows for multiple group_dn's to be assigned to the same org_role provided the org_id differs
# 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"
``` ```
## Bind & Bind Password ### Bind
#### Bind & Bind Password
By default the configuration expects you to specify a bind DN and bind password. This should be a read only user that can perform LDAP searches. By default the configuration expects you to specify a bind DN and bind password. This should be a read only user that can perform LDAP searches.
When the user DN is found a second bind is performed with the user provided username & password (in the normal Grafana login form). When the user DN is found a second bind is performed with the user provided username & password (in the normal Grafana login form).
...@@ -116,7 +101,7 @@ bind_dn = "cn=admin,dc=grafana,dc=org" ...@@ -116,7 +101,7 @@ bind_dn = "cn=admin,dc=grafana,dc=org"
bind_password = "grafana" bind_password = "grafana"
``` ```
### Single Bind Example #### Single Bind Example
If you can provide a single bind expression that matches all possible users, you can skip the second bind and bind against the user DN directly. If you can provide a single bind expression that matches all possible users, you can skip the second bind and bind against the user DN directly.
This allows you to not specify a bind_password in the configuration file. This allows you to not specify a bind_password in the configuration file.
...@@ -128,7 +113,7 @@ bind_dn = "cn=%s,o=users,dc=grafana,dc=org" ...@@ -128,7 +113,7 @@ bind_dn = "cn=%s,o=users,dc=grafana,dc=org"
In this case you skip providing a `bind_password` and instead provide a `bind_dn` value with a `%s` somewhere. This will be replaced with the username entered in on the Grafana login page. In this case you skip providing a `bind_password` and instead provide a `bind_dn` value with a `%s` somewhere. This will be replaced with the username entered in on the Grafana login page.
The search filter and search bases settings are still needed to perform the LDAP search to retrieve the other LDAP information (like LDAP groups and email). The search filter and search bases settings are still needed to perform the LDAP search to retrieve the other LDAP information (like LDAP groups and email).
## POSIX schema (no memberOf attribute) ### POSIX schema
If your ldap server does not support the memberOf attribute add these options: If your ldap server does not support the memberOf attribute add these options:
```bash ```bash
...@@ -136,27 +121,140 @@ If your ldap server does not support the memberOf attribute add these options: ...@@ -136,27 +121,140 @@ If your ldap server does not support the memberOf attribute add these options:
group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))" group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))"
## 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"]
## the %s in the search filter will be replaced with the attribute defined below
group_search_filter_user_attribute = "uid"
```
Also set `member_of = "dn"` in the `[servers.attributes]` section.
### Group Mappings
In `[[servers.group_mappings]]` you can map an LDAP group to a Grafana organization and role. These will be synced every time the user logs in, with LDAP being
the authoritative source. So, if you change a user's role in the Grafana Org. Users page, this change will be reset the next time the user logs in. If you
change the LDAP groups of a user, the change will take effect the next time the user logs in.
The first group mapping that an LDAP user is matched to will be used for the sync. If you have LDAP users that fit multiple mappings, the topmost mapping in the
TOML config will be used.
**LDAP specific configuration file (ldap.toml) example:**
```bash
[[servers]]
# other settings omitted for clarity
[[servers.group_mappings]]
group_dn = "cn=superadmins,dc=grafana,dc=org"
org_role = "Admin"
grafana_admin = true # Available in Grafana v5.3 and above
[[servers.group_mappings]]
group_dn = "cn=admins,dc=grafana,dc=org"
org_role = "Admin"
[[servers.group_mappings]]
group_dn = "cn=users,dc=grafana,dc=org"
org_role = "Editor"
[[servers.group_mappings]]
group_dn = "*"
org_role = "Viewer"
``` ```
Also change set `member_of = "cn"` in the `[servers.attributes]` section. Setting | Required | Description | Default
------------ | ------------ | ------------- | -------------
`group_dn` | Yes | LDAP distinguished name (DN) of LDAP group. If you want to match all (or no LDAP groups) then you can use wildcard (`"*"`) |
`org_role` | Yes | Assign users of `group_dn` the organisation role `"Admin"`, `"Editor"` or `"Viewer"` |
`org_id` | No | The Grafana organization database id. Setting this allows for multiple group_dn's to be assigned to the same `org_role` provided the `org_id` differs | `1` (default org id)
`grafana_admin` | No | When `true` makes user of `group_dn` Grafana server admin. A Grafana server admin has admin access over all organisations and users. Available in Grafana v5.3 and above | `false`
### Nested/recursive group membership
## LDAP to Grafana Org Role Sync Users with nested/recursive group membership must have an LDAP server that supports `LDAP_MATCHING_RULE_IN_CHAIN`
and configure `group_search_filter` in a way that it returns the groups the submitted username is a member of.
### Mappings **Active Directory example:**
In `[[servers.group_mappings]]` you can map an LDAP group to a Grafana organization
and role. These will be synced every time the user logs in, with LDAP being
the authoritative source. So, if you change a user's role in the Grafana Org.
Users page, this change will be reset the next time the user logs in. If you
change the LDAP groups of a user, the change will take effect the next
time the user logs in.
### Grafana Admin Active Directory 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.
with a servers.group_mappings section you can set grafana_admin = true or false to sync Grafana Admin permission. A Grafana server admin has admin access over all orgs & Multiple DN templates can be searched by combining filters with the LDAP OR-operator. Examples:
users.
### Priority ```bash
The first group mapping that an LDAP user is matched to will be used for the sync. If you have LDAP users that fit multiple mappings, the topmost mapping in the TOML config will be used. 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_user_attribute = "cn"
```
For troubleshooting, by changing `member_of` in `[servers.attributes]` to "dn" it will show you more accurate group memberships when [debug is enabled](#troubleshooting).
## Configuration examples
### OpenLDAP
[OpenLDAP](http://www.openldap.org/) is an open source directory service.
**LDAP specific configuration file (ldap.toml):**
```bash
[[servers]]
host = "127.0.0.1"
port = 389
use_ssl = false
start_tls = false
ssl_skip_verify = false
bind_dn = "cn=admin,dc=grafana,dc=org"
bind_password = 'grafana'
search_filter = "(cn=%s)"
search_base_dns = ["dc=grafana,dc=org"]
[servers.attributes]
name = "givenName"
surname = "sn"
username = "cn"
member_of = "memberOf"
email = "email"
# [[servers.group_mappings]] omitted for clarity
```
### Active Directory
[Active Directory](https://technet.microsoft.com/en-us/library/hh831484(v=ws.11).aspx) is a directory service which is commonly used in Windows environments.
Assuming the following Active Directory server setup:
* IP address: `10.0.0.1`
* Domain: `CORP`
* DNS name: `corp.local`
**LDAP specific configuration file (ldap.toml):**
```bash
[[servers]]
host = "10.0.0.1"
port = 3269
use_ssl = true
start_tls = false
ssl_skip_verify = true
bind_dn = "CORP\\%s"
search_filter = "(sAMAccountName=%s)"
search_base_dns = ["dc=corp,dc=local"]
[servers.attributes]
name = "givenName"
surname = "sn"
username = "sAMAccountName"
member_of = "memberOf"
email = "mail"
# [[servers.group_mappings]] omitted for clarity
```
#### Port requirements
In above example SSL is enabled and an encrypted port have been configured. If your Active Directory don't support SSL please change `enable_ssl = false` and `port = 389`.
Please inspect your Active Directory configuration and documentation to find the correct settings. For more information about Active Directory and port requirements see [link](https://technet.microsoft.com/en-us/library/dd772723(v=ws.10)).
## Troubleshooting
To troubleshoot and get more log info enable ldap debug logging in the [main config file]({{< relref "installation/configuration.md" >}}).
```bash
[log]
filters = ldap:debug
```
...@@ -326,15 +326,19 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) { ...@@ -326,15 +326,19 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
a.log.Info("Searching for user's groups", "filter", filter) a.log.Info("Searching for user's groups", "filter", filter)
// support old way of reading settings
groupIdAttribute := a.server.Attr.MemberOf
// but prefer dn attribute if default settings are used
if groupIdAttribute == "" || groupIdAttribute == "memberOf" {
groupIdAttribute = "dn"
}
groupSearchReq := ldap.SearchRequest{ groupSearchReq := ldap.SearchRequest{
BaseDN: groupSearchBase, BaseDN: groupSearchBase,
Scope: ldap.ScopeWholeSubtree, Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases, DerefAliases: ldap.NeverDerefAliases,
Attributes: []string{ Attributes: []string{groupIdAttribute},
// Here MemberOf would be the thing that identifies the group, which is normally 'cn' Filter: filter,
a.server.Attr.MemberOf,
},
Filter: filter,
} }
groupSearchResult, err = a.conn.Search(&groupSearchReq) groupSearchResult, err = a.conn.Search(&groupSearchReq)
...@@ -344,7 +348,7 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) { ...@@ -344,7 +348,7 @@ func (a *ldapAuther) searchForUser(username string) (*LdapUserInfo, error) {
if len(groupSearchResult.Entries) > 0 { if len(groupSearchResult.Entries) > 0 {
for i := range groupSearchResult.Entries { for i := range groupSearchResult.Entries {
memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i)) memberOf = append(memberOf, getLdapAttrN(groupIdAttribute, groupSearchResult, i))
} }
break break
} }
......
...@@ -50,18 +50,20 @@ export class TemplateSrv { ...@@ -50,18 +50,20 @@ export class TemplateSrv {
getAdhocFilters(datasourceName) { getAdhocFilters(datasourceName) {
let filters = []; let filters = [];
for (let i = 0; i < this.variables.length; i++) { if (this.variables) {
const variable = this.variables[i]; for (let i = 0; i < this.variables.length; i++) {
if (variable.type !== 'adhoc') { const variable = this.variables[i];
continue; if (variable.type !== 'adhoc') {
} continue;
}
// null is the "default" datasource // null is the "default" datasource
if (variable.datasource === null || variable.datasource === datasourceName) { if (variable.datasource === null || variable.datasource === datasourceName) {
filters = filters.concat(variable.filters);
} else if (variable.datasource.indexOf('$') === 0) {
if (this.replace(variable.datasource) === datasourceName) {
filters = filters.concat(variable.filters); filters = filters.concat(variable.filters);
} else if (variable.datasource.indexOf('$') === 0) {
if (this.replace(variable.datasource) === datasourceName) {
filters = filters.concat(variable.filters);
}
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment