У даній статті ми розглянемо, як налаштувати 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

установка контейнера nginx-ldap-auth

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 і перевіряв передану при авторизації зв’язку логін і пароль.

Дані користувача наступні

  • Логін: ldap_reader@corp.to.high
  • пароль: r05-2020
  • Група AD: Гості домену.

користувач для доступу до домену

гість домену

Забороніть користувачеві змінювати пароль і встановіть необмежений термін дії пароля (Never Expires), так як це сервісна УЗ.

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

Встановлюється командою:

# sudo apt install ldap-utils

Для перевірки доступності контролера домену та правильного налаштування користувача можна виконати команду:

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

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

Висновок для нашого домену буде такою:

ldap_initialize( ldap://192.168.0.16:389/??base )
filter: (sAMAccountName=ldap_reader)
requesting: All userApplication attributes
# extended LDIF
#
# LDAPv3
# base <DC=corp,DC=to,DC=high> with scope subtree
# filter: (sAMAccountName=ldap_reader)
# requesting: ALL
#
# ldap_reader, Users, corp.to.high
dn: CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: ldap_reader
givenName: ldap_reader
distinguishedName: CN=ldap_reader,CN=Users,DC=corp,DC=to,DC=high
instanceType: 4
whenCreated: 20210308212600.0Z
whenChanged: 20210308212700.0Z
displayName: ldap_reader
………...
# search reference
ref: ldap://ForestDnsZones.corp.to.high/DC=ForestDnsZones,DC=corp,DC=to,DC=high
# search reference
ref: ldap://DomainDnsZones.corp.to.high/DC=DomainDnsZones,DC=corp,DC=to,DC=high
# search reference
ref: ldap://corp.to.high/CN=Configuration,DC=corp,DC=to,DC=high
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 1
# 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: ldap_reader@corp.to.high'
--header 'X-Ldap-BindPass: r05-2020'
--header 'X-Ldap-Template: (sAMAccountName=%(username)s)' -vv -u ldap_reader:r05-2020

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

curl з header X-Ldap-BindDN, перевірка аутентфікаціі в Active Directory

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

Заголовки, що використовуються в запиті:

  • X-Ldap-URL – адреса ldap сервера, такий же, як при тестуванні за допомогою утиліти ldapsearch;
  • X-Ldap-BaseDN – початковий DN для пошуку;
  • X-Ldap-BindDN – обліковий запис з правами на читання дерева домену.
  • X-Ldap-BindPass – пароль користувача для доступу до AD;
  • X-Ldap-шаблон – в даному заголовку передається LDAP фільтр, за яким буде відбуватися пошук. У заголовку можна комбінувати різні фільтри. Детальніше можна подивитися в документації до демона nginx-ldap-auth.
  • опцією -u <логін>: <пароль> потрібно передати креденшели користувача, які потрібно перевірити в домені

Якщо передати невірні облікові дані, буде повернуто помилку 401 (не авторизований). Спробуємо передати невірний пароль, висновок буде такий:

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

Також в логах демона можна побачити висновок:

авторизація в ad http

172.17.0.1 - - [14/Mar/2021 19:17:45] using username/password from authorization header
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)"
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"
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',
'msgid': 3, 'msgtype': 97, 'result': 49, 'desc': u'Invalid credentials', 'ctrls': []}, server="ldap://192.168.0.16", login="ldap_reader"
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
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;
upstream backend {
     server registry:5000;
}
server {
        listen 8081;
        # Protected application
        location / {
            auth_request /auth-proxy;
            proxy_pass http://backend/;
        }
        location = /auth-proxy {
            internal;
            proxy_cache auth_cache;
            proxy_cache_valid 200 10m;
            # The following directive adds the cookie to the cache key
            proxy_cache_key "$http_authorization$cookie_nginxauth";
	proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_pass http://ldap-auth:8888;
            # URL and port for connecting to the LDAP server
            proxy_set_header X-Ldap-URL "ldap://192.168.0.16";
            # Base DN
            proxy_set_header X-Ldap-BaseDN "cn=Users,dc=corp,dc=to, dc=high";
            # Bind DN
            proxy_set_header X-Ldap-BindDN "ldap_reader@corp.to.high";
            # Bind password
            proxy_set_header X-Ldap-BindPass "r05-2020";
            proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";
        }
}

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

  • proxy_pass_request_body – забороняє передачу полів заголовка вихідного запиту на проксіруемий сервер;
  • proxy_set_header – встановлює заголовок Довжина вмісту;
  • 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 образ з ім’ям —Ім’я nginx-ldap;
  • —Посилання – опція дозволяє зв’язати в одну мережу контейнери, так як ми до них звертаємося по іменах в конфіги nginx. Без цих опцій з контейнера nginx НЕ буде ні перетворювати ім’я registry і ldap-auth;
  • -p: 8081: 8081 – прокидає порт назовні.

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

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

запуск nginx в контейнері з авторизацією в active directory

Тестуємо аутентифікацію користувача доменного користувача AD в Nginx

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

запит пароля

В логах веб сервера повинна з’явиться рядок звернення до / v2 / _catalog. Оскільки поточний користувач не авторизовані, сервер повернув код відповіді 401 код і пропонує авторизуватися. Після успішної авторизації повинен повернутися код відповіді 200.

успішна аутентфікація HTTP / 1.1 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" "-"
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 репозиторії.

після аутентфікаіі отриманий доступ до сервісу за nginx

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

В логах сервісу, який звертається до сервера ldap можна побачити наступне:

172.17.0.4 - - [21/Mar/2021 19:18:18] using username/password from authorization header
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)"
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"
172.17.0.4 - ldap_reader [21/Mar/2021 19:18:18] Auth OK for user "ldap_reader"
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 може виступати не обов’язково реєстру, Таким чином можна налаштувати аутентифікацію в Active Directory в в будь-якому вашому додатку, опублікованому через nginx.

Leave a Reply

Your email address will not be published. Required fields are marked *