Развёртывание и настройка Icinga 2 на Debian 8.6. Часть 10. Аутентификация и авторизация пользователей Active Directory в Icinga Web 2 (Kerberos и SSO)

В этой части нашего цикла заметок об Icinga будет рассмотрен пример того, как можно организовать доменную аутентификацию пользователей Active Directory (AD) с поддержкой Kerberos и Single sign-on (SSO) при подключении к веб-консоли Icinga Web 2.

Если мы заглянем в опорный документ Icinga Web 2 Authentication, то узнаем, что веб-консоль Icinga Web 2 способна работать с аутентификаций, основанной на каталоге Active Directory, других реализациях LDAP-каталогов, базах данных MySQL или PostgreSQL, а также делегировать процесс аутентификации непосредственно веб-серверу. Так, как в рассматриваемом нами примере будут использоваться такие вещи, как аутентификация с помощью Kerberos и дополнительная авторизация с помощью PAM, выбран вариант с делегированием процесса аутентификации веб-серверу. При этом процедуры внутренней проверки прав доступа к объектам веб-консоли Icinga Web 2 будут выполняться через специально созданное подключение к AD, как к LDAP-каталогу.

Подготовка инфраструктуры

Предполагаем, что наш сервер с Icinga Web 2 уже присоединён к домену Active Directory с помощью SSSD/realmd и на нём настроен Kerberos-клиент для взаимодействия с доменом: Подключение Debian GNU/Linux 8.6 к домену Active Directory с помощью SSSD и realmd.

Создадим в домене Active Directory две сервисные учётные записи доменного пользователя. Первую - для подключения и поиска в LDAP-каталоге (например DOM\s-Icinga-Apache-LDAP), вторую - для Kerberos-аутентификации пользователей, вызываемую веб-сервером Apache (например DOM\s-Icinga-Apache-Krb).

Для учётной записи DOM\s-Icinga-Apache-Krb необходимо зарегистрировать в домене запись servicePrincipalName (SPN) веб-сервера и сгенерировать keytab-файл, содержащий данную SPN-запись. Повторяться не буду, так как эта процедура пошагово рассмотрена в одной из прошлых заметок (см. пункты «Создание в домене AD сервисной учётной записи» и «Создание keytab-файла для сервисной учётной записи»). Предполагая, что необходимый keytab-файл у нас уже есть, размещаем его в доступном для службы веб-сервера месте и ограничиваем к нему доступ:

# chown www-data:root /etc/apache2/s-Icinga-Apache-Krb.keytab
# chmod 400 /etc/apache2/s-Icinga-Apache-Krb.keytab

Используемая здесь учётная запись www-data - это пользователь по умолчанию, от имени которого запускается служба apache2 в Debian.

***

Создадим в домене Active Directory группы безопасности, через членство в которых мы будем управлять доступом к Icinga Web 2.

Для начала создадим низкоуровневые группы доступа для администраторов (Icinga-Administrators@holding.com) и для пользователей (Icinga-Operators@holding.com). Эти группы будут определять совокупность доменных пользователей имеющих право доступа к веб-консоли Icinga, как таковой.

При необходимости создадим дополнительные группы более высокого уровня, которые будут иметь доступ только к информации о состоянии определённых хостов. Например, создадим отдельную группу для специалистов Телеком-блока Icinga-Telecom@holding.com и включим эту группу в группу Icinga-Operators@holding.com.

Создаём политику PAM

По аналогии с ранее описанным принципом, создадим в каталоге /etc/pam.d/ файл описания отдельной политики PAM, которая для процедур аутентификации и авторизации будет вызывать библиотеку SSSD:

# nano /etc/pam.d/apache2-icingaweb2

Наполним файл содержимым:

auth    required   pam_sss.so
account required   pam_listfile.so onerr=fail item=group sense=allow file=/etc/security/icingaweb2
account required   pam_sss.so

Первая строка определяет вызов библиотеки SSSD для аутентификации, вторая и третья строки отвечают за авторизацию. Вторая строка добавляет проверку членства в группе для аутентифицированного пользователя. При этом группы для проверки считываются из файла /etc/security/icingaweb2, который нам нужно создать дополнительно. В этом файле будут перечисляться доменные группы безопасности, которым можно разрешить доступ к веб-консоли Icinga:

