Автентифікація

На цій сторінці наведено огляд автентифікації в Kubernetes, з акцентом на автентифікацію в Kubernetes API.

Користувачі в Kubernetes

У всіх кластерах Kubernetes є дві категорії користувачів: службові облікові записи, які керуються Kubernetes, і звичайні користувачі.

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

  • адміністратор розповсюджує приватні ключі
  • сховище користувачів, таке як Keystone або Google Accounts
  • файл зі списком імен користувачів та паролів

У цьому відношенні Kubernetes не має обʼєктів, які представляють звичайні облікові записи користувачів. Звичайні користувачі не можуть бути додані до кластера через API виклик.

Хоча звичайного користувача не можна додати через API виклик, будь-який користувач, який предʼявляє дійсний сертифікат, підписаний центром сертифікації (CA) кластера, вважається автентифікованим. У цій конфігурації Kubernetes визначає імʼя користувача з поля загального імені (CN) у сертифікаті (наприклад, "/CN=bob"). Після цього підсистема контролю доступу на основі ролей (RBAC) визначає, чи авторизований користувач для виконання певної операції з ресурсом.

На відміну від цього, службові облікові записи є користувачами, якими керує Kubernetes API. Вони привʼязані до певних просторів імен і створюються автоматично API сервером або вручну через API виклики. Службові облікові записи привʼязані до набору облікових даних, збережених як Secrets, які монтуються в Podʼи, що дозволяє процесам всередині кластера взаємодіяти з Kubernetes API.

API запити привʼязані або до звичайного користувача, або до службово облікового запису, або обробляються як анонімні запити. Це означає, що кожен процес всередині або поза кластером, від користувача, який вводить kubectl на робочій станції, до kubelets на вузлах, до членів панелі управління, повинен автентифікуватися при виконанні запитів до API сервера, або бути обробленим як анонімний користувач.

Стратегії автентифікації

Kubernetes використовує клієнтські сертифікати, токени на предʼявника (bearer tokens) або проксі для автентифікації (authenticating proxy) для автентифікації API запитів через втулки автентифікації. Під час виконання HTTP запитів до API сервера втулки намагаються асоціювати наступні атрибути із запитом:

  • Імʼя користувача: рядок, який ідентифікує кінцевого користувача. Загальноприйняті значення можуть бути kube-admin або jane@example.com.
  • UID: рядок, який ідентифікує кінцевого користувача та намагається бути більш стабільним і унікальним, ніж імʼя користувача.
  • Групи: набір рядків, кожен з яких вказує на членство користувача в певній логічній групі користувачів. Загальноприйняті значення можуть бути system:masters або devops-team.
  • Додаткові поля: елемент map рядків для отримання переліку рядків, що містить додаткову інформацію, яку авторизатори можуть вважати корисною.

Примітка:

Усі значення є непрозорими для системи автентифікації та мають значення лише при інтерпретації авторизатором.

Анонімні запити

Коли увімкнено, запити, які не відхиляються іншими налаштованими методами автентифікації, розглядаються як анонімні запити та отримують імʼя користувача system:anonymous і групу system:unauthenticated.

Наприклад, на сервері з налаштованою автентифікацією за допомогою токенів та увімкненим анонімним доступом, запит з недійсним токеном автентифікації отримає помилку 401 Unauthorized. Запит без токена автентифікації буде розглядатися як анонімний запит.

Анонімний доступ стандартно ввімкнено, якщо використовується режим авторизації, відмінний від AlwaysAllow; його можна вимкнути, передавши опцію командного рядка --anonymous-auth=false серверу API. Вбудовані авторизатори ABAC та RBAC вимагають явної авторизації користувача system:anonymous або групи system:unauthenticated; якщо у вас є зwастарілі правила політики (з Kubernetes версії 1.5 або раніше), ці застарілі правила, що надають доступ користувачеві * або групі *, не дозволяють автоматично надавати доступ анонімним користувачам.

Налаштування анонімної автентифікації

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.34 [stable](стандартно увімкнено)

AuthenticationConfiguration можна використовувати для налаштування анонімного автентифікатора. Якщо ви встановили поле anonymous у файлі AuthenticationConfiguration, ви не можете встановити прапорець --anonymous-auth.

Основна перевага налаштування анонімного автентифікатора за допомогою конфігураційного файлу автентифікації полягає в тому, що, крім увімкнення та вимкнення анонімної автентифікації, ви також можете налаштувати, які точки доступу підтримують анонімну автентифікацію.

Ось приклад конфігураційного файлу автентифікації:

---
#
# УВАГА: це приклад конфігурації.
#        Не використовуйте його для вашого власного кластера!
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
anonymous:
  enabled: true
  conditions:
  - path: /livez
  - path: /readyz
  - path: /healthz

У наведеній конфігурації лише точки доступу /livez, /readyz і /healthz доступні для анонімних запитів. Будь-які інші точки доступу будуть недоступні, навіть якщо це дозволено конфігурацією RBAC.

Методи автентифікації

Ви можете одночасно ввімкнути кілька методів автентифікації. Зазвичай вам слід використовувати принаймні два методи:

  • токени службових облікових записів
  • принаймні один інший метод для автентифікації користувачів.

Коли увімкнено кілька модулів автентифікаторів, перший модуль, який успішно автентифікує запит, перериває подальшу оцінку. API сервер не гарантує порядок виконання автентифікаторів.

Група system:authenticated включена до списку груп для всіх автентифікованих користувачів.

Інтеграції з іншими протоколами автентифікації (LDAP, SAML, Kerberos, альтернативні схеми x509 тощо) є доступними; наприклад, за допомогою проксі автентифікації або вебхука автентифікації.

X.509 клієнтські сертифікати

Будь-який клієнт Kubernetes, який надає дійсний клієнтський сертифікат, підписаний центром сертифікації (CA) кластера client trust, вважається автентифікованим. У цій конфігурації Kubernetes визначає імʼя користувача з поля commonName в subject сертифіката (наприклад, commonName=bob представляє користувача з іменем користувача «bob»). Звідти механізми авторизації Kubernetes визначають, чи дозволено користувачеві виконувати певну операцію над ресурсом.

Автентифікація клієнтського сертифіката вмикається шляхом передачі опції --client-ca-file=<SOMEFILE> на сервер API. Ця опція налаштовує довірений центр сертифікації клієнта кластера. Посилання на файл повинно містити один або декілька центрів сертифікації, які сервер API може використовувати для перевірки клієнтських сертифікатів. Якщо клієнтський сертифікат представлений і перевірений, загальна назва субʼєкта використовується як імʼя користувача для запиту. Клієнтські сертифікати також можуть вказувати на членство користувача в групах за допомогою полів організації сертифіката. Щоб включити кілька членств у групах для користувача, додайте кілька полів організації в сертифікат.

Дивіться Управління сертифікатами, щоб дізнатися, як створити клієнтський сертифікат, або ознайомтеся з коротким прикладом далі на цій сторінці.

Сертифікати клієнтів, сумісні з Kubernetes

Ви можете предʼявити дійсний сертифікат, виданий CA в ланцюжку довіри, який API-сервер приймає для клієнтських сертифікатів, і використовувати його для автентифікації в Kubernetes. Сертифікат повинен бути дійсним; API-сервер перевіряє це на основі атрибутів X.509 notBefore і notAfter, а сертифікат повинен мати розширене використання ключа, що включає автентифікацію клієнта (ClientAuth).

Примітка:

Kubernetes 1.35 не підтримує відкликання сертифікатів. Будь-який виданий сертифікат залишається дійсним до закінчення терміну його дії.
Відповідність імені користувача

Kubernetes очікує клієнтський сертифікат, що містить атрибут commonName (OID 2.5.4.3), який використовується як імʼя користувача субʼєкта.

Відповідність ідентифікаторів користувачів
СТАН ФУНКЦІОНАЛУ: Kubernetes v1.34 [beta](стандартно увімкнено)

Щоб скористатися цією функцією, сертифікат повинен містити атрибут 1.3.6.1.4.1.57683.2, а також має бути увімкнено можливість AllowParsingUserUIDFromCertAuth (стандартно увімкнено).

Kubernetes може аналізувати опціональний UID користувача з сертифіката. UID відрізняється від імені користувача; це непрозоре значення, значення якого визначається особою, яка запросила сертифікат, або тим, хто встановив правила затвердження сертифіката.

Наприклад, UID може бути 1042 (просте ціле число) в одному кластері, але інший сертифікат може використовувати d3f77937-ec82-4f16-8010-61821abe315a (UUID) як UID.

Ось приклад, що пояснює, що це означає. Якщо у вас є сертифікат із загальною назвою «Ada Lovelace», а сертифікат також має атрибут uid (OID 0.9.2342.19200300.100.1.1) із uid, встановленим на «aaking1815», Kubernetes вважає, що імʼя користувача клієнта — «Ada Lovelace»; Kubernetes ігнорує атрибут uid, оскільки це не OID, специфічний для CNCF, який шукає Kubernetes. Якщо ви хочете, щоб aaking1815 розпізнавався Kubernetes як UID, його потрібно встановити як значення атрибуту OID 1.3.6.1.4.1.57683.2 в субʼєкті сертифіката.

Відповідність групі

Ви можете віднести користувача до груп, статично включивши інформацію про групи до сертифіката. Для кожної групи, членом якої є користувач, додайте назву групи як організацію (OID 2.5.6.4) до субʼєкта вашого сертифіката. Щоб включити кілька членств у групах для одного користувача, додайте кілька організацій до суб'єкта сертифіката (порядок не має значення). Для прикладу користувача розпізнаваним іменем для сертифіката може бути CN=Ada Lovelace,O=Users,O=Staff,O=Programmers, що розмістить її в групах «Programmers», «Staff», «system:authenticated» та «Users».

Внесення інформації про групу в сертифікат є необовʼязковим; якщо ви не вказали жодної групи в сертифікаті, користувач буде членом тільки групи «system:authenticated».

Сертифікати клієнтів вузлів

Kubernetes може використовувати той самий підхід для ідентифікації вузлів; вузли є клієнтами сервера API Kubernetes, на яких запущено kubelet (також, хоча це менш актуально в даному випадку, сервер API зазвичай є клієнтом кожного вузла). Наприклад: вузол "server-1a-antarctica42" з доменним імʼям "server-1a-antarctica42.cluster.example" може використовувати сертифікат, виданий "CN=system:node:server-1a-antarctica/42,O=system:nodes". Імʼя користувача вузла тоді буде "system:node:server-1a-antarctica/g42", а вузол буде членом «system:authenticated» і «system:nodes».

Kubelet використовує сертифікат і приватний ключ вузла для автентифікації на сервері API кластера.

Примітка:

Ідентифікатори машин для вузлів не є такими самими, як ServiceAccounts.

