Прикручиваем ActiveDirectory авторизацию к Kubernetes c помощью Keycloak

от автора

Данная статья написана с целью расширить уже существующую, но рассказывает про особенности связки именно с Microsoft ActiveDirectory, а так же дополняет ее.

В этой статье я расскажу как установить и настроить:

  • Keycloak — это проект с открытым исходным кодом. Который обеспечивает единую точку входа для приложений. Работает с множеством протоколов, в том числе с LDAP и OpenID которые нас интересуют.
  • Keycloak gatekeeper — реверс прокси приложения, позволяющее интегрировать авторизаию через Keycloak.
  • Gangway — приложение которе генерирует конфиг для kubectl с помощью которого через OpenID можно авторизоваться и подключиться к Kubernetes API.

Как работают права в Kubernetes.

Управлять правами пользователя/групп мы можем с помощью RBAC, об этом создано уже кучу статей, не буду подробно на этом останавливаться. Проблема в том что вы можете используя RBAC для того что бы ограничить права пользователя, но Kubernetes не чего не знает о пользователях. Получается что нужен механизм доставки пользователя в Kubernetes. Для этого мы добавим в Kuberntes OpenID провайдера который и будет говорить о том что такой пользователь действительно существует, а права ему уже выдаст сам Kubernetes.

Подготовка

  • Вам понадобится Kubernetes кластер или minikube
  • Active Directory
  • Домены:
    keycloak.example.org
    kubernetes-dashboard.example.org
    gangway.example.org
  • Сертификат для доменов или самоподписанный сертификат

Подробно останавливаться на том как создавать самоподписанные сертификат я не буду, надо создать 2 сертификата, это корневой(Центр сертификации) и wildcard клиентский для домена *.example.org

После того как вы получите/выпишите сертификаты, клиентский надо добавить в Kubernetes, для этого создаем для него secret:

kubectl create secret tls tls-keycloak --cert=example.org.crt --key=example.org.pem

Далее мы будет его использовать для нашего Ingress контроллера

Установка Keycloak

Я решил что проще всего использовать готовые решения для этого, а именно helm chart-ы.

Устанавливаем репозиторий и обновляем его:

helm repo add codecentric https://codecentric.github.io/helm-charts helm repo update

Создаем файл keycloak.yml cо следующим содержимым:

keycloak.yml

keycloak:   # Имя администратора   username: "test_admin"   # Пароль администратор     password: "admin"   # Эти флаги нужны что бы позволить загружать в Keycloak скрипты прямо через web морду. Это нам    понадобиться что бы починить один баг, о котором ниже.   extraArgs: "-Dkeycloak.profile.feature.script=enabled -Dkeycloak.profile.feature.upload_scripts=enabled"    # Включаем ingress, указываем имя хоста и сертификат который мы предварительно сохранили в secrets   ingress:     enabled: true      path: /     annotations:       kubernetes.io/ingress.class: nginx       ingress.kubernetes.io/affinity: cookie     hosts:       - keycloak.example.org     tls:     - hosts:         - keycloak.example.org       secretName: tls-keycloak   # Keycloak для своей работы требует базу данных, в тестовых целях я разворачиваю Postgresql прямо в Kuberntes, в продакшене так лучше не делать!   persistence:     deployPostgres: true     dbVendor: postgres  postgresql:   postgresUser: keycloak   postgresPassword: ""   postgresDatabase: keycloak   persistence:     enabled: true

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

Далее заходим в веб интерфейс keycloak.example.org

В левом углу нажимаем Add realm

Key Value
Name kubernetes
Display Name Kubernetes

Отключаем проверку подтверждения email пользователя:
Client scopes —> Email —> Mappers —> Email verified (Delete)

Настраиваем федерацию для импорта пользователей из ActiveDirectory, я оставлю ниже скриншоты думаю так будет понятней.

User federation —> Add provider… —> ldap

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


Если все хорошо, то после нажатия кнопки Synchronize all users вы уведите сообщение об успешном импорте пользователей.

Далее надо замапить наши группы

User federation —> ldap_localhost —> Mappers —> Create

Создание маппера

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

Надо создать клиента, в понятиях Keycloak это приложение которое будет у него авторизовываться. Важные пункты выделю на скриншоте красным.

Clients —> Create

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

Создадим scoupe для групп:

Client Scopes —> Create

Создание scoupe

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

