Главная » Хабрахабр » [Перевод] Понимаем RBAC в Kubernetes

[Перевод] Понимаем RBAC в Kubernetes

Прим. перев.: Статья написана Javier Salmeron — инженером из хорошо известной в Kubernetes-сообществе компании Bitnami — и была опубликована в блоге CNCF в начале августа. Автор рассказывает о самых основах механизма RBAC (управление доступом на основе ролей), появившегося в Kubernetes полтора года назад. Материал будет особенно полезным для тех, кто знакомится с устройством ключевых компонентов K8s (ссылки на другие подобные статьи см. в конце).

6
Слайд из презентации, сделанной сотрудником Google по случаю релиза Kubernetes 1.

6, когда авторизация на основе Role-Based Access Control (RBAC) получила статус бета-версии. Многие опытные пользователи Kubernetes могут вспомнить релиз Kubernetes 1. Все с восторгом приветствовали новую фичу, однако в то же время бесчисленное число пользователей были разочарованы. Так появился альтернативный механизм аутентификации, который дополнил уже существующий, но трудный в управлении и понимании, — Attribute-Based Access Control (ABAC). Эталонным примером стал Helm: простой запуск helm init + helm install больше не работал. StackOverflow и GitHub изобиловали сообщениями об ограничениях RBAC, потому что большая часть документации и примеров не учитывали RBAC (но сейчас уже всё в порядке). в инструкции). Внезапно нам потребовалось добавлять «странные» элементы вроде ServiceAccounts или RoleBindings ещё до того, как разворачивать чарт с WordPress или Redis (подробнее об этом см.

Многие из нас успели поиграть с Kubernetes с полными привилегиями администратора, и мы прекрасно понимаем, что в реальном окружении необходимо: Оставив же эти неудачные первые попытки в стороне, нельзя отрицать тот огромный вклад, что внёс RBAC в превращение Kubernetes в готовую к production платформу.

  • Иметь множество пользователей с разными свойствами, обеспечивающими нужный механизм аутентификации.
  • Иметь полный контроль над тем, какие операции может исполнять каждый пользователь или группа пользователей.
  • Иметь полный контроль над тем, какие операции может исполнять каждый процесс в поде.
  • Ограничивать видимость определённых ресурсов в пространствах имён.

И в этом отношении RBAC — ключевой элемент, предоставляющий столь необходимые возможности. В статье мы быстро пройдёмся по основам (для подробностей смотрите это видео; по ссылке 1-часовой вебинар от Bitnami на английском языке — прим. перев.) и немного углубимся в самые запутанные моменты.

Ключ к пониманию RBAC в Kubernetes

Чтобы полностью осознать идею RBAC, нужно понимать, что к ней причастны три элемента:

  • Subjects (субъекты) — совокупность пользователей и процессов, которые хотят иметь доступ в Kubernetes API;
  • Resources (ресурсы) — совокупность объектов Kubernetes API, доступных в кластере. Их примерами (среди прочих) являются Pods, Deployments, Services, Nodes, PersistentVolumes;
  • Verbs (глаголы) — совокупность операций, которые могут быть выполнены над ресурсами. Существуют различные verbs (get, watch, create, delete и т.п.), но все они в конечном счёте являются операциями из разряда CRUD (Create, Read, Update, Delete).

Если помнить об этих трёх элементах, ключевая идея RBAC звучит так:

Другими словами, мы хотим указать для заданного пользователя, какие операции могут быть исполнены на множестве ресурсов. — Мы хотим соединить субъекты, ресурсы API и операции.

Разбираемся с объектами RBAC в API

В соединении этих трёх типов сущностей становятся понятными и доступные в Kubernetes API объекты RBAC:

  • Roles соединяют ресурсы и глаголы. Они могут повторно использоваться для разных субъектов. Привязаны к одному пространству имён (мы не можем использовать шаблоны, представляющие более одного [пространства имён], зато можем деплоить один и тот же объект роли в разные пространства имён). Если вы хотите применить роль ко всему кластеру, есть аналогичный объект ClusterRoles.
  • RoleBindings соединяют оставшиеся сущности-субъекты. Указав роль, которая уже связывает объекты API с глаголами, теперь мы выбираем субъекты, которые могут их использовать. Эквивалентом для уровня кластера (т.е. без привязки к пространствам имён) является ClusterRoleBindings.

В примере ниже мы выдаём пользователю jsalmeron право на чтение, получение списка и создание подов в пространстве имён test. Это означает, что jsalmeron сможет выполнять такие команды:

kubectl get pods --namespace test
kubectl describe pod --namespace test pod-name
kubectl create --namespace test -f pod.yaml # в этом файле описание пода

… но не такие:

kubectl get pods --namespace kube-system # другое пространство имён
kubectl get pods --namespace test -w # требует также глагола watch

Примеры YAML-файлов:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: name: pod-read-create namespace: test
rules:
- apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "create"]

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata: name: salme-pods namespace: test
subjects:
- kind: User name: jsalmeron apiGroup: rbac.authorization.k8s.io
roleRef: Role kind: Role name: ns-admin apiGroup: rbac.authorization.k8s.io

Другой интересный момент в следующем: теперь, когда пользователь может создавать поды, можем ли мы ограничить, как много? Для этого потребуются другие объекты, не относящиеся напрямую к спецификации RBAC и позволяющие настраивать ограничения по количеству ресурсов: ResourceQuota и LimitRanges. Их определённо стоит изучить при конфигурации столь важной составляющей кластера [как создание подов].