Приклад

Ви можете використовувати openssl для створення запиту на підписання сертифіката:

# У цьому прикладі передбачається, що ви вже маєте приватний ключ alovelace.pem.
openssl req -new -key alovelace.pem -out alovelace-csr.pem -subj "/CN=alovelace/O=app1/O=app2"

Це створить запит на підписання для імені користувача «alovelace», що належить до двох груп, «app1» та «app2». Потім ви можете підписати цей запит на підписання за допомогою сертифікаційного центру довіри клієнта вашого кластера, щоб отримати сертифікат, який можна використовувати для автентифікації клієнта у вашому кластері.

Bootstrap токени

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.18 [stable]

Для спрощення початкового налаштування нових кластерів, Kubernetes включає тип токена на предʼявника (bearer token), який керується динамічно, так званий Bootstrap Token. Ці токени зберігаються як Secrets у просторі імен kube-system, де ними можна динамічно керувати та створювати. Менеджер контролерів містить контролер TokenCleaner, який видаляє bootstrap токени в міру їх завершення.

Токени мають форму [a-z0-9]{6}.[a-z0-9]{16}. Перший компонент є ID токена, а другий компонент є Secret токена. Ви вказуєте токен у HTTP заголовку наступним чином:

Authorization: Bearer 781292.db7bc3a58fc5f07e

Ви повинні увімкнути Bootstrap Token Authenticator з прапорцем --enable-bootstrap-token-auth на API сервері. Ви повинні увімкнути контролер TokenCleaner за допомогою аргументу командного рядка --controllers для kube-controller-manager. Це робиться за допомогою чогось типу --controllers=*,tokencleaner. kubeadm зробить це за вас, якщо ви використовуєте його для початкового налаштування кластера.

Автентифікатор автентифікує як system:bootstrap:<Token ID>. Він включений у групу system:bootstrappers. Імена користувачів та групи навмисно обмежені, щоб перешкоджати користувачам використовувати ці токени після початкового налаштування. Імена користувачів та групи можна використовувати (і використовуються kubeadm) для створення відповідних політик авторизації для підтримки початкового налаштування кластера.

Детальнішу інформацію про автентифікатор Bootstrap Token та контролери, а також про керування цими токенами за допомогою kubeadm, дивіться у Bootstrap Tokens.

Додавання токена на предʼявника в запит

При використанні автентифікації за допомогою токена на предʼявника з HTTP-клієнта, API-сервер очікує заголовок Authorization із значенням Bearer <token>. Токен на предʼявника повинен бути послідовністю символів, яку можна ввести в значення заголовка HTTP, використовуючи лише засоби кодування та цитування HTTP. Наприклад: якщо токен на предʼявника має вигляд 31ada4fd-adec-460c-809a-9e56ceb75269, то в заголовку HTTP він буде виглядати так, як показано нижче.

Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269

Токени службових облікових записів

Службовий обліковий запис є автоматично увімкненим автентифікатором, який використовує підписані токени на предʼявника (bearer tokens) для перевірки запитів. Втулок приймає два необовʼязкові прапорці:

  • --service-account-key-file Файл, що містить PEM-кодовані x509 RSA або ECDSA приватні або публічні ключі, що використовуються для перевірки токенів службових облікових записів. Вказаний файл може містити кілька ключів, і прапорець може бути вказаний кілька разів з різними файлами. Якщо не вказано, використовується --tls-private-key-file.
  • --service-account-lookup Якщо увімкнено, токени, які видаляються з API, будуть відкликані.

Службові облікові записи зазвичай створюються автоматично API сервером та асоціюються з Podʼами, які працюють у кластері через ServiceAccount Контролер допуску. Токени на предʼявника (bearer tokens) монтуються в Podʼи у відомих місцях, що дозволяє процесам всередині кластера взаємодіяти з API сервером. Облікові записи можуть бути явно асоційовані з Podʼами, використовуючи поле serviceAccountName у PodSpec.

Примітка:

serviceAccountName зазвичай опускається, оскільки це робиться автоматично.
apiVersion: apps/v1 # ця apiVersion актуальна станом з Kubernetes 1.9
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3
  template:
    metadata:
    # ...
    spec:
      serviceAccountName: bob-the-bot
      containers:
      - name: nginx
        image: nginx:1.14.2

Токени на предʼявника службових облікових записів (bearer tokens) є цілком дійсними для використання за межами кластера і можуть бути використані для створення ідентичностей для тривалих завдань, які бажають взаємодіяти з API Kubernetes. Щоб вручну створити службовий обліковий запис, використовуйте команду kubectl create serviceaccount (NAME). Це створює службовий обліковий запис у поточному просторі імен.

kubectl create serviceaccount jenkins
serviceaccount/jenkins created

Ви можете вручну створити відповідний токен:

kubectl create token jenkins
eyJhbGciOiJSUzI1NiIsImtp...

Створений токен є підписаним JSON Web Token (JWT).

Підписаний JWT може бути використаний як токен на предʼявника (bearer token) для автентифікації як вказаний службовий обліковий запис. Дивіться вище для інформації про те, як токен включається у запит. Зазвичай ці токени монтуються в Podʼи для доступу до API сервера всередині кластера, але можуть бути використані й ззовні кластера.

Службові облікові записи автентифікуються з імʼям користувача system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT), і належать групам system:serviceaccounts та system:serviceaccounts:(NAMESPACE).

Попередження:

Оскільки токени службових облікових записів також можуть зберігатися в обʼєктах Secret API, будь-який користувач з правами на запис до Secrets може запитати токен, і будь-який користувач з правами на читання до тих Secrets може автентифікуватися як службовий обліковий запис. Будьте обережні при наданні дозволів на службові облікові записи та можливості читання або запису для Secrets.

Зовнішні інтеграції

Kubernetes має вбудовану підтримку OpenID Connect (OIDC); див. JSON Web Token автентифікація.

Інтеграція з іншими протоколами автентифікації (наприклад: LDAP, SAML, Kerberos, альтернативні схеми X.509) може бути здійснена за допомогою проксі-сервера автентифікації або шляхом інтеграції з веб-хуком автентифікації.

Ви також можете використовувати будь-який власний метод, який видає клієнтські сертифікати X.509 клієнтам, за умови, що API-сервер довірятиме дійсним сертифікатам. Прочитайте Клієнтські сертифікати X.509, щоб дізнатися, як створити сертифікат.

Якщо ви випускаєте сертифікати для клієнтів, ви (як адміністратор хмарної платформи) повинні переконатися, що термін дії сертифіката та інші ваші проєктні рішення забезпечують належний рівень безпеки.

JSON Web Token автентифікація

Ви можете налаштувати Kubernetes для автентифікації користувачів за допомогою токенів, сумісних із JSON Web Token (JWT). Механізм автентифікації JWT використовується для токенів ServiceAccount, які видає сам Kubernetes, а також його можна використовувати для інтеграції з іншими джерелами ідентифікації.

Система автентифікації намагається проаналізувати необроблений токен ID і перевірити, чи він підписаний налаштованим емітентом. Для токенів, випущених зовні, відкритий ключ для перевірки підпису отримується з публічної точки доступу емітента за допомогою OIDC discovery.

Мінімальний допустимий JWT повинен містити наступні твердження:

{
  "iss": "https://example.com",   // має збігатися з issuer.url
  "aud": ["my-app"],              // принаймні один з елементів в issuer.audiences повинен збігатися з твердженням "aud" в наданих JWT.
  "exp": 1234567890,              // закінчення терміну дії токена у вигляді часу Unix (кількість секунд, що минули з 1 січня 1970 року UTC)
  "<username-claim>": "user"      // це твердження для імені користувача, налаштоване в claimMappings.username.claim або claimMappings.username.expression
}

Тип селектора JWT egress

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.34 [beta](стандартно увімкнено)

Поле egressSelectorType у конфігурації емітента JWT дозволяє вказати, який селектор egress слід використовувати для надсилання всього трафіку, повʼязаного з емітентом (виявлення, JWKS, розподілені заявки тощо). Для цієї функції необхідно ввімкнути функцію StructuredAuthenticationConfigurationEgressSelector.

Токени OpenID Connect

OpenID Connect — це варіант OAuth2, підтримуваний деякими провайдерами OAuth2, зокрема Microsoft Entra ID, Salesforce та Google. Головне розширення протоколу OAuth2 полягає в додатковому полі, яке повертається разом із токеном доступу, називається ID Token. Цей токен є JSON Web Token (JWT) з добре відомими полями, такими як електронна пошта користувача, підписаними сервером.

Для ідентифікації користувача автентифікатор використовує id_token (а не access_token) з відповіді токена OAuth2 як токен носія. Дивіться вище для того, як токен включається у запит.

Сервер APIkubectlПровайдер ідентичностіКористувачСервер APIkubectlПровайдер ідентичностіКористувач1. Вхід до Провайдера ідентичності2. Надання access_token,id_token та refresh_token3. Виклик kubectlз --token, що є id_tokenАБО додавання токенів до .kube/config4. Authorization: Bearer...5. Чи є підпис JWT дійсним?6. Чи не минув термін дії JWT? (iat+exp)7. Чи авторизований користувач?8. Авторизовано: Виконаннядії та повернення результату9. Повернення результату
  1. Увійдіть до свого провайдера ідентифікації.

  2. Ваш провайдер ідентифікації надасть вам access_token, id_token та refresh_token.

  3. При використанні kubectl використовуйте свій id_token з аргументом командного рядка --token або додайте його безпосередньо до свого kubeconfig.

  4. kubectl надсилає ваш id_token у заголовку Authorization до сервера API.

  5. Сервер API перевіряє, чи є підпис JWT дійсним.

  6. Перевіряє, чи не минув термін дії id_token.

    Виконує перевірку вимог та/або користувача, якщо з AuthenticationConfiguration налаштовані вирази CEL.

  7. Переконується, що користувач авторизований.

  8. Після авторизації сервер API повертає відповідь kubectl.

  9. kubectl надає зворотній звʼязок користувачу.

Оскільки всі дані, необхідні для верифікації вашої особи, містяться в id_token, Kubernetes не потрібно "дзвонити додому" до провайдера ідентичності. У моделі, де кожен запит є stateless, це забезпечує дуже масштабоване рішення для автентифікації. Це має кілька викликів:

  1. Kubernetes не має "вебінтерфейсу" для ініціювання процесу автентифікації. Немає оглядача або інтерфейсу для збору облікових даних, тому вам потрібно спочатку автентифікуватися у свого провайдера ідентичності.
  2. id_token не можна відкликати, він схожий на сертифікат, тому він повинен бути короткостроковим (лише кілька хвилин), що може бути дуже незручним, оскільки потрібно отримувати новий токен кожні кілька хвилин.
  3. Для автентифікації в панелі управління Kubernetes, ви повинні використовувати команду kubectl proxy або зворотний проксі, який вставляє id_token.

