Настройка аутентификации через auth proxy

Вы можете настроить Grafana так, чтобы аутентификацию обрабатывал обратный прокси HTTP. Популярные веб-серверы имеют очень обширный список подключаемых модулей аутентификации, и любой из них можно использовать с функцией AuthProxy. Ниже подробно описаны параметры конфигурации для auth proxy.

Bash
[auth.proxy]
# Defaults to false, but set to true to enable this feature
enabled = true
# HTTP Header name that will contain the username or email
header_name = X-WEBAUTH-USER
# HTTP Header property, defaults to `username` but can also be `email`
header_property = username
# Set to `true` to enable auto sign up of users who do not exist in Grafana DB. Defaults to `true`.
auto_sign_up = true
# Define cache time to live in minutes
# If combined with Grafana LDAP integration it is also the sync interval
# Set to 0 to always fetch and sync the latest user data
sync_ttl = 15
# Limit where auth proxy requests come from by configuring a list of IP addresses.
# This can be used to prevent users spoofing the X-WEBAUTH-USER header.
# Example `whitelist = 192.168.1.1, 192.168.1.0/24, 2001::23, 2001::0/120`
whitelist =
# Optionally define more headers to sync other user attributes
# Example `headers = Name:X-WEBAUTH-NAME Role:X-WEBAUTH-ROLE Email:X-WEBAUTH-EMAIL Groups:X-WEBAUTH-GROUPS`
headers =
# Non-ASCII strings in header values are encoded using quoted-printable encoding
;headers_encoded = false
# Check out docs on this for more details on the below setting
enable_login_token = false

Взаимодействие с AuthProxy Grafana через curl

Bash
curl -H "X-WEBAUTH-USER: admin"  http://localhost:3000/api/users
[
    {
        "id":1,
        "name":"",
        "login":"admin",
        "email":"admin@localhost",
        "isAdmin":true
    }
]

Затем мы можем отправить второй запрос к методу /api/user, который вернёт сведения о вошедшем в систему пользователе. Мы используем этот запрос, чтобы показать, как Grafana автоматически добавляет указанного нами нового пользователя в систему. Здесь мы создаём нового пользователя с именем «anthony».

Bash
curl -H "X-WEBAUTH-USER: anthony" http://localhost:3000/api/user
{
    "email":"anthony",
    "name":"",
    "login":"anthony",
    "theme":"",
    "orgId":1,
    "isGrafanaAdmin":false
}

Совместная работа аутентификации Apache с AuthProxy Grafana

Я продемонстрирую, как использовать Apache для аутентификации пользователей. В этом примере мы используем BasicAuth с основанным на текстовом файле обработчиком аутентификации Apache, то есть файлами htpasswd. Однако можно использовать любые доступные возможности аутентификации Apache.

Apache BasicAuth

В этом примере мы используем Apache в качестве обратного прокси перед Grafana. Apache обрабатывает аутентификацию пользователей, прежде чем переслать запросы в серверную службу Grafana.

Конфигурация Apache