Субъекты: пользователи и… ServiceAccounts?

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

  • Users — глобальные пользователи, предназначены для людей или процессов, живущих вне кластера;
  • ServiceAccounts — ограниченные пространством имён и предназначенные для процессов внутри кластера, запущенных на подах.

Сходство обоих типов заключается в необходимости аутентифицироваться в API для исполнения определённых операций над множеством ресурсов, и их предметные области выглядят весьма конкретными. Они также могут относиться к группам, поэтому RoleBinding позволяет привязывать более одного субъекта (хотя для ServiceAccounts допустима лишь одна группа — system:serviceaccounts). Тем не менее, основное отличие и есть причина головной боли: у пользователей нет соответствующих им объектов в Kubernetes API. Получается, что такая операция существует:

kubectl create serviceaccount test-service-account # OK

… но вот такой уже нет:

kubectl create user jsalmeron # Ошибка!

У этой ситуации серьёзное последствие: если кластер не будет хранить информацию о пользователях, администратору придётся управлять учётными записями вне кластера. Здесь есть разные способы решения проблемы: TLS-сертификаты, токены, OAuth2 и т.п.

Чтобы создать файлы с ними, можно воспользоваться командами kubectl config (что не требуют доступа к Kubernetes API, поэтому могут исполняться любым пользователем). Вдобавок, потребуется создать контексты kubectl, чтобы мы могли получить доступ к кластеру через эти новые учётные записи. В приведённом выше видео есть пример по созданию пользователя с TLS-сертификатами.

RBAC в Deployments: пример

Мы видели пример, в котором указанному пользователю выдаются права на операции в кластере. Но что насчёт Deployments, требующих доступа к Kubernetes API? Рассмотрим конкретный сценарий, чтобы разобраться получше.

Будем использовать Helm-чарт для RabbitMQ от Bitnami (из официального репозитория helm/charts), который использует контейнер bitnami/rabbitmq. Возьмём для примера популярное инфраструктурное приложение — RabbitMQ. Из-за этого процесс внутри контейнера требует доступа к Kubernetes API, и нам потребуется настроить ServiceAccount с правильными RBAC-привилегиями. В контейнер встроен плагин для Kubernetes, отвечающий за обнаружение других членов кластера RabbitMQ.

Когда речь заходит о ServiceAccounts, следуйте этой хорошей практике:

— Настраивайте ServiceAccounts для каждого Deployment с минимальным набором привилегий.

Хотя это кажется более простым решением, в конечном счёте оно может привести к уязвимости в безопасности, позволяющей выполнять нежелательные операции. В случае приложений, требующих доступа к Kubernetes API, у вас может возникнуть соблазн создать некий «привилегированный ServiceAccount», который сможет делать в кластере практически всё. (В видео рассматривается пример Tiller [компонента Helm] и последствий наличия ServiceAccounts с большими привилегиями.)

Вдобавок, у разных Deployments будут разные потребности в смысле доступа к API, поэтому для каждого Deployment разумно иметь разные ServiceAccounts.

Не забывая об этом, посмотрим, какая конфигурация RBAC будет правильной для случая Deployment'а с RabbitMQ.

Так и происходит обнаружение остальных членов кластера RabbitMQ. В документации плагина и его исходном коде можно увидеть, что он запрашивает у Kubernetes API список Endpoints. Поэтому чарт RabbitMQ от Bitnami создаёт:

  • ServiceAccount для подов с RabbitMQ:

    }
    apiVersion: v1
    kind: ServiceAccount
    metadata: name: {{ template "rabbitmq.fullname" . }} labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}"
    {{- end }}

  • Role (мы предполагаем, что весь кластер RabbitMQ разворачивается в едином пространстве имён), разрешающую глагол get для ресурса Endpoint:

    {{- if .Values.rbacEnabled }}
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}"
    rules:
    - apiGroups: [""] resources: ["endpoints"] verbs: ["get"] {{- end }}

  • RoleBinding, соединяющую ServiceAccount с ролью:

    {{- if .Values.rbacEnabled }}
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}"
    subjects:
    - kind: ServiceAccount name: {{ template "rabbitmq.fullname" . }}
    roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: {{ template "rabbitmq.fullname" . }}-endpoint-reader
    {{- end }}

Это минимальный набор операций, который требуется для того, чтобы всё работало. Схема показывает, что мы разрешили процессам, запущенным в подах RabbitMQ, исполнять операции get над объектами Endpoint. В то же время мы знаем, что развёрнутый чарт безопасен и не выполнит нежелательных действий внутри кластера Kubernetes.

Заключительные мысли

Чтобы работать с Kubernetes в production, политики RBAC не являются опциональными. Их нельзя рассматривать как набор объектов API, который должны знать только администраторы. Они на самом деле нужны разработчикам для развёртывания безопасных приложений и полного использования потенциала, предлагаемого Kubernetes API для облачных (cloud native) приложений. Больше информации по RBAC можно получить по этим ссылкам:

P.S. от переводчика

Читайте также в нашем блоге:


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Как открыть ИП в Германии, если ты программист, и не набить шишек

В последние недели Берлин — популярная тема на Хабре. Не случайно — в Германии много возможностей для работы в ИТ с комфортным переездом. Но бюрократия она и в Африке бюрократия, а если встают вопросы об индивидуальном предпринимательстве за рубежом — ...

4 октября, Москва — Backend Stories 2.0

В четверг, 4 октября, на площадке Deworkacy (ул. Большая Полянка, д.2/10, стр 1) мы проведём митап для backend-разработчиков. 00, подробности — под катом.19:20–19:30, Павел Дерендяев, вступительное слово. Начинаем в 19. 30–20:10, Иван Походня, «Как мы хотели в Java 11 и ...