Налаштування сервера API

Використання аргументів командного рядка

Щоб увімкнути втулок, налаштуйте наступні аргументи командного рядка на сервері API:

ПараметрОписПрикладОбовʼязковий
--oidc-issuer-urlURL провайдера, який дозволяє серверу API знаходити публічні ключі підпису. Приймаються лише URL-адреси, що використовують схему https://. Це зазвичай URL виявлення провайдера, змінений на порожній шляхЯкщо URL виявлення OIDC провайдера https://accounts.provider.example/.well-known/openid-configuration, значення повинно бути https://accounts.provider.exampleТак
--oidc-client-idІдентифікатор клієнта, для якого мають бути видані всі токени.kubernetesТак
--oidc-username-claimJWT вимога для використання як імені користувача. Стандартно sub, яке очікується що має бути унікальним ідентифікатором кінцевого користувача. Адміністратори можуть вибрати інші вимоги, такі як email або name, залежно від свого провайдера. Однак, вимоги, відмінні від email, будуть мати префікс URL провайдера, щоб уникнути зіткнень назв з іншими втулками.subНі
--oidc-username-prefixПрефікс, доданий до вимог імені користувача, щоб уникнути зіткнень з наявними іменами (наприклад, користувачами system:). Наприклад, значення oidc: створить імена користувачів, такі як oidc:jane.doe. Якщо цей аргумент не вказано, і значення --oidc-username-claim відрізняється від email, стандартний префікс ( Issuer URL )#, де ( Issuer URL ) — це значення --oidc-issuer-url. Значення - можна використовувати для відключення всіх префіксів.oidc:Ні
--oidc-groups-claimJWT вимога для використання як групи користувача. Якщо вимога присутня, вона повинна бути масивом рядків.groupsНі
--oidc-groups-prefixПрефікс, доданий до вимог груп, щоб уникнути зіткнень з наявними назвами (наприклад, групами system:). Наприклад, значення oidc: створить назви груп, такі як oidc:engineering та oidc:infra.oidc:Ні
--oidc-required-claimПара ключ=значення, яка описує обовʼязкову вимогу в ID Token. Якщо встановлено, вимога перевіряється на наявність в ID Token з відповідним значенням. Повторіть цей аргумент, щоб вказати кілька вимог.claim=valueНі
--oidc-ca-fileШлях до сертифіката для ЦС, який підписав вебсертифікат вашого провайдера ідентичності. Стандартно використовується кореневий ЦС хосту./etc/kubernetes/ssl/kc-ca.pemНі
--oidc-signing-algsПрийняті алгоритми підпису. Стандартно RS256. Дозволені значення: RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512. Значення визначаються RFC 7518 https://tools.ietf.org/html/rfc7518#section-3.1.RS512Ні
Налаштування автентифікації з файлу
СТАН ФУНКЦІОНАЛУ: Kubernetes v1.34 [stable](стандартно увімкнено)

Підхід з використанням конфігураційного файлу дозволяє налаштовувати декілька JWT автентифікаторів, кожен з унікальними issuer.url та issuer.discoveryURL. Конфігураційний файл навіть дозволяє використовувати CEL вирази для зіставлення тверджень на атрибути користувача, а також для перевірки тверджень та інформації про користувача. API сервер також автоматично перезавантажує автентифікатори при зміні конфігураційного файлу. Ви можете використовувати метрику apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds для моніторингу часу останнього перезавантаження конфігурації сервером API.

Необхідно вказати шлях до конфігураційного файлу автентифікації використовуючи аргумент командного рядка --authentication-config для сервера API. Якщо ви хочете використовувати аргументи командного рядка замість конфігураційного файлу, вони продовжать працювати як раніше. Щоб отримати нові можливості, такі як налаштування декількох автентифікаторів, встановлення декількох аудиторій для одного видавця, перейдіть на використання конфігураційного файлу.

Для Kubernetes версії v1.35, формат файлу структурованої конфігурації автентифікації є на рівні бета-версії, і механізм використання цієї конфігурації також є на рівні бета-версії. За умови, що ви не вимкнули спеціально функційну можливість StructuredAuthenticationConfiguration для вашого кластера, ви можете увімкнути структуровану автентифікацію, вказавши аргумент командного рядка --authentication-config для kube-apiserver. Приклад файлу конфігурації структурованої автентифікації наведено нижче.

Примітка:

