Single Sign-On, или Танцы Шестерых
Эта статеечка изначально писалась как памятка для себя, но по настойчивым просьбам коллег я всё-таки через полтора года собрался с духом и публикую её.
Материал прозаичен, но может оказаться кому-нибудь полезным, чему я буду очень рад. Ещё больше буду признателен конструктивным советам и отзывам.
Итак, наша тема — «Как реализовать Single Sign-On для веб-приложения в условиях разношёрстности и нормальной лохматости системного зоопарка».
Single Sign-On. Вводная
Доверился кому, так доверяй во всём.
© Цецилий Стаций
Для тех, кто не в курсе (хотя они вряд ли станут читать этот материал), скажу, что Single Sign-On (в дальнейшем повествовании — «SSO») в общепринятом представлении не является ни технологией, ни тем более неким магическим протоколом. SSO — это подход, метод, позволяющий реализовать связность AAA (Authentication & Authorization & Accounting) между разнородными системами и приложениями без дополнительных телодвижений со стороны конечного пользователя.
Типичными примерами SSO являются, например, решения, построенные целиком на продуктах Microsoft; в этом случае сервер (ы) Active Directory обеспечивают не только хранение каталога, но и управляют поведением подключенных к домену рабочих станций, установленным на них софтом и всем прочим, вплоть до железа (мы же все умеем запрещать политиками тот же USB). Сквозная парадигма AAA в такой ситуации обеспечивается почти автоматически при использовании продуктов Microsoft, то есть в гомогенной среде.
Гетерогенная IT-структура в отношении прозрачности AAA несколько сложнее, однако и для этой среды уже выработано много способов реализации и несть им числа.
В качестве примеров:
- Известная компания Atlassian имеет на борту хорошо зарекомендовавший себя продукт Atlassian Crowd, решающий подобные задачи, однако он заточен под конкретную линейку программных продуктов этой компании.
- Многие из нас используют Портал ГосУслуг, и, абсолютно все мы, являясь ответственными налогоплательщиками, знаем, что на сайте nalog.ru доступна аутентификация через Портал ГосУслуг.
- Парадоксальный, но на удивление частый вариант аутентификации: «Вхожу на Google, затем на Facebook с аутентификацией через Google, а потом на AliExpress с аутентификацией через Facebook».
Два из трёх вышеперечисленных пункта не имеют никакого отношения к SSO.
Угадаете, какие? :)
Аксиома
В рамках этой статьи принимаем, что SSO реализовано и работает исключительно в рамках Intranet (в корпоративной среде), и при этом обеспечивает достаточную надёжность, отказоустойчивость и безопасность.
Задача
На входе мы имеем:
- Веб-приложение, построенное на платформе InterSystems.
- Линуксовые серверы, на котором оно крутится. Серверы расположены в интранете Заказчика.
- Развитая Microsoft-инфраструктура Заказчика, в том числе и весьма неплохо настроенные групповые политики на грамотном лесе доменов и связке контроллеров.
- Уважаемый Заказчик, сказавший ключевые фразы «Надо!» и «Чтобы было готово вчера!».
- И, к счастью, полноценный тестовый сервер, так что нам есть где развернуться!
Сразу оговорюсь, что есть и более простые пути решения этой задачки, помимо описанного ниже, но мы же их не ищем. Ну и требования Заказчика были не самые однозначные.
Итак, приступаем!
Танцуем с Пингвинами. Linux
Домен: Эукариоты, Царство: Животные, Подцарство: Эуметазои, Тип: Хордовые, Подтип: Позвоночные, Инфратип: Челюстноротые, Надкласс: Четвероногие, Класс: Птицы, Подкласс: Новонёбные, Отряд: Пингвинообразные, Семейство: Пингвиновые, Вид: Oracle Linux Server release 7.2
Установка
Нам достался вполне оперившийся потомок/клон RHEL под именем Oracle Linux Server release 7.2.
Настройка
Как всегда, Линукс в его серверном виде прост, беззаботен и безотказен, но нам важно убедиться, что он правильно сконфигурирован, особенно в части сетевых настроек.
Тестирование
Сначала смотрим на настройки DNS, т.к. это критично для работоспособности всего решения:
[root@my-test-server ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search my-domain.ru
nameserver 172.16.0.1
nameserver 172.16.0.2
На этом этапе необходимо проверить доступность серверов DNS (которые, в нашем случае, являются и домен-контроллерами). Сделать это можно по-разному, просто используйте свои любимые утилиты и методы проверки (host, dig, telnet, ping, …). Важно, чтобы нужные нам порты были доступны и работоспособны, а в случае DNS это в первую очередь TCP/53. И не забываем про кощунство и жадность сетевых администраторов и безопасников (я сам такой), которые могут закрыть вам всё, включая ICMP, и оставить только парочку затребованных и согласованных портов. Что есть правильно.
Собачий вальс. Kerberos
Це́рбер, также Ке́рбер (от др.-греч. Κέρβερος, лат. Cerberus) — в греческой мифологии порождение Тифона и Ехидны (Тартара и Геи), трёхголовый пёс, у которого из пастей течёт ядовитая смесь. Цербер охранял выход из царства мёртвых Аида, не позволяя умершим возвращаться в мир живых. Однако это удивительное по силе существо было побеждено Гераклом в одном из его подвигов.
Уверен, что не нужно напоминать про необходимость правильной настройки Kerberos для «плодотворного сотрудничества» с MSAD.
Разумеется, для установки и конфигурирования вам необходимы root’овые права на сервере. Или sudo. Или «Звоните Солу».
Установка
Установка и настройка необходимых пакетов производится довольно просто, если «злые сетевые админы» дали вашему серверу выход в Интернет.
К сожалению, Интернет с доступом к репозиториям нужен на этапе установки, если добрые админы не установили всё нужное заблаговременно.
И всё печально, если нет ни доступа, ни установленных пакетов.
Однако будем оптимистами и, считая, что админы хотя бы на часик открыли канал, выполняем установку:
[root@my-test-server ~]# yum install krb5-workstation
Загружены модули: ulninfo
Разрешение зависимостей
--> Проверка сценария
---> Пакет krb5-workstation.x86_64 0:1.14.1-26.el7 помечен для установки
--> Обработка зависимостей: libkadm5(x86-64) = 1.14.1-26.el7 пакета: krb5-workstation-1.14.1-26.el7.x86_64
--> Обработка зависимостей: krb5-libs(x86-64) = 1.14.1-26.el7 пакета: krb5-workstation-1.14.1-26.el7.x86_64
--> Обработка зависимостей: libkadm5srv_mit.so.10(kadm5srv_mit_10_MIT)(64bit) пакета: krb5-workstation-1.14.1-26.el7.x86_64
--> Обработка зависимостей: libkadm5srv_mit.so.10()(64bit) пакета: krb5-workstation-1.14.1-26.el7.x86_64
--> Проверка сценария
---> Пакет krb5-libs.x86_64 0:1.13.2-10.el7 помечен для обновления
---> Пакет krb5-libs.x86_64 0:1.14.1-26.el7 помечен как обновление
---> Пакет libkadm5.x86_64 0:1.14.1-26.el7 помечен для установки
--> Проверка зависимостей окончена
Зависимости определены
==============================================================
Package Архитектура Версия Репозиторий Размер
==============================================================
Установка:
krb5-workstation x86_64 1.14.1-26.el7 ol7_latest 772 k
Установка зависимостей:
libkadm5 x86_64 1.14.1-26.el7 ol7_latest 172 k
Обновление зависимостей:
krb5-libs x86_64 1.14.1-26.el7 ol7_latest 741 k
Итого за операцию
====+++++=============================================
Установить 1 пакет (+1 зависимый)
Обновить ( 1 зависимый)
Объем загрузки: 1.6 M
Is this ok [y/d/N]: y
Downloading packages:
No Presto metadata available for ol7_latest
(1/3): krb5-libs-1.14.1-26.el7.x86_64.rpm | 741 kB 00:00:00
(2/3): libkadm5-1.14.1-26.el7.x86_64.rpm | 172 kB 00:00:00
(3/3): krb5-workstation-1.14.1-26.el7.x86_64.rpm | 772 kB 00:00:00
--------------------------------------------------------------------------------
Общий размер 3.9 MB/s | 1.6 MB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Обновление : krb5-libs-1.14.1-26.el7.x86_64 1/4
Установка : libkadm5-1.14.1-26.el7.x86_64 2/4
Установка : krb5-workstation-1.14.1-26.el7.x86_64 3/4
Очистка : krb5-libs-1.13.2-10.el7.x86_64 4/4
Проверка : krb5-libs-1.14.1-26.el7.x86_64 1/4
Проверка : libkadm5-1.14.1-26.el7.x86_64 2/4
Проверка : krb5-workstation-1.14.1-26.el7.x86_64 3/4
Проверка : krb5-libs-1.13.2-10.el7.x86_64 4/4
Установлено:
krb5-workstation.x86_64 0:1.14.1-26.el7
Установлены зависимости:
libkadm5.x86_64 0:1.14.1-26.el7
Обновлены зависимости:
krb5-libs.x86_64 0:1.14.1-26.el7
Выполнено!
Само собой, как используемый менеджер пакетов, так и их версии у вас могут быть другими, но сути дела это не меняет.
И Да, обещаю, что более таких наиполнейших листингов тривиальной установки в статье не появится.
Настройка
Вполне работающий файл конфигурации Kerberos изначально будет выглядеть примерно так:
[root@my-test-server ~]# cat /etc/krb5.conf
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = true
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = MY-DOMAIN.RU
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
MY-DOMAIN.RU = {
kdc = ad.my-domain.ru
admin_server = ad.my-domain.ru
}
[domain_realm]
.my-domain.ru = MY-DOMAIN.RU
my-domain.ru = MY-DOMAIN.RU
где ad.my-domain.ru обязательно должен быть правильным FQDN, разрешаемым и доступным. Это важно!
Тестирование
На следующем шаге у нас, как правило, всё происходит очень просто.
Просто убеждаемся, что всё плохо:
[root@my-test-server ~]# klist
klist: Credentials cache keyring 'persistent:0:0' not found
Зовём специалистов по трёхголовым собачкам (AKA сисадмина, знающего сверхсекретный доменный админский логин/пароль), и просим его ввести его примерно вот так:
[root@my-test-server ~]# kinit SuperPuperAdmin
Password for SuperPuperAdmin@MY-DOMAIN.RU: ************************
После этого klist должен вернуть уже что-то осмысленное.
Засим нашу собачку считаем готовой, хотя…
Общеизвестно, что Ниссан — это невыгулянный Пассат.
Танец Великих Равнин. Apache
Апачи — собирательное название для нескольких культурно родственных племён североамериканских индейцев, говорящих на апачских языках атабаскской ветви семьи на-дене.Апачи создали свой собственный захватывающий танец в масках по названию гахан, которым они празднуют достижение совершеннолетия девочками. Также у апачей и поныне есть танцевальные обряды для видений и предсказаний.
Начинаем охотиться вместе с индейцами племён Апачи.
Установка
Как и прежде, пакеты — это наше всё (за исключением всемогущих шаманов-Админов, разумеется):
[root@my-test-server ~]# yum install httpd
Загружены модули: ulninfo
Разрешение зависимостей
[…skipped…]
Установлено:
httpd.x86_64 0:2.4.6-45.0.1.el7
Установлены зависимости:
httpd-tools.x86_64 0:2.4.6-45.0.1.el7
Выполнено!
Настройка
Этого, конечно, недостаточно, потому что свежеустановленный индеец не знает нашего языка. Сконфигурируем его примерно так:
[root@my-test-server ~]# cat > /etc/httpd/conf.d/ensemble.conf
DocumentRoot "/opt/isc/ensemble/csp"
CSPModulePath /opt/isc/ensemble/csp/bin/
LoadModule csp_module_sa /opt/isc/ensemble/csp/bin/CSPa24.so
User cacheusr
Group cacheusr
CSP On
SetHandler csp-handler-sa
ServerName my-test-server.my-domain.ru />
Options MultiViews FollowSymLinks
AllowOverride None
Require all granted
Require all denied
HostnameLookups Off
CSP On
SetHandler csp-handler-sa
SetHandler cspsys-handler-sa
SetHandler csp-handler-sa
CSPFileTypes csp cls zen cxw
Alias /csp/ /opt/isc/ensemble/csp/
AllowOverride None
Options MultiViews FollowSymLinks ExecCGI
Require all granted
Require all denied
И дадим «пиночек под задочек»:
[root@my-test-server ~]# systemctl restart httpd
Убедимся, что он научился разговаривать по-нашенски, зайдя в System Management Portal.
Апачи некогда были гордым и независимым народом, у них это в крови, поэтому со всем уважением и вежливостью попросим Apache браться за работу вместе с нашим Пингвином-Прорицателем:
[root@my-test-server ~]# systemctl is-enabled httpd
disabled
[root@my-test-server ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@my-test-server ~]# systemctl is-enabled httpd
enabled
Прослушавши «Пионерскую Зорьку», сделав водные процедуры, выгулявши трёхглавую собачку и причесав индейца, переходим к «Производственной Гимнастике», которая сегодня будет танцевальной (и даже с бубнами).
Танцуем Самбу!
Са́мба (порт. samba) — бразильский танец, символ национальной идентичности бразильцев. Танец обрёл мировую известность благодаря бразильским карнавалам. Одна из разновидностей самбы вошла в обязательную пятёрку латиноамериканской программы бальных танцев. Исполняется в темпе 50–52 удара в минуту, в размере 2/4 или 4/4.
Как всем нам прекрасно известно, наша любимая Samba в серверном варианте совершенно логично разделена на три основных исполняемых модуля: (smb|nmb|winbind)d.
Теоретически нам нужен только работоспособный winbindd. Да, это всего лишь один из демонов Самбы. Но он, установленный отдельно от всего пакета, почему-то на имеющейся платформе работать не захотел, а разбираться в причинах его недовольства не захотелось уже мне.
Поэтому устанавливаемся по полной.
Установка
Процедура очень проста, особенно, если ваш (а) Админ (ша) танцует вместе с вами.
[root@my-test-server ~]# yum install samba
Загружены модули: ulninfo
Разрешение зависимостей
--> Проверка сценария
---> Пакет samba.x86_64 0:4.4.4-9.el7 помечен для установки
--> Проверка зависимостей окончена
[…skipped…]
Установить 1 пакет (+12 зависимых)
Объем загрузки: 6.6 M
Объем изменений: 23 M
Is this ok [y/d/N]: y
[…skipped…]
Установлено:
samba.x86_64 0:4.4.4-9.el7
Установлены зависимости:
libaio.x86_64 0:0.3.109-13.el7 libldb.x86_64 0:1.1.26-1.el7 libtalloc.x86_64 0:2.1.6-1.el7
libtdb.x86_64 0:1.3.8-1.el7_2 libtevent.x86_64 0:0.9.28-1.el7 libwbclient.x86_64 0:4.4.4-9.el7
pytalloc.x86_64 0:2.1.6-1.el7 samba-client-libs.x86_64 0:4.4.4-9.el7 samba-common.noarch 0:4.4.4-9.el7
samba-common-libs.x86_64 0:4.4.4-9.el7 samba-common-tools.x86_64 0:4.4.4-9.el7 samba-libs.x86_64 0:4.4.4-9.el7
Выполнено!
Костюмчик готов, затягиваем галстук:
[root@my-test-server ~]# yum install samba-winbind
[…skipped…]
Установлено:
samba-winbind.x86_64 0:4.4.4-9.el7
Установлены зависимости:
samba-winbind-modules.x86_64 0:4.4.4-9.el7
Выполнено!
Настройка
Мало прийти на карнавал, нужно ещё и немного потанцевать (уже с бубнами):
[root@my-test-server ~]# cat /etc/samba/smb.conf
# See smb.conf.example for a more detailed config file or
# read the smb.conf manpage.
# Run 'testparm' to verify the config is correct after
# you modified it.
[global]
workgroup = AD
security = ads
server string = my-test-server
netbios name = my-test-server
security = ads
realm = my-domain.ru
password server = *
Репетируем первые шаги (разумеется, ошибаемся на первых порах):
[root@my-test-server ~]# systemctl restart winbind
Job for winbind.service failed because the control process exited with error code. See "systemctl status winbind.service" and "journalctl -xe" for details.
Зовём на помощь учителей танца, и («Как много нам открытий чудных…») это оказываются те же самые кинологи, помогавшие нам в приручении нашего трёхглавого щеночка!
[root@my-test-server ~]# net ads join --U SuperPuperAdmin@my-domain.ru
Enter root's password: ************************
И надеемся на чудо… Всё зависит от рук и от места, откуда они растут…
«Разлук так много на земле.
И разных судеб,
Надежду дарит на заре.
Паромщик людям»
© Prodigy & Rammstein, 2048
Если затем видим примерно вот такое:
[root@my-test-server]# net ads info
LDAP server: 172.16.0.123
LDAP server name: AD.my-domain.ru
Realm: MY-DOMAIN.RU
Bind Path: dc=MYDOMAiN,dc=RU
LDAP port: 389
Server time: Сб, 33 ноя 2049 17:48:12 ATL
KDC server: 172.16.0.123
Server time offset: 0
то Счастье уже почти Есть!
Тестирование
Проверяем его (Счастья) наличие:
[root@my-test-server /]# wbinfo -g
MYDOMAIN\proverka
MYDOMAIN\управление
MYDOMAIN\установка
MYDOMAIN\снабжение
MYDOMAIN\юристы
MYDOMAIN\бухгалтерия
MYDOMAIN\пользователи запад
MYDOMAIN\пользователи север
MYDOMAIN\пользователи windows
MYDOMAIN\пользователи 1c
MYDOMAIN\СуперПуперАдминистраторы
MYDOMAIN\КомуМожноВИнтернет
Есть контакт!
Медляк. mod_auth_ntlm_winbind
Прежде чем танцевать медленный танец, придется кого-то на него пригласить, ведь в одиночку под него двигаться не считается приемлемым. Улучите момент и подойдите к приглянувшейся девушке. Собравшись танцевать медленный танец, объявите о своем намерении потенциальной партнерше прямо, без ненужного многословия. Не будьте излишне развязны и напористы, оставьте за ней решение, согласиться или нет. В последнем случае она откажется, но поблагодарит вас.
Установка
Найдите в Сети живой репозиторий с mod_auth_ntlm_winbind.
Да, их мало живых (я забрал с какого-то svn).
Да, версии совсем не новые.
Да, вам нужно будет их собрать «вручную».
Да, не все соберутся.
Да, даже после патчей и правок вручную.
Да, для сборки понадобится полностью настроенное окружение (gcc + glib + apxs + headers + *-dev + …).
И ДА, это — единственный известный мне вариант, который работает стабильно.
Настройка
С настройкой всё более-менее элементарно, добавьте в ваш конфиг-файл Apache (в основной, либо в conf.d/xyz.conf, по желанию):
AuthName "NTLM my-domain.ru"
NegotiateAuth on
NegotiateAuthHelper "/usr/bin/ntlm_auth --helper-protocol=gss-spnego"
NTLMBasicAuthoritative on
AuthType Negotiate
require valid-user
#LogLevel debug ## Включите для отладки
Разумеется, пути должны быть указаны правильно для вашей инсталляции, как и все прочие параметры.
Для первоначальной отладки советую раскомментировать строчку LogLevel, тогда в файлы протоколов Apache будут записываться дополнительные и иногда очень полезные сообщения.
Белый танец. Кто кого?…
Leicht versprochen, leicht gebrochen.
На очень закономерный и весьма своевременный (к концу статьи-то!) вопрос «А нафига мы всё это делали?» отвечу, что всё это всего-то ради одной строчки в серверном ответе HTTP!…
Бочка мёда
Нам нужен верный автоматически передаваемый веб-сервером REMOTE_USER (или HTTP_REMOTE_USER — не суть важно), чтобы:
- пользователь, успешно залогинившись в Windows под своим доменным аккаунтом,
- пройдя все проверки в MSAD,
- зашёл затем веб-браузером в приложение, разработанное на одном из продуктов InterSystems,
- установленном на Linux-сервере, который тоже включен в домен,
- на котором установлен и настроен веб-сервер Apache с нужным модулем,
- вернул нам имя доменного аккаунта пользователя (sAMAccountName).
И мы его получаем!
После этого мы запросто сможем с серверной стороны используя, например, LDAP-доступ к AD, запросить иные реквизиты этого пользователя (членство в группах, и т.п.).
Про эту механику планируется отдельная статья, там есть свои тонкости.
Парочка ложек дёгтя
- Пока только браузеры от MS (IE, Edge) нативно работают с NTLM (а мы используем именно NTML). Впрочем, и в FireFox, и в Chrome есть возможность донастройки, более того, в корпоративной среде возможна как их централизованная настройка, так и дистрибуция преднастроенных пакетов средствами групповых политик.
- Не всем сразу становится понятно, что же делать с полученным REMOTE_USER на стороне InterSystems Caché. Единого мнения на сей счёт пока нет, а вариантов много самых разнообразных, начиная от задания всем пользователям одного сверхсекретного пароля с последующим вызовом %session.Login () и до создания своей пользовательско-ролевой модели безопасности. Есть тема для дискуссии!
Single Sign-On. Выводная
Я буду весьма признателен, если подскажете в комментариях более удачную конфигурацию; допускаю даже, что появилась новая механика взаимодействия AAA для связки Linux + Apache + MSAD, про которую я не знаю.
Спасибо!