Pull to refresh

SSO и Kibana: интеграция Kibana со встроенной аутентификацией Windows (Single Sign-On)

Reading time 10 min
Views 14K

В этой статье мне хотелось бы поделиться способом настройки технологии единого входа (SSO) в Elastic Stack, использующим X-Pack для аутентификации пользователей и разграничения доступа к данным.


Stop SSO


Надо сказать, что активные попытки настроить SSO в Кибане с Active Directory начались у меня после прочтения статьи Integrating third party Auth with Kibana. Как всегда в таких блогах был приведён простой и рабочий пример, который подходит для "домашнего использования", но мало применимый на предприятиях со сложной инфраструктурой. И вот только после выхода Elastic Stack v.5.6.2, а если более конкретно — патча в X-Pack 5.6.2, который наконец-то сделал возможным использвание “user impersonation” c Active Directory, единый вход (SSO) заработал в полной мере.


“Олицетворение пользователя” (user impersonation) — это ключевой компонент в этой системе, с помощью которого одной учётной записи (например технический пользователь) разрешается посылать запросы от имени других, уже аутентифицированных пользователей. В Elastic Stack X-Pack эта функция называется run_as.


Справедливости ради надо заметить, что SSO можно было настроить и до этого патча — если использовать LDAP. Но так как LDAP realm в Elasticsearch не поддерживает вложенные группы (nested groups), то рассматривать это решение было не серьёзно.


Архитектура


Архитерктура предлагаемого решения будет выглядеть следующим образом:



Картинка позаимствована в уже упомянутом блоге, изменены только названия у нескольких компонентов. Надеюсь, что Эластик не будет возражать (если узнает), а если будет, то придётся нарисовать свои квадратики в PPT.


Описание работы


  • Пользователи посылают запрос на веб-сервер (IIS), который аутентифицирует их через механизм Windows Authenticated (все остальные методы аутентификации отключены в конфигурации этого веб-сайта).
  • Если аутентификация прошла успешно, то IIS устанавливает переменную окружения REMOTE_USER=DOMAIN\user.
  • Эта переменная будет использоваться в дополнительном модуле Helicon rewrite для установки имперсонифицированного HTTP-заголовка (impersonation header) es-security-runas-user.
  • Модуль Helicon rewrite устанавливает также и HTTP-заголовок аутентификации (Basic) для специального технического внутреннего пользователя Elasticsearch.
  • Специальная роль в Elasticsearch используется для разрешения запуска поисковых запросов от имени других пользователей. Так как имперсонификация должна быть разрешена только для пользователей домена, то эта роль будет выглядеть примерно так: *@domain.name.
  • Настраиваем AD realm для X-Pack'a
  • Так как доступ пользователей к индексам будет регулироваться только через AD-группы, то AD-realm должен использовать параметер unmapped_groups_as_roles: true. Это значит, что имя AD-группы будет именем роли в Elasticsearch (см. ниже про безопасность и производительность1).
  • Все пользователи нашей системы (Кибаны), вне зависимости от того, к каким индексам в Elasticsearch им предоставлен доступ, должны иметь права на чтение и запись в индекс .kibana. Значит, в AD нужно создать специальную группу, в которую будут включаться все те пользователи, которым нужно пользоваться Кибаной. Кроме того, в Elasticsearch нужно создать роль с таким же именем и с правами на изменение индекса .kibana. Для примера, так будет выглядеть конфигурация пользователя отдела администрирования сетевого оборудования:
    • Пользователь Кибаны: AD-группа = ES роль = ELK.Users права на индекс .kibana*:
      • manage, read, index, delete
    • Доступ к сетевым логам: AD-группа = ES роль = ELK.Network.Admins права на индексы net-*:
      • read, view_index_metadata

Установка


  • Настраиваем TLS на Кибане и Elasticsearch сервере: инструкция. Этот пункт опциональный, но желательный — несолидно ведь предлагать систему аутентификации без шифрования траффика.
  • Устанавливаем IIS (Microsoft Internet Information Services) для аутентификации пользователей через NTLM. Так как этот веб-сервер будет использоваться в качестве прокси и никакой другой работы выполнять не будет, можно IIS установить на одном сервере с Кибаной.
  • "Улучшаем" IIS:
    • Application Request Routing (ARR) — расширение, которое позволяет IIS работать в качестве балансера нагрузки. В нашем случае он будет использваться как обратный прокси сервер (reverse proxy).
    • Helicon ISAPI_Rewrite 3 engine — сторонный модуль, эмулирующий работу движка Apache rewrite. Он нужен, потому что IIS (на данный момент) не может установить переменную REMOTE_USER когда используется NTLM, так как встроенный IIS Rewrite модуль вызывается до аутентификации пользователя.

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