Якщо ви вкажете --authentication-config разом з будь-якими аргументами командного рядка --oidc-*, це є некоректною конфігурацією. У цій ситуації сервер API повідомить про помилку й одразу завершить роботу. Якщо ви хочете перейти на використання структурованої конфігурації автентифікації, вам потрібно видалити аргументи командного рядка --oidc-* і використовувати конфігураційний файл замість них.
---
#
# УВАГА: це приклад конфігурації.
#        Не використовуйте це для вашого кластера!
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
# список автентифікаторів для автентифікації користувачів Kubernetes за допомогою токенів, що відповідають стандарту JWT.
# максимальна кількість дозволених автентифікаторів – 64.
jwt:
- issuer:
    # URL має бути унікальним для всіх автентифікаторів.
    # URL не повинен конфліктувати з видавцем, налаштованим у --service-account-issuer.
    url: https://example.com # Те ж саме, що і --oidc-issuer-url.
    # discoveryURL, якщо вказано, замінює URL, що використовується для отримання інформації про виявлення,
    # замість використання "{url}/.well-known/openid-configuration".
    # Точно вказане значення використовується, тому "/.well-known/openid-configuration"
    # має бути включено у discoveryURL, якщо це потрібно.
    #
    # Поле "issuer" у отриманій інформації про виявлення має збігатися з полем "issuer.url"
    # в AuthenticationConfiguration і буде використовуватися для перевірки твердження "iss" у наданих JWT.
    # Це для сценаріїв, коли точки доступу well-known та jwks розміщені в іншому
    # місці, ніж видавець (наприклад, локально в кластері).
    # discoveryURL має відрізнятися від URL, якщо вказано, і має бути унікальним для всіх автентифікаторів.
    discoveryURL: https://discovery.example.com/.well-known/openid-configuration
    # PEM-кодовані сертифікати CA, які використовуються для перевірки підключення при отриманні
    # інформації про виявлення. Якщо не вказано, буде використовуватися системний перевіряючий.
    # Те саме значення, що і вміст файлу, на який посилається аргумент командного рядка --oidc-ca-file.
    certificateAuthority: <PEM-кодовані сертифікати CA>
    # audiences – це набір прийнятних аудиторій, для яких повинен бути виданий JWT.
    # Принаймні один з елементів повинен збігатися з твердженням "aud" у наданих JWT.
    audiences:
    - my-app # Те ж саме, що і --oidc-client-id.
    - my-other-app
    # це повинно бути встановлено на "MatchAny", коли вказано кілька аудиторій.
    audienceMatchPolicy: MatchAny
    # egressSelectorType є індикатором того, який селектор виходу має використовуватися для надсилання всього трафіку, повʼязаного з
    # цим видавцем (виявлення, JWKS, розподілені твердження тощо). Якщо не вказано, не використовується жоден спеціальний набір.
    # Перед використанням поля egressSelectorType необхідно увімкнути функцію
    # StructuredAuthenticationConfigurationEgressSelector.
    # Коли вказано, допустимі варіанти - "controlplane" і "cluster". Це відповідає асоційованим
    # значенням у --egress-selector-config-file.
    # - controlplane: для трафіку, призначеного для контрольної площини.
    # - cluster: для трафіку, призначеного для системи, що керується Kubernetes.
    egressSelectorType: <egress-selector-type>
  # правила, що застосовуються для перевірки тверджень токена для автентифікації користувачів.
  claimValidationRules:
    # Те ж саме, що і --oidc-required-claim key=value.
  - claim: hd
    requiredValue: example.com
    # Замість claim та requiredValue, ви можете використовувати expression для перевірки твердження.
    # expression – це вираз CEL, який оцінюється до булевого значення.
    # всі вирази повинні бути true для успішної перевірки.
  - expression: 'claims.hd == "example.com"'
    # Повідомлення налаштовує повідомлення про помилку, яке відображається в логах сервера API, коли перевірка не вдається.
    message: вимога hd має бути встановлена на example.com
  - expression: 'claims.exp - claims.nbf <= 86400'
    message: загальний час життя токена не повинен перевищувати 24 години
  claimMappings:
    # username представляє опцію для атрибута імені користувача.
    # Це єдиний обовʼязковий атрибут.
    username:
      # Те ж саме, що і --oidc-username-claim. Взаємовиключно з username.expression.
      claim: "sub"
      # Те ж саме, що і --oidc-username-prefix. Взаємовиключно з username.expression.
      # якщо username.claim встановлено, username.prefix обовʼязково має бути встановлено.
      # Встановіть значення "" явно, якщо префікс не потрібен.
      prefix: ""
      # Взаємовиключно з username.claim і username.prefix.
      # expression – це вираз CEL, який оцінюється як рядок.
      #
      # 1.  Якщо у виразі username.expression використовується 'claims.email', то 'claims.email_verified' має бути використано у
      # username.expression або extra[*].valueExpression або claimValidationRules[*].expression.
      # Приклад виразу правила валідації вимоги, який автоматично збігається з валідацією
      # застосовується, коли username.claim має значення 'email' - 'claims.?email_verified.orValue(true) == true'.
      # Явно порівнюючи значення з true, ми дозволяємо перевірці типів побачити, що результат буде булевим, і
      # щоб переконатися, що небулевий email_verified буде перехоплено під час виконання.
      # 2.  Якщо імʼя користувача, що оцінюється на основі виразу username.expression, є порожнім рядком, запит на автентифікацію
      # запит не буде виконано.
      expression: 'claims.username + ":external-user"'
    # groups представляє опцію для атрибута групи.
    groups:
      # Те ж саме, що і --oidc-groups-claim. Взаємовиключно з groups.expression.
      claim: "sub"
      # Те ж саме, що і --oidc-groups-prefix. Взаємовиключно з groups.expression.
      # якщо groups.claim встановлено, groups.prefix обовʼязково має бути встановлено.
      # Встановіть значення "" явно, якщо префікс не потрібен.
      prefix: ""
      # Взаємовиключно з groups.claim і groups.prefix.
      # expression – це вираз CEL, який оцінюється як рядок або список рядків.
      expression: 'claims.roles.split(",")'
    # uid представляє опцію для атрибута унікального ідентифікатора.
    uid:
      # Взаємовиключно з uid.expression.
      claim: "sub"
      # Взаємовиключно з uid.claim.
      # expression – це вираз CEL, який оцінюється як рядок.
      expression: 'claims.uid'
    # екстра атрибути для додавання до обʼєктв UserInfo. Ключі мають бути у вигляді шляху з префіксом домену та бути унікальними.
    extra:
    - key: "example.com/tenant"
      # valueExpression – це вираз CEL, який оцінюється як рядок або список рядків.
      valueExpression: 'claims.tenant'
    # правила валідації, що застосовуються до фінального обʼєкта користувача.
    userValidationRules:
      #  expression – це вираз CEL, який оцінюється до булевого значення.
      # всі вирази повинні бути true для успішної перевірки.
    - expression: "!user.username.startsWith('system:')"
      # message налаштовує повідомлення про помилку, яке відображається в логах сервера API, коли перевірка не вдається.
      message: 'неможна використовувате це імʼя користувача, зарезервовано префіксом system:'
    - expression: "user.groups.all(group, !group.startsWith('system:'))"
      message: 'неможна використовувате цю назву групи, зарезервовано префіксом system:'
  • Вираз правил валідації твердження (claim)

    jwt.claimValidationRules[i].expression представляє вираз, який буде оцінений CEL. Вирази CEL мають доступ до вмісту корисного навантаження токена, організованого у змінну CEL claims. claims - це карта імен тверджень (як рядків) до значень тверджень (будь-якого типу).

  • Вираз правила валідації користувача

    jwt.userValidationRules[i].expression представляє вираз, який буде оцінений CEL. Вирази CEL мають доступ до вмісту userInfo, організованого у змінну CEL user. Зверніться до UserInfo API документації для отримання схеми user.

  • Вираз зіставлення твердження

    jwt.claimMappings.username.expression, jwt.claimMappings.groups.expression, jwt.claimMappings.uid.expression jwt.claimMappings.extra[i].valueExpression представляє вираз, який буде оцінений CEL. Вирази CEL мають доступ до вмісту корисного навантаження токена, організованого у змінну CEL claims. claims — зіствлення імен тверджень (як рядків) до значень тверджень (будь-якого типу).

    Щоб дізнатися більше, дивіться Документацію по CEL.

    Ось приклади AuthenticationConfiguration з різними корисними навантаженнями токена.

    apiVersion: apiserver.config.k8s.io/v1
    kind: AuthenticationConfiguration
    jwt:
    - issuer:
        url: https://example.com
        audiences:
        - my-app
      claimMappings:
        username:
          expression: 'claims.username + ":external-user"'
        groups:
          expression: 'claims.roles.split(",")'
        uid:
          expression: 'claims.sub'
        extra:
        # key - рядок, який буде використано як додатковий атрибут key.
        # key має бути шляхом з префіксом домену (наприклад, example.org/foo). Всі символи перед першим "/" повинні бути дійсними
        # субдомену, як визначено в RFC 1123. Всі символи після першого "/" повинні
        # бути дійсними символами HTTP-шляху, як визначено в RFC 3986.
        # k8s.io, kubernetes.io та їх субдомени зарезервовані для використання в Kubernetes і не можуть бути використані.
        # ключ має бути рядковим та унікальним для всіх додаткових атрибутів.
        - key: 'example.com/tenant'
          valueExpression: 'claims.tenant'
      userValidationRules:
      - expression: "!user.username.startsWith('system:')" # вибарз буде оцінений як true, тоож валідація пройде успішно.
        message: 'username cannot used reserved system: prefix'
    
    TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6ImY3dF9tOEROWmFTQk1oWGw5QXZTWGhBUC04Y0JmZ0JVbFVpTG5oQkgxdXMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNzAzMjMyOTQ5LCJpYXQiOjE3MDExMDcyMzMsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJqdGkiOiI3YzMzNzk0MjgwN2U3M2NhYTJjMzBjODY4YWMwY2U5MTBiY2UwMmRkY2JmZWJlOGMyM2I4YjVmMjdhZDYyODczIiwibmJmIjoxNzAxMTA3MjMzLCJyb2xlcyI6InVzZXIsYWRtaW4iLCJzdWIiOiJhdXRoIiwidGVuYW50IjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjRhIiwidXNlcm5hbWUiOiJmb28ifQ.TBWF2RkQHm4QQz85AYPcwLxSk-VLvQW-mNDHx7SEOSv9LVwcPYPuPajJpuQn9C_gKq1R94QKSQ5F6UgHMILz8OfmPKmX_00wpwwNVGeevJ79ieX2V-__W56iNR5gJ-i9nn6FYk5pwfVREB0l4HSlpTOmu80gbPWAXY5hLW0ZtcE1JTEEmefORHV2ge8e3jp1xGafNy6LdJWabYuKiw8d7Qga__HxtKB-t0kRMNzLRS7rka_SfQg0dSYektuxhLbiDkqhmRffGlQKXGVzUsuvFw7IGM5ZWnZgEMDzCI357obHeM3tRqpn5WRjtB8oM7JgnCymaJi-P3iCd88iu1xnzA
    

    де корисне навантаження токена:

      {
        "aud": "kubernetes",
        "exp": 1703232949,
        "iat": 1701107233,
        "iss": "https://example.com",
        "jti": "7c337942807e73caa2c30c868ac0ce910bce02ddcbfebe8c23b8b5f27ad62873",
        "nbf": 1701107233,
        "roles": "user,admin",
        "sub": "auth",
        "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a",
        "username": "foo"
      }
    

    Токен із зазначеною вище AuthenticationConfiguration створить наступний об’єкт UserInfo і успішно автентифікує користувача.

    {
        "username": "foo:external-user",
        "uid": "auth",
        "groups": [
            "user",
            "admin"
        ],
        "extra": {
            "example.com/tenant": ["72f988bf-86f1-41af-91ab-2d7cd011db4a"]
        }
    }
    

    apiVersion: apiserver.config.k8s.io/v1
    kind: AuthenticationConfiguration
    jwt:
    - issuer:
        url: https://example.com
        audiences:
        - my-app
      claimValidationRules:
      - expression: 'claims.hd == "example.com"' # маркер нижче не має цього твердження, тому перевірка не вдасться.
        message: the hd claim must be set to example.com
      claimMappings:
        username:
          expression: 'claims.username + ":external-user"'
        groups:
          expression: 'claims.roles.split(",")'
        uid:
          expression: 'claims.sub'
        extra:
        - key: 'example.com/tenant'
          valueExpression: 'claims.tenant'
      userValidationRules:
      - expression: "!user.username.startsWith('system:')" # tвибарз буде оцінений як true, тоож валідація пройде успішно.
        message: 'username cannot used reserved system: prefix'
    
    TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6ImY3dF9tOEROWmFTQk1oWGw5QXZTWGhBUC04Y0JmZ0JVbFVpTG5oQkgxdXMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNzAzMjMyOTQ5LCJpYXQiOjE3MDExMDcyMzMsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJqdGkiOiI3YzMzNzk0MjgwN2U3M2NhYTJjMzBjODY4YWMwY2U5MTBiY2UwMmRkY2JmZWJlOGMyM2I4YjVmMjdhZDYyODczIiwibmJmIjoxNzAxMTA3MjMzLCJyb2xlcyI6InVzZXIsYWRtaW4iLCJzdWIiOiJhdXRoIiwidGVuYW50IjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjRhIiwidXNlcm5hbWUiOiJmb28ifQ.TBWF2RkQHm4QQz85AYPcwLxSk-VLvQW-mNDHx7SEOSv9LVwcPYPuPajJpuQn9C_gKq1R94QKSQ5F6UgHMILz8OfmPKmX_00wpwwNVGeevJ79ieX2V-__W56iNR5gJ-i9nn6FYk5pwfVREB0l4HSlpTOmu80gbPWAXY5hLW0ZtcE1JTEEmefORHV2ge8e3jp1xGafNy6LdJWabYuKiw8d7Qga__HxtKB-t0kRMNzLRS7rka_SfQg0dSYektuxhLbiDkqhmRffGlQKXGVzUsuvFw7IGM5ZWnZgEMDzCI357obHeM3tRqpn5WRjtB8oM7JgnCymaJi-P3iCd88iu1xnzA
    

    де корисне навантаження токена:

      {
        "aud": "kubernetes",
        "exp": 1703232949,
        "iat": 1701107233,
        "iss": "https://example.com",
        "jti": "7c337942807e73caa2c30c868ac0ce910bce02ddcbfebe8c23b8b5f27ad62873",
        "nbf": 1701107233,
        "roles": "user,admin",
        "sub": "auth",
        "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a",
        "username": "foo"
      }
    

    Токен із зазначеною вище AuthenticationConfiguration не зможе автентифікуватись, оскільки твердження hd не має значення example.com. Сервер API поверне помилку 401 Unauthorized.

    apiVersion: apiserver.config.k8s.io/v1
    kind: AuthenticationConfiguration
    jwt:
    - issuer:
        url: https://example.com
        audiences:
        - my-app
      claimValidationRules:
      - expression: 'claims.hd == "example.com"'
        message: the hd claim must be set to example.com
      claimMappings:
        username:
          expression: '"system:" + claims.username' # це призведе до додавання префіксу "system:" до імені користувача і не пройде перевірку.
        groups:
          expression: 'claims.roles.split(",")'
        uid:
          expression: 'claims.sub'
        extra:
        - key: 'example.com/tenant'
          valueExpression: 'claims.tenant'
      userValidationRules:
      - expression: "!user.username.startsWith('system:')" # імʼя користувача буде system:foo, а вираз матиме значення false, тому перевірка не вдасться.
        message: 'username cannot used reserved system: prefix'
    
    TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6ImY3dF9tOEROWmFTQk1oWGw5QXZTWGhBUC04Y0JmZ0JVbFVpTG5oQkgxdXMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNzAzMjMyOTQ5LCJoZCI6ImV4YW1wbGUuY29tIiwiaWF0IjoxNzAxMTEzMTAxLCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwianRpIjoiYjViMDY1MjM3MmNkMjBlMzQ1YjZmZGZmY2RjMjE4MWY0YWZkNmYyNTlhYWI0YjdlMzU4ODEyMzdkMjkyMjBiYyIsIm5iZiI6MTcwMTExMzEwMSwicm9sZXMiOiJ1c2VyLGFkbWluIiwic3ViIjoiYXV0aCIsInRlbmFudCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0YSIsInVzZXJuYW1lIjoiZm9vIn0.FgPJBYLobo9jnbHreooBlvpgEcSPWnKfX6dc0IvdlRB-F0dCcgy91oCJeK_aBk-8zH5AKUXoFTlInfLCkPivMOJqMECA1YTrMUwt_IVqwb116AqihfByUYIIqzMjvUbthtbpIeHQm2fF0HbrUqa_Q0uaYwgy8mD807h7sBcUMjNd215ff_nFIHss-9zegH8GI1d9fiBf-g6zjkR1j987EP748khpQh9IxPjMJbSgG_uH5x80YFuqgEWwq-aYJPQxXX6FatP96a2EAn7wfPpGlPRt0HcBOvq5pCnudgCgfVgiOJiLr_7robQu4T1bis0W75VPEvwWtgFcLnvcQx0JWg
    

    де корисне навантаження токена:

      {
        "aud": "kubernetes",
        "exp": 1703232949,
        "hd": "example.com",
        "iat": 1701113101,
        "iss": "https://example.com",
        "jti": "b5b0652372cd20e345b6fdffcdc2181f4afd6f259aab4b7e35881237d29220bc",
        "nbf": 1701113101,
        "roles": "user,admin",
        "sub": "auth",
        "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a",
        "username": "foo"
      }
    

    Токен із наведеною вище AuthenticationConfiguration створить такий обʼєкт UserInfo:

    {
        "username": "system:foo",
        "uid": "auth",
        "groups": [
            "user",
            "admin"
        ],
        "extra": {
            "example.com/tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a"
        }
    }
    

    який не пройде перевірку користувача, оскільки ім’я користувача починається з system:. Сервер API поверне помилку 401 Unauthorized.