Icinga-Administrators@holding.com
Icinga-Operators@holding.com

Таким образом мы организовали низкоуровневое ограничение доступа к веб-консоли Icinga, чтобы к ней не могли беспрепятственно подключаться любые аутентифицированные пользователи домена. Более высокоуровневое разграничение доступа к самим объектам мониторинга в веб-консоли Icinga мы рассмотрим далее на примере группы Icinga-Telecom@holding.com.

Добавляем LDAP-ресурс для авторизации в Icinga Web 2

Подключимся к веб-консоли Icinga Web 2 и добавим новый ресурс, который будет использоваться в качестве подключаемого источника данных. В меню навигации перейдём в Configuration > Application, переключимся на закладку Resources  и нажмём Create a New Resource.

В открывшейся справа форме создания нового ресурса заполним все необходимые поля:

  • В качестве типа ресурса выберем LDAP;
  • Присвоим простое имя ресурсу, например "icingaweb_ldap";
  • В качестве хоста укажем имя контроллера домена AD;
  • Тип шифрования и порт - 389 (для незащищённого соединения по протоколу LDAP или защищённого по протоколу StartTLS) либо 636 (для защищённого соединения по протоколу LDAPS);
  • Root DN – коневой контейнер или OU в AD, в котором будет производиться поиск объектов (группы и пользователи);
  • Bind DN/Password – Имя пользователя (в формате distinguishedName) и пароль, от созданной нами ранее в домене служебной учётной записи DOM\s-Icinga-Apache-LDAP

После того, ка все атрибуты создаваемого ресурса заданы, произведём проверку подключения к LDAP-каталогу с помощью кнопки Validate Configuration.

И если в настройках мы выбрали шифрование LDAP-соединений с помощью StartTLS или LDAPS, вероятней всего получим сообщение об ошибке, говорящее о проблемах установления соединения

Это вполне резонно, так как в конфигурации по умолчанию ldap-клиент на нашем сервере Icinga настроен таким образом, что перед установкой защищённого соединения пытается провести проверку подлинности цифрового сертификата, который предоставляет ему контроллер домена AD на начальном этапе соединения. И здесь нам придётся немного отвлечься от Icinga, чтобы решить данную проблему.

***

Есть 2 варианта решения этой проблемы - неправильный и правильный. Начнём с неправильного, так как он наиболее прост. Решение заключается в отключении механизма проверки сертификатов для SSL/TLS и оно коснётся всех сервисов в системе, которые пользуются услугами ldap-клиента (OpenLDAP), что само по себе не очень правильно и хорошо.

Открываем файл /etc/ldap/ldap.conf, комментируем параметр TLS_CACERT и добавляем строчку TLS_REQCERT never:

...
#TLS_CACERT     /etc/ssl/certs/ca-certificates.crt
TLS_REQCERT never

Правильный же вариант заключается в том, чтобы добавить на наш сервер Icinga доверенные корневые сертификаты корпоративных доменных Центров сертификации, которыми были выданы сертификаты, используемые нашими контроллерами домена AD. В результате этого ldap-клиент сможет использовать добавленные корневые сертификаты для проверки сертификатов, предоставляемых контроллерами домена Active Directory, когда мы будем к ним подключаться с использованием SSL/TLS в процессе аутентификации и авторизации доменных пользователей на веб-консоли Icinga. Описание этой несложной процедуры можно найти на отдельной Вики-странице: Добавление в Linux корневых сертификатов X.509 локального корпоративного Центра сертификации. Так, как в нашем случае сервер Icinga развёрнут на базе Debian GNU/Linux, нам потребуется создать отдельный файл-бандл, который будет содержать в себе все доверенные сертификаты доменных ЦС и указать этот файл в конфигурации клиента OpenLDAP. Имея на руках все корневые сертификаты доменных ЦС, объединяем их в один файл.

# mkdir /etc/ssl/certs-corp-ca
# cat ./AD-RootCA.pem  ./AD-SubCA.pem > /etc/ssl/certs-corp-ca/AD-Chain.pem

