Модель прав доступа в кластере Amazon EKS
Модель прав доступа в Amazon EKS должна быть построена так, чтобы:
- ограничить права сервисов по принципу минимально достаточных полномочий;
- разделить права внутри Kubernetes и права в AWS;
- отдельно управлять доступом приложений, пользователей, CI/CD и рабочих нод;
- не использовать прикладные IAM права на уровне нод;
- исключить статические AWS ключи в приложениях;
- обеспечить понятный аудит: кто, к чему и на каком основании имеет доступ.
Важно понимать, что в EKS нет одной общей системы прав.
Есть несколько независимых контуров доступа, которые решают разные задачи.
Основные контуры доступа
| Контур | Кто получает доступ | Механизм | К чему даётся доступ |
|---|---|---|---|
| Управление EKS через AWS API | администраторы, Terraform, CI/CD | AWS IAM | создание и изменение кластеров, node groups, add-ons, Access Entries |
| Доступ людей и автоматизации к Kubernetes API | инженеры, CI/CD, GitOps | EKS Access Entries, EKS Access Policies, Kubernetes RBAC | namespaces, Deployments, Pods, Secrets и другие объекты Kubernetes |
| Доступ приложения к Kubernetes API | Pod от имени ServiceAccount | Kubernetes RBAC | объекты Kubernetes API |
| Доступ приложения к AWS API | Pod от имени ServiceAccount | EKS Pod Identity или IRSA | S3, SQS, DynamoDB, Secrets Manager, KMS и другие сервисы AWS |
| Системные права рабочих нод | EC2 worker node или Fargate infrastructure | Node IAM Role или Fargate Pod Execution Role | регистрация ноды, загрузка образов, работа системных компонентов |
Эти контуры не заменяют друг друга.
Например:
- IAM права на S3 не дают приложению права читать Kubernetes Secrets;
- Kubernetes Role не даёт приложению доступ к SQS;
- IAM права на управление кластером EKS не означают автоматический доступ ко всем объектам внутри Kubernetes;
- роль рабочей ноды не должна использоваться как общая роль для приложений.
Общий принцип
Каждый сервис в кластере работает от выделенного Kubernetes ServiceAccount.
Этот ServiceAccount используется как идентификатор приложения и связывается с двумя независимыми моделями прав:
- через Kubernetes RBAC определяются права сервиса внутри кластера;
- через EKS Pod Identity или IRSA сервис получает ограниченные права в AWS.
Связка выглядит так:
Приложение
|
v
Kubernetes ServiceAccount
|
+--> Kubernetes RBAC --> Kubernetes API
|
+--> EKS Pod Identity или IRSA --> IAM Role --> AWS API
При этом сам ServiceAccount не содержит IAM политику и не выдаёт права автоматически.
Он только идентифицирует workload. Права появляются после того, как к ServiceAccount привязаны:
- Role или ClusterRole через RoleBinding или ClusterRoleBinding;
- IAM-роль через Pod Identity Association или аннотацию IRSA.
Для большинства приложений рекомендуется модель:
Один сервис
-> один ServiceAccount
-> отдельный набор Kubernetes RBAC прав
-> отдельная IAM роль или отдельный набор IAM ограничений
Объединять несколько сервисов под одним ServiceAccount или одной IAM ролью стоит только в том случае, если у них действительно одинаковые:
- требования к доступу;
- владельцы;
- уровень доверия;
- жизненный цикл;
- профиль риска.
Права внутри Kubernetes: RBAC
Для управления действиями сервисов внутри кластера используется стандартный механизм Kubernetes RBAC.
Для каждого сервиса или группы однородных сервисов создаётся отдельный ServiceAccount.
Через Role или ClusterRole задаются разрешённые операции с объектами Kubernetes.
Например:
- чтение конкретного ConfigMap;
- чтение Secret в своём namespace;
- просмотр Pods;
- создание Job;
- обновление определённого Custom Resource;
- доступ к объектам только в одном namespace.
Через RoleBinding или ClusterRoleBinding роль привязывается к соответствующему ServiceAccount.
В манифесте приложения явно указывается, под каким ServiceAccount должен запускаться Pod:
spec:
template:
spec:
serviceAccountName: orders-api
Если ServiceAccount не указан, Pod запускается от ServiceAccount default своего namespace.
Для production сервисов лучше не использовать общий default ServiceAccount. Отдельный ServiceAccount делает права явными и упрощает аудит.
Role и ClusterRole
Role задаёт права внутри одного namespace.
ClusterRole может использоваться:
- для кластерных ресурсов;
- для прав, которые должны действовать во всех namespace;
- как переиспользуемый шаблон прав, который затем привязывается через RoleBinding в конкретном namespace.
По умолчанию предпочтительнее использовать Role и RoleBinding.
ClusterRoleBinding следует применять только тогда, когда сервису действительно нужны права на уровне всего кластера.
Пример минимального RBAC
Сервису orders-api разрешено читать только один ConfigMap в namespace orders:
apiVersion: v1
kind: ServiceAccount
metadata:
name: orders-api
namespace: orders
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: orders-config-reader
namespace: orders
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["orders-config"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: orders-api-config-reader
namespace: orders
subjects:
- kind: ServiceAccount
name: orders-api
namespace: orders
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: orders-config-reader
Такой сервис не сможет:
- читать другие ConfigMap;
- читать Secrets;
- изменять Deployment;
- выполнять команды в других Pods;
- работать с объектами в других namespace.
Важная особенность Kubernetes RBAC
Kubernetes RBAC работает по модели разрешений.
Явного deny в RBAC нет.
Если субъект получил право хотя бы через одну Role, ClusterRole или binding, это право считается разрешённым.
Поэтому права из разных ролей складываются.
Нельзя выдать широкую роль, а затем другой ролью запретить часть операций.
Какие права особенно опасны
Особого контроля требуют разрешения на:
- чтение Secrets;
- создание и изменение RoleBinding и ClusterRoleBinding;
- создание Pods с произвольным ServiceAccount;
pods/exec;pods/attach;pods/portforward;- изменение admission webhooks;
- изменение CustomResourceDefinition;
- использование
impersonate; - доступ ко всем ресурсам через
resources: ["*"]; - выполнение всех операций через
verbs: ["*"].
Формально такие права могут не называться cluster-admin, но на практике часто позволяют повысить привилегии.
Нужно ли монтировать ServiceAccount token
Если приложению не требуется доступ к Kubernetes API, стандартный ServiceAccount token лучше не монтировать:
spec:
template:
spec:
serviceAccountName: orders-api
automountServiceAccountToken: false
Это уменьшает количество credentials внутри контейнера.
EKS Pod Identity и IRSA используют отдельные механизмы передачи workload token, поэтому отсутствие обычного Kubernetes API token не отменяет необходимость правильно настроить IAM-доступ приложения.
Доступ пользователей и CI/CD к Kubernetes API
Доступ инженеров, администраторов, Terraform, CI/CD и GitOps контроллеров должен рассматриваться отдельно от доступа приложений.
Для новых кластеров EKS основной механизм - EKS Access Entries.
Access Entry связывает IAM principal с конкретным кластером EKS.
В качестве principal обычно используется IAM Role:
Пользователь или CI/CD
-> AssumeRole
-> IAM Role
-> EKS Access Entry
-> EKS Access Policy или Kubernetes RBAC
-> Kubernetes API
После создания Access Entry права можно задать двумя способами.
EKS Access Policies
К Access Entry можно привязать готовую EKS Access Policy.
Она может дать доступ:
- ко всему кластеру;
- только к определённым namespace;
- на уровне администратора;
- на уровне редактирования;
- на уровне просмотра.
Важно: EKS Access Policy - это не обычная IAM policy.
Она задаёт права внутри Kubernetes API, а не права на вызовы AWS API.
Kubernetes RBAC через группы
Access Entry можно связать с Kubernetes group.
После этого права группы задаются обычными RoleBinding и ClusterRoleBinding.
Этот вариант подходит, когда готовые EKS Access Policies слишком широкие и требуется более точное управление правами.
Например:
IAM Role команды orders
-> EKS Access Entry
-> Kubernetes group: orders-developers
-> RoleBinding в namespace orders
Что делать с aws-auth
ConfigMap aws-auth долгое время использовался для привязки IAM ролей и пользователей к Kubernetes-группам.
Сейчас этот механизм считается устаревающим.
Для новых кластеров следует использовать EKS Access Entries.
Для существующих кластеров возможен переходный режим API_AND_CONFIG_MAP, в котором одновременно работают Access Entries и aws-auth.
Практические правила для доступа людей
- использовать IAM Roles, а не постоянные IAM User credentials;
- использовать AWS IAM Identity Center или другой механизм федерации;
- не выдавать
cluster-adminдля ежедневной работы; - ограничивать команды своими namespace;
- создать отдельную break-glass роль для аварийного доступа;
- отдельно разделять роли чтения, эксплуатации и администрирования;
- описывать Access Entries и bindings через Infrastructure as Code.
Права из EKS Access Policies и Kubernetes RBAC складываются.
Поэтому нельзя считать, что более узкий RoleBinding ограничит широкую Access Policy.
Также команда kubectl auth can-i показывает Kubernetes RBAC, но не всегда отражает права, полученные через EKS Access Policies. При аудите необходимо проверять оба механизма.
Управление EKS через AWS API
Отдельный контур - права на управление самим сервисом Amazon EKS.
Это IAM разрешения на операции вида:
- создание и удаление кластеров;
- изменение endpoint access;
- создание managed node groups;
- установка add-ons;
- создание Access Entries;
- создание Pod Identity Associations;
- обновление версии Kubernetes;
- изменение параметров control plane.
Например, право вызвать eks:UpdateClusterConfig относится к AWS API.
Оно не равно праву изменить Deployment через Kubernetes API.
И наоборот, пользователь с cluster-admin внутри Kubernetes не обязательно имеет право изменить настройки кластера через AWS API.
Эти два типа административного доступа необходимо разделять.
Права приложений в AWS
Доступ приложений к S3, SQS, DynamoDB, Secrets Manager, KMS и другим сервисам AWS должен осуществляться через временные credentials.
Статические значения AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY не должны храниться:
- в Kubernetes Secrets;
- в ConfigMap;
- в Helm values;
- в CI/CD variables без необходимости;
- внутри контейнерного образа.
В Amazon EKS для workload identity используются два основных механизма:
- EKS Pod Identity;
- IAM Roles for Service Accounts, или IRSA.
EKS Pod Identity
Для новых приложений на Linux EC2 нодах EKS основной вариант - EKS Pod Identity.
Связка выглядит так:
Pod
-> Kubernetes ServiceAccount
-> EKS Pod Identity Association
-> IAM Role
-> временные credentials
-> AWS API
Для работы Pod Identity:
- В кластере работает EKS Pod Identity Agent.
- Создаётся IAM роль с trust policy для сервиса
pods.eks.amazonaws.com. - В EKS создаётся association между:
- кластером;
- namespace;
- ServiceAccount;
- IAM ролью.
- AWS SDK внутри приложения получает временные credentials через стандартную credential provider chain.
Пример trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "pods.eks.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
}
Пример создания association:
aws eks create-pod-identity-association \
--cluster-name production \
--namespace orders \
--service-account orders-api \
--role-arn arn:aws:iam::111122223333:role/orders-api
Аннотация на ServiceAccount для Pod Identity не требуется.
Связь хранится на уровне EKS API.
Преимущества Pod Identity
- не требуется отдельный IAM OIDC provider для каждого кластера;
- trust policy IAM роли проще переиспользовать между кластерами;
- association явно связывает роль с cluster, namespace и ServiceAccount;
- поддерживаются session tags;
- session tags можно использовать для ABAC;
- проще централизованно управлять большим количеством кластеров и ролей.
Ограничения Pod Identity
Pod Identity используется для Pods на поддерживаемых Linux EC2 нодах Amazon EKS.
Он не заменяет IRSA для всех сценариев.
В частности, IRSA остаётся необходимым вариантом для:
- AWS Fargate;
- Windows worker nodes;
- сред, где Pod Identity Agent недоступен;
- существующих интеграций, которые уже корректно работают через IRSA.
IRSA: IAM Roles for Service Accounts
IRSA остаётся актуальным и поддерживаемым механизмом.
Связка выглядит так:
Pod
-> Kubernetes ServiceAccount
-> OIDC token
-> AWS STS AssumeRoleWithWebIdentity
-> IAM Role
-> временные credentials
-> AWS API
Для работы IRSA:
- Для кластера EKS настраивается IAM OIDC identity provider.
- Для приложения создаётся IAM роль.
- В trust policy роли указывается конкретный ServiceAccount и namespace.
- К IAM-роли прикрепляется минимально необходимая IAM policy.
- ServiceAccount аннотируется ARN IAM роли.
- AWS SDK внутри приложения обменивает подписанный token на временные credentials через AWS STS.
Пример ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
name: orders-api
namespace: orders
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/orders-api
Пример основной части trust policy:
{
"Condition": {
"StringEquals": {
"oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLE:aud": "sts.amazonaws.com",
"oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLE:sub": "system:serviceaccount:orders:orders-api"
}
}
}
Условие sub ограничивает использование роли конкретным ServiceAccount в конкретном namespace.
Условие aud подтверждает, что token предназначен для AWS STS.
Не следует без необходимости разрешать AssumeRole всем ServiceAccount кластера или всему namespace.
Что именно происходит при запуске Pod с IRSA
EKS не передаёт приложению постоянные AWS ключи.
В Pod монтируется подписанный ServiceAccount token.
AWS SDK находит этот token через стандартную credential provider chain, вызывает STS AssumeRoleWithWebIdentity и получает временные credentials IAM-роли.
Поэтому приложению не нужно самостоятельно хранить или обновлять AWS-ключи.
Pod Identity или IRSA
Практический выбор можно свести к следующей таблице.
| Сценарий | Рекомендуемый механизм |
|---|---|
| Новое приложение на Linux EC2-нодах EKS | EKS Pod Identity |
| Pod на AWS Fargate | IRSA |
| Pod на Windows worker node | IRSA |
| Существующая рабочая интеграция через IRSA | можно оставить IRSA |
| Одна IAM-роль используется в нескольких кластерах | EKS Pod Identity |
| Требуется ABAC по cluster, namespace или ServiceAccount | EKS Pod Identity |
| Среда вне стандартного Amazon EKS | зависит от среды, часто IRSA или другой OIDC-механизм |
Оба механизма решают одну задачу: дают приложению временные AWS credentials без статических ключей.
Основное различие - в способе установления доверия и связывания ServiceAccount с IAM ролью.
IAM политики приложений
Независимо от того, используется Pod Identity или IRSA, IAM policy должна быть минимальной.
Плохо:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
Лучше:
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::orders-archive/incoming/*"
}
Следует ограничивать:
- список действий;
- список ресурсов;
- конкретные S3 prefixes;
- конкретные SQS queues;
- конкретные DynamoDB tables;
- конкретные Secrets Manager secrets;
- конкретные KMS keys;
- регион и аккаунт, где это возможно;
- дополнительные условия через IAM Conditions.
Для крупных платформ можно использовать ABAC, но только если схема тегов и правила их назначения контролируются централизованно.
Роль рабочей ноды
Использование Pod Identity или IRSA не отменяет IAM роль рабочей ноды.
Node IAM Role по-прежнему требуется для системных операций.
Например:
- регистрация ноды в кластере;
- работа kubelet;
- получение контейнерных образов из Amazon ECR;
- взаимодействие с EC2 и VPC на системном уровне;
- работа EKS Pod Identity Agent;
- работа сетевых компонентов в некоторых конфигурациях.
Правильный принцип:
Node IAM Role
-> только системные права ноды
Application IAM Role
-> только прикладные права конкретного сервиса
Неправильный принцип:
Node IAM Role
-> доступ ко всем S3, SQS, DynamoDB и Secrets Manager
-> все Pods на ноде потенциально наследуют общий риск
Почему нельзя выдавать прикладные права ноде
Если IAM права приложения находятся в роли ноды, невозможно надёжно определить:
- какой сервис использует конкретное разрешение;
- как отозвать доступ только у одного сервиса;
- какой Pod обращался к AWS API;
- как ограничить blast radius при компрометации контейнера.
Кроме того, Pod может попытаться получить credentials instance profile через EC2 Instance Metadata Service.
Поэтому необходимо:
- ограничивать доступ Pods к IMDS;
- использовать IMDSv2;
- не запускать обычные приложения с
hostNetwork: trueбез необходимости; - не использовать privileged containers без необходимости;
- переносить системные add-ons на отдельные workload IAM роли, где это поддерживается.
Например, AWS VPC CNI лучше использовать с отдельной IAM ролью, а не хранить его права в общей роли ноды.
Fargate Pod Execution Role
Для AWS Fargate используется Fargate Pod Execution Role.
Она нужна инфраструктуре Fargate, например для загрузки контейнерного образа.
Эта роль не должна рассматриваться как прикладная роль контейнера.
Для доступа самого приложения к S3, SQS, DynamoDB и другим AWS сервисам на Fargate используется IRSA.
Даёт ли отдельная IAM роль полную изоляцию
Отдельный ServiceAccount и отдельная IAM роль значительно уменьшают blast radius, но сами по себе не создают абсолютную границу безопасности.
Компрометация одного сервиса не должна давать доступ к ресурсам других сервисов, если одновременно выполнены следующие условия:
- IAM policy ограничена конкретными действиями и ресурсами;
- trust policy ограничена конкретным ServiceAccount;
- у Pod нет доступа к credentials роли ноды;
- у ServiceAccount нет избыточных Kubernetes RBAC-прав;
- сервис не может создавать Pods от имени чужого ServiceAccount;
- сервис не может изменять RoleBinding и ClusterRoleBinding;
- сервис не может выполнять команды в Pods других приложений;
- сервис не может читать чужие Secrets;
- Pod не запущен в privileged режиме без необходимости;
- не используются опасные host mounts;
- сетевой доступ также ограничен.
Поэтому корректный вывод выглядит так:
Выделенная workload identity не гарантирует абсолютную изоляцию, но существенно уменьшает последствия компрометации и делает права приложения явными, проверяемыми и независимо отзываемыми.
Сетевой доступ как дополнительный уровень защиты
IAM и Kubernetes RBAC отвечают за авторизацию.
Они не заменяют сетевую сегментацию.
Дополнительно следует использовать:
- private endpoint Kubernetes API;
- ограничение public endpoint по CIDR или его отключение;
- Kubernetes NetworkPolicy;
- Security Groups for Pods, если они подходят архитектуре;
- отдельные namespaces и node groups для разных уровней доверия;
- ограничение egress доступа;
- VPC endpoints для AWS-сервисов, где это необходимо.
Например, IAM policy может разрешать доступ только к одной SQS queue, а NetworkPolicy - запрещать сервису произвольные соединения с другими приложениями внутри кластера.
Это разные уровни защиты, которые дополняют друг друга.
Аудит и эксплуатация
Модель прав должна быть не только минимальной, но и проверяемой.
Для аудита используются несколько источников.
AWS CloudTrail
CloudTrail позволяет увидеть:
- изменения IAM-ролей и политик;
- создание и изменение Access Entries;
- создание Pod Identity Associations;
- вызовы AWS API от имени workload IAM-роли;
- изменения настроек EKS.
EKS control plane logs:
Для Kubernetes API следует включить control plane logs, в первую очередь:
audit;authenticator;api.
Audit logs позволяют увидеть, какой Kubernetes субъект выполнял операции с объектами кластера.
Infrastructure as Code:
Через код должны управляться:
- IAM Roles;
- IAM Policies;
- trust policies;
- EKS Access Entries;
- EKS Access Policies;
- Pod Identity Associations;
- Kubernetes ServiceAccounts;
- Roles и ClusterRoles;
- RoleBindings и ClusterRoleBindings;
- настройки endpoint access;
- control plane logging.
Это позволяет:
- проводить code review;
- видеть историю изменений;
- обнаруживать ручные изменения;
- сравнивать права между средами;
- автоматически проверять политики.
Что проверять регулярно:
Необходимо периодически отвечать на следующие вопросы:
- какие IAM роли имеют доступ к Kubernetes API;
- кто имеет
cluster-admin; - какие ServiceAccount имеют ClusterRoleBinding;
- кто может читать Secrets;
- кто может использовать
pods/exec; - кто может создавать Pods с произвольным ServiceAccount;
- какие IAM policies содержат wildcard actions или resources;
- есть ли неиспользуемые Access Entries;
- есть ли неиспользуемые IAM роли;
- какие Pods могут получить credentials ноды;
- какие роли используются сразу несколькими несвязанными сервисами;
- какие права можно удалить на основе CloudTrail и audit logs.
Рекомендуемая итоговая модель
Пользователи и CI/CD:
IAM Role
-> EKS Access Entry
-> EKS Access Policy или Kubernetes RBAC
-> Kubernetes API
Приложение внутри Kubernetes:
Kubernetes ServiceAccount
-> Role или ClusterRole
-> RoleBinding или ClusterRoleBinding
-> Kubernetes API
Приложение в AWS:
Kubernetes ServiceAccount
-> EKS Pod Identity или IRSA
-> IAM Role
-> конкретные AWS ресурсы
Рабочая нода:
Node IAM Role
-> только системные разрешения
-> без прикладного доступа к данным сервисов
Основные правила
- Каждый сервис запускается от выделенного ServiceAccount.
- Права внутри Kubernetes выдаются только через RBAC.
- По умолчанию используются namespace-scoped Role и RoleBinding.
- ClusterRoleBinding применяется только при реальной необходимости.
- Доступ приложения к AWS выдаётся через EKS Pod Identity или IRSA.
- Для новых workload на Linux EC2 нодах предпочтителен EKS Pod Identity.
- Для Fargate и Windows используется IRSA.
- IAM policy ограничивается конкретными actions и resources.
- Trust policy ограничивается конкретной workload identity.
- Прикладные AWS права не добавляются в Node IAM Role.
- Статические AWS ключи не хранятся в Kubernetes.
- Доступ людей и CI/CD управляется через EKS Access Entries.
aws-authне используется как основной механизм для новых кластеров.- Административные права AWS API и Kubernetes API разделяются.
- Все права описываются через Infrastructure as Code.
- CloudTrail и Kubernetes audit logs включены и регулярно анализируются.
Вывод
Модель прав доступа в Amazon EKS состоит не из одной связи ServiceAccount с IAM ролью, а из нескольких независимых уровней.
Для приложений центральным идентификатором является Kubernetes ServiceAccount.
Через Kubernetes RBAC он определяет права сервиса внутри кластера.
Через EKS Pod Identity или IRSA он связывается с IAM ролью и получает ограниченный доступ к AWS API.
Доступ людей и CI/CD к Kubernetes API управляется отдельно через EKS Access Entries, EKS Access Policies и Kubernetes RBAC.
Рабочие ноды сохраняют собственную IAM роль, но эта роль должна содержать только системные разрешения и не использоваться для доступа приложений к бизнес ресурсам.
В результате каждый субъект получает только тот набор прав, который необходим ему для работы:
- приложение - к своим Kubernetes объектам и AWS ресурсам;
- инженер - к нужным namespace;
- CI/CD - к конкретным операциям развёртывания;
- нода - только к системным функциям;
- администратор - к управлению платформой в рамках отдельной роли.
Такая модель уменьшает blast radius, упрощает аудит, исключает статические ключи и позволяет независимо отзывать права каждого сервиса, пользователя или компонента платформы.
Комментарии