Обмеження
  1. Розподілені твердження не працюють через вирази CEL.

Kubernetes не надає постачальника ідентифікаційних даних OpenID Connect. Ви можете скористатися наявним загальнодоступним постачальником ідентифікаційних даних OpenID Connect або запустити власного постачальника ідентифікаційних даних, який підтримує протокол OpenID Connect.

Для того, щоб провайдер ідентифікації працював з Kubernetes, він повинен:

  1. Підтримувати OpenID Connect discovery

    Публічний ключ для перевірки підпису отримується з публічної точки доступу видавця за допомогою OIDC discovery. Якщо ви використовуєте файл конфігурації автентифікації, провайдер ідентифікації не обовʼязково має публічно відкривати точку доступу discovery. Ви можете розмістити точку доступу discovery в іншому місці, ніж видавець (наприклад, локально в кластері) і вказати issuer.discoveryURL у файлі конфігурації.

  2. Працювати через TLS з не застарілими шифрами

  3. Мати сертифікат, підписаний ЦС (навіть якщо ЦС не комерційний або самопідписний)

Зауваження щодо вимоги #3 вище, яка вимагає сертифікат, підписаний центром сертифікації. Якщо ви розгортаєте власного постачальника посвідчень, ви ПОВИННІ мати сертифікат вебсервера вашого постачальника посвідчень, підписаний сертифікатом з прапорцем CA, встановленим у значення TRUE, навіть якщо він самопідписний. Це повʼязано з тим, що реалізація TLS-клієнта GoLang дуже сувора до стандартів перевірки сертифікатів. Якщо у вас немає під рукою центру сертифікації, ви можете створити простий центр сертифікації і підписану пару з сертифіката і ключа за допомогою стандартних інструментів генерації сертифікатів.

Використання kubectl

Варіант 1 — Автентифікатор OIDC

Перший варіант — використання автентифікатора kubectl oidc, який встановлює id_token як токен на предʼявника для всіх запитів і оновлює токен після закінчення його терміну дії. Після того, як ви увійшли до свого провайдера, використовуйте kubectl, щоб додати ваші id_token, refresh_token, client_id та client_secret для налаштування втулка.

Провайдери, які не повертають id_token як частину відповіді на оновлення токена, не підтримуються цим втулком і повинні використовувати Варіант 2 (вказуючи --token).

kubectl config set-credentials USER_NAME \
   --auth-provider=oidc \
   --auth-provider-arg=idp-issuer-url=( issuer url ) \
   --auth-provider-arg=client-id=( your client id ) \
   --auth-provider-arg=client-secret=( your client secret ) \
   --auth-provider-arg=refresh-token=( your refresh token ) \
   --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
   --auth-provider-arg=id-token=( your id_token )

Як приклад, запустіть наведену нижче команду після автентифікації у постачальника ідентифікаційної інформації:

kubectl config set-credentials mmosley  \
        --auth-provider=oidc  \
        --auth-provider-arg=idp-issuer-url=https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP  \
        --auth-provider-arg=client-id=kubernetes  \
        --auth-provider-arg=client-secret=1db158f6-177d-4d9c-8a8b-d36869918ec5  \
        --auth-provider-arg=refresh-token=q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXqHega4GAXlF+ma+vmYpFcHe5eZR+slBFpZKtQA= \
        --auth-provider-arg=idp-certificate-authority=/root/ca.pem \
        --auth-provider-arg=id-token=eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knw

Що створить наведену нижче конфігурацію:

users:
- name: mmosley
  user:
    auth-provider:
      config:
        client-id: kubernetes
        client-secret: 1db158f6-177d-4d9c-8a8b-d36869918ec5
        id-token: eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knw
        idp-certificate-authority: /root/ca.pem
        idp-issuer-url: https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP
        refresh-token: q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXq
      name: oidc

Після закінчення терміну дії вашого id_token kubectl спробує оновити ваш id_token за допомогою ваших refresh_token і client_secret, зберігаючи нові значення для refresh_token і id_token у вашому .kube/config.

Варіант 2 — Використання аргумента командного рядка --token

Команда kubectl дозволяє передати токен за допомогою аргумента командного рядка --token. Скопіюйте та вставте id_token у цей параметр:

kubectl --token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL21sYi50cmVtb2xvLmxhbjo4MDQzL2F1dGgvaWRwL29pZGMiLCJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNDc0NTk2NjY5LCJqdGkiOiI2RDUzNXoxUEpFNjJOR3QxaWVyYm9RIiwiaWF0IjoxNDc0NTk2MzY5LCJuYmYiOjE0NzQ1OTYyNDksInN1YiI6Im13aW5kdSIsInVzZXJfcm9sZSI6WyJ1c2VycyIsIm5ldy1uYW1lc3BhY2Utdmlld2VyIl0sImVtYWlsIjoibXdpbmR1QG5vbW9yZWplZGkuY29tIn0.f2As579n9VNoaKzoF-dOQGmXkFKf1FMyNV0-va_B63jn-_n9LGSCca_6IVMP8pO-Zb4KvRqGyTP0r3HkHxYy5c81AnIh8ijarruczl-TK_yF5akjSTHFZD-0gRzlevBDiH8Q79NAr-ky0P4iIXS8lY9Vnjch5MF74Zx0c3alKJHJUnnpjIACByfF2SCaYzbWFMUNat-K1PaUk5-ujMBG7yYnr95xD-63n8CO8teGUAAEMx6zRjzfhnhbzX-ajwZLGwGUBT4WqjMs70-6a7_8gZmLZb2az1cZynkFRj2BaCkVT3A2RrjeEwZEtGXlMqKJ1_I2ulrOVsYx01_yD35-rw get nodes

Автентифікація за допомогою вебхука

Вебхук автентивікації Kubernetes — є механізмом який здійснює виклик HTTP для перевірки токенів на предʼявника.

Щодо налаштування API-сервера:

  • --authentication-token-webhook-config-file — файл конфігурації, який описує, як отримати доступ до віддаленого сервісу вебхука.
  • --authentication-token-webhook-cache-ttl — як довго кешувати рішення щодо автентифікації. Стандартно дві хвилини.
  • --authentication-token-webhook-version визначає, чи використовувати authentication.k8s.io/v1beta1 або authentication.k8s.io/v1 обʼєкти TokenReview для надсилання/отримання інформації від вебхука. Стандартно v1beta1.

Файл конфігурації використовує формат файлу kubeconfig. У файлі clusters посилається на віддалений сервіс, а users посилається на вебхук API-сервера. Приклад:

# Версія API Kubernetes
apiVersion: v1
# Тип обʼєкта API
kind: Config
# clusters посилається на віддалений сервіс.
clusters:
  - name: name-of-remote-authn-service
    cluster:
      certificate-authority: /path/to/ca.pem         # ЦС для перевірки віддаленого сервісу.
      server: https://authn.example.com/authenticate # URL віддаленого сервісу для запиту. 'https' рекомендовано для промислового застосування.

# users посилається на конфігурацію вебхука API-сервера.
users:
  - name: name-of-api-server
    user:
      client-certificate: /path/to/cert.pem # сертифікат для використання втулком вебхука
      client-key: /path/to/key.pem          # ключ, що відповідає сертифікату

# файли kubeconfig потребують контексту. Надати один для API-сервера.
current-context: webhook
contexts:
- context:
    cluster: name-of-remote-authn-service
    user: name-of-api-server
  name: webhook

Коли клієнт намагається автентифікуватись на API-сервері за допомогою токена на предʼявника, як розглядалось вище, вебхук автентифікації надсилає POST-запит з JSON-серіалізованим обʼєктом TokenReview, що містить токен для віддаленого сервісу.

Зверніть увагу, що обʼєкти API вебхука підпадають під ті ж правила сумісності версій, що й інші обʼєкти API Kubernetes. Виконавці повинні перевірити поле apiVersion запиту, щоб забезпечити правильну десеріалізацію, і повинні відповідати обʼєктом TokenReview тієї ж версії, що й запит.

Примітка:

API-сервер Kubernetes типово надсилає запити authentication.k8s.io/v1beta1 для зворотної сумісності. Щоб отримувати запити authentication.k8s.io/v1, API-сервер повинен бути запущений з параметром --authentication-token-webhook-version=v1.
{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "TokenReview",
  "spec": {
    # Непрозорий токен на прежʼявника носія, надісланий на API-сервер
    "token": "014fbff9a07c...",

    # Необовʼязковий список ідентифікаторів аудиторії для сервера, якому був представлений токен.
    # Автентифікатори токенів, що враховують аудиторію (наприклад, OIDC автентифікатори токенів)
    # повинні перевірити, що токен був призначений для принаймні однієї з аудиторій у цьому списку,
    # і повернути перетин цього списку та дійсних аудиторій для токена в статусі відповіді.
    # Це гарантує, що токен дійсний для автентифікації на сервері, якому він був представлений.
    # Якщо аудиторії не надані, токен повинен бути перевірений для автентифікації на API-сервері Kubernetes.
    "audiences": ["https://myserver.example.com", "https://myserver.internal.example.com"]
  }
}

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "spec": {
    # Непрозорий токен на предʼявника, надісланий на API-сервер
    "token": "014fbff9a07c...",

    # Необовʼязковий список ідентифікаторів аудиторії для сервера, якому був представлений токен.
    # Автентифікатори токенів, що враховують аудиторію (наприклад, OIDC автентифікатори токенів)
    # повинні перевірити, що токен був призначений для принаймні однієї з аудиторій у цьому списку,
    # і повернути перетин цього списку та дійсних аудиторій для токена в статусі відповіді.
    # Це гарантує, що токен дійсний для автентифікації на сервері, якому він був представлений.
    # Якщо аудиторії не надані, токен повинен бути перевірений для автентифікації на API-сервері Kubernetes.
    "audiences": ["https://myserver.example.com", "https://myserver.internal.example.com"]
  }
}