Client Scopes —> groups —> Mappers —> Create

Маппер

Добавляем маппинг наших групп в Default Client Scopes:

Clients —> kubernetes —> Client Scopes —> Default Client Scopes
Выбираем groups в Available Client Scopes, нажимаем Add selected

Получаем secret(и записываем его куда нить) который мы будем использовать для авторизации в Keycloak:

Clients —> kubernetes —> Credentials —> Secret
На этом настройка окончена, но у меня возникла ошибка когда после успешной авторизации я получал ошибку 403. Баг репорт.

Фикс:

Client Scopes —> roles —> Mappers —> Create

Mapper

Код скрипта

// add current client-id to token audience token.addAudience(token.getIssuedFor());  // return token issuer as dummy result assigned to iss again token.getIssuer(); 

Настройка Kubernetes

Нам надо указать где лежит наш корневой сертификат от сайта, и где находиться провайдер OIDC.
Для этого редактируем файл /etc/kubernetes/manifests/kube-apiserver.yaml

kube-apiserver.yaml

 ... spec:   containers:   - command:     - kube-apiserver ...     - --oidc-ca-file=/var/lib/minikube/certs/My_Root.crt     - --oidc-client-id=kubernetes     - --oidc-groups-claim=groups     - --oidc-issuer-url=https://keycloak.example.org/auth/realms/kubernetes     - --oidc-username-claim=email ... 

Обновляем kubeadm конфиг в кластере:

kubeadm config

kubectl edit -n kube-system configmaps kubeadm-config

 ... data:   ClusterConfiguration: |     apiServer:       extraArgs:         oidc-ca-file: /var/lib/minikube/certs/My_Root.crt         oidc-client-id: kubernetes         oidc-groups-claim: groups         oidc-issuer-url: https://keycloak.example.org/auth/realms/kubernetes         oidc-username-claim: email ... 

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

Для защиты вашего веб приложение можно использовать keycloak gatekeeper. Помимо того что данный реверс прокси будет авторизировать пользователя перед тем как показать страницу, дак еще и передавать конечному приложению информацию о вас в заголовках. Тем самым если ваше приложение поддерживает OpenID, то пользователь сразу авторизуется. Рассмотрим на примере Kubernetes Dashboard

Установка Kubernetes Dashboard

 helm install stable/kubernetes-dashboard --name dashboard -f values_dashboard.yaml 

values_dashboard.yaml

enableInsecureLogin: true service:   externalPort: 80 rbac:   clusterAdminRole: true   create: true serviceAccount:   create: true   name: 'dashboard-test' 

Настройка прав доступа:

Создадим ClusterRoleBinding который будет давать права админа кластера(стандартная ClusterRole cluster-admin) для пользователей состоящих в группе DataOPS.

 kubectl apply -f rbac.yaml 

rbac.yaml

 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata:   name: dataops_group roleRef:   apiGroup: rbac.authorization.k8s.io   kind: ClusterRole   name: cluster-admin subjects: - apiGroup: rbac.authorization.k8s.io   kind: Group   name: DataOPS 

Установка keycloak gatekeeper:

 helm repo add gabibbo97 https://gabibbo97.github.io/charts/ helm repo update helm install gabibbo97/keycloak-gatekeeper --version 2.1.0 --name keycloak-gatekeeper -f values_proxy.yaml 

values_proxy.yaml

  # Включаем ingress ingress:   enabled: true   annotations:     kubernetes.io/ingress.class: nginx   path: /   hosts:     - kubernetes-dashboard.example.org   tls:    - secretName: tls-keycloak      hosts:        - kubernetes-dashboard.example.org  # Говорим где мы будем авторизовываться у OIDC провайдера discoveryURL: "https://keycloak.example.org/auth/realms/kubernetes" # Имя клиента которого мы создали в Keycloak ClientID: "kubernetes" # Secret который я просил записать ClientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727" # Куда перенаправить в случае успешной авторизации. Формат <SCHEMA>://<SERVICE_NAME>.><NAMESAPCE>.<CLUSTER_NAME> upstreamURL: "http://dashboard-kubernetes-dashboard.default.svc.cluster.local" # Пропускаем проверку сертификата, если у нас самоподписанный skipOpenidProviderTlsVerify: true # Настройка прав доступа, пускаем на все path если мы в группе DataOPS rules:   - "uri=/*|groups=DataOPS" 

