Перейти к содержанию

Настройка доступа к Kubernetes

Пошагово: что сделать в кластере, что в админке и что на рабочей машине сотрудника. Что это за функция и почему сертификатов два — в обзоре раздела.

Порядок здесь не произвольный. Сначала кластер учат доверять Alatyr, потом сервер Alatyr учат выдавать credential, и только потом это получает сотрудник: на каждом шаге есть, что проверить, а обратный порядок оставляет вас с сертификатом, который негде предъявить.

Половина работы — не наша, и это намеренно

Шаги 1 и 2 меняют то, как ваш API-сервер аутентифицирует всех пользователей. Alatyr их не автоматизирует и автоматизировать не будет: такое решение не принимают за вас.

Шаг 1. Научите кластер доверять цепочке Alatyr

API-сервер должен знать корень, которым подписаны сертификаты Alatyr, — иначе он не пустит никого.

Сначала возьмите саму цепочку. Она лежит в PKI-бэкенде, в той точке монтирования, которая обслуживает цель k8s (в поставляемой конфигурации это pki_k8s, см. «Встроенный УЦ»):

# <mount> — точка монтирования издателя цели k8s, обычно pki_k8s
curl -s "$VAULT_ADDR/v1/<mount>/ca_chain" > alatyr-ca-chain.pem

# Запасной путь для установки с одним самоподписанным корнем,
# где цепочка не настроена:
[ -s alatyr-ca-chain.pem ] || curl -s "$VAULT_ADDR/v1/<mount>/ca/pem" > alatyr-ca-chain.pem

Берите ca_chain, а не один сертификат

Корень в боевой раскладке ничего не выписывает — под ним стоят промежуточные УЦ, по одному на цель. Поэтому /ca/pem вернёт вам один промежуточный, и связка, названная «корневой CA», будет содержать ровно не ту половину. Такая ошибка уже стоила времени в соседнем сценарии 802.1X: неполная цепочка читается как недоверие к УЦ, хотя причина совсем другая. ca_chain содержит и промежуточный, и корень, поэтому ошибиться половиной в нём нельзя.

Потом положите её в клиентский CA API-сервера:

kube-apiserver --client-ca-file=/etc/kubernetes/pki/alatyr-ca-chain.pem

Способ передать флаг зависит от того, чем поднят кластер: у k3s это --kube-apiserver-arg; у управляемых кластеров (EKS, GKE, AKS) эта настройка часто недоступна вовсе — проверьте это до того, как пообещаете доступ пользователям. Чтобы флаг подействовал, API-сервер нужно перезапустить.

Результат. Сертификат Alatyr теперь аутентифицируется в вашем кластере. Прав у такого пользователя пока нет никаких — это правильный порядок, права даёт следующий шаг.

Шаг 2. Привяжите RBAC к субъекту сертификата

Kubernetes берёт Subject CN сертификата как имя пользователя. Alatyr кладёт туда идентичность сотрудника (почта или UPN), поэтому привязка идёт на пользователя:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alice-dev-read
  namespace: dev
subjects:
  - kind: User
    name: alice@corp.local        # ровно тот CN, который выдал Alatyr
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

Привязывайте самую узкую роль, которая решает задачу, и по пространствам имён. Привязка cluster-admin на сертификат, отзыв которого кластер не проверяет, — худшее из доступных здесь сочетаний.

kind: Group здесь не сработает

Kubernetes берёт группы из Subject O, а Alatyr это поле не заполняет. Привязывайте пользователей. Это осознанное решение, а не недоделка — подробнее в «Нюансах и пределах».

Результат. В кластере есть привязка на имя сотрудника. Проверить её можно будет на шаге 7, когда у сотрудника появится доступ.

Шаг 3. Включите брокер на сервере Alatyr

Брокер — то, что превращает аппаратную идентичность сотрудника в десятиминутный сертификат. У него свой слушатель, отдельный от основного: этот порт запрашивает клиентский сертификат, а основной сервер обычно стоит за обратным прокси, который TLS терминирует, — до него сертификат сотрудника просто не доходит.

Четыре переменные окружения на сервере:

Переменная Что это
ALATYR_K8S_BROKER_LISTEN адрес слушателя брокера, например :8443
ALATYR_K8S_BROKER_TLS_CERT PEM-файл серверного сертификата брокера
ALATYR_K8S_BROKER_TLS_KEY PEM-файл приватного ключа брокера
ALATYR_K8S_BROKER_URL адрес брокера глазами устройства, например https://alatyr.corp:8443

Пустой ALATYR_K8S_BROKER_LISTEN означает «брокера нет», и это штатное состояние для установки без Kubernetes. Адрес без пары ключ/сертификат — отказ при старте, намеренно: «брокер включён» и «брокер не умеет TLS» не должны выглядеть одинаково.

ALATYR_K8S_BROKER_URL нужен отдельно от ..._LISTEN: слушатель живёт на своём порту, и устройство не может его угадать. Этот адрес уезжает агенту тем же опросом, что и назначенные цели, — и только тем устройствам, которым цель k8s назначена.

Настройте сдвиг NotBefore у роли PKI. Десятиминутный сертификат, у которого «не действует до» равно ровно «сейчас», не работает на машине, часы которой отстают хотя бы немного, — и отказ придёт от кластера, словами «сертификат ещё не действителен», то есть не укажет ни на часы, ни на Alatyr. Vault принимает это только на уровне роли:

vault write pki_k8s/roles/k8s not_before_duration=5m …

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

Результат. В журнале сервера при старте есть строка о поднятом слушателе брокера, и порт отвечает.

Убедитесь, что цель k8s направлена в свой издатель

Какая цель куда ходит за подписью — запись в базе, а не переменная окружения. Откройте Настройки → Удостоверяющие центры и проверьте, что у строки Kubernetes (kubectl) стоит статус «Настроен». Без этого заявки уедут в vault_failed. Таблица соответствия целей и точек монтирования — во «Встроенном УЦ».

Шаг 4. Заведите кластеры в реестре

Сертификат не отвечает на вопрос, куда ходить и какому CA доверять. Отвечает реестр: список держит сервер, а kubeconfig по нему пишет агент на устройстве. Без этого шага сотруднику пришлось бы подбирать адрес и имя для SNI руками — ровно та боль, ради которой раздел и существует.

Откройте Кластеры Kubernetes в левом меню и нажмите «Добавить кластер»:

Поле Что вписать
Имя короткое имя, например prod. Оно станет именем контекста в kubectl, поэтому двух одинаковых быть не может
Адрес API-сервера только https — по этому адресу поедет клиентский сертификат сотрудника
Имя для SNI заполнять, только если имя в сертификате кластера не совпадает с адресом. Пусто — совпадает
CA-бандл (PEM) сертификат УЦ самого кластера, целиком, как есть. Ссылкой на файл заменить нельзя
Выдавать устройствам появляется при изменении: выключенный кластер устройствам не уезжает

Пустой реестр — это не «настройка по умолчанию», а отсутствие доступа

Пока в реестре нет ни одного кластера, устройствам не поедет ни один. Пустой список здесь читается как «ничего не положено», а не как «ещё не заполнили». Админка говорит это отдельной плашкой ровно потому, что обратное прочтение напрашивается.

Кластеры уезжают только на устройства, которым назначена цель k8s: список несёт адреса и CA внутренних кластеров, то есть карту инфраструктуры.

Результат. Кластер виден в списке со статусом «Выдаётся: да».

Шаг 5. Разрешите выдачу и назначьте цель устройству

Доступ не появляется у сотрудника сам: сначала выдачу разрешает администратор.

  1. Откройте Настройки → Политика выдачи и включите строку «Kubernetes (kubectl)» в колонке «Выдаём». У каждой цели здесь свой переключатель: включать «mTLS пользователя» или любую другую цель ради Kubernetes не требуется. Если выдача включается не для всего парка машин, а точечно — откройте Устройства, раскройте строку нужной машины и в блоке «Цели на этой машине» у строки k8s переключите «как в системе» на «разрешить сверх системного».
  2. Там же, в раскрытой строке машины, отметьте цель k8s. Цель — это то, что Alatyr выдаёт на устройство; цель k8s означает доступ к кластерам. Назначение цели и разрешение её выдавать — разные действия, нужны оба.

Результат. Через несколько минут агент на машине сотрудника создаст ключ в чипе и подаст заявку.

Шаг 6. Одобрите заявку

Откройте раздел Запросы в левом меню. Заявка появится в статусе pending. Раскройте её: в карточке написано прямым текстом, какое именно устройство какой сертификат и для чьей личности запрашивает — там должно стоять «Kubernetes» и почта того самого сотрудника. Убедитесь в этом и одобрите заявку.

Одобрение здесь — человеческое действие и остаётся им: заявка несёт идентичность сотрудника, и сервисный аккаунт с ролью cert-auto-approver её одобрить не может.

Результат. Заявка в статусе installed, у устройства появилась идентичность k8s. Это основание — сертификат, который предъявляется только Alatyr. Кластер его никогда не увидит.

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

Шаг 7. Проверьте на рабочей машине

На машине сотрудника — где стоит агент Alatyr и работает kubectl.

Сначала убедитесь, что идентичность на месте:

alatyr-agent k8s self-test