Віддалений сервіс повинен заповнити поле status запиту, щоб вказати на успішність входу. Поле spec тіла відповіді ігнорується та може бути опущене. Віддалений сервіс повинен повернути відповідь, використовуючи ту ж версію API TokenReview, яку він отримав. Успішна перевірка маркера носія буде виглядати так:

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      # Обовʼязково
      "username": "janedoe@example.com",
      # Необовʼязково
      "uid": "42",
      # Необовʼязкові членства у групах
      "groups": ["developers", "qa"],
      # Необовʼязкова додаткова інформація, надана автентифікатором.
      # Це не повинно містити конфіденційних даних, оскільки це може бути записано в логах
      # або обʼєктах API та доступно для вебхуків допуску.
      "extra": {
        "extrafield1": [
          "extravalue1",
          "extravalue2"
        ]
      }
    },
    # Необовʼязковий список, який можуть повернути автентифікатори токенів, що враховують аудиторію,
    # містить аудиторії зі списку `spec.audiences`, для яких токен був дійсним.
    # Якщо це опущено, токен вважається дійсним для автентифікації на API-сервері Kubernetes.
    "audiences": ["https://myserver.example.com"]
  }
}

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      # Обовʼязково
      "username": "janedoe@example.com",
      # Необовʼязково
      "uid": "42",
      # Необовʼязкові членства у групах
      "groups": ["developers", "qa"],
      # Необовʼязкова додаткова інформація, надана автентифікатором.
      # Це не повинно містити конфіденційних даних, оскільки це може бути записано в логах
      # або обʼєктах API та доступно для вебхуків допуску.
      "extra": {
        "extrafield1": [
          "extravalue1",
          "extravalue2"
        ]
      }
    },
    # Необовʼязковий список, який можуть повернути автентифікатори токенів, що враховують аудиторію,
    # містить аудиторії зі списку `spec.audiences`, для яких токен був дійсним.
    # Якщо це опущено, токен вважається дійсним для автентифікації на API-сервері Kubernetes.
    "audiences": ["https://myserver.example.com"]
  }
}

Невдала спроба запиту виглядатиме так:

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "TokenReview",
  "status": {
    "authenticated": false,
    # Необовʼязково включати деталі, чому автентифікація не вдалася.
    # Якщо помилка не вказана, API поверне загальне повідомлення Unauthorized.
    # Поле error ігнорується, коли authenticated=true.
    "error": "Credentials are expired"
  }
}

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": false,
    # Необовʼязково включати деталі, чому автентифікація не вдалася.
    # Якщо помилка не вказана, API поверне загальне повідомлення Unauthorized.
    # Поле error ігнорується, коли authenticated=true.
    "error": "Credentials are expired"
  }
}

Автентифікація зворотного проксі-сервера

Попередження:

Якщо у вас є центр сертифікації (CA), який також використовується в іншому контексті, не довіряйте цьому центру сертифікації для ідентифікації проксі-клієнтів, що проходять автентифікацію, якщо ви не розумієте ризики та механізми захисту використання цього CA.

API-сервер може бути налаштований для ідентифікації користувачів на основі значень заголовків запиту, таких як X-Remote-User. Цей механізм призначений для використання в комбінації з проксі-сервером автентифікації, який встановлює значення заголовка запиту.

Використання зворотного проксі-сервера автентифікації відрізняється від імітації користувача. При імітації користувача один користувач надсилає запит до сервера API, щоб той розглядав цей запит як такий, що надсилається іншим користувачем. При використанні зворотного проксі-сервера автентифікації сервер API довіряє своєму прямому клієнту, який надає інформацію про особу, що надсилає оригінальний запит.

Дивіться конфігурацію заголовка веб-запиту, щоб дізнатися про конфігурацію цього за допомогою аргументів командного рядка.

Приклад

Наприклад, з цією конфігурацією:

--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-

цей запит:

GET / HTTP/1.1
X-Remote-User: fido
X-Remote-Group: dogs
X-Remote-Group: dachshunds
X-Remote-Extra-Acme.com%2Fproject: some-project
X-Remote-Extra-Scopes: openid
X-Remote-Extra-Scopes: profile

призведе до такої інформації про користувача:

name: fido
groups:
- dogs
- dachshunds
extra:
  acme.com/project:
  - some-project
  scopes:
  - openid
  - profile

Сертифікат клієнта

Для запобігання підробці заголовків, проксі-сервер автентифікації повинен представити дійсний клієнтський сертифікат на API-сервер для перевірки за допомогою вказаного CA перед тим, як заголовки запиту будуть перевірені.

Дивіться довідку про опцію командного рядка для режиму автентифікації заголовка запиту.

Не використовуйте CA, який використовується в іншому контексті, якщо ви не розумієте ризики та механізми захисту використання CA.

Інтеграція статичного файлу токенів

Сервер API зчитує статичні токени на предʼявника з файлу, якщо в командному рядку вказано опцію --token-auth-file=<SOMEFILE>. У Kubernetes 1.35 токени діють необмежений час, і список токенів не можна змінити без перезапуску сервера API.

Файл токенів — це CSV-файл, що містить щонайменше 3 стовпці: токен, імʼя користувача, ідентифікатор користувача, а також список опціональних імен груп, розділених комами.

Примітка:

Якщо у вас більше однієї групи, стовпець повинен бути у подвійних лапках, наприклад:

token,user,uid,"group1,group2,group3"

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

Якщо ви використовуєте цей метод під час створення кластера, а потім переходите на інший метод автентифікації, який буде використовуватися в довгостроковій перспективі, вам слід деактивувати токен, який використовувався для завантаження (для цього потрібно перезапустити кожен API-сервер).

В інших випадках, особливо коли важлива дуже швидка ротація токенів, проєкт Kubernetes рекомендує використовувати автентифікатор токенів webhook замість цього механізму.

Імперсонізація користувачів

Імперсонізація користувача надає метод, за допомогою якого користувач може діяти від імені іншого користувача через заголовки імперсонізації.

Конфігурація автентифікації

Ви можете налаштувати автентифікацію Kubernetes за допомогою аргументів командного рядка або файлу конфігурації.

Зазвичай використовується поєднання цих підходів.

Конфігурація за допомогою аргументів командного рядка

Ви можете використовувати наступні аргументи командного рядка, щоб налаштувати спосіб автентифікації клієнтів панеллю управління вашого кластера.

У довідці командного рядка для API-сервера більш детально описані всі відповідні аргументи командного рядка.

Конфігурація анонімної автентифікації

--anonymous-auth
Контролює, чи можуть клієнти, які не пройшли автентифікацію, надсилати запити через захищений порт API-сервера. Анонімні запити мають імʼя користувача system:anonymous та імʼя групи system:unauthenticated. Див. також анонімні запити.

Конфігурація токенів Bootstrap

--enable-bootstrap-token-auth
Якщо встановлено цей прапорець, для автентифікації можна використовувати токени Bootstrap.

Конфігурація автентифікації сертифікатів

--client-ca-file
Шлях до довірених анкерів для перевірки ідентичності клієнта, коли клієнти використовують автентифікацію сертифікатів X.509.

Конфігурація OIDC

--oidc-ca-file
Шлях до довірчих анкерів для перевірки ідентичності клієнта, коли клієнти використовують OIDC.
--oidc-client-id
Ідентифікатор клієнта для клієнта OpenID Connect.
--oidc-username-claim
Імʼя заявки JWT для вказання імені користувача. Заявка, яка використовується як імʼя користувача. Імʼя заявки у стандартному варіанті — sub, оскільки це має бути унікальний ідентифікатор кінцевого користувача. Ви можете вибрати інші заявки, наприклад email або name. Для заявок, відмінних від sub або email, kube-apiserver додає префікс до імені групи (щоб уникнути конфліктів імен).
--oidc-username-prefix
Префікс, що додається до заявки на імʼя користувача, щоб запобігти конфліктам з наявними іменами (такими як system: користувачі). Наприклад, значення oidc: створить імена користувачів, такі як oidc:jane.doe. Якщо цей аргумент не вказано, а --oidc-username-claim має значення, відмінне від email, префікс приймає стандартне значення ( Issuer URL )#, де ( Issuer URL ) — це значення --oidc-issuer-url. Ви можете вказати значення префікса як -, щоб вимкнути додавання префікса до імені користувача.
--oidc-groups-claim
Імʼя власного запиту OpenID Connect для визначення груп користувачів. Запит у токені повинен бути масивом рядків. Немає стандартного значення.
--oidc-groups-prefix
Префікс, що додається до запитів груп, щоб запобігти конфліктам з наявними іменами (такими як групи system:). Наприклад, значення oidc: створить імена груп, такі як oidc:engineering та oidc:infra. Префікс за замовчуванням — oidc:
--oidc-issuer-url
URL-адреса емітента OpenID. Схема URL-адреси повинна бути https. Якщо URL-адреса виявлення OIDC емітента — https://accounts.provider.example/.well-known/openid-configuration, значення має бути https://accounts.provider.example.
--oidc-required-claim
Заява, яка повинна бути присутня в токені, перш ніж Kubernetes автентифікує клієнта. Формат — key=value. Цей аргумент можна вказати більше ніж один раз.
--oidc-signing-algs
Прийнятні алгоритми підпису. Допустимі значення: RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512. Значення визначені в RFC 7518. Стандартно — RS512.

Конфігурація ServiceAccount

--api-audiences
Визначає аудиторію автентифікації для токенів службового облікового запису.
--service-account-extend-token-expiration
Цей прапорець увімкне передбачуване подовження терміну дії службового облікового запису під час генерації токена, що сприяє безпечному переходу від старих токенів до функції привʼязаних токенів службового облікового запису. Див. автентифікація службових облікових даних.
--service-account-issuer
Ідентифікатор емітента токена службового облікового запису. Емітент підтверджує цей ідентифікатор у запиті iss кожного виданого токена. Kubernetes рекомендує використовувати тут URL-адресу зі схемою, встановленою на https.
--service-account-jwks-uri
Перезаписує URI для JSON Web Key Set у документі виявлення, який обслуговується за адресою /.well-known/openid-configuration
--service-account-key-file
Шлях до файлу, що містить PEM-кодовані відкриті або закриті ключі X.509 (RSA або ECDSA), які використовуються для перевірки токенів ServiceAccount. Зазначений файл може містити кілька ключів, і ви можете вказати аргумент кілька разів з різними шляхами.
--service-account-lookup
Якщо true, сервер API перевіряє наявність токенів ServiceAccount в etcd як частину автентифікації.
--service-account-max-token-expiration
Максимальний термін дії токена, створеного емітентом токенів службового облікового запису, у вигляді рядка тривалості Kubernetes.
--service-account-signing-endpoint
Шлях до сокета, на якому прослуховує зовнішній підписувач JWT. Ви можете використовувати це для інтеграції із зовнішнім підписувачем токенів.
--service-account-signing-key-file
Шлях до файлу, що містить поточний приватний ключ емітента токенів службового облікового запису. Зміни, внесені до цього файлу під час роботи API-сервера, не перечитуються.