Правим конфигурацию клиента OpenLDAP (/etc/ldap/ldap.conf), указав в параметре TLS_CACERT путь к файлу, в который мы только что собрали доверенные корневые сертификаты доменных ЦС. При этом прочие параметры TLS_CA* лучше закомментировать:

...
#TLS_CACERT     /etc/ssl/certs/ca-certificates.crt
#TLS_CACERTDIR  /etc/ssl/certs
TLS_CACERT      /etc/ssl/certs-corp-ca/AD-Chain.pem

***

После сделанных изменений вернёмся в веб-интерфейс Icinga Web 2 и снова проведём валидацию создаваемого нами LDAP-ресурса:

Как видим, на этот раз соединение с использованием защищённого протокола прошло успешно.

После сохранения, заданная нами через веб-интерфейс конфигурация нового ресурса будет сохранена в файле /etc/icingaweb2/resources.ini

[icingaweb_db]
...

[icinga_ido]
...

[director_db]
...

[icingaweb_ldap]
type = "ldap"
hostname = "dc01.holding.com"
port = "389"
encryption = "starttls"
root_dn = "OU=KOM,DC=holding,DC=com"
bind_dn = "CN=s-Icinga-Apache-LDAP,OU=Security Users,OU=KOM,DC=holding,DC=com"
bind_pw = "StrOnGPass0rwD"

Далее созданный LDAP-ресурс мы будем использовать при создании User Group Backend для авторизации в Icinga Web 2.

Добавляем User Backend для аутентификации в Icinga Web 2

Так как мы хотим использовать преимущества Kerberos и SSO для автоматической аутентификации доменных пользователей при подключении к веб-консоли Icinga Web 2, нам потребуется создать User Backend со специальным типом External, то есть передать управление процедурой аутентификации пользователей непосредственно веб-серверу Apache. Однако если в веб-консоли мы заглянем туда, где создаются объекты типа User Backend (Configuration > Application, закладка Authentication - Create a New User Backend), то увидим, что в текущей версии Icinga Web 2 среди возможных для выбора типов Backend Type нет типа External.

Не знаю почему так, но это вполне разрешимый вопрос, так как в создание внешнего аутентификатора описано в документе 05-Authentication.md 

Перейдём на консоль нашего сервера Icinga и добавим руками новую секцию [kerberos] перед секцией [icingaweb2] в конфигурационном файле /etc/icingaweb2/authentication.ini

[kerberos]
backend = "external"
strip_username_regexp = "/@.*$/"

[icingaweb2]
backend = "db"
resource = "icingaweb_db"

В параметре backend укажем ключевое слово "external", а в дополнительном параметре strip_username_regexp укажем регулярное выражение, с помощью которого из имени аутентифицированного пользователя будет отсекаться доменный суффикс.

Теперь вернёмся в веб-консоль Icinga Web 2, обновим страницу, и проверим, что в списке User Backend отображается добавленный нами через конфигурационный файл внешний аутентификатор. Нажмём кнопку Validate Configuration и убедимся в том, что веб-консоль не возвращает ошибок:

Аутентификация в Icinga Web 2 настроена, переходим к настройке авторизации.

Добавляем User Group Backend для авторизации в Icinga Web 2

Теперь создадим в Icinga Web 2 объект типа User Group Backend, который будет использоваться для механизма авторизации (проверки членства аутентифицированного пользователя в группах AD). Перейдём в Configuration > Application, выберем закладка Authentication и нажмём Create a New User Group Backend.

В открывшейся справа форме создания User Group Backend выберем тип ActiveDirectory, укажем понятное нам имя, например "icingaweb2_AD_group". В поле LDAP Connection из выпадающего списка выберем созданный нами ранее LDAP-ресурс. Поле User Backend оставляем без выбора, так как по условиям нашей задачи используется внешний аутентификатор. Отметим опцию Nested Group Search, чтобы при поиске членства в доменных группах учитывались вложенные группы. Остальные параметры можно оставить предложенные по умолчанию, если конечно нам не требуется дополнительная LDAP-фильтрация, которую можно здесь настроить.