Команда открывает ключ цели k8s и выданный на него сертификат и печатает k8s-identity: OK, субъект, серийный номер и срок. Если она отвечает, что идентичности нет, — возвращайтесь к шагам 5 и 6.

Затем попросите агента написать kubeconfig:

alatyr-agent k8s kubeconfig

Вывод выглядит так:

kubeconfig записан: /home/ivan/.kube/alatyr.config
кластеров: 2
Ваш ~/.kube/config НЕ тронут. Объединить:
  export KUBECONFIG=/home/ivan/.kube/alatyr.config:$HOME/.kube/config

Файл Alatyr пишет свой (~/.kube/alatyr.config, либо $XDG_CONFIG_HOME/alatyr/kubeconfig, если переменная задана) и ваш ~/.kube/config не трогает: там свои кластеры сотрудника. Объединяются они штатным способом, который kubectl поддерживает сам:

export KUBECONFIG=$HOME/.kube/alatyr.config:$HOME/.kube/config

Никакого файла сертификата и файла ключа в этом kubeconfig нет и быть не может — там стоит вызов агента, и сертификат появляется на десять минут в памяти.

Теперь проверьте обе половины разом:

kubectl auth whoami          # ожидается тот CN, который выдал Alatyr
kubectl auth can-i list pods -n dev

Результат. kubectl auth whoami печатает имя сотрудника, а can-i отвечает по вашей привязке RBAC из шага 2.

Не останавливайтесь на «сертификат выдан» — это половина, которую видит Alatyr. Проверять надо ту, которую он не видит.

Шаг 8. Решите, спрашивать ли человека при выдаче

Ступень настраивается в Настройки → Безопасность по умолчанию, блок «Подтверждение при выдаче доступа к кластеру»:

Значение Что происходит
Не спрашивать выдача идёт молча
Спросить раз в окно первая выдача за окно показывает вопрос с именем кластера и запрашивающей программы, дальше внутри окна — молча. Окно задаётся тут же, умолчание — 15 минут
Спрашивать каждый раз вопрос на каждую выдачу

Умолчание — «Спросить раз в окно», и это отличает данную ступень от соседних: поднятая ступень здесь никому не отказывает, а показывает человеку окно.

Проверьте это до раздачи доступа на macOS

На хосте, где спросить человека негде, поднятая ступень отказывает в выдаче, а не выдаёт молча. Два таких случая встречаются на практике:

  • macOS — спрашивать при выдаче credential там пока нечем вовсе;
  • любая машина без графического сеанса — сервер, терминал по SSH.

Молчаливая выдача при ступени, заказанной как «спрашивать», была бы ровно той поломкой, ради предотвращения которой ступень заводят. Что ступень закрывает, а что нет — в «Нюансах и пределах».

Результат. На вкладке Обзор в настройках видно текущее значение ступени и его последствие.


Если доступ не работает

Проверяйте по порядку: сверху — самые частые причины. Почти все они называют себя сами — плагин Alatyr пишет, какая именно проверка отказала, чтобы это не превращалось в расследование на стороне кластера.

kubectl сообщает, что плагин отказал, и в тексте есть no broker address has reached this device. В этом развёртывании выдача credential не настроена: не задан ALATYR_K8S_BROKER_URL (шаг 3) либо устройству не назначена цель k8s (шаг 5).

В тексте есть no clusters are registered for this device. Реестр ответил пустым списком. Это ответ, а не отсутствующая настройка: либо в реестре нет ни одного включённого кластера (шаг 4), либо устройству не назначена цель.

Плагин называет кластер, которого «нет», и перечисляет доступные. Имя в --cluster не совпадает с именем в реестре. Правильное имя взять больше неоткуда, поэтому плагин его и печатает.

kubectl auth whoami не проходит, а сертификат выглядит действительным. Почти всегда это пропущенный шаг 1 или неперезапущенный API-сервер.

Кластер говорит, что сертификат «истёк или ещё не действует», а выдан он секунды назад. Это часы устройства, а не ваш кластер. Проверьте синхронизацию времени на машине сотрудника. Alatyr отказывает в таком случае раньше кластера и называет величину расхождения — текст начинается с this host's clock differs from the server by. Чинится это на устройстве; ни настройки кластера, ни настройки Alatyr к этому отношения не имеют.

Выдача отказывается со ссылкой на подтверждение человеком. Поднята ступень из шага 8, а спросить на этой машине нечем: macOS или хост без графического сеанса.

В stderr появляется «долгоживущий агент недоступен — окно тишины не действует». Подтверждение живёт в памяти постоянно работающего агента. Если агент не запущен, вопрос задаётся на каждый вызов kubectl — это честная деградация, и она названа вслух.

Что дальше