Конфігурація статичних токенів

--token-auth-file
Шлях до файлу конфігурації для статичних токенів на предʼявника. Зміни, внесені до цього файлу під час роботи API-сервера, не перечитуються.

Конфігурація автентифікації веб-хука

--authentication-token-webhook-cache-ttl
Як довго (у вигляді специфікації тривалості Kubernetes) сервер API повинен зберігати в кеші результати HTTP-викликів для перевірки токенів.
--authentication-token-webhook-config-file
Шлях до конфігурації клієнта у форматі kubeconfig, яка визначає, як API-сервер автентифікується під час виконання HTTP-викликів. Зміни, внесені до цього файлу під час роботи API-сервера, не перечитуються.
--authentication-token-webhook-version
Версія API TokenReview, яка використовується під час виконання HTTP-викликів для перевірки токенів.

Web request authentication configuration

Увага:

Перед тим, як вказати ці аргументи командного рядка, слід прочитати документацію про налаштування [проксі-сервера автентифікації] (#authenticating-proxy), оскільки там міститься важлива інформація щодо безпеки, якої необхідно дотримуватися.
--requestheader-client-ca-file
Обовʼязково. Шлях до пакета сертифікатів у форматі PEM, що містить довірені анкери для перевірки автентичності ідентичності проксі-сервера. Перед перевіркою заголовків запиту на наявність імен користувачів необхідно предʼявити дійсний сертифікат клієнта і перевірити його на відповідність вимогам центрів сертифікації, зазначених у вказаному файлі.
--requestheader-allowed-names
Необовʼязково. Розділений комами список значень загальних імен (CN). Якщо встановлено, перед перевіркою заголовків запиту на наявність імен користувачів необхідно предʼявити дійсний сертифікат клієнта із CN у вказаному списку. Якщо поле порожнє, допускаються будь-які CN.
--requestheader-username-headers
Обовʼязково; нечутливий до регістру. Імена заголовків, які слід перевірити, в зазначеному порядку, для ідентифікації користувача. Перший заголовок, що містить значення, використовується як ім'я користувача.
--requestheader-group-headers
Необов'язково; нечутливий до регістру. Імена заголовків, які слід перевірити, в зазначеному порядку, для груп користувача. Рекомендується використовувати X-Remote-Group. Усі значення у всіх зазначених заголовках використовуються як імена груп.
--requestheader-extra-headers-prefix
Необовʼязково; не чутливий до регістру. Префікси заголовків, які слід шукати для визначення додаткової інформації про користувача. Рекомендується використовувати X-Remote-Extra-. Додаткові дані зазвичай використовуються налаштованими втулками авторизації. Усі заголовки, що починаються з будь-якого із зазначених префіксів, мають префікс видалений. Решта імені заголовка перетворюється на нижній регістр і декодується у процентному форматі і стає додатковим ключем, а значення заголовка є додатковим значенням.

Конфігурація за допомогою файлу конфігурації

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.34 [stable](стандартно увімкнено)

Коли ви вказуєте аргумент командного рядка --authentication-config для kube-apiserver, API-сервер завантажує файл за вказаним вами шляхом і використовує вміст цього файлу для налаштування автентифікації.

Вміст цього файлу можна змінювати під час роботи API-сервера, і в цьому випадку API-сервер повторно зчитує файл.

Примітка:

Зміни до цього файлу повинні вноситися атомарним способом (наприклад: запис у тимчасовий файл партнера, а потім перейменування тимчасового файлу для заміни цього файлу).

Шлях до файлу конфігурації

--authentication-config
Цей спеціальний аргумент командного рядка вказує, що ви хочете налаштувати автентифікацію за допомогою файлу конфігурації.

Приклад

Ось приклад файлу конфігурації (структурованої) автентифікації Kubernetes:

---
#
# УВАГА: це приклад конфігурації.
#        Перевірте та виправте її перед використанням у власному кластері!
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
anonymous:
  enabled: false

Втулки облікових даних client-go

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.22 [stable]

k8s.io/client-go та інструменти, які використовують його, такі як kubectl та kubelet, можуть виконувати зовнішню команду для отримання облікових даних користувача.

Ця функція призначена для клієнтських інтеграцій з протоколами автентифікації, які не підтримуються на рівні k8s.io/client-go (LDAP, Kerberos, OAuth2, SAML та ін.). Вутулок реалізує логіку, специфічну для протоколу, а потім повертає непрозорі облікові дані для використання. Майже всі випадки використання втулків автентифікації потребують наявності компоненту на стороні сервера з підтримкою автентифікації токенів webhook, щоб інтерпретувати формат облікових даних, який генерується клієнтським втулком.

Примітка:

У попередніх версіях kubectl вбудовано підтримувалися автентифікація в AKS та GKE, але це більше не актуально.

Приклад використання

У гіпотетичному сценарії використання організація запускає зовнішню службу, яка обмінює облікові дані LDAP на підписані токени, специфічні для користувача. Служба також може відповідати на запити автентифікатора токенів webhook, щоб перевірити токени. Користувачам буде потрібно встановити втулок автентифікації на своїй робочій станції.

Для автентифікації в API:

  • Користувач видає команду kubectl.
  • Вутулок облікових даних запитує користувача облікові дані LDAP, обмінює облікові дані зовнішньою службою на токен.
  • Вутулок облікових даних повертає токен client-go, який використовує його як токен власника на сервері API.
  • Сервер API використовує автентифікатор токенів webhook, щоб надіслати TokenReview зовнішній службі.
  • Зовнішня служба перевіряє підпис на токені та повертає імʼя користувача та групи.

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

Втулки облікових даних налаштовуються через файли конфігурації kubectl як частина полів користувача.

apiVersion: v1
kind: Config
users:
- name: my-user
  user:
    exec:
      # Команда для виконання. Обовʼязково.
      command: "example-client-go-exec-plugin"

      # Версія API, яку слід використовувати при декодуванні ресурсу ExecCredentials. Обовʼязково.
      #
      # Версія API, що повертається втулком, ПОВИННА відповідати версії, вказаній тут.
      #
      # Щоб інтегруватися з інструментами, які підтримують кілька версій (наприклад, client.authentication.k8s.io/v1beta1),
      # встановіть змінну середовища, передайте аргумент інструменту, що вказує, яку версію очікує втулка виконання,
      # або прочитайте версію з обʼєкта ExecCredential у змінній середовища KUBERNETES_EXEC_INFO.
      apiVersion: "client.authentication.k8s.io/v1"

      # Змінні середовища, що встановлюються під час виконання втулку. Необовʼязково.
      env:
      - name: "FOO"
        value: "bar"

      # Аргументи, які передаються під час виконання втулку. Необовʼязково.
      args:
      - "arg1"
      - "arg2"

      # Текст, який показуєтсья користувачу, коли виконуваний файл не знайдено. Необовʼязково.
      installHint: |
        example-client-go-exec-plugin потрібно для автентифікації
        в поточному кластері.  Його можна встановити:

        На macOS: brew install example-client-go-exec-plugin

        На Ubuntu: apt-get install example-client-go-exec-plugin

        На Fedora: dnf install example-client-go-exec-plugin

        ...

      # Чи надавати інформацію про кластер, яка може містити
      # дуже великі дані сертифікату CA, цьому втулка виконання як частину KUBERNETES_EXEC_INFO
      # змінної середовища.
      provideClusterInfo: true

      # Угода між втулком виконання та стандартним введенням/виведенням. Якщо
      # угода не може бути виконана, цей втулок виконання не буде запущено, та буде
      # повернено помилку. Допустимі значення: "Never" (цей втулок виконання ніколи не використовує стандартний ввід),
      # "IfAvailable" (цей втулок виконання хоче використовувати стандартний ввід, якщо він доступний),
      # або "Always" (цей втулок виконання вимагає стандартний ввід для роботи). Обовʼязково.
      interactiveMode: Never
clusters:
- name: my-cluster
  cluster:
    server: "https://172.17.4.100:6443"
    certificate-authority: "/etc/kubernetes/ca.pem"
    extensions:
    - name: client.authentication.k8s.io/exec # зарезервоване імʼя розширення для кожної конфігурації виконання кластера
      extension:
        arbitrary: config
        this: може бути надано через змінну середовища KUBERNETES_EXEC_INFO при встановленні provideClusterInfo
        you: ["можете", "покласти", "будь-що", "тут"]
contexts:
- name: my-cluster
  context:
    cluster: my-cluster
    user: my-user
current-context: my-cluster

apiVersion: v1
kind: Config
users:
- name: my-user
  user:
    exec:
      # Команда для виконання. Обовʼязково.
      command: "example-client-go-exec-plugin"

      # Версія API, яку слід використовувати при декодуванні ресурсу ExecCredentials. Обовʼязково.
      #
      # Версія API, повернута втулком, ПОВИННА відповідати версії, вказаній тут.
      #
      # Щоб інтегруватися з інструментами, які підтримують кілька версій (наприклад, client.authentication.k8s.io/v1),
      # встановіть змінну середовища, перед ```yaml
      apiVersion: "client.authentication.k8s.io/v1beta1"

      # Змінні середовища, що встановлюються під час виконання втулку. Необовʼязково.
      env:
      - name: "FOO"
        value: "bar"

      # Аргументи, які передаються під час виконання втулку. Необовʼязково.
      args:
      - "arg1"
      - "arg2"

      # Текст, який показується користувачу, коли виконуваний файл не знайдено. Необовʼязково.
      installHint: |
        example-client-go-exec-plugin потрібно для автентифікації
        в поточному кластері.  Його можна встановити:

        На macOS: brew install example-client-go-exec-plugin

        На Ubuntu: apt-get install example-client-go-exec-plugin

        На Fedora: dnf install example-client-go-exec-plugin

        ...

      # Чи надавати інформацію про кластер, яка може містити
      # дуже великі дані сертифікату CA, цьому втулку виконання як частину KUBERNETES_EXEC_INFO
      # змінної середовища.
      provideClusterInfo: true

      # Угода між втулком виконання та стандартним введенням/виведенням. Якщо
      # угода не може бути виконана, цей втулок виконання не буде запущено, а буде
      # повернено помилку. Допустимі значення: "Never" (цей втулок виконання ніколи не використовує стандартний ввід),
      # "IfAvailable" (цей втулок виконання хоче використовувати стандартний ввід, якщо він доступний),
      # або "Always" (цей втулок виконання вимагає стандартний ввід для роботи). Необовʼязково.
      # Стандартно - "IfAvailable".
      interactiveMode: Never
clusters:
- name: my-cluster
  cluster:
    server: "https://172.17.4.100:6443"
    certificate-authority: "/etc/kubernetes/ca.pem"
    extensions:
    - name: client.authentication.k8s.io/exec # зарезервоване імʼя розширення для кожної конфігурації виконання кластера
      extension:
        arbitrary: config
        this: може бути надано через змінну середовища KUBERNETES_EXEC_INFO при встановленні provideClusterInfo
        you: ["можете", "покласти", "будь-що", "тут"]
contexts:
- name: my-cluster
  context:
    cluster: my-cluster
    user: my-user
current-context: my-cluster

Відносні шляхи до команд інтерпретуються відносно теки файлу конфігурації. Якщо KUBECONFIG встановлено на /home/jane/kubeconfig, а команда виконання — ./bin/example-client-go-exec-plugin, то виконується бінарний файл /home/jane/bin/example-client-go-exec-plugin.

- name: my-user
  user:
    exec:
      # Шлях відносно теки kubeconfig
      command: "./bin/example-client-go-exec-plugin"
      apiVersion: "client.authentication.k8s.io/v1"
      interactiveMode: Never

Формати вводу та виводу

Виконана команда виводить обʼєкт ExecCredential у stdout. k8s.io/client-go автентифікується в Kubernetes API, використовуючи отримані облікові дані в status. Виконана команда отримує обʼєкт ExecCredential на вхід через змінну середовища KUBERNETES_EXEC_INFO. Цей вхід містить корисну інформацію, таку як очікувана версія API поверненого обʼєкта ExecCredential та чи може втулок використовувати stdin для взаємодії з користувачем.

Під час запуску з інтерактивної сесії (тобто термінал), stdin може бути наданий прямо втулку. Втулки повинні використовувати поле spec.interactive вхідного обʼєкта ExecCredential зі змінної середовища KUBERNETES_EXEC_INFO для визначення, чи був наданий stdin. Вимоги втулка до stdin (тобто чи stdin є необовʼязковим, строго обовʼязковим або ніколи не використовується для успішного запуску втулка) вказується за допомогою поля user.exec.interactiveMode у kubeconfig (див. таблицю нижче для дійсних значень). Поле user.exec.interactiveMode є необовʼязковим у client.authentication.k8s.io/v1beta1 і обовʼязковим у client.authentication.k8s.io/v1.

Значення interactiveMode
Значення interactiveModeЗначення
NeverЦей втулок виконання ніколи не потребує використання стандартного вводу, і тому втулок виконання буде запущений незалежно від того, чи доступний стандартний ввід для введення користувача.
IfAvailableЦей втулок виконання хоче використовувати стандартний ввід, якщо він доступний, але може працювати, якщо стандартний ввід недоступний. Тому втулок виконання буде запущений незалежно від наявності введення з стандартного вводу. Якщо стандартний ввід доступний для введення користувача, він буде наданий цьому втулку виконання.
AlwaysЦей втулок виконання потребує стандартний ввід для роботи, і тому втулок виконання буде запущений лише тоді, коли стандартний ввід доступний для введення користувача. Якщо стандартний ввід недоступний для введення користувача, втулок виконання не буде запущений, і виконавець втулку поверне помилку.

Для використання облікових даних токена власника, втулок повертає токен у статусі ExecCredential

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token"
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token"
  }
}

