argocd – налаштування інтеграції з freeipa

Опис

В цьому дописі налаштуємо інтеграцію з freeipa(LDAP). Надалі орієнтуючись на ldap групи будемо нарізати доступи розробникам до їхніх проєктів. Варто згадати що є декілька варіантів аутентифікації в кластері кубернетес і одним з надійних та перевірених є використання OIDC провайдерів, а саме популярний провайдер DEX.

OIDC(OpenID Connect) – це механізм автентифікації який базується на OAuth 2.0(протокол авторизації). Він дозволяє перевіряти ідентичність користувача на основі аутентифікованого сеансу, проведеного провайдером автентифікації. Основними компонентами є  

  1. ID Token: це JSON Web Token, який містить відомості про користувача;
  2. UserInfo Endpoint: кінцева точка, де клієнт може отримати дані користувача за умови, що у нього є дійсний access token;
  3. Discovery: механізм, дозволяє клієнтам дізнаватися про конфігурацію провайдера;

Dex – популярний OIDC провайдер для аутентифікації користувачів. Він дозволяє налаштовувати аутентифікацію користувачів через зовнішні служби LDAP, SAML. Kubernetes буде комунікувати з Dex через OIDC для аутентифікації.

За допомогою Dex ми:

  • Підвищуємо безпеку.
    (використовувати політики автентифікації й не тільки)
  • Отримуємо гнучкість.
    (Кожна організація має унікальні вимоги, і Dex досить гнучкий, щоб дозволити використовувати майже будь-якого постачальника ідентифікаційної інформації).
  • Забезпечуємо централізовану систему автентифікації.

Перед початком налаштування у повинно бути:

  • розгорнутий argoсd;
  • встановлена утиліта argocd-cli;
  • створений системний користувач у freeipa для інтеграції;

Налаштування

Щоб не виникало проблем з групами та налаштуванням ldap переглянемо доступні атрибути для тестового користувача. Для цього скористаємось командою ldapsearch, запустимо її на сервері freeipa:

ldapsearch -W -D uid=<USER>,cn=users,cn=accounts,dc=example,dc=com -b "uid=<USER>,cn=users,cn=accounts,dc=example,dc=com" '(memberof=cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com)'

Отримали вивід, в якому є необхідна інформація. Щоб не було проблем з пошуком груп в ldap варто звернути увагу на доступні objectClass оскільки вони можуть бути в кожного свої:

Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <uid=test_user,cn=users,cn=accounts,dc=example,dc=com> with scope subtree
# filter: (memberof=cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com)
# requesting: ALL
#

# test_user, users, accounts, example.com
dn: uid=test_user,cn=users,cn=accounts,dc=example,dc=com
memberOf: cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com
krbExtraData:: ********************
krbPasswordExpiration: *************
krbLastPwdChange: *************
krbLoginFailedCount: 0
krbLastFailedAuth: *************
gidNumber: *********
uidNumber: ***********
ipaUniqueID: *******8-6***-***c-8***-1**2****7**4b
ou: EC
givenName: Test
krbPrincipalName: [email protected]
mail: [email protected]
uid: test_user
homeDirectory: /home/test_user
sn: User
gecos: Test User
initials: TU
loginShell: /bin/bash
objectClass: posixaccount
objectClass: ipaobject
title: TEST
krbCanonicalName: [email protected]
cn: Test User
displayName: Test User
mepManagedEntry: cn=test_user,cn=groups,cn=accounts,dc=example,dc=com
krbLastAdminUnlock: ************

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

також опції для користувачів та груп можемо отримати через UI, для цього в freeipa потрібно перейти в IPA Server > Configuration:

Створимо файл patch-dex.yaml в якому опишемо необхідні параметри для configmap argocd:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://<YOUR_ARGOCD_URL>
  dex.config: |
    connectors:
    - type: ldap
      id: ldap
      name: LDAP
      config:
        host: <YOUR_IPA_SERVER_URL>:636
        bindDN: uid=<INTEGRATION_IPA_USER>,cn=users,cn=accounts,dc=example,dc=com
        bindPW: <INTEGRATION_IPA_PASS>
        insecureNoSSL: false
        insecureSkipVerify: true
        usernamePrompt: Username
        # Ldap user serch attributes
        userSearch:
          baseDN: "cn=users,cn=accounts,dc=example,dc=com"
          filter: "(objectClass=posixAccount)"
          username: uid
          idAttr: DN
          emailAttr: mail
          nameAttr: cn
        # Ldap group serch attributes
        groupSearch:
          baseDN: "cn=groups,cn=accounts,dc=example,dc=com"
          filter: "(objectClass=ipaobject)"
          userMatchers:
          - userAttr: DN
            groupAttr: member
          nameAttr: cn