После сохранения созданного User Group Backend, его конфигурация попадёт в файл /etc/icingaweb2/groups.ini, который примет примерно следующий вид:

[icingaweb2]
backend = "db"
resource = "icingaweb_db"

[icingaweb2_AD_group]
resource = "icingaweb_ldap"
user_backend = "none"
group_class = "group"
group_name_attribute = "sAMAccountName"
group_member_attribute = "member"
backend = "msldap"
nested_group_search = "1"

Параметры авторизации настроены, переходим к проверке.

Проверяем возможность поиска доменных групп

На данном этапе фактическое соединение Icinga Web 2 c AD настроено и теперь мы можем проверить, как работает поиск доменных групп безопасности. Перейдём в веб-консоли в Configuration > Authentication и переключимся на закладку User Groups. Здесь из выпадающего списка выберем ранее созданный User Group Backend и убедимся в том, что поиск групп работает и группа отображает свой состав

Если всё в порядке, то можем приступать к созданию Ролей Icinga Web 2, привязанных к доменным группам безопасности.

Создаём роли с привязкой к доменным группам

Для разграничения прав доступа к объектам веб-консоли Icinga Web 2 используется ролевая модель. Давайте попробуем создать пару Ролей. Для этого перейдём в Configuration > Authentication, и на закладке Roles нажмём Create a New Role.

В открывшейся справа форме добавления Роли, укажем понятное нам имя роли. Предположим, это будет роль Администраторов Icinga с неограниченными правами доступа. В поле Groups укажем имя доменной группы безопасности, которая объединяет администраторов Icinga. В перечне набора прав выберем первую позицию – Allow everything, которая определяет неограниченный доступ.

Теперь по аналогии создадим вторую роль, но уже с ограниченным доступом к объектам в icinga Web 2. Предположим, что у нас в Icinga есть Группа Хостов с именем "KOM-Telecom" и эта группа привязана только к некоторым хостам (клиентам Icinga), доступ к которым в веб-консоли мы и хотим разрешить для специалистов Телеком-блока, которые входят в доменную группу безопасности Icinga-Telecom@holding.com.

Создадим соответствующую Роль с привязкой к доменной группе безопасности. В наборе прав доступа Permissions Set на этот раз снимем указатель с верхней позиции, разрешающей всё, и отметим только те вещи, к которым нужно разрешить доступ. А в дополнительных полях фильтрации добавим фильтр по имени Группы Хостов:

По аналогии мы можем создать столько Ролей с привязкой к доменным группам безопасности, сколько потребуется. Создаваемые нами роли будут попадать на сервере Icinga Web 2 в конфигурационный файл /etc/icingaweb2/roles.ini:

[Administrators]
users = "icingaweblocaladmin"
permissions = "*"
groups = "Administrators"

[Administrators_AD]
groups = "Icinga-Administrators"
permissions = "*"

[Telecom]
groups = "Icinga-Telecom"
permissions = "module/director, director/inspect, module/monitoring, monitoring/command/schedule-check"
monitoring/filter/objects = "hostgroup_name=KOM-Telecom"

Можем считать, что с настройкой авторизации закончили, теперь перейдём к настройке внешней аутентификации пользователей средствами веб-сервера Apache.

Настройка Apache на Kerberos-аутентификацию и PAM авторизацию

По началу для аутентификации в Apache я попробовал вместо модуля auth-kerb использовать модуль auth-gssapi, по аналогии с тем, как это было описано ранее, однако такой вариант в моём окружении не заработал, возможно в силу того, что в репозиториях Debian Jessie модуль auth-gssapi довольно старой версии (1.0.3-2) и эта версия имеет какие-то проблемы. Поэтому в данном примере я буду использовать уже проверенный модуль auth-kerb.

Итак, устанавливаем модули, необходимые веб-серверу Apache в Debian для поддержки Kerberos-аутентификации с дополнительной авторизацией через PAM:

# apt-get install libapache2-mod-auth-kerb libapache2-mod-authnz-pam

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

# apache2ctl -M | grep -E "kerb|pam"

 auth_kerb_module (shared)
 authnz_pam_module (shared)

