# LDAP authentification

<https://habr.com/ru/companies/flant/articles/710010/>

[Deckhouse](https://deckhouse.ru/) — Kubernetes-платформа с открытым кодом, с помощью которой можно создавать идентичные Kubernetes-кластеры в любой инфраструктуре и автоматически управлять ими. Для проверки подлинности в Deckhouse используется модуль [user-authn](https://deckhouse.ru/documentation/v1/modules/150-user-authn/). Он настраивает единую систему аутентификации, интегрированную с Kubernetes и веб-интерфейсами других модулей — например, с Grafana.

user-authn поддерживает несколько внешних провайдеров и протоколов аутентификации: GitHub, GitLab, Bitbucket Cloud, Crowd, LDAP и OIDC. В статье расскажу, как развернуть сервер LDAP и настроить через него доступ к приложению.

![](/files/53mOBwCON4V8PYtVrNpv)

## Подготовка

Нам потребуется кластер Kubernetes с установленной платформой Deckhouse. Кластер [можно развернуть](https://deckhouse.ru/gs/) в облаке или локально (на kind). Установка занимает от 15 до 30 минут.

[В конфигурации](https://deckhouse.ru/documentation/v1/deckhouse-configure-global.html) Deckhouse в параметре [publicDomainTemplate](https://deckhouse.ru/documentation/v1/deckhouse-configure-global.html#parameters-modules-publicdomaintemplate) должен быть корректный шаблон DNS-имен, который указывает на IP-адреса Ingress-контроллеров кластера. Также можно воспользоваться сервисом типа [sslip.io](https://sslip.io/); в этом случае в publicDomainTemplate достаточно будет указать шаблон `%s.x.x.x.x.sslip.io`, где `x.x.x.x` — ваш IP-адрес.

В командах и шаблонах, которые приводятся в статье, будет задействовано пространство имен `openldap-demo`. При необходимости его можно изменить.

## Настройка LDAP-сервера

Развернем LDAP-сервер:

```
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/ldap.yaml
```

Прежде чем продолжить, убедимся, что Pod сервера запустился, то есть в статусе `Running`:

```
# kubectl -n openldap-demo get pod
NAME                                            READY   STATUS    RESTARTS   AGE
ldap-6c949b6c6d-4zxg7                    1/1      Running     0                   1m
```

В конфигурации развернутого LDAP-сервера есть два пользователя:

* `johndoe@example.com` (пароль `bar`) — входит в группу `admins`;
* `janedoe@example.com` (пароль `foo`) — входит в группы `admins` и `developers`.

Далее, для примера, предоставим доступ пользователю `janedoe@example.com` из группы `developers`.

Создадим в кластере ресурс DexProvider, который «подключит» созданный LDAP-сервер и будет использоваться при аутентификации:

```
kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/dex-provider.yaml
```

## Настройка веб-приложения

Развернем в качестве приложения простой echo-server, который выводит на страницу информацию об HTTP-запросе.

Выполним команду, указав в переменной `DOMAINNAME` используемый вами домен:

```
DOMAINNAME=<ВАШ_ДОМЕН>
curl https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/echo-service.yaml | sed "s/{{ __cluster__domain__ }}/${DOMAINNAME}/" | kubectl create -f -
```

Приложение будет развернуто в пространстве имен `openldap-demo`. Ingress-ресурс приложения будет настроен на поддомен `echo`.

Проверим, что Pod `echoserver` запустился:

```
# kubectl -n openldap-demo get pod
NAME                                            READY   STATUS    RESTARTS   AGE
echoserver-6944fb9c86-9flgh            1/1      Running     0                   1m
ldap-6c949b6c6d-4zxg7                    1/1      Running     0                   3m
```

Откроем браузер и убедимся, что приложение доступно по адресу `echo.<ВАШ_ДОМЕН>` без авторизации.

## Настройка аутентификации

Приступим к самому интересному: закроем доступ к приложению.

Чтобы включить аутентификацию, нужно:

* включить аутентификацию через развернутый экземпляр OAuth2 Proxy в Ingress-ресурсе приложения.

OAuth2 Proxy будет принимать запросы на аутентификацию от nginx и выполнять аутентификацию в LDAP.

Создадим ресурс DexAuthenticator, указав в переменной `DOMAINNAME` используемый вами домен:

```
DOMAINNAME=<ВАШ_ДОМЕН>
curl https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/dex-authenticator.yaml | sed "s/{{ __cluster__domain__ }}/${DOMAINNAME}/" | kubectl create -f -
```

Убедимся, что в пространстве имен `openldap-demo` появился и запустился Pod `echoserver-dex-authenticator`:

```
# kubectl -n openldap-demo get pod
NAME                                                         READY   STATUS    RESTARTS   AGE
echoserver-6944fb9c86-9flgh                     1/1         Running   0                    5m
echoserver-dex-authenticator-6bdd57cc95-wvbgk   2/2     Running   1          2m
ldap-6c949b6c6d-4zxg7                             1/1          Running   0                    8m
```

Посмотрим на ресурс DexAuthenticator. Обратите внимание на параметр [spec.allowedGroups](https://deckhouse.ru/documentation/v1/modules/150-user-authn/cr.html#dexauthenticator-v1-spec-allowedgroups): он содержит список групп, которым будет разрешен доступ к приложению. В нашем случае это группа `developers`, в которую входит пользователь `janedoe@example.com`:

```
# kubectl -n openldap-demo get dexauthenticator echoserver -o yaml
apiVersion: deckhouse.io/v1
kind: DexAuthenticator
...
spec:
  allowedGroups:
  - developers
...
```

Теперь настроим Ingess-контроллер так, чтобы он использовал OAuth2 Proxy.

Укажем две аннотации на Ingress-ресурсе приложения, выполнив команды:

```
kubectl -n openldap-demo annotate ingress echoserver 'nginx.ingress.kubernetes.io/auth-signin=https://$host/dex-authenticator/sign_in'
kubectl -n openldap-demo annotate ingress echoserver 'nginx.ingress.kubernetes.io/auth-url=https://echoserver-dex-authenticator.openldap-demo.svc.cluster.local/dex-authenticator/auth'
```

Обновим страницу приложения в браузере — сработает переадресация на страницу входа:

![](/files/LrUMap4DrwtYHzoC5I6j)

Выберем способ входа через LDAP-сервер: *Log in with OpenLDAP Demo*. Войдем под пользователем `janedoe@example.com` (пароль в LDAP: `foo`).

Проверим, что все работает как нужно. Откроем браузер в безопасном режиме и попробуем войти под другим пользователем — `johndoe@example.com` (пароль в LDAP: `bar`). Получим ошибку `User not in allowed groups`, так как пользователь `johndoe` не состоит в группе `developers`.

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

Также можно создать *статического пользователя*, то есть учетную запись, все данные которой хранятся в кластере Kubernetes. Об этом — дальше.

## Добавление статического пользователя

Для аутентификации статического пользователя внешние провайдеры аутентификации не используются. Нужно создать custom resource [User](https://deckhouse.ru/documentation/v1/modules/150-user-authn/cr.html#user).

Создадим пользователя `openldap-demo@example.com`, который состоит в группе `developers`, с паролем `bar` и временем жизни учетной записи — 24 часа:

```
kubectl create -f - <<"EOF"
apiVersion: deckhouse.io/v1
kind: User
metadata:
 name: openldap-demo
spec:
 email: openldap-demo@example.com
 # echo "bar" | htpasswd -BinC 10 "" | cut -d: -f2
 password: '$2a$10$spCnoGzDIRicDfiTmtImwu7sn2Csjj6oWRoLjNs6N/bV3WDsxioui'
 groups:
   - developers
 ttl: 24h
EOF
```

> Обратите внимание: в комментарии к полю password приведены команды генерации пароля. Они пригодятся, если вы хотите использовать другой пароль.

После того, как пользователь создан, в приложение можно войти, выбрав *Log in with Email*.

Более подробную информацию о настройке аутентификации в кластере можно найти в описании модуля [user-authn](https://deckhouse.ru/documentation/v1/modules/150-user-authn/). Также в документации есть [готовые примеры](https://deckhouse.ru/documentation/v1/modules/150-user-authn/usage.html) использования модуля.

## Убираем за собой

Для удаления созданных выше ресурсов выполним:

```
kubectl delete dexprovider openldap-demo
kubectl delete user openldap-demo
kubectl delete ns openldap-demo
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.konstantinsecurity.com/readme/architect/kubernetes/frameworks/deckhouse/ldap-authentification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
