- PVSM.RU - https://www.pvsm.ru -
Прим. перев.: Статья написана Javier Salmeron — инженером из хорошо известной в Kubernetes-сообществе компании Bitnami — и была опубликована в блоге CNCF в начале августа. Автор рассказывает о самых основах механизма RBAC (управление доступом на основе ролей), появившегося в Kubernetes полтора года назад. Материал будет особенно полезным для тех, кто знакомится с устройством ключевых компонентов K8s (ссылки на другие подобные статьи см. в конце).
Слайд из презентации [1], сделанной сотрудником Google по случаю релиза Kubernetes 1.6
Многие опытные пользователи Kubernetes могут вспомнить релиз Kubernetes 1.6, когда авторизация на основе Role-Based Access Control (RBAC) получила статус бета-версии. Так появился альтернативный механизм аутентификации, который дополнил уже существующий, но трудный в управлении и понимании, — Attribute-Based Access Control (ABAC). Все с восторгом приветствовали новую фичу, однако в то же время бесчисленное число пользователей были разочарованы. StackOverflow и GitHub изобиловали сообщениями об ограничениях RBAC, потому что большая часть документации и примеров не учитывали RBAC (но сейчас уже всё в порядке). Эталонным примером стал Helm: простой запуск helm init
+ helm install
больше не работал. Внезапно нам потребовалось добавлять «странные» элементы вроде ServiceAccounts
или RoleBindings
ещё до того, как разворачивать чарт с WordPress или Redis (подробнее об этом см. в инструкции [2]).
Оставив же эти неудачные первые попытки в стороне, нельзя отрицать тот огромный вклад, что внёс RBAC в превращение Kubernetes в готовую к production платформу. Многие из нас успели поиграть с Kubernetes с полными привилегиями администратора, и мы прекрасно понимаем, что в реальном окружении необходимо:
И в этом отношении RBAC — ключевой элемент, предоставляющий столь необходимые возможности. В статье мы быстро пройдёмся по основам (для подробностей смотрите это видео [3]; по ссылке 1-часовой вебинар от Bitnami на английском языке — прим. перев.) и немного углубимся в самые запутанные моменты.
Чтобы полностью осознать идею RBAC, нужно понимать, что к ней причастны три элемента:
Если помнить об этих трёх элементах, ключевая идея 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
[4] и LimitRanges
[5]. Их определённо стоит изучить при конфигурации столь важной составляющей кластера [как создание подов].
Одной из сложностей, с которой сталкиваются многие пользователи 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
, чтобы мы могли получить доступ к кластеру через эти новые учётные записи. Чтобы создать файлы с ними, можно воспользоваться командами kubectl config
(что не требуют доступа к Kubernetes API, поэтому могут исполняться любым пользователем). В приведённом выше видео есть пример по созданию пользователя с TLS-сертификатами.
Мы видели пример, в котором указанному пользователю выдаются права на операции в кластере. Но что насчёт Deployments, требующих доступа к Kubernetes API? Рассмотрим конкретный сценарий, чтобы разобраться получше.
Возьмём для примера популярное инфраструктурное приложение — RabbitMQ. Будем использовать Helm-чарт для RabbitMQ [6] от Bitnami (из официального репозитория helm/charts), который использует контейнер bitnami/rabbitmq [7]. В контейнер встроен плагин для Kubernetes, отвечающий за обнаружение других членов кластера RabbitMQ. Из-за этого процесс внутри контейнера требует доступа к Kubernetes API, и нам потребуется настроить ServiceAccount
с правильными RBAC-привилегиями.
Когда речь заходит о ServiceAccounts
, следуйте этой хорошей практике:
— Настраивайте ServiceAccounts для каждого Deployment с минимальным набором привилегий.
В случае приложений, требующих доступа к Kubernetes API, у вас может возникнуть соблазн создать некий «привилегированный ServiceAccount
», который сможет делать в кластере практически всё. Хотя это кажется более простым решением, в конечном счёте оно может привести к уязвимости в безопасности, позволяющей выполнять нежелательные операции. (В видео рассматривается пример Tiller [компонента Helm] и последствий наличия ServiceAccounts
с большими привилегиями.)
Вдобавок, у разных Deployments будут разные потребности в смысле доступа к API, поэтому для каждого Deployment разумно иметь разные ServiceAccounts
.
Не забывая об этом, посмотрим, какая конфигурация RBAC будет правильной для случая Deployment'а с RabbitMQ.
В документации плагина [8] и его исходном коде [9] можно увидеть, что он запрашивает у Kubernetes API список Endpoints. Так и происходит обнаружение остальных членов кластера RabbitMQ. Поэтому чарт RabbitMQ от Bitnami создаёт:
{{- if .Values.rbacEnabled }}
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 }}
{{- 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 }}
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 можно получить по этим ссылкам:
Читайте также в нашем блоге:
Автор: Дмитрий Шурупов
Источник [19]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/avtorizatsiya/292159
Ссылки в тексте:
[1] презентации: https://www.slideshare.net/codedellemc/code-webinar-kubernetes-overview-and-16-update-with-matthew-de-lio
[2] инструкции: https://docs.bitnami.com/kubernetes/how-to/configure-rbac-in-your-kubernetes-cluster/#use-case-2-enable-helm-in-your-cluster
[3] это видео: https://www.youtube.com/watch?v=CnHTCTP8d48
[4] ResourceQuota
: https://kubernetes.io/docs/concepts/policy/resource-quotas/#object-count-quota
[5] LimitRanges
: https://kubernetes.io/docs/concepts/policy/resource-quotas/#requests-vs-limits
[6] Helm-чарт для RabbitMQ: https://github.com/kubernetes/charts/tree/master/stable/rabbitmq
[7] контейнер bitnami/rabbitmq: https://bitnami.com/stack/rabbitmq/containers
[8] документации плагина: https://github.com/rabbitmq/rabbitmq-peer-discovery-k8s/tree/master/examples/k8s_statefulsets
[9] его исходном коде: https://github.com/rabbitmq/rabbitmq-peer-discovery-k8s/blob/2abd4ac578c98d6085c46cd3f3c4297e417cb641/src/rabbit_peer_discovery_k8s.erl#L152
[10] ServiceAccount: https://github.com/kubernetes/charts/blob/master/stable/rabbitmq/templates/serviceaccount.yaml
[11] Role: https://github.com/kubernetes/charts/blob/master/stable/rabbitmq/templates/role.yaml
[12] RoleBinding: https://github.com/helm/charts/blob/master/stable/rabbitmq/templates/rolebinding.yaml
[13] Configure RBAC in your Kubernetes Cluster: https://docs.bitnami.com/kubernetes/how-to/configure-rbac-in-your-kubernetes-cluster/
[14] Using RBAC authorization: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
[15] 11 способов (не) стать жертвой взлома в Kubernetes: https://habr.com/company/flant/blog/417905/
[16] Как на самом деле работает планировщик Kubernetes?: https://habr.com/company/flant/blog/335552/
[17] За кулисами сети в Kubernetes: https://habr.com/company/flant/blog/420813/
[18] Наш опыт с Kubernetes в небольших проектах: https://habr.com/company/flant/blog/331188/
[19] Источник: https://habr.com/post/422801/?utm_source=habrahabr&utm_medium=rss&utm_campaign=422801
Нажмите здесь для печати.