Альтративно, можна повернути PEM-кодований сертифікат клієнта та ключ для використання TLS-автентифікації клієнта. Якщо втулок повертає різний сертифікат та ключ при наступному виклику, k8s.io/client-go закриє існуючі зʼєднання з сервером, щоб змусити новий TLS-обмін.

Якщо вказано, що clientKeyData та clientCertificateData повинні бути присутніми.

clientCertificateData може містити додаткові проміжні сертифікати для відправки на сервер.

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "status": {
    "clientCertificateData": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "clientKeyData": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "status": {
    "clientCertificateData": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "clientKeyData": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
  }
}

Додатково відповідь може включати термін дії облікового запису, форматований як RFC 3339 мітка часу.

Наявність або відсутність терміну дії має такий вплив:

  • Якщо термін дії включений, токен власника та TLS-облікові дані кешуються до моменту закінчення строку дії, або якщо сервер відповідає з кодом стану HTTP 401, або при завершенні процесу.
  • Якщо термін дії відсутній, токен власника та TLS-облікові дані кешуються до моменту, коли сервер відповідає з кодом стану HTTP 401 або до моменту завершення процесу.

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token",
    "expirationTimestamp": "2018-03-05T17:30:20-08:00"
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token",
    "expirationTimestamp": "2018-03-05T17:30:20-08:00"
  }
}

Щоб дозволити втулку виконання отримувати інформацію, що специфічна для кластера, встановіть provideClusterInfo у поле user.exec в kubeconfig. Втулок потім отримає цю інформацію, специфічну для кластера, у змінній середовища KUBERNETES_EXEC_INFO. Інформацію з цієї змінної середовища можна використовувати для виконання логіки отримання облікових даних, специфічних для кластера. Наступний маніфест ExecCredential описує зразок інформації для кластера.

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "spec": {
    "cluster": {
      "server": "https://172.17.4.100:6443",
      "certificate-authority-data": "LS0t...",
      "config": {
        "arbitrary": "config",
        "this": "can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo",
        "you": ["can", "put", "anything here"]
    },
    "interactive": true
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "spec": {
    "cluster": {
      "server": "https://172.17.4.100:6443",
      "certificate-authority-data": "LS0t...",
      "config": {
        "arbitrary": "config",
        "this": "can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo",
        "you": ["can", "put", "anything", "here"]
      }
    },
    "interactive": true
  }
}

Доступ API до інформації про автентифікацію для клієнта

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.28 [stable]

Ви можете використовувати API SelfSubjectReview, щоб дізнатися, як ваш кластер Kubernetes показує вашу інформацію про автентифікацію, щоб ідентифікувати вас як клієнта. Це працює незалежно від того, чи автентифікуєтеся ви як користувач (зазвичай представляючи реальну особу), чи як обліковий запис ServiceAccount.

У типовому кластері Kubernetes усі автентифіковані користувачі можуть створювати SelfSubjectReviews. Доступ до цього надається вбудованою роллю system:basic-user ClusterRole.

Можливість клієнта дізнатися свою власну ідентичність є надзвичайно корисною під час усунення несправностей у складному потоці автентифікації, який використовується в кластері Kubernetes; наприклад, якщо ви використовуєте [автентифікацію за допомогою токена веб-хука](/docs/reference/access-authn-authz/authentication/# webhook-token-authentication) або [проксі-сервер автентифікації] (/docs/reference/access-authn-authz/authentication/#authenticating-proxy).

Якщо ви хочете запитати це в командному рядку, див. [Доступ CLI до інформації про автентифікацію] (#self-subject-review-cli).

HTTP-доступ до інформації про автентифікацію

SelfSubjectReviews не має полів, які можна налаштувати. Отримавши запит, сервер API Kubernetes заповнює статус атрибутами користувача і повертає його користувачеві. Це не зберігає іменований ресурс у вашому кластері: ви не можете отримати SelfSubjectReview, і він видаляється після завершення вашого запиту POST.

Приклад запиту (тіло буде SelfSubjectReview):

POST /apis/authentication.k8s.io/v1/selfsubjectreviews
{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview"
}

Приклад відповіді:

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview",
  "status": {
    "userInfo": {
      "username": "janedoe@example.com",
      "groups": [
        "viewers",
        "editors",
        "system:authenticated"
      ]
    }
  }
}

Примітка:

Сервер API Kubernetes заповнює userInfo після застосування всіх механізмів автентифікації, включаючи імперсонацію. Якщо ви або проксі-сервер автентифікації виконуєте SelfSubjectReview з використанням імперсонації, ви бачите деталі та властивості користувача, від імені якого було виконано автентифікацію.

У цьому прикладі відповіді не показано всі доступні поля; не всі механізми автентифікації заповнюють кожне доступне поле. Дивіться довідку про API SelfSubjectReview, щоб дізнатися, які поля доступні.

Ось ще один приклад, який також містить поля uid та extra:

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview",
  "status": {
    "userInfo": {
      "username": "janedoe@example.com",
      "groups": [
        "viewers",
        "editors",
        "system:authenticated"
      ],
      "uid": "000042",
      "extra": {
        "firstName": [
          "Jane"
        ],
        "familyName": [
          "Doe"
        ],
        "projectAssignments": [
          "web-frontend",
          "ai-training-proof-of-concept"
        ],
      }
    }
  }
}

Дані в цих опціональних полях походять з вашої інтеграції автентифікації або з бази даних користувачів, яку вона використовує. Імʼя користувача, UID, додаткова інформація та всі групи з іменами, що не починаються з system:, походять з джерел поза Kubernetes.

Під час запиту до API Kubernetes через HTTP ви можете вимагати відповідь у форматі JSON або YAML, використовуючи заголовок HTTP Accept:, наприклад:

POST /apis/authentication.k8s.io/v1/selfsubjectreviews HTTP/1.1
Accept: application/json;q=1.0
Content-Type: application/json
…інші заголовки запиту

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview"
}

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview",
  "status": {
    "userInfo": {
      "username": "jane.doe",
      "uid": "b79dbf30-0c6a-11ed-861d-0242ac120002",
      "groups": [
        "students",
        "teachers",
        "system:authenticated"
      ],
      "extra": {
        "skills": [
          "reading",
          "learning"
        ],
        "subjects": [
          "math",
          "sports"
        ]
      }
    }
  }
}

POST /apis/authentication.k8s.io/v1/selfsubjectreviews HTTP/1.1
Accept: application/yaml;q=1.0
Content-Type: application/json
…інші заголовки запиту

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview"
}

apiVersion: authentication.k8s.io/v1
kind: SelfSubjectReview
status:
  userInfo:
    username: jane.doe
    uid: b79dbf30-0c6a-11ed-861d-0242ac120002
    groups:
    - students
    - teachers
    - system:authenticated
    extra:
      skills:
      - reading
      - learning
      subjects:
      - math
      - sports

Доступ CLI до інформації про автентифікацію

Для зручності також доступна команда kubectl auth whoami:

kubectl auth whoami

Результат буде схожим на:

  ATTRIBUTE         VALUE
  Username          george.boole
  Groups            [system:authenticated]

Дивіться kubectl auth whoami для отримання додаткової інформації.

Що далі