Система централизованного управления авторизацией пользователей на FreeIPA в Docker

в 9:09, , рубрики: DNS, docker, freeipa, linux, ит-инфраструктура, магия, Настройка Linux, Серверное администрирование, системное администрирование

На волне популярности Docker на Хабре, после участия в некоторых дискуссиях в комментариях относительно Docker, и в связи с недавней необходимостью настроить централизованную авторизацию для кластера Linux машин, я решил написать небольшую заметку. Здесь будет показан яркий, на мой взгляд, пример применения Docker'a для небольшой частной задачи.

Вот так, кстати, выглядит FreeIPA WebUI (официальное демо, временное демо у меня на сервере (подробности в комментариях)) (кликабельно):

Система централизованного управления авторизацией пользователей на FreeIPA в Docker - 1 Система централизованного управления авторизацией пользователей на FreeIPA в Docker - 2

Какие задачи я хотел решить при помощи FreeIPA:

  1. Иметь возможность создавать/изменять/удалять акаунты пользователей централизовано, а не на каждом отдельном сервере
  2. Централизованные плавила для sudo
  3. В последствии мы подключим к этой системе ещё и VPN авторизацию, а потом может и другие внутриофисные сервисы

Да, скорее всего FreeIPA в нашем случае это выстрел пушкой по воробьям, но с другой стороны — альтернатив что-то не видно. Я рассматривал такие варианты: NIS (по-моему он уже давно должен отправиться на отдых), OpenLDAP +… +… (не очень дружелюбно, да и FreeIPA в итоге под собой имеет LDAP, только нам не приходится с ним иметь дело напрямую), тут перечень заканчивается, я не нашёл ничего больше.

Итак, приступим!

Настройка сервера

Перечень используемых технологий:

  • FreeIPA — открытый проект компании RedHat, который объединяет в себе множество других открытых проектов: 389 Directory Server, MIT Kerberos, NTP, DNS (bind), Dogtag certificate system, SSSD и другие. При этом у данного решения есть Web UI, CLI, XMLRPC, JSONRPC API и Python SDK.
  • Dnsmasq — легковесный DNS сервер (позже я объясню зачем мне он нужен был в дополнение к bind, который используется в FreeIPA).
  • Docker — open-source платформа, автоматизирующая развертывание приложений в легковесные, переносимые, самодостаточные контейнеры, которые могут без изменений переноситься между серверами. © Используем Docker и не волнуемся о vendor-lock

FreeIPA, в следствие того, что это продукт RedHat, естественно умеет хорошо разворачиваться на CentOS и Fedora и практически никак не разворачивается на других дистрибутивах. (прим. Я не особо задавался целью, поэтому может и есть где-то инструкции, но пакетов в Debian/Ubuntu для FreeIPA сервера нет, зато есть клиентский пакет freeipa-client, но об этом потом.)

Меня этот факт ни разу не расстроил, а, наоборот, воодушевил! Это же идеальная задача для Docker, когда на серверах Debian/Ubuntu/Gentoo/etc. То есть я мог взять базовый образ Fedora, поставить там нужные пакеты, собрать всё в кучу и запустить, НО ещё более приятной новостью для меня стал официальный Docker образ freeipa-server (есть у них и клиент, но меня интересовал вариант с клиентом на Ubuntu, поэтому я запускал ubuntu образ в Docker и таким образом моделировал и быстро начинал с начала для отладки процесса «с нуля»).

Вообще, запуск freeipa-server не вызвал никаких проблем, всё в соответствии с документацией к образу Docker'a:

  1. Создаём директорию, которая будет монтироваться в образ для конфигов FreeIPA, которые нужно оставлять после перезапуска (в документации предлагается использовать /var/lib/ipa-data/, но я не люблю засорять систему, поэтому /opt/):
    $ sudo mkdir -p /opt/dockers/freeipa-data
    

  2. Добавим файл с опциями, которые будут использоваться при инсталяции freeipa-server:
    $ sudo tee /opt/dockers/freeipa-data/ipa-server-install-options
    --ds-password=The-directory-server-password
    --admin-password=The-admin-password
    

  3. Всё, запускаем (в доке не хватает проброса портов, хотя это и очевидно, что нужно сделать; стоит также отметить, что в доке написано, что нужно подключать раздел с префиксом :Z:rw, но у меня docker сказал, что не понимает что это такое, в гугле ничего вразумительного не нашёл, работает и без него; кто подскажет, что это?):
    $ docker run 
        --name freeipa-server-test 
        -it 
        --rm 
        --hostname freeipa.example.test 
        --volume /opt/dockers/freeipa-data:/data 
        --publish "443:443" 
        --publish "389:389" 
        --publish "636:636" 
        --publish "88:88" 
        --publish "88:88/udp" 
        --publish "464:464" 
        --publish "464:464/udp" 
        adelton/freeipa-server
    

  4. После недолгой установки вам любезно предоставят bash — на этом установка и настройка FreeIPA Server по большому счёту завершена. Можете добавить freeipa.example.test себе в /etc/hosts, пройти на https://freeipa.example.test/, залогиниться под admin и создать пользователя.