Приступаем к настройке всех компонентов (мечта — написать инсталлятор...).


IIS


  • Настройка SSL
    В сети полно инструкций для настройки SSL/TLS в IIS, например IIS SSL how-to. Но я всё равно перечислю некоторые шаги. Предположим, что у нас уже есть PEM сертификат, конвертируем его в PKCS#12 формат для IIS:

openssl pkcs12 -export -out domain.name.pfx -inkey domain.name.key -in domain.name.crt

  • Импортируем этот сертификат в IIS:
    • IIS Manager ⇒ Top level navigation tree ⇒ Server certificates ⇒ Import …
  • Выбираем этот сертификат в Binding'e для HTTPS (port 443) в нашем сайте:
    • IIS Manager ⇒ Top level navigation tree ⇒ Sites ⇒ Default Web Site ⇒ Bindings…
      • Настраиваем обратный прокси для коммуникации IIS ⇔ Kibana (предполагается, что Кибана работает локально на том же сервере и использует свой стандартный порт — 5601)
      • IIS Manager ⇒ Top level navigation tree ⇒ Application Request Routing Cache ⇒ Server Proxy Settings … ⇒

Enable proxy [x]
Reverse proxy: localhost:5601

  • Центр сертификации (Certificate authority) сертификата Kibana
    Если случилось так, что сертификат Кибаны подписан "незнакомым" СА (не из PKI организации), то этот СА необходимо добавить в “Trusted Root Certification Authorities” на сервере с IIS:
    • Вызываем mmc (с правами администратора) ⇒ Add or Remove Snap-ins ⇒ Certificates ⇒ Add ⇒ Computer account ⇒ Local computer ⇒ Certificates (Local computer) ⇒ Trusted Root Certification Authorities ⇒ Certificate ⇒ импортируем "CA.crt"

Helicon Rewrite engine


По умолчанию модуль устанавливается в C:\Program Files.
Добавляем в конфигурационный файл C:\Program Files\Helicon\ISAPI_Rewrite3\httpd.conf следующее:


RewriteEngine on
RewriteCond %{REMOTE_USER} (.*)\\(.*)
RewriteHeader es-security-runas-user: .* (%2)(@company.com)
RewriteHeader Authorization: .* (Basic\ aWlzOnNlY3JldHBhc3N3b3Jk)
RewriteRule ^/logout / [R,L]

Как это работает:


  • после аутентификации пользователя его логин DOMAIN\user конвертируется модулем в формат userPrincipalName (user@company.com) и отправляется Кибане новым HTTP заголовком es-security-runas-user
  • добавляем еще один HTTP заголовок для Basic авторизации, где значение aWlzOnNlY3JldHBhc3N3b3Jk это закодированные base64 логин и пароль технического пользователя: iis:secretpassword (его мы создадим в Elasticsearch чуть позже).
  • ну и если пользователь кликнет на /logout, мы просто перенаправим его на стартовую страницу Кибаны, где он опять автоматически авторизуется

Kibana


Для SSO добавляем следующие параметры в kibana.yml:


elasticsearch.requestHeadersWhitelist: [ es-security-runas-user, authorization ]
xpack.monitoring.elasticsearch.requestHeadersWhitelist: [ es-security-runas-user, authorization ]

Elasticsearch


X-Pack уже установлен, конфигурируем AD в elasticsearch.yml:


xpack:
    security:
      authc:
        realms:
          native_realm:
            type: native
            order: 0
          company_ad_realm:
            enabled: true
            type: active_directory
            order: 1
            domain_name: company.com
            user_search:
              base_dn: "DC=company,DC=com"
            group_search:
              base_dn: "DC=company,DC=com"
            url: ldaps://server.company.com:636
            ssl.verification_mode: none
            bind_dn: "CN=user,OU=People,DC=company,DC=com"
            bind_password: "XXXXXXXXXX"
            unmapped_groups_as_roles: true
            cache.ttl: 300s

