[Перевод] Пользователи и авторизация RBAC в Kubernetes
Прим. перев.: Продолжая недавно затронутую нами тему безопасности Kubernetes в целом и RBAC — в частности, публикуем перевод этого материала от французского консультанта из международной компании Big Data-компании Adaltas. Автор в деталях показывает, как создавать пользователей, наделять их правами и в дальнейшем обслуживать.
Настройка и запуск кластера Kubernetes — это только начало: ведь его необходимо еще и эксплуатировать. Чтобы обезопасить доступ к кластеру, нужно задать идентификационные данные пользователей и грамотно управлять настройками аутентификации и авторизации.
(Иллюстрация взята из блога CNCF — прим. перев.)
Эта статья посвящена тому, как создавать пользователей, используя клиентские сертификаты X.509, и как управлять авторизацией с помощью базовых API-объектов RBAC в Kubernetes. Мы также поговорим о некоторых открытых проектах, упрощающих администрирование кластера: rakkess, kubectl-who-can, rbac-lookup и RBAC Manager.
Предварительные условия и допущения
Прежде всего необходимо сделать несколько допущений:
Если у вас нет готового кластера Kubernetes, рекомендую обратиться к статье коллеги (Arthur BUSSER), в которой он рассказывает об установке Kubernetes на CentOS 7 с использованием Vagrant.
В нашем кластере 4 узла: один мастер и 3 рабочих. Мастер также будет использоваться в качестве пограничного узла для взаимодействия с кластером.
API-объекты RBAC
Управление доступом на основе ролей (RBAC) — это метод регулирования доступа к компьютерам и сетевым ресурсам, опирающийся на роли отдельных пользователей в компании. RBAC можно использовать со всеми ресурсами Kubernetes, которые поддерживают CRUD (Create, Read, Update, Delete). Примеры таких ресурсов:
- пространства имен;
- Pod’ы;
- Deployment’ы;
- постоянные тома (PersistentVolumes);
- ConfigMap’ы.
А вот примеры возможных операций с ними:
-
create
(создание); -
get
(получение); -
delete
(удаление); -
list
(просмотр списка); -
update
(обновление).
Для управления RBAC в Kubernetes, нам необходимо объявить:
-
Role
иClusterRole
. Это просто наборы правил, представляющие набор разрешений.Role
может использоваться только для предоставления доступа к ресурсам внутри пространств имен.ClusterRole
может предоставлять те же разрешения, что иRole
, а также давать доступ к ресурсам, доступных в пределах всего кластера, и так называемым нересурсным endpoint’ам (вроде/healthz
— прим. перев.). -
Subjects
. Subject (субъект) — это сущность, которая будет выполнять операции в кластере. Ей могут являться пользователи, сервисы или даже группы. -
RoleBinding
иClusterRoleBinding
. Как следует из названия, это просто привязка субъекта к Role или ClusterRole.
В Kubernetes имеются следующие роли по умолчанию:
-
view
: доступ только для чтения, исключает секреты; -
edit
: перечисленное выше + возможность редактировать большинство ресурсов, исключает роли и привязки ролей; -
admin
: перечисленное выше + возможность управлять ролями и привязками ролей на уровне пространств имен; -
cluster-admin
: все возможные привилегии.
Конечно, можно создавать свои Roles
и ClusterRoles
, но мы рекомендуем максимально использовать роли, определенные по умолчанию, насколько это позволяет ситуация. Иначе во всем этом можно быстро запутаться.
Пример использования
Мы создадим два пространства имен: my-project-dev
и my-project-prod
, —, а также двух пользователей: jean
и sarah
— с различными ролями в этих пространствах имен:
- my-project-dev:
- jean: edit
- my-project-prod:
- jean: view
- sarah: edit
Создание и аутентификация пользователей с помощью клиентских сертификатов X.509
Как правило, имеется два типа пользователей: учетные записи служб (service accounts), управляемые Kubernetes, и обычные пользователи. Мы сфокусируемся на последних. Вот как они описываются в официальной документации:
Предполагается, что обычными пользователями управляет внешняя, независимая служба. В ее роли может выступать администратор, распределяющий закрытые ключи, хранилище пользователей вроде Keystone или Google Accounts, или даже файл со списком имен пользователей и паролей. В связи с этим в Kubernetes нет объектов, представляющих обычных пользователей. Обычных пользователей нельзя добавить в кластер через вызов API.
Существует несколько способов управления обычными пользователями:
- Базовая аутентификация (basic auth):
- передача конфигурации API-серверу со следующим (или похожим) содержимым: password, username, uid, group;
- Клиентский сертификат X.509:
- создание секретного ключа пользователя и запроса на подпись сертификата;
- заверение его в центре сертификации (Kubernetes CA) для получения сертификата пользователя;
- Bearer-токены (JSON Web Tokens, JWT):
- OpenID Connect;
- слой аутентификации поверх OAuth 2.0;
- веб-хуки (webhooks).
В этой статье мы будем использовать сертификаты X.509 и OpenSSL из-за их простоты. Создание пользователей проходит в несколько этапов — мы пройдем их все. Операции следует выполнять под учеткой пользователя с правами администратора кластера (cluster-admin). Вот все шаги по созданию пользователя (на примере jean
):
- Создайте пользователя на мастере, а затем перейдите в его домашнюю директорию для выполнения остальных шагов:
useradd jean && cd /home/jean
- Создайте закрытый ключ:
openssl genrsa -out jean.key 2048
- Создайте запрос на подпись сертификата (certificate signing request, CSR).
CN
— имя пользователя,O
— группа. Можно устанавливать разрешения по группам. Это упростит работу, если, например, у вас много пользователей с одинаковыми полномочиями:# Без группы openssl req -new -key jean.key \ -out jean.csr \ -subj "/CN=jean" # С группой под названием $group openssl req -new -key jean.key \ -out jean.csr \ -subj "/CN=jean/O=$group" # Если пользователь входит в несколько групп openssl req -new -key jean.key \ -out jean.csr \ -subj "/CN=jean/O=$group1/O=$group2/O=$group3"
- Подпишите CSR в Kubernetes CA. Мы должны использовать сертификат CA и ключ, которые обычно находятся в
/etc/kubernetes/pki
. Сертификат будет действителен в течение 500 дней:openssl x509 -req -in jean.csr \ -CA /etc/kubernetes/pki/ca.crt \ -CAkey /etc/kubernetes/pki/ca.key \ -CAcreateserial \ -out jean.crt -days 500
- Создайте каталог
.certs
. В нем мы будем хранить открытый и закрытый ключи пользователя:mkdir .certs && mv jean.crt jean.key .certs
- Создайте пользователя внутри Kubernetes:
kubectl config set-credentials jean \ --client-certificate=/home/jean/.certs/jean.crt \ --client-key=/home/jean/.certs/jean.key
- Задайте контекст для пользователя:
kubectl config set-context jean-context \ --cluster=kubernetes --user=jean
- Отредактируйте файл конфигурации пользователя. В нем содержится информация, необходимая для аутентификации в кластере. Можно воспользоваться файлом конфигурации кластера, который обычно лежит в
/etc/kubernetes
: переменныеcertificate-authority-data
иserver
должны быть такими же, как в упомянутом файле:apiVersion: v1 clusters: - cluster: certificate-authority-data: {Сюда вставьте данные} server: {Сюда вставьте данные} name: kubernetes contexts: - context: cluster: kubernetes user: jean name: jean-context current-context: jean-context kind: Config preferences: {} users: - name: jean user: client-certificate: /home/jean/.certs/jean.cert client-key: /home/jean/.certs/jean.key
Теперь нужно скопировать приведенный выше конфиг в каталог.kube
:mkdir .kube && vi .kube/config
- Осталось сделать пользователя владельцем всех созданных файлов и каталогов:
chown -R jean: /home/jean/
Пользователь jean
успешно создан. То же самое проделаем и для пользователя sarah
. Шагов довольно много, и на создание большого количества пользователей может уйти длительное время. Поэтому я написал Bash-скрипты, автоматизирующие процесс: их можно найти в репозитории на GitHub.
Прим. перев.: Как мы писали в своей недавней статье, упростить эту процедуру можно и более «родным» для Kubernetes путём — через новые возможности в консольной утилите kubeadm. Впрочем, помните, что на момент публикации этого перевода они доступы в виде альфа-версии. Пример команды для создания пользователя — kubeadm alpha kubeconfig user
.
Теперь у нас есть пользователи, и можно переходить к созданию двух пространств имен:
kubectl create namespace my-project-dev
kubectl create namespace my-project-prod
Поскольку мы пока не определили авторизацию пользователей, у них не должно быть доступа к ресурсам кластера:
User: Jean
kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "jean" cannot list resource "nodes" in API group "" at the cluster scope
kubectl get pods -n default
Error from server (Forbidden): pods is forbidden: User "jean" cannot list resource "pods" in API group "" in the namespace "default"
kubectl get pods -n my-project-prod
Error from server (Forbidden): pods is forbidden: User "jean" cannot list resource "pods" in API group "" in the namespace "my-project-prod"
kubectl get pods -n my-project-dev
Error from server (Forbidden): pods is forbidden: User "jean" cannot list resource "pods" in API group "" in the namespace "my-project-dev"
User: Sarah
kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "sarah" cannot list resource "nodes" in API group "" at the cluster scope
kubectl get pods -n default
Error from server (Forbidden): pods is forbidden: User "sarah" cannot list resource "pods" in API group "" in the namespace "default"
kubectl get pods -n my-project-prod
Error from server (Forbidden): pods is forbidden: User "sarah" cannot list resource "pods" in API group "" in the namespace "my-project-prod"
kubectl get pods -n my-project-dev
Error from server (Forbidden): pods is forbidden: User "sarah" cannot list resource "pods" in API group "" in the namespace "my-project-dev"
Создание Role и ClusterRole
Мы будем использовать ClusterRole
, доступный по умолчанию. Впрочем, также покажем, как создавать свои Role
и ClusterRole
. По сути Role
и ClusterRole
— это всего лишь набор действий (называемых как verbs
, т.е. дословно — «глаголов»), разрешенных для определенных ресурсов и пространств имен. Вот пример YAML-файла:
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: list-deployments
namespace: my-project-dev
rules:
- apiGroups: [ apps ]
resources: [ deployments ]
verbs: [ get, list ]
---------------------------------
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: list-deployments
rules:
- apiGroups: [ apps ]
resources: [ deployments ]
verbs: [ get, list ]
Чтобы их создать, выполните команду:
kubectl create -f /path/to/your/yaml/file
Привязка Role или ClusterRole к пользователям
Теперь привяжем ClusterRole
по умолчанию (edit
и view
) к нашим пользователям следующим образом:
jean
:-
edit
— в пространстве именmy-project-dev
; -
view
— в пространстве именmy-project-prod
;
-
sarah
:-
edit
— в пространстве именmy-project-prod
.
-
RoleBinding’и нужно задавать по пространствам имен, а не по пользователям. Другими словами, для авторизации jean
мы создадим два RoleBinding’а. Пример YAML-файла, определяющего RoleBinding’и для jean
:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jean
namespace: my-project-dev
subjects:
- kind: User
name: jean
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
---------------------------------
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jean
namespace: my-project-prod
subjects:
- kind: User
name: jean
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
Мы разрешаем jean
просматривать (view
) my-project-prod
и редактировать (edit
) my-project-dev
. То же самое необходимо сделать с авторизациями для sarah
. Для их активации выполните команду:
kubectl apply -f /path/to/your/yaml/file
В данном случае была использована kubectl apply
вместо kubectl create
. Разница между ними в том, что create
создает объект и больше ничего не делает, а apply
— не только создает объект (в случае, если его не существует), но и обновляет при необходимости.
Давайте проверим, получили ли наши пользователи нужные разрешения.
- Пользователь:
sarah
(edit
вmy-project-prod
)-
my-project-prod
- может выводить список pod’ов (1);
- может создавать deployment’ы (2).
-
my-project-dev
- не может выводить список pod’ов (4);
- не может создавать deployment’ы (5).
-
(1) kubectl get pods -n my-project-prod
No resources found.
(2) kubectl run nginx --image=nginx --replicas=1 -n my-project-prod
deployment.apps/nginx created
(3) kubectl get pods -n my-project-prod
NAME READY STATUS RESTARTS AGE
nginx-7db9fccd9b-t14qw 1/1 Running 0 4s
(4) kubectl get pods -n my-project-dev
Error from server (Forbidden): pods is forbidden: User "sarah" cannot list resource "pods" in API group "" in the namespace "my-project-dev"
(5) kubectl run nginx --image=nginx --replicas=1 -n my-project-dev
Error from server (Forbidden): deployments.apps is forbidden: User "sarah" cannot create resource "deployments" in API group "apps" in the namespace "my-project-dev"
- Пользователь:
jean
(view
вmy-project-prod
иedit
вmy-project-dev
)-
my-project-prod
- может выводить список pod’ов (1);
- может выводить список deployment’ов (2);
- не может удалять deployment’ы (3).
- my-project-dev:
- может выводить список pod’ов (4);
- может создавать deployment’ы (5);
- может выводить список deployment’ов (6);
- может удалять deployment’ы (7).
-
(1) kubectl get pods -n my-project-prod
NAME READY STATUS RESTARTS AGE
nginx-7db9fccd9b-t14qw 1/1 Running 0 101s
(2) kubectl get deploy -n my-project-prod
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 110s
(3) kubectl delete deploy/nginx -n my-project-prod
Error from server (Forbidden): deployments.extensions "nginx" is forbidden: User "jean" cannot delete resource "deployments" in API group "extensions" in the namespace "my-project-prod"
(4) kubectl get pods -n my-project-dev
No resources found.
(5) kubectl run nginx --image=nginx --replicas=1 -n my-project-dev
deployment.apps/nginx created
(6) kubectl get deploy -n my-project-dev
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/1 1 0 13s
(7) kubectl delete deploy/nginx -n my-project-dev
deployment.extensions "nginx" deleted
(8) kubectl get deploy -n my-project-dev
No resources found.
Управление пользователями и их авторизацией
Итак, мы успешно задали различные роли и авторизации пользователей. Возникает вопрос: как теперь управлять всем этим? Как узнать, правильно ли заданы права доступа для конкретного пользователя? Как узнать, кто обладает полномочиями на выполнение определенного действия? Как получить общую картину разрешений пользователей?
Нам необходимы ответы на все эти вопросы, чтобы обеспечить безопасность кластера. Команда kubectl auth can-i
позволяет выяснить, может ли пользователь выполнить определенное действие:
# kubectl auth can-i $action $resource --as $subject
(1) kubectl auth can-i list pods
(2) kubectl auth can-i list pods --as jean
Первая команда (1) позволяет пользователю узнать, может ли он выполнить некое действие. Вторая (2) — позволяет администратору выдать себя за пользователя, чтобы узнать, может ли тот выполнить определенное действие. Подобное «перевоплощение» разрешено только для пользователей с привилегиями администратора кластера.
Это практически все, что можно сделать с помощью встроенного инструментария. Именно поэтому представлю и некоторые Open Source-проекты, позволяющие расширить возможности, предлагаемые командой kubectl auth can-i. Прежде чем представить их, установим зависимости: Go и Krew.
Установка Go
Go — язык программирования с открытым исходным кодом, позволяющий создавать простое, надежное и эффективное программное обеспечение. Он был разработан компанией Google под вдохновением от Си и Pascal, на основе оригинальной концепции Robert Griesemer, Rob Pike и Ken Thompson.
wget https://dl.google.com/go/go1.12.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.12.5.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
Установка Krew
Krew — это инструмент, упрощающий использование плагинов kubectl. Krew помогает находить нужные плагины, устанавливать и управлять ими. По функциям он напоминает такие инструменты, как apt, dnf или brew. Krew совместим только с kubectl версии 1.12 и выше.
set -x; cd "$(mktemp -d)" &&
curl -fsSLO "https://storage.googleapis.com/krew/v0.2.1/krew.{tar.gz,yaml}" &&
tar zxvf krew.tar.gz &&
./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" install \
--manifest=krew.yaml --archive=krew.tar.gz
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
rakkess
Этот проект позволяет просмотреть все полномочия, которые были предоставлены пользователю. Например, он помогает ответить на вопрос о том, что может делать jean
. Прежде всего давайте установим его:
kubectl krew install access_matrix
Документацию по проекту можно найти в репозитории на GitHub. Вот пример его работы:
kubectl access-matrix -n my-project-dev --as jean
kubect-who-can
Этот проект позволяет нам узнать, какие пользователи могут выполнить определенное действие. Он помогает ответить на вопрос: «Кто может это сделать?». Установка:
go get -v github.com/aquasecurity/kubectl-who-can
Документация — в GitHub-репозитории. Пример работы:
kubectl-who-can list pods -n default
No subjects found with permissions to list pods assigned through RoleBindings
CLUSTERROLEBINDING SUBJECT TYPE SA-NAMESPACE
cluster-admin system:masters Group
rbac-manager rbac-manager ServiceAccount rbac-manager
system:controller:attachdetach-controller attachdetach-controller ServiceAccount kube-system
system:controller:clusterrole-aggregation-controller clusterrole-aggregation-controller ServiceAccount kube-system
system:controller:cronjob-controller cronjob-controller ServiceAccount kube-system
system:controller:daemon-set-controller daemon-set-controller ServiceAccount kube-system
system:controller:deployment-controller deployment-controller ServiceAccount kube-system
system:controller:endpoint-controller endpoint-controller ServiceAccount kube-system
system:controller:generic-garbage-collector generic-garbage-collector ServiceAccount kube-system
system:controller:horizontal-pod-autoscaler horizontal-pod-autoscaler ServiceAccount kube-system
system:controller:job-controller job-controller ServiceAccount kube-system
system:controller:namespace-controller namespace-controller ServiceAccount kube-system
system:controller:node-controller node-controller ServiceAccount kube-system
system:controller:persistent-volume-binder persistent-volume-binder ServiceAccount kube-system
system:controller:pod-garbage-collector pod-garbage-collector ServiceAccount kube-system
system:controller:pvc-protection-controller pvc-protection-controller ServiceAccount kube-system
system:controller:replicaset-controller replicaset-controller ServiceAccount kube-system
system:controller:replication-controller replication-controller ServiceAccount kube-system
system:controller:resourcequota-controller resourcequota-controller ServiceAccount kube-system
system:controller:statefulset-controller statefulset-controller ServiceAccount kube-system
system:coredns coredns ServiceAccount kube-system
system:kube-controller-manager system:kube-controller-manager User
system:kube-scheduler system:kube-scheduler User
rbac-lookup
Этот проект предоставляет обзор RBAC-правил. Он помогает ответить на вопросы: «В какую роль входят jean
и sarah
?», «В какую роль входят все пользователи?», «В какую роль входит вся группа?». Для установки выполните команду:
kubectl krew install rbac-lookup
Документация — в GitHub-репозитории. Вот пример работы:
kubectl-rbac_lookup jean
SUBJECT SCOPE ROLE
jean my-project-dev ClusterRole/edit
jean my-project-prod ClusterRole/view
kubectl-rbac_lookup sarah
SUBJECT SCOPE ROLE
sarah my-project-prod ClusterRole/edit
kubectl-rbac_lookup --kind user
SUBJECT SCOPE ROLE
jean my-project-dev ClusterRole/edit
jean my-project-prod ClusterRole/view
sarah my-project-prod ClusterRole/edit
system:anonymous kube-public Role/kubeadm:bootstrap-signer-clusterinfo
system:kube-controller-manager kube-system Role/extension-apiserver-authentication-reader
system:kube-controller-manager kube-system Role/system::leader-locking-kube-controller-manager
system:kube-controller-manager cluster-wide ClusterRole/system:kube-controller-manager
system:kube-proxy cluster-wide ClusterRole/system:node-proxier
system:kube-scheduler kube-system Role/extension-apiserver-authentication-reader
system:kube-scheduler kube-system Role/system::leader-locking-kube-scheduler
system:kube-scheduler cluster-wide ClusterRole/system:kube-scheduler
system:kube-scheduler cluster-wide ClusterRole/system:volume-scheduler
kubectl-rbac_lookup --kind group
SUBJECT SCOPE ROLE
system:authenticated cluster-wide ClusterRole/system:basic-user
system:authenticated cluster-wide ClusterRole/system:discovery
system:authenticated cluster-wide ClusterRole/system:public-info-viewer
system:bootstrappers:kubeadm:default-node-token cluster-wide ClusterRole/system:node-bootstrapper
system:bootstrappers:kubeadm:default-node-token cluster-wide ClusterRole/system:certificates.k8s.io:certificatesigningrequests:nodeclient
system:bootstrappers:kubeadm:default-node-token kube-system Role/kube-proxy
system:bootstrappers:kubeadm:default-node-token kube-system Role/kubeadm:kubelet-config-1.14
system:bootstrappers:kubeadm:default-node-token kube-system Role/kubeadm:nodes-kubeadm-config
system:masters cluster-wide ClusterRole/cluster-admin
system:nodes kube-system Role/kubeadm:kubelet-config-1.14
system:nodes kube-system Role/kubeadm:nodes-kubeadm-config
system:nodes cluster-wide ClusterRole/system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
system:unauthenticated cluster-wide ClusterRole/system:public-info-viewer
RBAC Manager
Как очевидно следует из названия этого проекта, он является менеджером RBAC. Он упрощает множество необходимых манипуляций. Пожалуй, самым важным является создание RoleBinding’ов. Ранее мы видели, что при создании различных ролей для пользователя необходимо создавать различные RoleBinding’и. RBAC Manager помогает, позволяя сделать всего один RoleBinding сразу со всей авторизацией. Для установки необходимо загрузить YAML-файл из репозитория на GitHub:
kubectl apply -f /path/to/rbac/manager/yaml/file
Официальная документация — в GitHub-репозитории. Пример работы:
apiVersion: rbacmanager.reactiveops.io/v1beta1
kind: RBACDefinition
metadata:
name: jose
rbacBindings:
- name: jose
subjects:
- kind: User
name: jose
roleBindings:
- namespace: my-project-prod
clusterRole: edit
- namespace: my-project-dev
clusterRole: edit
Заключение
Мы создали пользователей в кластере Kubernetes с помощью клиентского сертификата X.509 с OpenSSL и наделили их полномочиями. Для более простого создания пользователей вы можете воспользоваться скриптом, доступном в моем репозитории на GitHub(или экспериментальными командами kubeadm — прим. перев.). Что касается администрирования кластера, можно воспользоваться Open Source-проектами, представленными в статье:
- kubectl auth can-i: выяснить, может ли пользователь выполнить некоторое действие;
- rakkess: узнать все действия, которые может выполнить пользователь;
- kubectl-who-can: определить, какие пользователи могут выполнить некоторое действие;
- rbac-lookup: получить общий обзор RBAC;
- RBAC Manager: упростить конфигурацию, объединяя привязки к правам, автоматизируя изменения в RBAC, используя лейблы как селекторы для назначения прав.
Создание пользователей может превратиться в весьма затратное по времени занятие, особенно если необходимо задать большое количество пользователей за раз (или создавать их часто). Облегчить ситуацию может подключение корпоративного LDAP к кластеру Kubernetes. Некоторые Open Source-проекты (Kismatic [проект выглядит заброшенным — прим. перев.] и ObjectifLibre) предлагают вебхуки для Kubernetes, позволяющие проводить прямую аутентификацию через LDAP. Другое возможное решение состоит в том, чтобы настроить сервер OpenID с корпоративным LDAP в качестве бэкенда.
P.S. от переводчика
Читайте также в нашем блоге: