Защита доступа к Kubernetes с помощью RBAC

KubernetesBeginner
Практиковаться сейчас

Введение

Аутентификация Kubernetes определяет, кто выполняет запрос, а авторизация — какие действия разрешены этой сущности. RBAC описывает разрешения как глаголы для API-ресурсов и связывает их с пользователями, группами или ServiceAccount.

Вы создадите читателя с ограниченной областью действия в пространстве имён, свяжете его идентичность с разрешениями, а затем с помощью имперсонации проверите как разрешённые, так и запрещённые действия.

RBAC проще понимать через три вопроса: Кто? (ServiceAccount), Что ему разрешено делать? (Role) и Кто получает эти разрешения? (RoleBinding). Создание только одного или двух из этих объектов не завершает цепочку авторизации.

Создание идентичности ServiceAccount

На этом шаге создайте ServiceAccount с областью действия в пространстве имён для компонента приложения.

ServiceAccount — это идентичность Kubernetes API, предназначенная для рабочих нагрузок и автоматизации. Это не пользователь Linux внутри контейнера. Выделенная идентичность позволяет этому примеру не наследовать ServiceAccount default пространства имён.

cd /home/labex/project/rbac-access
kubectl create serviceaccount inventory-reader -n practice-rbac
kubectl get serviceaccount inventory-reader -n practice-rbac -o yaml

Полная идентичность имеет вид system:serviceaccount:practice-rbac:inventory-reader. Само по себе создание идентичности не предоставляет никаких разрешений приложения.

В выводе YAML метаданные подтверждают пространство имён и имя. Не ожидайте, что автоматически появится долгоживущий Secret с токеном: современные версии Kubernetes при необходимости проецируют краткоживущие токены в Pod.

Возвращаемый объект содержит выделенные имя и пространство имён, но не автоматически созданный Secret с токеном:

kind: ServiceAccount
metadata:
  name: inventory-reader
  namespace: practice-rbac

Определение разрешений в пределах пространства имён

На этом шаге создайте Role, разрешающую чтение Pod и ConfigMap только в practice-rbac.

Каждое правило объединяет группы API, ресурсы и глаголы. Для основных ресурсов, таких как Pod и ConfigMap, apiGroups: [""] указывает пустую строку. Глаголы get, list и watch обозначают чтение отдельных объектов, чтение коллекций и отслеживание изменений.

cd /home/labex/project/rbac-access
cat <<'EOF' > inventory-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: {name: inventory-reader, namespace: practice-rbac}
rules:
  - apiGroups: [""]
    resources: [pods, configmaps]
    verbs: [get, list, watch]
EOF

Примените Role и выведите её описание. Команда describe представляет правила политики в виде таблицы, которую удобнее проверять, чем исходный YAML:

kubectl apply -f inventory-role.yaml
kubectl describe role inventory-reader -n practice-rbac

Пустая группа API выбирает основные ресурсы. Role никогда не предоставляет доступ за пределами своего пространства имён.

Также обратите внимание на отсутствующие разрешения: здесь нет create, update, patch или delete. Принцип минимальных привилегий определяется не только выданными, но и намеренно не выданными разрешениями.

Resources   Non-Resource URLs  Resource Names  Verbs
---------   -----------------  --------------  -----
configmaps  []                 []              [get list watch]
pods        []                 []              [get list watch]

Таблица разворачивает общее правило YAML в отдельную строку для каждого ресурса. В обеих строках указаны одинаковые три глагола, разрешающие только чтение.

Связывание Role с идентичностью

На этом шаге свяжите Role с ServiceAccount с помощью RoleBinding.

Императивная команда получается компактной, поскольку оба объекта уже существуют. Параметр --role указывает источник разрешений, а --serviceaccount использует формат namespace:name для идентификации субъекта.

cd /home/labex/project/rbac-access
kubectl create rolebinding inventory-reader -n practice-rbac --role=inventory-reader --serviceaccount=practice-rbac:inventory-reader
kubectl get rolebinding inventory-reader -n practice-rbac -o yaml

roleRef указывает разрешения, а subjects — идентичности, которые их получают. В данном случае обе стороны остаются ограниченными пространством имён.

Role и ServiceAccount с одинаковым именем всё равно не связаны, пока не создано это сопоставление. Имена предназначены для удобства людей, а RoleBinding является фактическим соединением авторизации.

В YAML проследите связь от roleRef.name: inventory-reader к субъекту, у которого kind имеет значение ServiceAccount, имя — inventory-reader, а пространство имён — practice-rbac.

Проверка разрешённых и запрещённых действий

На этом шаге используйте kubectl auth can-i с параметром --as, чтобы выполнить имперсонацию ServiceAccount.

Для проверки авторизации нужны как положительные, так и отрицательные сценарии. Ответ yes подтверждает возможность выполнять необходимые действия, а no показывает, что разрушительные операции и доступ из другого пространства имён случайно не разрешены.

cd /home/labex/project/rbac-access
IDENTITY=system:serviceaccount:practice-rbac:inventory-reader
kubectl auth can-i list pods -n practice-rbac --as="$IDENTITY"
kubectl auth can-i get configmaps -n practice-rbac --as="$IDENTITY"
kubectl auth can-i delete pods -n practice-rbac --as="$IDENTITY" || true
kubectl auth can-i list pods -n default --as="$IDENTITY" || true

Первые два ответа должны быть yes, а удаление и чтение списка из другого пространства имён должны вернуть no. Имперсонация позволяет проверить авторизацию, не раскрывая и не создавая токен.

kubectl auth can-i возвращает ненулевой код завершения оболочке вместе с ответом no. Два суффикса || true позволяют продолжить выполнение намеренно отклонённых проверок; они не изменяют решение авторизации.

yes
yes
no
no

Интерпретируйте эти результаты как две необходимые возможности и две защищённые границы. Набор тестов, содержащий только ответы yes, не подтвердил бы соблюдение принципа минимальных привилегий.

Текущий пользователь лаборатории имеет право выполнять имперсонацию этого ServiceAccount для тестирования. Параметр --as изменяет идентичность, которую API-сервер проверяет для данной команды; он не меняет пользователя оболочки и не переключает учётные данные kubectl навсегда.

Итоги

Вы создали ServiceAccount, описали разрешения только для чтения в пространстве имён с помощью Role, назначили их через RoleBinding и с помощью имперсонации подтвердили как разрешённые, так и запрещённые действия.