Bash
    <VirtualHost *:80>
        ServerAdmin webmaster@authproxy
        ServerName authproxy
        ErrorLog "logs/authproxy-error_log"
        CustomLog "logs/authproxy-access_log" common

        <Proxy *>
            AuthType Basic
            AuthName GrafanaAuthProxy
            AuthBasicProvider file
            AuthUserFile /etc/apache2/grafana_htpasswd
            Require valid-user

            RewriteEngine On
            RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
            RequestHeader set X-WEBAUTH-USER "%{PROXY_USER}e"
        </Proxy>

        RequestHeader unset Authorization

        ProxyRequests Off
        ProxyPass / http://localhost:3000/
        ProxyPassReverse / http://localhost:3000/
    </VirtualHost>
  • Первые четыре строки конфигурации virtualhost стандартны, поэтому мы не будем подробно останавливаться на том, что они делают.

  • Мы используем блок конфигурации <proxy> для применения наших правил аутентификации к каждому проксируемому запросу. Эти правила включают требование базовой аутентификации, при которой учётные данные user:password хранятся в файле /etc/apache2/grafana_htpasswd. Этот файл можно создать с помощью команды htpasswd.

    • Следующая часть конфигурации — это сложная часть. Мы используем движок перезаписи Apache для создания нашего заголовка X-WEBAUTH-USER, заполненного аутентифицированным пользователем.
      • RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER}, NS]: Эта строка — немного магии. Она делает следующее: для каждого запроса использует функцию упреждающего просмотра (LA-U) rewriteEngines, чтобы определить, чему будет равна переменная REMOTE_USER после обработки запроса. Затем присваивает результат переменной PROXY_USER. Это необходимо, поскольку переменная REMOTE_USER недоступна для функции RequestHeader.

      • RequestHeader set X-WEBAUTH-USER “%{PROXY_USER}e”: Теперь, когда аутентифицированное имя пользователя хранится в переменной PROXY_USER, мы создаём новый заголовок запроса HTTP, который будет отправлен нашему серверному Grafana и будет содержать имя пользователя.

  • RequestHeader unset Authorization удаляет заголовок Authorization из запроса HTTP до того, как он будет переслан в Grafana. Это гарантирует, что Grafana не попытается аутентифицировать пользователя с помощью этих учётных данных (BasicAuth является поддерживаемым обработчиком аутентификации в Grafana).

  • Последние 3 строки — это просто стандартная конфигурация обратного прокси для направления всех аутентифицированных запросов на наш сервер Grafana, работающий на порту 3000.

Полное пошаговое руководство с использованием Docker

В этом примере мы используем официальный Docker-образ Grafana, доступный на Docker Hub.

  • Создайте файл grafana.ini со следующим содержимым
Bash
[users]
allow_sign_up = false
auto_assign_org = true
auto_assign_org_role = Editor

[auth.proxy]
enabled = true
header_name = X-WEBAUTH-USER
header_property = username
auto_sign_up = true

Запустите контейнер Grafana, используя наш пользовательский grafana.ini для замены /etc/grafana/grafana.ini. Мы не открываем никаких портов для этого контейнера, так как к нему будет подключаться только наш контейнер Apache.

Bash
docker run -i -v $(pwd)/grafana.ini:/etc/grafana/grafana.ini --name grafana grafana/grafana

Контейнер Apache

В этом примере мы используем официальный Docker-образ Apache, доступный на Docker Hub

  • Создайте файл с именем httpd.conf со следующим содержимым
Bash
ServerRoot "/usr/local/apache2"
Listen 80
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<IfModule unixd_module>
User daemon
Group daemon
</IfModule>
ServerAdmin you@example.com
<Directory />
    AllowOverride none
    Require all denied
</Directory>
DocumentRoot "/usr/local/apache2/htdocs"
ErrorLog /proc/self/fd/2
LogLevel error
<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog /proc/self/fd/1 common
</IfModule>
<Proxy *>
    AuthType Basic
    AuthName GrafanaAuthProxy
    AuthBasicProvider file
    AuthUserFile /tmp/htpasswd
    Require valid-user
    RewriteEngine On
    RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
    RequestHeader set X-WEBAUTH-USER "%{PROXY_USER}e"
</Proxy>
RequestHeader unset Authorization
ProxyRequests Off
ProxyPass / http://grafana:3000/
ProxyPassReverse / http://grafana:3000/
  • Создайте файл htpasswd. Мы создаём нового пользователя anthony с паролем password

    Bash
    htpasswd -bc htpasswd anthony password
  • Запустите контейнер HTTP-сервера Apache, используя наш пользовательский httpd.conf и наш файл htpasswd. Контейнер будет слушать порт 80, и мы создаём ссылку на контейнер grafana, чтобы этот контейнер мог разрешить имя хоста grafana в IP-адрес контейнера Grafana.

    Bash
    docker run -i -p 80:80 --link grafana:grafana -v $(pwd)/httpd.conf:/usr/local/apache2/conf/httpd.conf -v $(pwd)/htpasswd:/tmp/htpasswd httpd:2.4

Использование Grafana

Когда наши контейнеры Grafana и Apache запущены, вы можете подключиться к http://localhost/ и войти, используя имя пользователя и пароль, которые мы создали в файле htpasswd.

Note

Если пользователь удалён из Grafana, он не сможет войти в систему и выполнить повторную синхронизацию, пока не истечёт sync_ttl.

Синхронизация команд

Note

Доступно в Grafana Enterprise и для клиентов на отдельных планах Grafana Cloud. Информацию о ценах см. на странице цены или свяжитесь с нашей командой продаж.

С синхронизацией команд можно настроить синхронизацию между командами в вашем провайдере аутентификации и Grafana. Вы можете отправлять значения Grafana как часть заголовка HTTP, и Grafana сопоставит их с вашей структурой команд. Это позволяет автоматически помещать пользователей в определённые команды.

Для поддержки этой функции auth proxy допускает необязательные заголовки для сопоставления дополнительных атрибутов пользователя. Конкретный атрибут для поддержки синхронизации команд — Groups.

Bash
# Optionally define more headers to sync other user attributes
headers = "Groups:X-WEBAUTH-GROUPS"

Вы используете заголовок X-WEBAUTH-GROUPS для отправки информации о команде для каждого пользователя. В частности, набора group ID Grafana, к которым принадлежит пользователь.

Во-первых, нам нужно настроить сопоставление между вашим провайдером аутентификации и Grafana. Следуйте этим инструкциям, чтобы добавить группы в команду внутри Grafana.

После этого вы можете проверить свои сопоставления, запросив API.

Bash
# First, inspect your teams and obtain the corresponding ID of the team we want to inspect the groups for.
curl -H "X-WEBAUTH-USER: admin" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" http://localhost:3000/api/teams/search
{
  "totalCount": 2,
  "teams": [
    {
      "id": 1,
      "orgId": 1,
      "name": "Core",
      "email": "core@grafana.com",
      "avatarUrl": "/avatar/327a5353552d2dc3966e2e646908f540",
      "memberCount": 1,
      "permission": 0
    },
    {
      "id": 2,
      "orgId": 1,
      "name": "Loki",
      "email": "loki@grafana.com",
      "avatarUrl": "/avatar/102f937d5344d33fdb37b65d430f36ef",
      "memberCount": 0,
      "permission": 0
    }
  ],
  "page": 1,
  "perPage": 1000
}

# Then, query the groups for that particular team. In our case, the Loki team which has an ID of "2".
curl -H "X-WEBAUTH-USER: admin" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" http://localhost:3000/api/teams/2/groups
[
  {
    "orgId": 1,
    "teamId": 2,
    "groupId": "lokiTeamOnExternalSystem"
  }
]

Наконец, всякий раз, когда Grafana получает запрос с заголовком X-WEBAUTH-GROUPS: lokiTeamOnExternalSystem, аутентифицируемый пользователь будет помещён в указанную команду. Помещение в несколько команд поддерживается с помощью значений, разделённых запятыми, например lokiTeamOnExternalSystem,CoreTeamOnExternalSystem.

Bash
curl -H "X-WEBAUTH-USER: leonard" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" http://localhost:3000/dashboards/home
{
  "meta": {
    "isHome": true,
    "canSave": false,
    ...
}

Таким образом, пользователь leonard будет автоматически помещён в команду Loki в рамках аутентификации Grafana.

Note

Пустой X-WEBAUTH-GROUPS или отсутствие заголовка групп удалит пользователя из всех команд.

Узнать больше о синхронизации команд

Когда enable_login_token установлен в true, Grafana после успешной проверки заголовка auth proxy назначит пользователю токен входа и cookie. Вам нужно настроить ваш auth proxy так, чтобы он предоставлял заголовки только для маршрута /login. Запросы через другие маршруты будут аутентифицироваться с помощью cookie.

Используйте настройки login_maximum_inactive_lifetime_duration и login_maximum_lifetime_duration в разделе [auth] для управления сроком жизни сессии.