Настройка доступа к 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. Разрешите выдачу и назначьте цель устройству¶
Доступ не появляется у сотрудника сам: сначала выдачу разрешает администратор.
- Откройте Настройки → Политика выдачи и включите строку «Kubernetes
(kubectl)» в колонке «Выдаём». У каждой цели здесь свой
переключатель: включать «mTLS пользователя» или любую другую цель ради
Kubernetes не требуется. Если выдача включается не для всего парка машин,
а точечно — откройте Устройства, раскройте строку нужной машины и в
блоке «Цели на этой машине» у строки
k8sпереключите «как в системе» на «разрешить сверх системного». - Там же, в раскрытой строке машины, отметьте цель
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 — это честная
деградация, и она названа вслух.
Что дальше¶
- Два режима доставки — чем отличается локальный прокси от плагина и когда он нужен.
- Нюансы и пределы — чего механизм не обещает, включая то, как на самом деле работает отзыв.