Пользователь, указанный в bind_dn, должен обладать правами на подключение и поиск в AD.
Проверка сертификата AD оключена (ssl.verification_mode: none), потому что центр сертификации (СА) AD не указан (параметр: ssl.certificate_authorities).


Создаем в Elasticsearch технического пользователя (iis) и роль (тоже iis) для имперсонизации ("олицетворение пользователя" — звучит ещё ужаснее):


POST _xpack/security/role/iis


{
  "run_as": [
    "*@company.com"
  ]
}

POST _xpack/security/user/iis


{
  "password": "secretpassword",
  "roles": [
    "iis"
  ],
  "full_name": "Service Account for IIS reverse proxy"
}

Теперь создаем роль для всех пользователей Кибаны. Напомню — имя роли должно быть именем группы в AD, члены которой будут иметь доступ к Кибане (пусть эта группа называется "ELK.Users"):


POST _xpack/security/role/ELK.Users


{
    "indices": [
          {
            "names": [
              ".kibana*"
            ],
            "privileges": ["read", "manage", "index", "delete"]
          }
    ]
}

Кибана хранит все настройки в одном индексе (.kibana или .kibana-6), поэтому все пользователи Кибаны должны иметь права на чтение и запись в этот индекс.


Теперь, для примера, создадим роль, члены которой будут иметь доступ к индексам net-*, в которых хранятся данные с сетевых устройств:


POST _xpack/security/role/ELK.Network.Admins


{
    "indices": [
          {
            "names": [
              "net-*"
            ],
            "privileges": ["read", "view_index_metadata"]
          }
    ]
}

Ещё один пример — "кастомная" супер-пользовательская роль для администраторов Elasticsearch2:


POST _xpack/security/role/ELK.Admins


{
      "cluster": [
        "all"
      ],
      "indices": [
        {
          "names": [
            "*"
          ],
          "privileges": [
            "all"
          ]
        }
      ]
}

Таким образом, члены AD-группы "ELK.Admins" получают полный доступ к Elasticsearch кластеру.


Результат


Включаем и удивляемся! Про ввод логина можно забыть.



При открытии корневой страницы нашего IIS-proxy сайта, пользователь был успешно аутентифицирован.
Замечание: если этот пользователь имеет доступ только к данным индексов net-*, то он всё равно будет видеть все сконфигурированные индексы в Кибане — обратите внимание на выпадающий список. Но при выборе индексов, к которым он не имеет доступа, пользователь будет видеть No results found. Но эта проблема к SSO не имеет отношения.


"Что-то пошло не так"


Тестирование и устранение неполадок.


Случай 1: Пользователя (или его группу) забыли добавить в AD-группу "пользователей Кибаны" (ELK.Users) или он вообще не должен иметь доступа к Кибане:


Config: Error 403 Forbidden: action [indices:data/write/update] is unauthorized for user [iis] run as [user@company.com]: [security_exception] action [indices:data/write/update] is unauthorized for user [iis] run as ...

Error 403 Forbidden


Пользователь был успешно аутентифицирован IIS (NTLM, Kerberos и т.д.) и посредством технического пользователя iis аутентифицировался в Кибане. Но т.к. реальный аккаунт user@company.com не входит в AD-группу "любителей Кибаны", то и в Elasticsearch у него нет роли на запись/чтение в индекс .kibana.
Я пока не знаю, как сделать сообщение или страничку "доступ запрещен" более "дружелюбным".


Случай 2: IIS использует SSL в конфигурации прокси-модуля (опция "Enable SSL offloading" выключена, как и задумано), a в Кибане забыли настроить HTTPS. Тогда мы можем наблюдать следующее в kibana.log:


{"type":"log","@timestamp":"2017-10-03T15:11:32Z","tags":["connection","client","error"],"pid":10416,"level":"error","message":"Parse Error","error":{"message":"Parse Error","name":"Error","stack":"Error: Parse Error\n    at Error (native)","code":"HPE_INVALID_METHOD"}}

Случай 3: Центр сертификации, подписавший сертификат Кибаны, неизвестен IIS
Открываем стартовую страничку IIS-Kibana:


HTTP Error 502.3 - Bad Gateway
A security error occurred

и соответствующая ошибка в логе Кибаны:


