> For the complete documentation index, see [llms.txt](https://book.konstantinsecurity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.konstantinsecurity.com/readme/architect/kubernetes/auth/ldap.md).

# LDAP

<https://habr.com/ru/articles/441112/>

![](/files/GM4dloI1oNSAYh9n8V8W)

Небольшая инструкция о том, как используя Keycloak можно связать Kubernetes с вашим LDAP-сервером и настроить импорт пользователей и групп. Это позволит настраивать RBAC для ваших пользователей и использовать auth-proxy чтобы защитить Kubernetes Dashboard и другие приложения, которые не умеют производить авторизацию самостоятельно.

## Установка Keycloak

Предположим что у вас уже есть LDAP-сервер. Это может быть Active Directory, FreeIPA, OpenLDAP или что-либо еще. Если LDAP-сервера у вас нет, то в принципе вы можете создавать пользователей прямо в интерфейсе Keycloak, либо использовать публичные oidc-провайдеры (Google, Github, Gitlab), результат получится почти такой же.

Первым делом установим сам Keycloak, установка может выполняться отдельно, так и сразу в Kubernetes-кластер, как правило если у вас имеется несколько Kubernetes-кластеров, было бы проще установить его отдельно. С другой стороны вы всегда можете использовать [официальный helm-чарт](https://github.com/helm/charts/tree/master/stable/keycloak) и установить его прямо в ваш кластер.

Для хранения данных Keycloak вам понадобится база данных. По умолчанию используется `h2` (все данные хранятся локально), но возможно также использовать `postgres`, `mysql` или `mariadb`.

Если вы все же надумали установить Keycloak отдельно, более подробные инструкции вы найдете в [официальной документации](https://www.keycloak.org/docs/latest/getting_started/index.html).

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

Первым делом создадим новый realm. Realm — это пространство нашего приложения. Каждое приложение может иметь свой realm с разными пользователями и настройками авторизации. Master realm используется самим Keycloak и использовать его для чего-нибудь еще неправильно.

Нажимаем **Add realm**

| Option            | Value                                                                   |
| ----------------- | ----------------------------------------------------------------------- |
| Name              | kubernetes                                                              |
| Display Name      | Kubernetes                                                              |
| HTML Display Name | \<img src="<https://kubernetes.io/images/nav\\_logo.svg>" width="400" > |

Kubernetes по умолчанию проверяет подтвержден у пользователя email или нет. Так как мы используем собственный LDAP-сервер, то тут эта проверка почти всегда будет возвращать `false`. Давайте отключим представление этого параметра в Kubernetes:

**Client scopes** --> **Email** --> **Mappers** --> **Email verified** (Delete)

Теперь настроим федерацию, для этого перейдем в:

**User federation** --> **Add provider...** --> **ldap**

Приведу пример настройки для FreeIPA:

| Option                         | Value                                                   |
| ------------------------------ | ------------------------------------------------------- |
| Console Display Name           | freeipa.example.org                                     |
| Vendor                         | Red Hat Directory Server                                |
| UUID LDAP attribute            | ipauniqueid                                             |
| Connection URL                 | ldaps\://freeipa.example.org                            |
| Users DN                       | cn=users,cn=accounts,dc=example,dc=org                  |
| Bind DN                        | uid=keycloak-svc,cn=users,cn=accounts,dc=example,dc=org |
| Bind Credential                |                                                         |
| Allow Kerberos authentication: | on                                                      |
| Kerberos Realm:                | EXAMPLE.ORG                                             |
| Server Principal:              | HTTP/freeipa.<example.org@EXAMPLE.ORG>                  |
| KeyTab:                        | /etc/krb5.keytab                                        |

Пользователя `keycloak-svc` нужно создать заранее на нашем LDAP-сервере.

В случае с Active Directory, достаточно просто выбрать **Vendor: Active Directory** и необходимые настройки подставятся в форму автоматически.

Нажимаем **Save**

Теперь перейдем:

**User federation** --> **freeipa.example.org** --> **Mappers** --> **First Name**

| Option         | Value     |
| -------------- | --------- |
| Ldap attribure | givenName |

Теперь включим маппинг групп:

**User federation** --> **freeipa.example.org** --> **Mappers** --> **Create**

| Option                        | Value                                        |
| ----------------------------- | -------------------------------------------- |
| Name                          | groups                                       |
| Mapper type                   | group-ldap-mapper                            |
| LDAP Groups DN                | cn=groups,cn=accounts,dc=example,dc=org      |
| User Groups Retrieve Strategy | GET\_GROUPS\_FROM\_USER\_MEMBEROF\_ATTRIBUTE |

На этом настройка федерации закончена, перейдем к настройке клиента.

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

Создадим нового клиента (приложение которое будет получать пользователей из Keycloak). Переходим:

**Clients** --> **Create**

| Option              | Value                                |
| ------------------- | ------------------------------------ |
| Client ID           | kubernetes                           |
| Access Type         | confidential                         |
| Root URL            | <http://kubernetes.example.org/>     |
| Valid Redirect URIs | <http://kubernetes.example.org/\\>\* |
| Admin URL           | <http://kubernetes.example.org/>     |

Так же создадим scope для групп:

**Client Scopes** --> **Create**

| Option          | Value       |
| --------------- | ----------- |
| Template        | No template |
| Name            | groups      |
| Full group path | false       |

И настроим mapper для них:

**Client Scopes** --> **groups** --> **Mappers** --> **Create**

| Option           | Value            |
| ---------------- | ---------------- |
| Name             | groups           |
| Mapper Type      | Group membership |
| Token Claim Name | groups           |

Теперь нам нужно включить маппинг груп в нашем client scope:

**Clients** --> **kubernetes** --> **Client Scopes** --> **Default Client Scopes**

Выбираем **groups** в **Available Client Scopes**, нажимаем **Add selected**

Теперь настроим аутентификацию нашего приложения, переходим:

**Clients** --> **kubernetes**

| Option                | Value |
| --------------------- | ----- |
| Authorization Enabled | ON    |

Нажимем **save** и на этом настройка клиента завершена, теперь на вкладке

**Clients** --> **kubernetes** --> **Credentials**

вы сможете получить **Secret** который мы будем использовать в дальнейшем.

## Настройка Kubernetes

Настройка Kubernetes для OIDC-авторизации достаточно тривиальна и не является чем-то очень сложным. Все что вам нужно это положить CA-сертификат вашего OIDC-сервера в `/etc/kubernetes/pki/oidc-ca.pem` и добавить необходимые опции для kube-apiserver.

Для этого обновите `/etc/kubernetes/manifests/kube-apiserver.yaml` на всех ваших мастерах:

```
...
spec:
  containers:
  - command:
    - kube-apiserver
...
    - --oidc-ca-file=/etc/kubernetes/pki/oidc-ca.pem
    - --oidc-client-id=kubernetes
    - --oidc-groups-claim=groups
    - --oidc-issuer-url=https://keycloak.example.org/auth/realms/kubernetes
    - --oidc-username-claim=email
...
```

А так-же обновите kubeadm конфиг в кластере, что бы не потерять эти настройки при обновлении:

```
kubectl edit -n kube-system configmaps kubeadm-config
```

```
...
data:
  ClusterConfiguration: |
    apiServer:
      extraArgs:
        oidc-ca-file: /etc/kubernetes/pki/oidc-ca.pem
        oidc-client-id: kubernetes
        oidc-groups-claim: groups
        oidc-issuer-url: https://keycloak.example.org/auth/realms/kubernetes
        oidc-username-claim: email
...
```

На этом настройка Kubernetes завершена. Вы можете повторить данные действия во всех ваших Kubernetes-кластерах.

## Начальная авторизация

После данных действий вы уже будете иметь Kubernetes-кластер с настроенной OIDC-авторизацией. Единственный момент, что ваши пользователи пока что не имеют настроенного клиента как и собственного kubeconfig. Что бы эту проблему решить нужно настроить автоматическую выдачу kubeconfig пользователям после успешной авторизации.

Для этого можно использовать специальные web-приложения, которые позволяют провести аутентификацию пользователя а затем скачать готовый kubeconfig. Одно из самых удобных — это [Kuberos](https://github.com/negz/kuberos), он позволяет в одном конфиге описать все Kubernetes-кластеры и легко переключаться между ними.

Для настройки Kuberos достаточно описать template для kubeconfig и запустить со следующими параметрами:

```
kuberos https://keycloak.example.org/auth/realms/kubernetes kubernetes /cfg/secret /cfg/template
```

Для более детальной информации смотрите [Usage](https://github.com/negz/kuberos#usage) на Github.

Так же возможно использовать [kubelogin](https://github.com/int128/kubelogin) если вы хотите производить авторизацию непосредственно на компьютере пользователя. В этом случае пользователю откроется браузер с формой авторизации на localhost.

Полученный kubeconfig можно проверить на сайте [jwt.io](https://jwt.io/#debugger-io). Просто скопируейте значение `users[].user.auth-provider.config.id-token` из вашего kubeconfig в форму на сайте и сразу получите расшифровку.

## Настройка RBAC

При настройке RBAC можно ссылаться как на имя пользователя (поле `name` в jwt-токене), так и на группу пользователей (поле `groups` в jwt-токене). Вот пример настройки прав для группы `kubernetes-default-namespace-admins`:

**kubernetes-default-namespace-admins.yaml**

```jsx
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: default-admins
  namespace: default
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernetes-default-namespace-admins
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: default-admins
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: kubernetes-default-namespace-admins
```

Больше примеров для RBAC можно найти в [официальной документации Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)

## Настройка auth-proxy

Есть замечательный проект [keycloak-gatekeeper](https://github.com/keycloak/keycloak-gatekeeper), который позволяет защитить любое приложение, предоставляя пользователю возможность аутентифицироваться на OIDC-сервере. Я покажу как можно настроить его на примере Kubernetes Dashboard:

**dashboard-proxy.yaml**

```jsx
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kubernetes-dashboard-proxy
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: kubernetes-dashboard-proxy
    spec:
      containers:
      - args:
        - --listen=0.0.0.0:80
        - --discovery-url=https://keycloak.example.org/auth/realms/kubernetes
        - --client-id=kubernetes
        - --client-secret=<your-client-secret-here>
        - --redirection-url=https://kubernetes-dashboard.example.org
        - --enable-refresh-tokens=true
        - --encryption-key=ooTh6Chei1eefooyovai5ohwienuquoh
        - --upstream-url=https://kubernetes-dashboard.kube-system
        - --resources=uri=/*
        image: keycloak/keycloak-gatekeeper
        name: kubernetes-dashboard-proxy
        ports:
        - containerPort: 80
          livenessProbe:
            httpGet:
              path: /oauth/health
              port: 80
            initialDelaySeconds: 3
            timeoutSeconds: 2
          readinessProbe:
            httpGet:
              path: /oauth/health
              port: 80
            initialDelaySeconds: 3
            timeoutSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard-proxy
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: kubernetes-dashboard-proxy
  type: ClusterIP
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://book.konstantinsecurity.com/readme/architect/kubernetes/auth/ldap.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
