Настройка аутентификации в Nginx через Active Directory (LDAP)

В данной статье мы рассмотрим, как настроить basic аутентификацию в Nginx через LDAP каталог. В качестве сервера LDAP будем использовать Windows Active Directory. Так как у Nginx нет официального встроенного модуля авторизации через LDAP (в отличии от Apache или Tomcat), разработчики предлагают использовать сторонний сервис nginx-ldap-auth , который будет обращаться к LDAP и выступать своего рода прокси между Nginx и сервером каталога LDAP ldap сервером. Для начала давайте запустим сервис и посмотрим, как он работает.

Настройка и запуск сервиса аутентификации nginx-ldap-auth

Для запуска сервиса nginx-ldap-auth будем использовать docker. Для начала нужно клонировать репозиторий с сервисом с github:

# sudo git clone https://github.com/nginxinc/nginx-ldap-auth

# cd nginx-ldap-auth

Если у вас не установлен утилиты git, можно просто скачать архив с исходниками и распаковать его в директорию nginx-ldap-auth.

В директории уже имеется готовый Dockerfile. Для сборки контейнера нужно выполнить:

# sudo docker build -t nginx-ldap-auth-daemon .

Вывод при сборке будет таким:

Sending build context to Docker daemon 208.9kB Step 1/7 : ARG PYTHON_VERSION=2 Step 2/7 : FROM python:${PYTHON_VERSION}-alpine ---> 8579e446340f Step 3/7 : COPY nginx-ldap-auth-daemon.py /usr/src/app/ ---> Using cache ---> a0b2c58fd4af Step 4/7 : WORKDIR /usr/src/app/ ---> Using cache ---> 2d93d045af89 Step 5/7 : RUN apk --no-cache add openldap-dev && apk --no-cache add --virtual build-dependencies build-base && pip install python-ldap && apk del build -dependencies ---> Using cache ---> fd942ca28c6e Step 6/7 : EXPOSE 8888 ---> Using cache ---> 0d5b7bab2edf Step 7/7 : CMD ["python", "/usr/src/app/nginx-ldap-auth-daemon.py", "--host", "0.0.0.0", "--port", "8888"] ---> Using cache ---> 3eb60dda0847 Successfully built 3eb60dda0847 Successfully tagged nginx-ldap-auth-daemon:latest

Docker image готов, можно запустить контейнер. Для этого выполните команду:

# sudo docker run -p 8888:8888 --name ldap-auth nginx-ldap-auth-daemon

Вывод данной команды будет таким:

Start listening on 0.0.0.0:8888…

Эта команда запустит контейнер из образа nginx-ldap-auth-daemon, c названием контейнера ldap-auth и пробросит порт 8888 из контейнера на host машину. Проброс портов нужен, чтобы проверить работу и выполнить отладку аутентификации в Active Directory. В дальнейшем, можно исключить этот параметр. Также для отладки мы не добавили ключ -d, который запустил бы контейнер и отвязал бы его от консоли, но тогда не было видно лога работы, который полезен при отладке.

Давайте теперь разберем, как работает сервис nginx-ldap-auth. Данный демон является небольшим web сервисом, к которому можно отправить HTTP запрос методом get с определенными заголовками, он в свою очередь обратится в Active Directory и проверит авторизационные данные. Если они верны, он ответит HTTP кодом 200 ОК, если нет, то вернет 401 код (не авторизован).

Для проверки нужен настроенный сервер Active Directory либо OpenLDAP. В данной статье будет рассмотрен контроллер домена на Windows Server 2008 R2, но в README репозитория демона заявлена поддержка и других LDAP серверов.

  • Имя домена: corp.to.high
  • IP контроллера домена: 192.168.0.16

Создадим пользователя с правами гость. Назовем его ldap_reader. Данный пользователь нужен, чтобы от его имени демон обращался в AD и проверял переданную при авторизации связку логин и пароль.

Данные пользователя следующие