Отредактируем конфигурационный файл Apache, определяющий конфигурацию веб-узла Icinga Web 2 ( по умолчанию это файл /etc/apache2/conf-available/icingaweb2.conf ), дополнив в нём секцию, где описан доступ к каталогу /usr/share/icingaweb2/public:

...
<Directory "/usr/share/icingaweb2/public">
  AuthType Kerberos
  AuthName "Kerberos Login"
  Krb5Keytab /etc/apache2/s-Icinga-Apache-Krb.keytab
  KrbAuthRealms HOLDING.COM
  KrbMethodK5Passwd on
  Require pam-account apache2-icingaweb2
  ... 
</Directory>
...

Как видно, здесь используется аутентификация Kerberos c ранее приготовленным keytab-файлом и вызовом ранее созданной политики PAM "apache2-icingaweb2" для авторизации пользователей.

После внесённых изменений перезапустим службы Icinga и Apache:

# systemctl restart icinga2
# systemctl restart apache2

Теперь попытаемся с клиентского компьютера получить доступ к веб-консоли Icinga Web 2 и процедура аутентификации и авторизации должна пройти для пользователя прозрачно без каких либо запросов на ввод учётных данных.

Опционально: Страница ошибки 401 для Apache

При желании можно дополнительно оформить свою веб-страницу, которая будет показываться пользователям, не имеющим доступа к веб-консоли Icinga Web 2. Для этого в корневой каталог Apache по умолчанию ( /var/www/html/ ) поместим подготовленную HTML-страничку, например IcingaUnauthorized.html:

Однако практические тесты показали, что адекватно такую страницу пользователям отображает только браузер Mozilla Firefox. Internet Explorer, в свойственной ему манере, показывает собственную страницу ошибки (не говорю уже про чудоковатое требование к тому, что размер кастомной страницы ошибок должен превышать определённый размер в байтах). А Google Chrome вообще выплёвывает из себя что-то типа ERR_INVALID_RESPONSE. Поэтому, делать страницу ошибки или нет - остаётся делом вкуса.

Защита соединений с веб-сервером с помощью SSL-сертификата

Не смотря на то, что для аутентификации пользователей на веб-сайте Icinga Web 2 мы используем защищённый протокол Kerberos, дополнительно усилить сессионную защиту HTTP-соединений с помощью SSL всё же не будет лишним.

Для этого нам потребуется сделать пару несложных вещей – активировать модуль веб-сервера для поддержки SSL (mod_ssl) и сгенерировать SSL-сертификат веб-сервера, который в последствии в паре с закрытым ключом от этого сертификата нужно будет привязать к конфигурации веб-сервера.

Модуль поддержки SSL в Apache на Debian установлен в конфигурации по умолчанию, поэтому нам остаётся только активировать его (при активации этого модуля будет активирован ряд других вспомогательных модулей):

# a2enmod ssl

Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
  service apache2 restart

Убедимся в том, что модуль SSL отображается в списке активированных модулей

# apache2ctl -M | grep ssl

 ssl_module (shared)

По поводу генерации закрытого ключа и сертификата для веб-сервера Apache, опять же, я повторяться не буду, так как подобная процедура рассматривалась ранее, например, в заметке Установка сертификата от Windows Server CA на веб-сервер Apache. Предполагая, что у нас уже есть на руках готовые файлы ключа и сертификата в формате PEM размещаем их на нашем сервере Icinga Web 2 в каталогах /etc/ssl/private/ и /etc/ssl/certs/ соответственно.

# mv ~/KOM-AD01-MON20.key /etc/ssl/private/
# mv ~/KOM-AD01-MON20.pem /etc/ssl/certs/
# chmod 640 /etc/ssl/private/KOM-AD01-MON20.key
# chown root:www-data /etc/ssl/private/KOM-AD01-MON20.key

Теперь нам остаётся лишь исправить конфигурацию веб-сайта Icinga Web 2 в Apache, таким образом, чтобы обязательно использовался протокол HTTPS. В итоге конфигурационный файл /etc/apache2/conf-available/icingaweb2.conf примет примерно следующий вид:

<VirtualHost *:80>
    ServerName "KOM-AD01-MON20.holding.com"
    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>