После этого при попытке зайти на kubernetes-dashboard.example.org, произойдет перенаправление на Keycloak и в случае удачной авторизации мы попадем в Dashboard уже залогиненным.

Установка gangway

Для удобства можно добавить gangway который будет генерировать файл конфига для kubectl, с помощью которого мы уже под нашим пользователем попадем в Kubernetes.

 helm install --name gangway stable/gangway -f values_gangway.yaml 

values_gangway.yaml

 gangway:   # Произвольное имя кластера   clusterName: "my-k8s"   # Где у нас OIDC провайдер   authorizeURL: "https://keycloak.example.org/auth/realms/kubernetes/protocol/openid-connect/auth"   tokenURL: "https://keycloak.example.org/auth/realms/kubernetes/protocol/openid-connect/token"   audience: "https://keycloak.example.org/auth/realms/kubernetes/protocol/openid-connect/userinfo"   # Теоритически сюда можно добавить groups которые мы замапили   scopes: ["openid", "profile", "email", "offline_access"]   redirectURL: "https://gangway.example.org/callback"   # Имя клиента   clientID: "kubernetes"   # Секрет   clientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727"   # Если оставить дефолтное значние, то за имя пользователя будет братья <b>Frist name</b> <b>Second name</b>, а при "sub" его логин   usernameClaim: "sub"   # Доменное имя или IP адресс API сервера   apiServerURL: "https://192.168.99.111:8443"  # Включаем Ingress ingress:   enabled: true   annotations:     kubernetes.io/ingress.class: nginx     nginx.ingress.kubernetes.io/proxy-buffer-size: "64k"   path: /   hosts:   - gangway.example.org   tls:   - secretName: tls-keycloak     hosts:       - gangway.example.org  # Если используем самоподписанный сертификат, то его(открытый корневой сертификат) надо указать. trustedCACert: |-  -----BEGIN CERTIFICATE-----  MIIDVzCCAj+gAwIBAgIBATANBgkqhkiG9w0BAQsFADA1MQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRGF0YU9QUzEUMBIGA1UEAxMLbXkgcm9vdCBrZXkwHhcNMjAwMjE0MDkxODAwWhcNMzAwMjE0MDkxODAwWjA1MQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRGF0YU9QUzEUMBIGA1UEAxMLbXkgcm9vdCBrZXkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDyP749PqqIRwNSqaK6qr0Zsi03G4PTCUlgaYTPZuMrwUVPK8xX2dWWs9MPRMOdXpgr8aSTZnVfmelIlVz4D7o2vK5rfmAe9GPcK0WbwKwXyhFU0flS9sU/g46ogHFrk03SZxQAeJhMLfEmAJm8LF5HghtGDs3t4uwGsB95o+lqPLiBvxRB8ZS3jSpYpvPgXAuZWKdZUQ3UUZf0X3hGLp7uIcIwJ7i4MduOGaQEO4cePeEJy9aDAO6qV78YmHbyh9kaW+1DL/Sgq8NmTgHGV6UOnAPKHTnMKXl6KkyUz8uLBGIdVhPxrlzG1EzXresJbJenSZ+FZqm3oLqZbw54Yp5hAgMBAAGjcjBwMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHISTOU/6BQqqnOZj+1xJfxpjiG0MAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAj7HC8ObibwOLT4ZYmISJZwub9lcE0AZ5cWkPW39j/syhdbbqjK/6jy2D3WUEbR+s1Vson5Ov7JhN5In2yfZ/ByDvBnoj7CP8Q/ZMjTJgwN7j0rgmEb3CTZvnDPAz8Ijw3FP0cjxfoZ1Z0V2F44Ry7gtLJWr06+MztXVyto3aIz1/XbMQnXYlzc3c3B5yUQIy44Ce5aLRVsAjmXNqVRmDJ2QPNLicvrhnUJsO0zFWI+zZ2hc4Ge1RotCrjfOc9hQY63jZJ17myCZ6QCD7yzMzAob4vrgmkD4q7tpGrhPY/gDcE+lUNhC7DO3l0oPy2wsnT2TEn87eyWmDiTFG9zWDew==  -----END CERTIFICATE----- 

Выглядит примерно так. Позволяет как сразу скачать файл конфига так и сформировать его использую набор команд:

ссылка на оригинал статьи https://habr.com/ru/post/489172/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *