Как работает аутентификация в Kubernetes: ServiceAccount и RBAC

В этой статье кратко определены основные понятия k8s, связанные с учетными записями:

  • аутентификация и авторизация;

  • сервисные аккаунты и секреты в их описании;

  • плагин управления доступом RBAC;

  • роли и привязки ролей.

Аутентификация и авторизация

Процесс доступа к ресурсу пользователя

Процесс доступа к ресурсу пользователя

Kubernetes различает два вида клиентов, подключающихся к серверу API:

  • Реальные люди (пользователи) — управляются внешней системой аутентификации, например, SSO. Для пользователей функционал CRUD (create, read, update, delete) посредством API невозможен.

  • Модули (работающие внутри них приложения) — используют учетные записи служб, которые создаются и хранятся в кластере как ресурсы ServiceAccount.

Сервер API может быть сконфигурирован с помощью одного или нескольких плагинов аутентификации и авторизации. Когда сервер API получает запрос, он проходит через список плагинов аутентификации, где каждый пытается определить отправителя. Первый плагин, который извлек эту информацию из запроса, возвращает обратно в ядро сервера API имя пользователя, идентификатор пользователя и группы, к которой принадлежит клиент. Параметры аутентификации активируются параметрами командной строки при запуске сервера API.

Есть несколько вариантов того, как проверить идентичность клиента, например:

  • из сертификата клиента;

  • из токена аутентификации, переданного по HTTP;

  • в результате обычной HTTP-аутентификации.

Группы

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

  • system: unauthenticated — неаутентифицированный клиент;

  • system: authenticated — аутентифицированный клиент;

  • system: serviceaccounts — все учетные записи сервисов;

  • system: serviceaccounts:- все учетные записи сервисов в конкретном пространстве имен.

ServiceAccount

ServiceAccount — объект, характеризующий учетную запись службы для каждого модуля (pod-а).
Алгоритм аутентификации:

  • Модуль, аутентифицируясь, отправляет на сервер содержимое файла /var/run/secrets/kubernetes.io/serviceaccount/token (файл монтируется в файловую систему каждого контейнера через специальный том secret). Этот файл содержит токен аутентификации для учетной записи ServiceAccount.

  • Когда приложение использует этот токен для подключения к серверу API, плагин аутентификации проверяет подлинность учетной записи ServiceAccount и передает имя пользователя учетной записи обратно в ядро сервера API. Имя пользователя для ServiceAccount форматируется следующим образом: system: serviceaccount: <имя учетной записи службы>.

  • Сервер API передает имя пользователя плагинам аутентификации, которые определяют, разрешено ли приложению выполнять действие с помощью этой учетной записи.

Учетная запись (УЗ) службы представляет собой способ проверки подлинности работающего в модуле приложения.
По умолчанию учетная запись ServiceAccount устанавливается автоматически. Каждый модуль (pod) связан ровно с одной учетной записью службы, но несколько модулей могут использовать одну и ту же учетную запись. Модуль может использовать учетную запись ServiceAccount только из своего пространства имен (namespace).

Дополнительную УЗ ServiceAccount нужно назначать модулям вручную в описании модуля в разделе: spec.serviceAccountName.

Авторизация ServiceAccount

Назначая модулям различные УЗ служб, можно контролировать то, к каким ресурсам имеет доступ каждый модуль. Когда запрос, несущий в себе токен аутентификации, поступает на сервер API, сервер использует этот токен для аутентификации клиента и определяет, разрешен ли ему доступ к операции. Сервер API получает эту информацию от общесистемного плагина авторизации, сконфигурированного админом кластера. Одним из плагинов является RBAC (role-based access control).


Для каждого пространства имен существует своя УЗ ServiceAccount, но для разграничения доступа могут создаваться дополнительные учетные записи. Токены аутентификации в учетных записях служб представляют собой маркеры JWT.

Монтируемые секреты УЗ службы

Токен учетной записи отображается в списке монтированных секретов (mountable secrets). По умолчанию модуль может смонтировать любой секрет.
Аннотация в описании УЗ службы типа:
kubernetes.io/enforce-mountable-secrets=«true» ограничивает монтирование секретов и разрешает модулю монтировать только те секреты, которые перечислены как монтируемые в УЗ службы (mountable secrets).

Секреты УЗ для выгрузки образов

УЗ ServiceAccount может содержать список секретов с учетными данными для выгрузки образов контейнеров из приватного хранилища образов (image pull secrets). Эти секреты не определяют, какие секреты выгрузки образов используются модулем. Они определяют, какие секреты автоматически добавляются во все модули с помощью учетной записи.

Листинг ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubernetes.io/enforce-mountable-secrets: "true"
  name: my-serviceaccount
  namespace: my-namespace
imagePullSecrets:
- name: regcred # эти секреты будут добавляться автоматически во все модули, использующие эту УЗ

Плагин RBAC

Плагин RBAC — это система распределения прав доступа к объектам в кластере Kubernetes. Он может применять правила разрешений системы к отдельным экземплярам ресурса или к нересурсным путям (/api, /health, etc).

Правила авторизации RBAC выстраиваются с помощью четырех ресурсов:

  • Role (для namespace), ClusterRole (для всего кластера) определяет, какие действия могут выполняться и на каком ресурсе.

  • RoleBinding, ClusterRoleBinding — привязывает роли к определенным группам, пользователям или сервисным УЗ.

Привязка роли уровня namespace — RoleBinding может ссылаться на кластерную роль ClusterRole, которая не имеет пространство имен. Привязка кластерной роли ClusterRoleBinding не может ссылаться на роль уровня пространства имен Role.

Стандартная ситуация: привязка роли ссылается на роль (в конкретном пространстве имен); привязка кластерной роли ссылается на кластерную роль (для ресурсов уровня кластера и нересурсных URL-путей)

Стандартная ситуация: привязка роли ссылается на роль (в конкретном пространстве имен); привязка кластерной роли ссылается на кластерную роль (для ресурсов уровня кластера и нересурсных URL-путей)

Но также привязка роли может ссылаться на кластерную роль, чтобы применить роль, содержащую пространство имен, ко всему кластеру; а привязка кластерной роли не может ссылаться на роль пространства имен, так как роль требует назначения в конкретном пространстве имен

Но также привязка роли может ссылаться на кластерную роль, чтобы применить роль, содержащую пространство имен, ко всему кластеру;, а привязка кластерной роли не может ссылаться на роль пространства имен, так как роль требует назначения в конкретном пространстве имен

С RBAC могут параллельно существовать и другие плагины управления доступом, и, если один из них позволяет пользователю выполнить действие, то действие разрешается.

Role

Role RBAC (и ClusterRole) содержат правила, представляющие набор разрешений. Разрешения являются аддитивными (правил «deny» нет). Если для роли не указан namespace, то используется текущий.

Для ресурса, которому назначается роль, нужно указывать его apiGroup, и нельзя назначить одну роль нескольким ресурсам из разных apiGroup, роли назначаются только для ресурсов одного типа apiGroup.
Можно разрешить доступ к конкретным экземплярам служб, указав их имена через дополнительное поле resourceNames.
После создания роли ее необходимо привязать к сервисной УЗ в каждом требуемом пространстве имен.

Листинг Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # пустые кавычки "" говорят о том, что используется корневая API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

RoleBinding

​Привязка роли предоставляет разрешения, определенные в роли, пользователю или группе пользователей. Она содержит список субъектов (пользователей, групп или учетных записей служб) и ссылку на предоставляемую роль.

Привязка роли всегда ссылается на одну роль, но может включать несколько субъектов даже из других пространств имен (namespace). RoleBinding не может предоставлять доступ к ресурсам уровня кластера.

Листинг RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
# Эта привязка роли позволяет «Джейн» читать модули в пространстве имен «по умолчанию».
# У вас уже должна быть роль с именем «pod-reader» в этом пространстве имен.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# Вы можете указать более одного «субъекта»
- kind: User
  name: jane # поле "name" чувствительно к регистру
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" указывает привязку к Role/ClusterRole
  kind: Role # здесь может быть Role или ClusterRole
  name: pod-reader # это имя должно совпадать с именем роли или кластерной роли, к которой вы хотите создать привязку роли
  apiGroup: rbac.authorization.k8s.io

ClusterRole

Некоторые ресурсы не имеют пространств имен, а некоторые URL-пути вовсе не являются ресурсами. Для разрешения доступа к ним используются кластерные роли. Они также используются, если нужно дать доступ к ресурсу, имеющему пространство имен, во всех пространствах имен.

Кластерные роли могут быть привязаны привязкой RoleBinding, только если для ресурсов этих ролей определено пространство имен.

Кластерные роли k8s:

  • View — просматривает все ресурсы кроме ролей, привязок ролей и секретов (с целью не допустить эскалацию привилегий)

  • Edit — позволяет вносить изменения в ресурсы; разрешены чтение и изменение секретов, но запрещены просмотр и изменение ролей, привязок ролей.

  • Admin — предоставляет полный контроль над пространством имен. Запрещено просматривать и изменять ресурс ResourceQuota и ресурс Namespace. Сервер API позволяет создавать и обновлять роли, только если они имеют все разрешения, перечисленные в этой роли (для пользователей).

  • Cluster-Admin — позволяет делать все, что и Admin, а также редактировать ресурс ResourceQuota и ресурс Namespace.

Каждая из перечисленных ролей имеет привязку ClusterRoleBinding, которая привязывает ее к пользователю, которого система аутентифицирует.
По умолчанию учетные записи в пространстве имен не имеют разрешений кроме разрешений для неаутентифицированного пользователя. Модули с приложениями внутри не могут просматривать состояние кластера.

Листинг ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" опущено, поскольку ClusterRoles не имеет пространства имен
  name: secret-reader
rules:
- apiGroups: [""]
   # необходимо указать на уровне HTTP имя ресурса для доступа к Secret
   # объекты в данном случае - это "секреты"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

ClusterRoleBinding

ClusterRoleBinding — используется только для привязки кластерных ролей (в том числе к ресурсам без пространсва имен или нересурсным URL-путям)

Доступ к нересурсным URL-путям должен быть предоставлен явным образом (это делается через кластерную роль и кластерную привязку роли system: discovery.
Для нересурсных URL-путей используются HTTP-запросы put, post, patch.

Листинг ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1
# Эта привязка роли кластера позволяет любому члену группы «manager» читать секреты в любом пространстве имен.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # имя чувствительно к регистру
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

На рисунке отображены два важных момента:1. К привязке роли можно привязать учетную запись из другого пространства имен.2. Роль не может быть назначена для ресурсов из других пространств имен (pod из ns cucumber) либо для ресурсов без пространства имен (persistentVolume).

На рисунке отображены два важных момента:
1. К привязке роли можно привязать учетную запись из другого пространства имен.
2. Роль не может быть назначена для ресурсов из других пространств имен (pod из ns cucumber) либо для ресурсов без пространства имен (persistentVolume).

Заключение

При назначении ролей следует соблюдать принцип наименьшего количества привилегий. Хорошей практикой является создание конкретной учетной записи и не кластерной роли для каждого модуля или набора модулей. Обычно модули запускаются под УЗ по умолчанию, которая автоматически создается для каждого пространства имен. Каждый кластер содержит набор кластерных ролей и кластерных привязок ролей, действующих по умолчанию.

Эта статья является кратким агрегатором сведений, характеризующих аутентификацию и авторизацию в Kubernetes и позволяет познакомиться с базовыми понятиями, такими как serviceAccount, RBAC, Role, RoleBinding, ClusterRole и ClusterRoleBinding.

Литература

© Habrahabr.ru