<VirtualHost *:443>
    ServerName "KOM-AD01-MON20.holding.com"
    DocumentRoot "/var/www/html"
    SSLEngine on
    SSLCertificateFile "/etc/ssl/certs/KOM-AD01-MON20.pem"
    SSLCertificateKeyFile "/etc/ssl/private/KOM-AD01-MON20.key"
    Alias /icingaweb2 "/usr/share/icingaweb2/public"
    <Directory "/usr/share/icingaweb2/public">
        AuthType Kerberos
        AuthName "Kerberos Login"
        Krb5Keytab /etc/apache2/s-Icinga-Apache-Krb.keytab
        KrbAuthRealms HOLDING.COM
        KrbMethodK5Passwd on
        Require pam-account apache2-icingaweb2
        ErrorDocument 401 /IcingaUnauthorized.html
        Options SymLinksIfOwnerMatch
        AllowOverride None
        SetEnv ICINGAWEB_CONFIGDIR "/etc/icingaweb2"
        EnableSendfile Off
        <IfModule mod_rewrite.c>
                RewriteEngine on
                RewriteBase /icingaweb2/
                RewriteCond %{REQUEST_FILENAME} -s [OR]
                RewriteCond %{REQUEST_FILENAME} -l [OR]
                RewriteCond %{REQUEST_FILENAME} -d
                RewriteRule ^.*$ - [NC,L]
                RewriteRule ^.*$ index.php [NC,L]
        </IfModule>
        <IfModule !mod_rewrite.c>
                DirectoryIndex error_norewrite.html
        </IfModule>
    </Directory>
</VirtualHost>

После внесённых изменений в конфигурацию Apache, произведём перезапуск службы:

# systemctl restart apache2

Теперь наш веб-сайт Apache имеет не только возможность безопасной и удобной аутентификации и авторизации доменных пользователей AD, но и имеет дополнительную защиту всех HTTP-соединений.

Однако, хочу отметить, что не смотря на полученное удобство аутентификации в таком решении имеется своя "ложка дегтя", хоть и несущественная (при условии нормальной работы Kerberos). Дело в том, что Icinga Web 2 спроектирована таким образом, что в процессе аутентификации пользователя предполагается последовательный перебор подключенных методов аутентификации из ранее упомянутого файла /etc/icingaweb2/authentication.ini. То есть, порядок следования секций в этом файле, описывающих тот или иной аутентификатор прямо влияет на последовательность вызова соответствующих методов аутентификации. Однако, у меня пока не получилось настроить откат на использование встроенной Form-based аутентификации (с использованием локальных учётных записей из базы данных Icinga Web 2) в том случае, если по какой-то причине не отрабатывает внешняя Kerberos аутентификация в Apache. В общем вопрос отката на встроенную аутентификацию пока остался открытым.

Отладка

В процессе настройки конфигурации Icinga Web 2 могут возникнуть ситуации неопределённости, разрешить которые может помочь включение расширенного логирования. Для этого откроем веб-консоль и перейдём в Configuration > Application. Здесь на закладке General мы можем изменить уровень логирования в поле Logging Level и подсмотреть имя лог-файла, в который будет вестись логирование.

Если веб-консоль уже недоступна по причине "очумелых ручек", то включить расширенное логирование можно методом прямой правки конфигурационного файла /etc/icingaweb2/config.ini с изменением соответствующих параметров в секции [logging]:

...
[logging]
log = "file"
level = "DEBUG"
file = "/var/log/icingaweb2/icingaweb2.log"
...

Дополнительные источники информации:

Только один комментарий Комментировать

  1. Роман Кулакович /

    Вот или лыжи не едут или одно из двух. Туплю и не могу понять в каком моменте. Взял свежий дебиан 9.0, ввел его в домен, вроде бы все настроил и работает за исключением сквозной авторизации. В Дебиан логинюсь под доменной учеткой, сама icinga видит доменные группы и никаких проблем быть не должно. Но при входе в админку icinga натыкаюсь на предложение авторизации от Апача, который не принимает пароль.

    По мануалу прошел уже 3 раза, ни как не могу обнаружить в чем проблема. Можете подсказать, на каком этапе что-то могло пойти не так.

Добавить комментарий