Запретите пользователю менять пароль и установите неограниченный срок действия пароля (Never Expires), так как это сервисная УЗ.

Для тестирования можно скачать утилиту для поиска в дереве LDAP, например ldapsearch.

Устанавливается командой:

# sudo apt install ldap-utils

Для проверки доступности контроллера домена и правильной настройки пользователя можно выполнить команду:

# ldapsearch -v -D " [email protected] " -w "r05-2020" -b "DC=corp,DC=to,DC=high" -H "ldap://192.168.0.16" "(sAMAccountName=ldap_reader)"

  • -D binddn учетная запись, для доступа к домену,
  • -w bindpassword пароль учетной записи,
  • -b searchbase – контейнер (OU) AD, в котором нужно искать пользователя (можно сузить область поиска для получения ответа более быстро),
  • -H адрес ldap сервера;
  • Затем указывается LDAP фильтр , по которому нужно выполнить поиск.

Вывод для нашего домена будет такой:

ldap_initialize( ldap://192.168.0.16:389/??base )_x000D_filter: (sAMAccountName=ldap_reader)_x000D_requesting: All userApplication attributes_x000D_# extended LDIF_x000D_#_x000D_# LDAPv3_x000D_# base <DC=corp,DC=to,DC=high> with scope subtree_x000D_# filter: (sAMAccountName=ldap_reader)_x000D_# requesting: ALL_x000D_#_x000D_# ldap_reader, Users, corp.to.high_x000D_dn: CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high_x000D_objectClass: top_x000D_objectClass: person_x000D_objectClass: organizationalPerson_x000D_objectClass: user_x000D_cn: ldap_reader_x000D_givenName: ldap_reader_x000D_distinguishedName: CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high_x000D_instanceType: 4_x000D_whenCreated: 20210308212600.0Z_x000D_whenChanged: 20210308212700.0Z_x000D_displayName: ldap_reader_x000D_………..._x000D_# search reference_x000D_ref: ldap://ForestDnsZones.corp.to.high/DC=ForestDnsZones,DC=corp,DC=to,DC=high_x000D_# search reference_x000D_ref: ldap://DomainDnsZones.corp.to.high/DC=DomainDnsZones,DC=corp,DC=to,DC=high_x000D_# search reference_x000D_ref: ldap://corp.to.high/CN=Configuration,DC=corp,DC=to,DC=high_x000D_# search result_x000D_search: 2_x000D_result: 0 Success_x000D_# numResponses: 5_x000D_# numEntries: 1_x000D_# numReferences: 3

Данный лог показывает, что пользователь найден и у пользователя ldap_reader есть доступ на чтение дерева домена. Проверим теперь работу демона авторизации. Для этого, выполним в консоли команду:

# curl --location --request GET 'http://localhost:8888'
--header 'X-Ldap-URL: ldap://192.168.0.16'
--header 'X-Ldap-BaseDN: CN=Users,DC=corp,DC=to,DC=high'
--header 'X-Ldap-BindDN: [email protected] '
--header 'X-Ldap-BindPass: r05-2020'
--header 'X-Ldap-Template: (sAMAccountName=%(username)s)' -vv -u ldap_reader:r05-2020

Вывод будет таким:

Note: Unnecessary use of -X or --request, GET is already inferred._x000D_* Rebuilt URL to: http://localhost:8888/_x000D_* Trying 127.0.0.1..._x000D_* TCP_NODELAY set_x000D_* Connected to localhost (127.0.0.1) port 8888 (#0)_x000D_* Server auth using Basic with user 'ldap_reader'_x000D_> GET / HTTP/1.1_x000D_> Host: localhost:8888_x000D_> Authorization: Basic bGRhcF9yZWFkZXI6cjA1LTIwMjA=_x000D_> User-Agent: curl/7.58.0_x000D_> Accept: */*_x000D_> X-Ldap-URL: ldap://192.168.0.16_x000D_> X-Ldap-BaseDN: CN=Users,DC=corp,DC=to,DC=high_x000D_> X-Ldap-BindDN: [email protected]_x000D_> X-Ldap-BindPass: r05-2020_x000D_> X-Ldap-Template: (sAMAccountName=%(username)s)_x000D_>_x000D_* HTTP 1.0, assume close after body_x000D_< HTTP/1.0 200 OK_x000D_< Server: BaseHTTP/0.3 Python/2.7.18_x000D_< Date: Sun, 14 Mar 2021 19:07:48 GMT_x000D_< * Closing connection 0

Заголовки, используемые в запросе:

  • X-Ldap-URL — адрес ldap сервера, такой же, как при тестировании с помощью утилиты ldapsearch ;
  • X-Ldap-BaseDN — начальный DN для поиска;
  • X-Ldap-BindDN — учетная запись с правами на чтение дерева домена.
  • X-Ldap-BindPass – пароль пользователя для доступа к AD;
  • X-Ldap-Template — в данном заголовке передается LDAP фильтр, по которому будет происходить поиск. В заголовке можно комбинировать разные фильтры. Подробнее можно посмотреть в документации к демону nginx-ldap-auth.
  • Опцией -u <login>:<password> нужно передать креденшелы пользователя, которые нужно проверить в домене

Если передать неверные учетные данные, будет возвращена ошибка 401 ( не авторизован). Попробуем передать неверный пароль, вывод будет такой:

* Rebuilt URL to: http://localhost:8888/_x000D_* Trying 127.0.0.1..._x000D_* TCP_NODELAY set_x000D_* Connected to localhost (127.0.0.1) port 8888 (#0)_x000D_* Server auth using Basic with user 'ldap_reader'_x000D_> GET / HTTP/1.1_x000D_> Host: localhost:8888_x000D_> Authorization: Basic bGRhcF9yZWFkZXI6cjA1LTIwMjAx_x000D_> User-Agent: curl/7.58.0_x000D_> Accept: */*_x000D_> X-Ldap-URL: ldap://192.168.0.16_x000D_> X-Ldap-BaseDN: CN=Users,DC=corp,DC=to,DC=high_x000D_> X-Ldap-BindDN: [email protected]_x000D_> X-Ldap-BindPass: r05-2020_x000D_> X-Ldap-Template: (sAMAccountName=%(username)s)_x000D_>_x000D_* HTTP 1.0, assume close after body_x000D_< HTTP/1.0 401 Unauthorized_x000D_< Server: BaseHTTP/0.3 Python/2.7.18_x000D_< Date: Sun, 14 Mar 2021 19:16:40 GMT_x000D_* Authentication problem. Ignoring this._x000D_< WWW-Authenticate: Basic realm="Restricted"_x000D_< Cache-Control: no-cache_x000D_<_x000D_* Closing connection 0

Также в логах демона можно увидеть вывод:

172.17.0.1 - - [14/Mar/2021 19:17:45] using username/password from authorization header_x000D_172.17.0.1 - ldap_reader [14/Mar/2021 19:17:45] searching on server "ldap://192.168.0.16" with base dn "CN=Users,DC=corp,DC=to,DC=high" with filter "(sAMAccountName=ldap_reader)"_x000D_172.17.0.1 - ldap_reader [14/Mar/2021 19:17:45] attempting to bind using dn "CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high"_x000D_172.17.0.1 - ldap_reader [14/Mar/2021 19:17:45] Error while binding as an existing user "CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high": {'info': u'80090308: LdapErr: DSID-0C0903AA, comment: AcceptSecurityContext error, data 52e, v1772',_x000D_'msgid': 3, 'msgtype': 97, 'result': 49, 'desc': u'Invalid credentials', 'ctrls': []}, server="ldap://192.168.0.16", login="ldap_reader"_x000D_172.17.0.1 - ldap_reader [14/Mar/2021 19:17:46] "GET / HTTP/1.1" 401 -

Настройка контейнера Nginx для авторизации в Active Directory (LDAP)

Мы проверили работу демона аутентфикации nginx-ldap-auth, теперь можно перейти к настройке Nginx. В данной статье, покажу, как настроить авторизацию для docker registry с учетной записью Active Directory. Nginx будем запускать в docker контейнере. Создадйте Dockerfile:

FROM nginx_x000D_COPY nginx-ldap-auth.conf /etc/nginx/conf.d/nginx-ldap-auth.conf

В директории с Dockerfile создадйте файл конфигурации nginx-ldap-auth.conf .
Содержание файла:

proxy_cache_path cache/ keys_zone=auth_cache:10m;_x000D_upstream backend {_x000D_ server registry:5000;_x000D_}_x000D_server {_x000D_ listen 8081;_x000D_ # Protected application_x000D_ location / {_x000D_ auth_request /auth-proxy;_x000D_ proxy_pass http://backend/;_x000D_ }_x000D_ location = /auth-proxy {_x000D_ internal;_x000D_ proxy_cache auth_cache;_x000D_ proxy_cache_valid 200 10m;_x000D_ # The following directive adds the cookie to the cache key_x000D_ proxy_cache_key "$http_authorization$cookie_nginxauth";_x000D_ proxy_pass_request_body off;_x000D_ proxy_set_header Content-Length "";_x000D_ proxy_pass http://ldap-auth:8888;_x000D_ # URL and port for connecting to the LDAP server_x000D_ proxy_set_header X-Ldap-URL "ldap://192.168.0.16";_x000D_ # Base DN_x000D_ proxy_set_header X-Ldap-BaseDN "cn=Users,dc=corp,dc=to, dc=high";_x000D_ # Bind DN_x000D_ proxy_set_header X-Ldap-BindDN "[email protected]";_x000D_ # Bind password_x000D_ proxy_set_header X-Ldap-BindPass "r05-2020";_x000D_ proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";_x000D_ }_x000D_}_x000D_

В данном конфиге указывается location, с опцией auth_request, которая позволяет отправить HTTP запрос для проверки авторизации. Мы указали внутренний адрес /auth-proxy, на который будет переадресован запрос авторизации. В данном location указаны опций, которые настраивают параметры кэширования и заголовки, которые будут отправлены в nginx-ldap-auth.

  • proxy_pass_request_body — запрещает передачу полей заголовка исходного запроса на проксируемый сервер;
  • proxy_set_header — устанавливает заголовок Content-Length ;
  • proxy_cache_valid 200 10m — кешировать ответ с кодом 200 на 10 минут (чтобы не отправлять запрос к серверу авторизации при каждом обращении);
  • proxy_cache_path — путь и другие параметры кэша;
  • proxy_cache_key — ключ кэширования;
  • proxy_pass – указывает на контейнера демона авторизации nginx-ldap-auth. Остальные опции аналогичны тем, что использовались при проверке демона. Файл конфига и dockerfile можно взять в github репозитории.

После создания конфига, нужно собрать контейнер:

# sudo docker build . -t nginx-ldap

Запустите контейнер с nginx с выводом в консоль:

# sudo docker run -p:8081:8081 --link ldap-auth --link registry --name nginx-ldap nginx-ldap

  • Запускаем nginx-ldap образ с именем —name nginx-ldap ;
  • —link — опция позволяет связать в одну сеть контейнеры, так как мы к ним обращаемся по именам в конфиге nginx. Без этих опций из контейнера nginx не будет резолвиться имя registry и ldap-auth;
  • -p:8081:8081 — прокидываем порт наружу.

Вывод команды будет такой:

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration_x000D_/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/_x000D_/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh_x000D_10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf_x000D_10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf_x000D_/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh_x000D_/docker-entrypoint.sh: Configuration complete; ready for start up

Тестируем аутентификацию пользователя доменного пользователя AD в Nginx

Теперь откройте браузер и перейдите по адресу: http://localhost:8081/v2/_catalog. После успешной авторизации nginx должен переадрессовать на приватный репозиторий docker, описанный в статье про Docker Registry Нам будет предложено окно базовой авторизации следующего вида.

В логах веб сервера должна появится строку обращения к /v2/_catalog . Т.к. текущий пользователь не авторизирован, сервер вернул код ответа 401 код и предлагает авторизоваться. После успешной авторизации должен вернуться код ответа 200 .

172.17.0.1 - - [21/Mar/2021:19:19:09 +0000] "GET /v2/_catalog HTTP/1.1" 401 179 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0" "-"_x000D_172.17.0.1 - ldap_reader [21/Mar/2021:19:19:20 +0000] "GET /v2/_catalog HTTP/1.1" 200 20 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0" "-"

Введите логин и пароль пользователя домена. Для теста можно использовать сервисного пользователя, которого создали для поиска по дереву домена.

После успешной авторизации должна открыться страница со списком образов в Docker репозитории.

У меня в репозитории в данный момент один образ, созданного в статье про создание простого микросервиса в docker .

В логах сервиса, который обращается к серверу ldap можно увидеть следующее:

172.17.0.4 - - [21/Mar/2021 19:18:18] using username/password from authorization header_x000D_172.17.0.4 - ldap_reader [21/Mar/2021 19:18:18] searching on server "ldap://192.168.0.16" with base dn "cn=Users,dc=corp,dc=to, dc=high" with filter "(sAMAccountName=ldap_reader)"_x000D_172.17.0.4 - ldap_reader [21/Mar/2021 19:18:18] attempting to bind using dn "CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high"_x000D_172.17.0.4 - ldap_reader [21/Mar/2021 19:18:18] Auth OK for user "ldap_reader"_x000D_172.17.0.4 - ldap_reader [21/Mar/2021 19:18:18] "GET /auth-proxy HTTP/1.0" 200

По логу видно, что выполнено подключение к LDAP серверу, выполнена авторизация и проверены учетные данные пользователя.

После проверки, можно остановить контейнеры, и запустить заново в фоновом режиме:

Удаляем контейнеры:

# sudo docker rm ldap-auth
# sudo docker rm nginx-ldap

Теперь можно запуститьконтейнеру nginx и nginx-ldap-auth в фоновом режиме. Также мы убрали в контейнере авторизации проброс портов наружу, это больше не нужно.

# sudo docker run -d --name ldap-auth nginx-ldap-auth-daemon
# sudo docker run -p:8081:8081 -d --link ldap-auth --link registry --name nginx-ldap nginx-ldap

В данной статье мы рассмотрели общий принцип настройки авторизации с учетными данными LDAP в nginx. В качестве конечного backend может выступать не обязательно docker registry , таким образом можно настроить аутентификацию в Active Directory в в любом вашем приложении, опубликованном через nginx.

admin

Share
Published by
admin

Recent Posts

Консоль удаленного рабочего стола(rdp console)

Клиент удаленного рабочего стола (rdp) предоставляет нам возможность войти на сервер терминалов через консоль. Что…

2 недели ago

Настройка сети в VMware Workstation

В VMware Workstation есть несколько способов настройки сети гостевой машины: 1) Bridged networking 2) Network…

2 недели ago

Логи брандмауэра Windows

Встроенный брандмауэр Windows может не только остановить нежелательный трафик на вашем пороге, но и может…

2 недели ago

Правильный способ отключения IPv6

Вопреки распространенному мнению, отключить IPv6 в Windows Vista и Server 2008 это не просто снять…

2 недели ago

Ключи реестра Windows, отвечающие за параметры экранной заставки

Параметры экранной заставки для текущего пользователя можно править из системного реестра, для чего: Запустите редактор…

2 недели ago

Как управлять журналами событий из командной строки

В этой статье расскажу про возможность просмотра журналов событий из командной строки. Эти возможности можно…

2 недели ago