Звертаємо увагу на filter: “(objectClass=ipaobject)” тут потрібно вказати той об’єкт який описаний у Вашій ipa(ми переглядали вище використовуючи ldapsearch), якщо він не вірний – dex не зможе отримати ldap групи.

Також є змога дуже чуттєві дані передавати через secrets, для цього потрібно:

kubectl -n argocd patch secrets argocd-secret --patch "{\"data\":{\"dex.ldap.bindPW\":\"$(echo IPA_INT_USER_PASS | base64 -w 0)\"}}"
kubectl -n argocd patch secrets argocd-secret --patch "{\"data\":{\"dex.ldap.bindDN\":\"$(echo uid=<INTEGRATION_IPA_USER>,cn=users,cn=accounts,dc=example,dc=com | base64 -w 0)\"}}"

та в configmap вказати:

bindDN: "$dex.ldap.bindDN"
bindPW: "$dex.ldap.bindPW"

Скажу відразу, варіант з використанням secrets не розглядав (поки що), проте гадаю комусь буде корисним.

Що ж застосовуємо описані нами зміни:

kubectl apply -f patch-dex.yaml

Взагалі argocd вміє в реальному часі перечитувати конфігураційні файли, тому видаляти або скейлити поди з dex та argo-server не обов’язково.

Далі пробуємо виконати вхід до argo за допомогою argocd-cli:

argocd login <YOUR_ARGOCD_URL> --sso

або через UI, де у Вас з’явиться кнопка “LOG IN VIA ...”(якщо кнопка не з’явилася — перегляньте ще раз configmap та усуньте помилки):

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

перевіряємо логи argocd-dex-server:

│ time="2023-08-16T10:56:12Z" level=info msg="performing ldap search cn=users,cn=accounts,dc=example,dc=com sub (&(objectClass=posixAccount)(uid=test_user))"                                                                                                         
│ time="2023-08-16T10:56:12Z" level=info msg="username \"test_user\" mapped to entry uid=test_user,cn=users,cn=accounts,dc=example,dc=com"                                                                                                                  
│ time="2023-08-16T10:56:12Z" level=info msg="performing ldap search cn=groups,cn=accounts,dc=example,dc=com sub (&(objectClass=ipaobject)(member=uid=test_user,cn=users,cn=accounts,dc=example,dc=com))"                                                                  
│ time="2023-08-16T10:56:12Z" level=info msg="login successful: connector \"ldap\", username=\"Test User\", preferred_username=\"\", email=\"[email protected]\", groups=[\"ipausers\"]

Як бачимо, логін пройшов успішно, ldap групи відображаються. Якщо в рядку groups=[] порожньо, не лякайтесь, варто погратися з filter: “(objectClass=””)” та додати Ваш об’єкт групи. Загалом інтеграцію налаштовано. Залишається розібратися з правами, на основі ldap груп нарізати відповідні доступи в argo. Даний процес розглянемо в окремій публікації.

Оскільки для розгортання використовувався helm, всі описані зміни додамо в custom-values.yaml знайшовши відповідні опції в файлі чарту valeus.yaml:

configs:
  cm:
    url: https://<YOUR_ARGOCD_URL>
    dex.config: |
      connectors:
      - type: ldap
        id: ldap
        name: LDAP
        config:
          # host and port of the LDAP server in form "host:port".
          host: <YOUR_FREEIPA_SERVER_URL>:636
          bindDN: uid=<FREEIPA_INT_USER>,cn=users,cn=accounts,dc=example,dc=com
          bindPW: <FREEIPA_INT_PASS>
          insecureNoSSL: false
          insecureSkipVerify: true
          usernamePrompt: Username
          # Ldap user serch attributes
          userSearch:
            baseDN: "cn=users,cn=accounts,dc=example,dc=com"
            filter: "(objectClass=posixAccount)"
            username: uid
            idAttr: DN
            emailAttr: mail
            nameAttr: cn
          # Ldap group serch attributes
          groupSearch:
            baseDN: "cn=groups,cn=accounts,dc=example,dc=com"
            filter: "(objectClass=ipaobject)"
            userMatchers:
            - userAttr: DN
              groupAttr: member
            nameAttr: cn

Корисні посилання

Click to rate this post!
[Total: 1 Average: 5]