"code":"ECONNRESET"
"message":"socket hang up"

Случай 4: Аутентификация Windows не включена для нашего веб-сайта
Tогда пользователи будут аутентифицированы в Кибане как iis юзер: "Service Account for IIS reverse proxy"


Тест 1: Всё в порядке с AD/LDAP? И как там дела обстоят с членством?
Используем ldapsearch или adfind — всячески рекомендую, скачивать здесь


ldapsearch -h server.company.com -b "DC=company,DC=com" -D "CN=user,OU=People,DC=company,DC=com" -w "XXXXXXX" samaccountname=user

adfind -f "userprincipalname=user@company.com"

Тест 2: Тестируем имперcонизацию


curl -k -v -u iis:secretpassword -H "es-security-runas-user: user@company.com" https://elastic-server:9200/.kibana/_search

Если этот тест пройден (HTTP/1.1 200 OK), то Elasticsearch настроен правильно, и может проверить права пользователя в AD.
Ну а если получаем что-то вроде:


{"error":{"root_cause":[{"type":"security_exception","reason":"action [indices:data/read/search] is unauthorized for user [iis] run as [user@company.com]"}],"type":"security_exception","reason":"action [indices:data/read/search] is unauthorized for user [iis] run as [user@company.com]"},"status":403}

то самое время включать дебаг и читать логи Elasticsearch'a:
PUT /_cluster/settings


{
  "transient": {
    "logger.org.elasticsearch.xpack.security.authc": "trace"
  }
}

Тест 3: Изменяем членство пользователя в AD и, чтобы Elasticsearch не ожидал инвалидации кэша, очищаем последний вручную


curl -k -u 'elastic:changeme' -X POST https://elastic-server:9200/_xpack/security/realm/company_ad_realm/_clear_cache

Примечание: elastic — это встроенный пользователь с паролем по-умолчанию (в версии 5.х) или с измененным на такой же (версия 6.х).


To-Dos


  • Создать "дружелюбную" страницу при возникновении “Internal Server Error”
    Если Elasticsearch не может проверить пользователя, по какой-либо причине (например, нет соединения с AD), то Кибана покажет такую JSON страничку:

{ statusCode: 500, error: Internal Server Error, message: An internal server error occurred }

В принципе, можно в том же Helicon Rewrite написать редирект при появлении этой ошибки, на кастомную страничку, которую можно поместить в:


<kibana-home>\optimize\bundles

Страничка будет доступна по адресу:


https://localhost/bundles/custom/error.htm

Спасибо за внимание!


Надеюсь, что теперь в Вашей организации уровень "юзер-экспириенса" и прочего "сатисфэкшена" будет ещё больше!




[1] Следующие соображения безопасности и производительности должны быть приняты во внимание при использование unmapped_groups_as_roles: true


  • Администратор AD теоретически получает полный доступ к ES кластеру: при создании в AD группы с именем superuser и добавлении в неё своей учётной записи, администратор становится супер-пользователем кластера, т.к. роль superuser является встроенной и её нельзя отключить или удалить. Тоже самое будет справедливым для других встроенных ролей: logstash_admin, machine_learning_admin и т.д. Никаких "воркэраундов" предложить не могу, только аудит AD.
  • Необходимо тщательно планировать и соблюдать соглашение о наименовании групп в AD (naming convention), чтобы избежать несанкционированного доступа к данным. Используйте префиксы (суфиксы) в именах групп для доступа к ES кластеру, например ELK.*.
  • Elasticsearch будет проверять каждую группу пользователя, на соответвии её роли в кластере. При большом количестве групп, в которые включён пользователь, эта проверка будет влиять на производительность. В крупных организациях, где пользователи имеют сотни, или даже тысячи групп, это может быть проблемой. Но, предупреждён — значит вооружён. К тому же, Elasticsearch кэширует группы и не обращается к AD при каждом поисковом запросе, см. параметр cache.ttl.

Если Вы всё же решили не использовать этот автоматический маппинг через AD-группы по описанным выше причинам, то отображать группы в роли придётся или через файлы или через API. &larrhk;


[2] В продукции создавать такую супер-пользовательскую роль не рекомендуется. Администрировать лучше по старинке — супер-юзером elastic и через curl. &larrhk;

Tags:
Hubs:
+13
Comments 2
Comments Comments 2

Articles