FreeIPA у себя в образе поднял целый зоопарк служб, в том числе и bind (DNS), который настроил по своему усмотрению (магия, которую практически невозможно повторить на других DNS). Для клиентов FreeIPA ожидается, что они будут иметь доступ к этому DNS, который ещё умеет как-то хитро failover обрабатывать, только вот в случае как здесь — всё в одном образе Docker я не очень вижу пользу с такого failover. Однако, я не стал идти на перекор и учёл пожелания разработчиков FreeIPA (кстати, это особенность Kerberos, всё-таки FreeIPA — просто объединяет множество пакетов).

Так вот, к чему я про DNS? Мне нужен был DNS внутри кластера, но мне категорически не хотелось влезать в bind внутри FreeIPA контейнера. Поэтому я решил воспользоваться проверенным решением — Dnsmasq. На Docker Hub есть минималистичный образ Dnsmasq, основанный на Alpine Linux — 6МБ.

Вот как я его подготовил:

  1. Создал директорию для конфигов:
    $ sudo mkdir -p /opt/dockers/dnsmasq.d
    

  2. Добавил туда конфиг dnsmasq:
    $ sudo tee /opt/dockers/dnsmasq.d/dnsmasq.conf
    address=/freeipa.example.test/10.12.0.172
    address=/server00.example.test/10.12.0.172
    address=/server01.example.test/10.12.0.173
    address=/server02.example.test/10.12.0.174
    

  3. Запускаем (DNS работает на 53/tcp и 53/udp портах, так что пробрасываем их, папку с конфигами):
    $ docker run 
        --name dnsmasq-test 
        --rm 
        --publish 53:53 
        --publish 53:53/udp 
        --cap-add NET_ADMIN 
        --volume /opt/dockers/dnsmasq.d:/etc/dnsmasq.d 
        --entrypoint /bin/sh 
        andyshinn/dnsmasq 
        -c '/usr/sbin/dnsmasq -k -h --conf-dir /etc/dnsmasq.d/'
    

  4. Проверяем, что работает:
    $ nslookup server00.example.test 127.0.0.1
    

Итого, у нас есть FreeIPA Server в одном контейнере и Dnsmasq в другом. Кстати, Dnsmasq, как можно было заметить, никак с bind DNS сервером FreeIPA ещё не взаимодействует.

Дальше я связал эти два сервиса в один docker-compose.yml:

docker-compose.yml

dnsmasq:
    image: andyshinn/dnsmasq
    ports:
        - "53:53"
        - "53:53/udp"
    cap_add:
        - NET_ADMIN
    links:
        - freeipa
    volumes:
        - "/opt/dockers/dnsmasq.d:/etc/dnsmasq.d"
    entrypoint: ["/bin/sh", "-c", "/usr/sbin/dnsmasq -k -h --conf-dir /etc/dnsmasq.d/ -S /example.test/`getent hosts freeipa | cut -f1 -d' '`"]

freeipa:
    image: adelton/freeipa-server
    hostname: freeipa.example.test
    ports:
        - "443:443"
        - "389:389"
        - "636:636"
        - "88:88"
        - "88:88/udp"
        - "464:464"
        - "464:464/udp"
    cap_add:
        - NET_ADMIN
    volumes:
        - "/opt/dockers/freeipa-data:/data"

Можно заметить небольшую магию с дополнительной опцией к команде dnsmasq, эта опция будет перенаправлять запросы к *.example.test на bind DNS, уставновленный в freeipa контейнере.

Удобство Docker Compose в данном конкретном случае в том, что его конфиг всё-таки удобнее читать, чем bash-скрипт с docker run. Да и лучше сразу делать хорошо. Сохраняем docker-compose.yml и запускаем:

$ docker-compose up -d

C сервером, наконец, закончили.

Настройка клиентов

Тут у меня есть решение в 2 команды :)

  1. Нужно исправить /etc/hosts таким образом, чтобы первым в списке было полностью определённое имя домена (FQDN):
    127.0.1.1    server00.example.test server00
    

  2. И теперь немного подредактировав вот эту команду (адрес Dnsmasq, имя домена, пароль admin'a в FreeIPA), можете её запустить:
    $ sudo bash -c 'echo -e "nameserver 10.12.0.172nsearch example.testn# HEAD ENDn#" >> /etc/resolvconf/resolv.conf.d/head && service resolvconf restart && bash -c "cat > /usr/share/pam-configs/mkhomedir <<EOF
    Name: activate mkhomedir
    Default: yes
    Priority: 900
    Session-Type: Additional
    Session:
            required                        pam_mkhomedir.so umask=0022 skel=/etc/skel
    EOF" && DEBIAN_FRONTEND=noninteractive apt-get install -y freeipa-client && ipa-client-install -U -N -p admin -w The-admin-password && service ssh restart'
    

    Здесь добавится нужный DNS сервер, перегрузится resolveconf, добавится PAM-модуль для автоматического создания домашних директорий, установится freeipa-client, запустится установка ipa-client и после успешной установки перегрузится ssh.

Вот и всё, теперь на этом хосте можно делать su/sudo/ssh, где пользователя при самом первом входе заставят сменить пароль, а при первом входе на новом хосте для пользователя будет автоматически создана домашняя директория из /etc/skel.

Выводы

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

В дальнейшем я, возможно, сподвигнусь написать о другом проекте, который интенсивно использует ограничения ресурсов, интегрированные в Docker (CPU, RAM).

Автор: frol

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js