Модуль 1.6: RBAC — рольовий контроль доступу
Складність:
[СЕРЕДНЯ]— поширена тема на іспитіЧас на проходження: 40–50 хвилин
Передумови: Модуль 1.1 (Площина управління), розуміння просторів імен
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете:
- Спроєктувати області видимості RBAC на рівні простору імен і кластера для доступу команд за принципом найменших привілеїв.
- Впровадити Role, ClusterRole, RoleBinding, ClusterRoleBinding та прив’язки сервісних акаунтів за допомогою
kubectl. - Діагностувати помилки авторизації Forbidden за допомогою
kubectl auth can-i, імперсонації та перевірки прив’язок. - Оцінити ризики підвищення привілеїв через символи підстановки, вбудовані ролі,
bind,escalate,impersonateта доступ до Secret’ів. - Порівняти RBAC із режимами авторизації Node та Webhook для спеціалізованих вимог безпеки.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: платформа розробки розміщує п’ять продуктових команд в одному кластері Kubernetes, де кожну команду ізольовано простором імен, а кожен конвеєр розгортання працює як власний сервісний акаунт. Одна команда просить дозвіл перезапускати поди, інша просить доступ лише для читання до журналів продакшену, а стек моніторингу просить можливість виявляти поди в кожному просторі імен. Якщо адміністратор надає cluster-admin, бо так швидше, кластер працюватиме наступну годину, але кожне скомпрометоване робоче навантаження й кожен викрадений токен конвеєра тепер матимуть шлях до контролю над продакшеном.
RBAC — це механізм, який перетворює ці неформальні прохання на точні дозволи API. Автентифікація лише відповідає на питання, хто зробив запит; авторизація вирішує, чи може ця ідентичність виконати дієслово на кшталт get, create або delete щодо ресурсу на кшталт pods, deployments, secrets чи rolebindings. Іспит Certified Kubernetes Administrator очікує, що ви ухвалюватимете це рішення під тиском часу, але та сама навичка важливіша у продакшені, бо помилки RBAC залишаються непомітними доти, доки користувача не заблокують або доки атакувальника не зупинять.
Цей модуль навчає RBAC як інструмент операційного проєктування, а не як купу YAML. Ви побудуєте ті самі чотири види об’єктів RBAC, що використовуються в реальних кластерах, прив’яжете їх до користувачів, груп і сервісних акаунтів, перевірите результат за допомогою імперсонації та поміркуєте про вбудовані ролі, агрегацію й засоби контролю ескалації. Мета не в тому, щоб запам’ятати кожен рядок дозволу; мета — прочитати помилку Forbidden і точно знати, яка область видимості, суб’єкт, посилання на роль чи дієслово могли б її пояснити.
Аналогія з фізичною перепусткою корисна, доки ви тримаєте область видимості чіткою. Role чи ClusterRole — це рівень перепустки, який визначає, до яких кімнат можна заходити, тоді як RoleBinding чи ClusterRoleBinding — це призначення, що видає цей рівень перепустки особі, групі або робочій ідентичності. Kubernetes додає один важливий нюанс: придатне для повторного використання визначення перепустки рівня кластера можна видати лише всередині одного простору імен, коли RoleBinding посилається на ClusterRole.
Конвеєр авторизації: хто вирішує?
Розділ «Конвеєр авторизації: хто вирішує?»Кожен запит до API Kubernetes надходить до API-сервера з набором атрибутів: автентифікований користувач, необов’язкові групи, запитуване дієслово, група API, ресурс, простір імен, ім’я ресурсу та інколи URL без ресурсу на кшталт /metrics. Авторизація починається лише після того, як автентифікація ідентифікувала того, хто робить запит, тож RBAC не є системою входу. Це шар політики, який відповідає на питання, чи може вже ідентифікований суб’єкт виконати одну запитувану дію.
API-сервер може запускати кілька авторизаторів, і їхній порядок має значення. Традиційний прапорець — --authorization-mode, зі значеннями на кшталт Node, RBAC, Webhook, ABAC (застарілий і відсутній у кластерах для іспиту CKA), AlwaysAllow та AlwaysDeny; сучасні кластери також можуть використовувати файл конфігурації авторизації. Кожен авторизатор повертає «дозволити», «заборонити» або «не маю думки», і API-сервер зупиняється, щойно якийсь авторизатор дає остаточну відповідь.
Дозволи RBAC є адитивними, тобто немає правила заборони, яке можна було б розмістити в Role, щоб скасувати дозвіл, наданий деінде. Якщо в Аліси є одна прив’язка, що надає get для подів, і ще одна, що надає delete для подів, Аліса має обидві можливості. Така адитивна модель робить обчислення передбачуваним, але вона також означає, що найменші привілеї треба проєктувати, надаючи менше, а не надаючи широко й намагаючись відняти пізніше.
Авторизація також відокремлена від контролю допуску. RBAC може вирішити, що користувач може створювати поди, але плагіни допуску все одно отримують пізнішу нагоду відхилити под, бо він порушує Pod Security, квоту, політику образів чи інше правило кластера. Ця відмінність має значення, коли ви бачите помилку після того, як RBAC виглядає правильним: Forbidden зазвичай вказує на авторизацію, тоді як повідомлення про валідацію чи допуск часто вказують на пізнішу стадію площини управління.
Небезпечна конфігурація, яку варто запам’ятати, — це AlwaysAllow,RBAC. Оскільки перший авторизатор схвалює все, RBAC ніколи не отримує корисної нагоди щось обмежити, і кластер поводиться так, наче авторизацію вимкнено. Ця деталь виглядає простою, але вона добра пастка для іспиту, бо прапорець усе ще містить слово RBAC, хоча попередній авторизатор уже ухвалив рішення.
Авторизація Node — це режим спеціального призначення для kubelet’ів, а не загальна заміна RBAC. Облікові дані kubelet мають ідентифікуватися як system:node:<nodeName> і належати до групи system:nodes; авторизатор Node тоді дозволяє kubelet читати й записувати лише ті об’єкти API, які потрібні для подів, запланованих на цю ноду. У посиленому кластері авторизацію Node поєднують із плагіном допуску NodeRestriction, який обмежує kubelet’и власним об’єктом Node та власними прив’язаними подами.
Авторизація Webhook делегує рішення зовнішньому HTTP-сервісу. Це може бути корисно, коли кластер має інтегруватися з центральним рушієм політик чи корпоративним сервісом авторизації, але це також додає синхронну залежність на шлях запиту. Якщо вебхук повільний, недоступний або налаштований з неправильною поведінкою при відмові, звичайні запити до API можуть стати повільними або зазнавати невдачі навіть тоді, коли об’єкти RBAC усередині кластера виглядають правильно.
Не плутайте авторизацію Webhook із вебхуками допуску — валідаційними чи мутаційними. Вебхуки авторизації відповідають на питання, чи дозволено запит узагалі, перед збереженням і перед тим, як допуск змінить об’єкт. Вебхуки допуску оцінюють об’єкт після того, як авторизація вже дозволила операцію, тобто вони добрі для політики щодо форми об’єкта, але не є заміною правильного RBAC щодо того, хто може викликати API.
Зробіть паузу й передбачте: якщо кластер працює з Node,RBAC,Webhook, запит kubelet може бути схвалений авторизацією Node ще до того, як консультуватимуть RBAC, тоді як запит людини-користувача до простору імен зазвичай доходить до RBAC. Чого б ви очікували, якби кожен авторизатор повертав «не маю думки»? Усталеною відповіддю є заборона, тож чиста відповідь Forbidden часто означає, що жоден налаштований авторизатор не знайшов відповідного дозволу.
Коли ви усуваєте проблеми з авторизацією, відокремлюйте шлях запиту від об’єкта політики. Помилку Forbidden у kubectl get pods -n dev могло спричинити відсутність RoleBinding, неправильний суб’єкт, Role у неправильному просторі імен або невідповідність групи API. Помилка Forbidden від kubelet чи агрегованого API-сервера натомість може стосуватися авторизації Node чи Webhook, тож перше діагностичне питання завжди таке: яка ідентичність і який авторизатор насправді задіяні.
Об’єкти RBAC: область видимості, правила та групи API
Розділ «Об’єкти RBAC: область видимості, правила та групи API»API RBAC має чотири види об’єктів, усі в групі API rbac.authorization.k8s.io. Role та ClusterRole визначають дозволи, тоді як RoleBinding і ClusterRoleBinding прикріплюють ці дозволи до суб’єктів. Більшість завдань CKA можна розв’язати, правильно поєднавши ці чотири об’єкти із запитуваним простором імен та запитуваною ідентичністю суб’єкта.
| Ресурс | Область видимості | Призначення |
|---|---|---|
| Role | Простір імен | Надає дозволи в межах простору імен |
| ClusterRole | Кластер | Надає дозволи на рівні всього кластера |
| RoleBinding | Простір імен | Прив’язує Role/ClusterRole до суб’єктів у просторі імен |
| ClusterRoleBinding | Кластер | Прив’язує ClusterRole до суб’єктів на рівні всього кластера |
Role завжди належить одному простору імен, і кожне правило всередині цієї Role обчислюється лише для запитів у цьому просторі імен. ClusterRole не прив’язана до простору імен, тож вона може описувати дозволи для ресурсів кластерного рівня, як-от Node та PersistentVolume, або визначати придатні для повторного використання дозволи для ресурсів простору імен, як-от поди та сервіси. Тонкий, але потужний патерн — це використання RoleBinding простору імен, яка посилається на ClusterRole: вона повторно використовує набір правил ClusterRole, обмежуючи надання простором імен RoleBinding.
flowchart LR subgraph Subjects ["Subject (Who?)"] U["User\nAlice"] SA["Service\nAccount"] G["Group"] end
subgraph Roles ["Role (What permissions?)"] R["Role\nverbs:\n- get\n- list\n- create"] end
subgraph Resources ["Resources (Which things?)"] P["pods"] S["services"] SEC["secrets"] end
U -. "Bound\nvia\nBinding" .-> R R --> P R --> S R --> SECУявіть правило як речення з трьома обов’язковими іменниками: група API, ресурс і дієслово. Група API визначає сімейство API, ресурс визначає колекцію об’єктів або субресурс, а дієслово визначає операцію. Якщо будь-яка частина неправильна, правило може виглядати розумним для людини, але не відповідатиме реальному запиту, який обчислює API-сервер.
| Дієслово | Опис |
|---|---|
get | Прочитати один ресурс |
list | Отримати список ресурсів (отримати всі) |
watch | Спостерігати за змінами |
create | Створити нові ресурси |
update | Змінити наявні ресурси |
patch | Частково змінити ресурси |
delete | Видалити ресурси |
deletecollection | Видалити кілька ресурсів |
Поширена група лише для читання — це get, list та watch, і ви постійно бачитимете цю комбінацію в ролях для перегляду та ролях моніторингу. Доступ для читання-запису зазвичай додає create, update, patch та delete, тоді як повний контроль використовує * для всіх дієслів. Символи підстановки зручні в лабораторії, але в спільному кластері вони також надають майбутні дієслова та майбутні ресурси, яких не існувало, коли роль було написано.
Дієслова Kubernetes — це логічні операції API, а не завжди команди оболонки один-до-одного. Команда на кшталт kubectl logs зазвичай перевіряє субресурс журналу пода, тоді як kubectl scale перевіряє субресурс scale для типу робочого навантаження. Коли команда несподівано не спрацьовує, перекладіть команду на ресурс і субресурс, які бачить API-сервер; інакше ви можете й далі надавати доступ до батьківського ресурсу, тоді як фактичний субресурс залишається забороненим.
RBAC містить особливі адміністративні дієслова, які мають змусити вас пригальмувати. Дієслово bind контролює, чи може користувач створити прив’язку, що посилається на роль, дозволами якої він ще не володіє. Дієслово escalate контролює, чи може користувач створити або оновити Role чи ClusterRole з дозволами понад власні, а impersonate дозволяє суб’єкту запиту діяти від імені іншого користувача, групи чи сервісного акаунта для запитів до API.
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-reader namespace: defaultrules: - apiGroups: [""] # "" = core API group (pods, services, etc.) resources: ["pods"] verbs: ["get", "list", "watch"]# Apply the Rolekubectl apply -f role-pod-reader.yaml
# Or create imperativelykubectl create role pod-reader \ --verb=get,list,watch \ --resource=pods \ -n defaultЦя Role навмисно вузька: вона надає доступ лише для читання до подів у просторі імен default і нічого більше. Вона не надає доступ до подів у production, не надає доступ до Secret’ів у default і не надає доступ до Node, бо Node мають кластерну область видимості. API-сервер не виводить пов’язані ресурси; ви маєте назвати кожен ресурс і субресурс, який насправді потрібен робочому навантаженню чи користувачу.
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: node-readerrules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"]# Applykubectl apply -f clusterrole-node-reader.yaml
# Or imperativelykubectl create clusterrole node-reader \ --verb=get,list,watch \ --resource=nodesClusterRole — це правильне місце для дозволів на Node, бо Node не належать простору імен. Якби ви спробували розмістити nodes у Role, об’єкт міг би бути прийнятий, але правило не може авторизувати запит до Node кластерного рівня всередині простору імен. Ця відмінність — поширене джерело помилок на іспиті, бо багато команд виглядають схожими, доки ви не запитаєте, чи має цільовий ресурс стовпець простору імен у kubectl api-resources.
Зробіть паузу й передбачте: ви створюєте Role з verbs: ["get", "list"] для resources: ["pods"] у просторі імен dev. Перш ніж щось перевіряти, вирішіть, чи може користувач бачити поди в production, отримувати список Node чи спостерігати за змінами подів у dev. Правильне міркування полягає в тому, що простір імен, ресурс і дієслово мають усі збігатися, тож дозволено лише get та list для подів у dev.
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: developer namespace: devrules: # Pods: full access - apiGroups: [""] resources: ["pods", "pods/log", "pods/exec"] verbs: ["*"]
# Deployments: full access - apiGroups: ["apps"] resources: ["deployments", "replicasets"] verbs: ["*"]
# Services: create and view - apiGroups: [""] resources: ["services"] verbs: ["get", "list", "create", "delete"]
# ConfigMaps: read only - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list"]
# Secrets: no access (not listed = denied)Кілька правил дозволяють вам виразити різні рівні дозволів для різних груп API, не створюючи окрему Role для кожного ресурсу. Зверніть увагу, що pods, services та configmaps використовують порожню основну групу API, тоді як deployments і replicasets використовують apps. Також зверніть увагу на відсутність Secret’ів: RBAC за замовчуванням забороняє, коли жодне правило не збігається, тож залишення Secret’ів поза переліком — це спосіб найменших привілеїв уникнути їх надання.
Поле resourceNames може обмежити правило конкретними наявними іменами об’єктів, як-от дозвіл оновлювати лише ConfigMap з іменем frontend-config. Це може бути корисним для оренд вибору лідера, схвалених об’єктів обслуговування або вузького автоматизаційного акаунта. Воно не може обмежити запити create верхнього рівня, бо ім’я об’єкта може не існувати на момент авторизації, і воно не може корисним для конкретного об’єкта способом обмежити deletecollection.
ClusterRole мають одну додаткову можливість, якої Role не мають: nonResourceURLs. Ці дозволи застосовуються до шляхів API-сервера, які не є об’єктами Kubernetes, як-от /healthz, /livez, /readyz чи /metrics. Оскільки URL без ресурсів не належать простору імен, Role простору імен не може їх надати, і правильний дизайн — це ClusterRole, прив’язана на рівні кластера або вузько до ідентичності, якій потрібна ця кінцева точка.
Іменовані ресурси — це ще одне місце, де форма запиту має значення. Якщо ви обмежуєте правило за допомогою resourceNames, запит, що отримує список колекції, має містити селектор поля для відповідного імені, бо API-сервер не може авторизувати необмежений список щодо одного дозволеного імені об’єкта. Це робить resourceNames корисним для дуже специфічної автоматизації, але незручним для людей, які очікують, що звичайні команди list і watch працюватимуть без додаткових селекторів.
| Група API | Ресурси |
|---|---|
"" (основна) | pods, services, configmaps, secrets, namespaces, nodes, persistentvolumes |
apps | deployments, replicasets, statefulsets, daemonsets |
batch | jobs, cronjobs |
networking.k8s.io | networkpolicies, ingresses |
rbac.authorization.k8s.io | roles, clusterroles, rolebindings, clusterrolebindings |
storage.k8s.io | storageclasses, volumeattachments |
# Find the API group for any resourcekubectl api-resources | grep deployment# NAME SHORTNAMES APIVERSION NAMESPACED KIND# deployments deploy apps/v1 true Deployment# ^^^^# API group is "apps"Перш ніж запускати це в середовищі іспиту, передбачте групу, яку ви очікуєте побачити, а потім перевірте її за допомогою kubectl api-resources. Ця звичка запобігає одній із найпоширеніших помилок RBAC: наданню apiGroups: [""] для ресурсу, який насправді живе в apps, batch чи іншій іменованій групі API. Основна група API — це порожній рядок "", а не "core", тому приклади YAML явно беруть порожнє значення в лапки.
Прив’язки, суб’єкти та ідентичність робочих навантажень
Розділ «Прив’язки, суб’єкти та ідентичність робочих навантажень»Суб’єкти RBAC — це ідентичності, які отримують дозволи. Суб’єктом може бути User, Group або ServiceAccount; сам Kubernetes не зберігає звичайні об’єкти User, тож ці імена надходять із шару автентифікації. ServiceAccount — це об’єкти API Kubernetes, і оскільки вони належать простору імен, суб’єкт ServiceAccount має містити і name, і namespace.
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: alice-pod-reader namespace: defaultsubjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.ioroleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io# Imperative commandkubectl create rolebinding alice-pod-reader \ --role=pod-reader \ --user=alice \ -n defaultЦя RoleBinding надає Алісі Role pod-reader лише в просторі імен default. RoleBinding належить простору імен навіть тоді, коли її суб’єкт є концепцією рівня кластера, як-от ім’я користувача чи групи. Якщо Алісі пізніше знадобиться той самий доступ у staging, ви створюєте ще одну RoleBinding у staging або використовуєте ретельно обрану ClusterRoleBinding, якщо доступ справді має охоплювати кожен простір імен.
Поле roleRef навмисно стабільне після створення прив’язки. На практиці, якщо прив’язка посилається на неправильну роль, видалення й повторне створення прив’язки зрозуміліше, ніж спроба перетворити одне надання на інше. Така поведінка підтримує можливість аудиту: зміна того, хто отримує роль, відрізняється від зміни того, яку роль надано, і інструменти перевірки можуть розглядати ці операції як окремі події безпеки.
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: bob-node-readersubjects: - kind: User name: bob apiGroup: rbac.authorization.k8s.ioroleRef: kind: ClusterRole name: node-reader apiGroup: rbac.authorization.k8s.io# Imperative commandkubectl create clusterrolebinding bob-node-reader \ --clusterrole=node-reader \ --user=bobClusterRoleBinding навмисно широка. Вона прив’язує ClusterRole по всьому кластеру, що необхідно для ресурсів кластерного рівня, як-от Node, але ризиковано, коли ClusterRole описує ресурси простору імен, як-от поди. Якщо ви прив’яжете view за допомогою ClusterRoleBinding, суб’єкт зможе переглядати дозволені ресурси в кожному просторі імен, а не лише в одному просторі імен команди.
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: dev-team-access namespace: developmentsubjects: # Bind to a user - kind: User name: alice apiGroup: rbac.authorization.k8s.io
# Bind to a group - kind: Group name: developers apiGroup: rbac.authorization.k8s.io
# Bind to a ServiceAccount - kind: ServiceAccount name: cicd-deployer namespace: developmentroleRef: kind: Role name: developer apiGroup: rbac.authorization.k8s.ioОдна прив’язка може містити кілька суб’єктів, але операційний компроміс — це чіткість аудиту. Прив’язка з іменем dev-team-access, яка надає доступ групі команди та акаунту конвеєра, може бути зручною, але вона також означає, що майбутні перевіряльники мають уважно дослідити перелік суб’єктів, щоб зрозуміти, хто має надання. У регульованих середовищах окремі прив’язки для людей і робочих навантажень часто роблять перевірку доступу легшою, навіть коли вони посилаються на те саме посилання на роль.
Зупиніться й подумайте: вам потрібно надати розробнику доступ лише для читання до подів у staging, але не в production. Ви можете створити Role pod-reader у staging і прив’язати її там, або створити придатну для повторного використання ClusterRole й прив’язати цю ClusterRole за допомогою RoleBinding у staging. Другий підхід зручніший для супроводу, коли багатьом просторам імен потрібні ті самі правила, тоді як RoleBinding усе одно тримає фактичне надання в межах простору імен.
# Use the built-in "edit" ClusterRole in the "production" namespace onlyapiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: alice-edit-production namespace: productionsubjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.ioroleRef: kind: ClusterRole # Using ClusterRole name: edit # Built-in ClusterRole apiGroup: rbac.authorization.k8s.io
# Alice can edit resources in "production" namespace onlyЦей приклад — патерн придатної для повторного використання ClusterRole в його найкомпактнішій формі. ClusterRole edit має кластерну область видимості як об’єкт, але RoleBinding існує в production, тож ефективний дозвіл застосовується лише всередині production. Це той патерн, до якого вам варто звертатися, коли багато просторів імен ділять один профіль дозволів, але кожен простір імен має різних користувачів, груп або сервісних акаунтів.
ServiceAccount надають ідентичність подам і контролерам. Под, який не встановлює .spec.serviceAccountName, отримує сервісний акаунт default у своєму просторі імен від контролера допуску ServiceAccount, і сучасний Kubernetes за замовчуванням монтує короткоживучі проєктовані токени, коли автоматичне монтування токенів увімкнено. Ця усталена ідентичність зазвичай має дуже мало дозволів, але це все одно ідентичність, яку вам слід враховувати в дизайні RBAC.
# List ServiceAccountskubectl get serviceaccountskubectl get sa
# Every namespace has a "default" ServiceAccountkubectl get sa default -o yaml# Create a ServiceAccountkubectl create serviceaccount myapp-sa
# Or with YAMLcat > myapp-sa.yaml << 'EOF'apiVersion: v1kind: ServiceAccountmetadata: name: myapp-sa namespace: defaultEOFkubectl apply -f myapp-sa.yamlСтворення спеціального сервісного акаунта — це еквівалент для робочого навантаження видачі окремої перепустки замість того, щоб дозволяти кожному процесу ділити загальну гостьову перепустку будівлі. Це дає вам одне місце для прив’язки дозволів, одну ідентичність для аудиту та одне ім’я для використання, коли помилка Forbidden повідомляє system:serviceaccount:<namespace>:<name>. Це також тримає дозволи застосунку окремо від дозволів конвеєра розгортання, які зазвичай мають бути різними ідентичностями.
Монтування токена ServiceAccount — це окреме дизайнерське рішення від надань RBAC. Под може мати ім’я ServiceAccount для секретів витягування образів чи угод щодо ідентичності, водночас вимикаючи автоматичне монтування токенів, коли він ніколи не викликає API Kubernetes. Зменшення впливу токенів не замінює RBAC, але воно зменшує цінність скомпрометованого контейнера, бо там може не бути доступних облікових даних API для повторного використання.
# Create a Rolekubectl create role pod-reader \ --verb=get,list,watch \ --resource=pods
# Bind it to the ServiceAccountkubectl create rolebinding myapp-pod-reader \ --role=pod-reader \ --serviceaccount=default:myapp-sa# ^^^^^^^^^^^^^^^^^# namespace:name formatapiVersion: v1kind: Podmetadata: name: myappspec: serviceAccountName: myapp-sa # Use this ServiceAccount containers: - name: myapp image: nginxВажлива діагностична деталь — це простір імен ServiceAccount. RoleBinding у production може прив’язати ServiceAccount із cicd, але суб’єкт має явно вказувати namespace: cicd; інакше прив’язка може посилатися на неправильну ідентичність або на ServiceAccount, який не використовується подом. Коли конвеєр повідомляє Forbidden, порівняйте ім’я ServiceAccount пода із суб’єктом RoleBinding, перш ніж переписувати саму Role.
Вбудовані ролі, агрегація та запобіжники ескалації
Розділ «Вбудовані ролі, агрегація та запобіжники ескалації»Kubernetes встановлює усталені ClusterRole та ClusterRoleBinding, щоб основні компоненти й поширені патерни доступу для користувачів працювали одразу. Деякі імена починаються з system:, що сигналізує про власність площини управління й має перешкоджати ручному редагуванню. Інші імена, як-от cluster-admin, admin, edit та view, призначені для того, щоб адміністратори прив’язували їх до користувачів, груп або сервісних акаунтів із ретельно обраною областю видимості.
| ClusterRole | Дозволи |
|---|---|
cluster-admin | Повний доступ до всього (суперкористувач) |
admin | Повний доступ у межах простору імен |
edit | Читання/запис більшості ресурсів, без RBAC |
view | Доступ лише для читання до більшості ресурсів |
Роль cluster-admin — це роль суперкористувача, і ClusterRoleBinding до неї фактично означає повний контроль над кластером. Роль admin зазвичай надають через RoleBinding у просторі імен, де вона дає широке адміністрування простором імен, не надаючи контролю над ресурсами кластерного рівня. Роль edit дозволяє більшість змін об’єктів простору імен, але уникає об’єктів RBAC, тоді як view є лише для читання й навмисно уникає Secret’ів, бо читабельні Secret’и часто означають придатні до використання облікові дані.
Вбудовані імена зручні, але їхнє значення для безпеки залежить від інших ідентичностей у просторі імен. Наприклад, суб’єкт із широкими правами створення подів може бути спроможним створити под, що використовує потужний сервісний акаунт, уже наявний у просторі імен, навіть якщо суб’єкт не може напряму редагувати об’єкти RBAC. Саме тому адміністрування простором імен — це не лише дієслова щодо ресурсів; воно також включає перегляд наявних сервісних акаунтів, Secret’ів і засобів контролю допуску.
# See all built-in ClusterRoleskubectl get clusterroles | grep -v "^system:"
# Inspect a ClusterRolekubectl describe clusterrole editAPI-сервер автоматично узгоджує усталені об’єкти RBAC під час запуску, коли RBAC активний. Якщо усталеній ClusterRole бракує потрібного правила або усталеній прив’язці бракує потрібного суб’єкта, Kubernetes відновлює відсутню частину, щоб основні компоненти продовжували працювати під час оновлень. Така поведінка захищає площину управління, але вона також означає, що вам не слід розглядати ручне редагування ролей system: як надійний механізм налаштування.
Агрегація ClusterRole — це точка розширення за вбудованими ролями admin, edit та view. ClusterRole може визначити aggregationRule, який вибирає інші ClusterRole за міткою, а контролер копіює вибрані правила в агреговану роль. Стандартні мітки відповідають патерну rbac.authorization.k8s.io/aggregate-to-<clusterrole-name>: "true", що дозволяє постачальникам кастомних ресурсів додавати правила читання чи редагування до звичних ролей для користувачів.
# Give alice admin access to namespace "myapp"kubectl create rolebinding alice-admin \ --clusterrole=admin \ --user=alice \ -n myapp
# Give bob view access to namespace "production"kubectl create rolebinding bob-view \ --clusterrole=view \ --user=bob \ -n productionАгрегація корисна, але це також місце, де маленька мітка може мати широкий вплив. ClusterRole з міткою для агрегації в view може надати кожному суб’єкту з доступом view доступ до нового кастомного ресурсу, тоді як мітка для агрегації в edit може надати мутацію в багатьох просторах імен, де прив’язано edit. Переглядайте мітки агрегації з такою самою серйозністю, яку ви застосовували б до прямих прив’язок.
Kubernetes містить явне запобігання ескалації для адміністрування RBAC. Користувач може створити або оновити Role чи ClusterRole лише тоді, коли він уже має кожен дозвіл, що міститься в новій ролі, якщо тільки він не має особливого дієслова escalate для цього типу ресурсу RBAC. Так само користувач може створити або оновити прив’язку лише тоді, коли він уже володіє дозволами вказаної ролі у відповідній області видимості, якщо тільки він не має дієслова bind для цієї ролі.
Цей запобіжник не дає розробнику простору імен надати собі cluster-admin лише тому, що він може створювати RoleBinding. Він також пояснює, чому адміністрування RBAC інколи дає збій у несподіваний спосіб: суб’єкт запиту може мати дозвіл створювати ресурс rolebindings, але не дозвіл прив’язувати потужну ClusterRole, названу в roleRef. Діагностуючи цей випадок, дослідіть і дозвіл створювати прив’язки, і повноваження суб’єкта прив’язувати вказану роль.
Запобігання підвищенню привілеїв застосовується на API-сервері, тож воно захищає і декларативні маніфести, і імперативні команди kubectl create rolebinding. Контролер GitOps, інсталятор пакетів чи людина-оператор усе одно представляють ідентичність, і ця ідентичність має бути авторизована для ролі чи прив’язки, яку вона намагається створити. Коли посібник зі встановлення просить bind чи escalate, розглядайте це як рішення безпеки платформи, а не як рутинний дозвіл простору імен.
Дієслово impersonate належить до тієї самої ментальної категорії, бо воно дозволяє суб’єкту попросити API-сервер обчислювати запити так, наче їх робить інший користувач, група чи сервісний акаунт. Адміністратори використовують імперсонацію для тестування й підтримки, але широка імперсонація рівноцінна широкому делегованому доступу. Якщо користувач може імперсонувати system:masters чи привілейований сервісний акаунт, кластер обчислюватиме його пізніші запити як цю сильнішу ідентичність.
Тестування та діагностика дозволів
Розділ «Тестування та діагностика дозволів»Усунення проблем RBAC має бути систематичним, бо багато збоїв виглядають однаково в командному рядку. Повідомлення Forbidden зазвичай містить користувача, дієслово, ресурс, групу API та простір імен, і ці поля — найшвидший шлях до зламаного об’єкта. Якщо помилка каже, що Аліса не може отримати список pods у групі API "" в просторі імен default, не починайте з Деплойментів чи ClusterRole для Node; починайте з дозволів на список подів у цьому просторі імен.
Що сталося б, якби ви створили дві RoleBinding у тому самому просторі імен — одну, що надає get для подів, і одну, що надає delete для подів? Користувач отримує обидва дозволи, бо RBAC є адитивним. Якщо ви хотіли б запобігти delete, ви видалили б прив’язку або уникнули надання ролі, що містить delete; ви не додавали б правило заборони, бо в RBAC немає правила заборони.
Команда kubectl auth can-i обгортає API перевірки авторизації Kubernetes, зокрема самоперевірки та імперсоновані перевірки. Це не заміна читанню YAML Role й прив’язки, але вона каже вам, яке рішення прийняв би API-сервер для конкретного запиту. Використовуйте її до та після зміни, щоб ви могли розрізнити «політику не застосовано» від «політику застосовано, але вона все одно неправильна».
# Check your own permissionskubectl auth can-i create podskubectl auth can-i delete deploymentskubectl auth can-i '*' '*' # Am I admin?
# Check in a specific namespacekubectl auth can-i create pods -n production
# Check for another user (requires admin)kubectl auth can-i create pods --as=alicekubectl auth can-i delete nodes --as=bob
# Check for a ServiceAccountkubectl auth can-i list secrets --as=system:serviceaccount:default:myapp-saПеревірки імперсонації вимагають дозволу імперсонувати цільову ідентичність, тож невдача із запуском діагностики сама по собі може бути проблемою RBAC. У кластері для іспиту ви часто працюєте як адміністратор і можете вільно використовувати --as; у продакшені роль підтримки може потребувати вузько обмеженої імперсонації, щоб тестувати сервісні акаунти, не отримуючи їхніх справжніх токенів. Завжди робіть імперсонований простір імен явним для сервісних акаунтів, використовуючи повний рядок system:serviceaccount:<namespace>:<name>.
# What can I do in this namespace?kubectl auth can-i --list
# What can alice do?kubectl auth can-i --list --as=alice
# What can a ServiceAccount do?kubectl auth can-i --list --as=system:serviceaccount:default:myapp-saФорма списку корисна для широких аудитів, але вона може бути зашумленою, бо дозволи з кількох прив’язок об’єднуються. Сфокусована перевірка на кшталт kubectl auth can-i get secrets -n production --as=... краща, коли ви маєте одну очікувану дію. Використовуйте форму списку, коли ви підозрюєте, що символ підстановки, вбудована роль чи ClusterRoleBinding надали більше, ніж передбачалося.
Перегляди правил також мають сліпу пляму: вони показують ефективні дозволи, які може підсумувати API-сервер, але не обов’язково організаційну причину, чому ці дозволи існують. Якщо користувач успадковує доступ через кілька груп, вивід може сказати вам, що delete pods дозволено, не називаючи квитка, команди чи бізнес-власника за наданням. Поєднуйте вивід команди з перевіркою прив’язок і членством у групах вашого провайдера ідентичності, коли виконуєте реальну перевірку доступу.
# Error: pods is forbiddenkubectl get pods# Error: User "alice" cannot list resource "pods" in API group "" in namespace "default"
# Debug steps:# 1. Check what permissions the user haskubectl auth can-i --list --as=alice
# 2. Check what roles are bound to the userkubectl get rolebindings -A -o wide | grep alicekubectl get clusterrolebindings -o wide | grep alice
# 3. Check the role's ruleskubectl describe role <role-name> -n <namespace>kubectl describe clusterrole <clusterrole-name>Сценарій вправи: конвеєр CI/CD не може розгорнути в production, а kubectl auth can-i create deployments -n production --as=system:serviceaccount:cicd:pipeline повертає no. Імовірний шлях пошуку — це простір імен суб’єкта, простір імен RoleBinding, група API Role та написання ресурсу deployment. Якщо RoleBinding живе в production, але суб’єкт випадково каже namespace: production, прив’язка посилається на system:serviceaccount:production:pipeline, а не на справжню ідентичність конвеєра в cicd.
Kubernetes 1.35 та новіші заслуговують особливої уваги щодо потокових субресурсів, які використовуються exec, attach та port-forward. Ці операції відкривають з’єднання до субресурсу пода, і сучасна авторизація очікує дозвіл create для субресурсів на кшталт pods/exec, pods/attach та pods/portforward. Застаріла роль, яка надавала лише get для pods/exec, може спричинити заплутані збої після оновлення, бо звичайні читання подів усе одно працюють.
Найбезпечніший спосіб оновити ці потокові дозволи — розглядати їх як інтерактивний доступ, а не як звичайний перегляд. Користувач, який може виконати exec у контейнер, може читати змінні середовища, досліджувати змонтовані файли та запускати команди з Linux-дозволами контейнера. Тому надання pods/exec має бути ближчим до надання доступу до оболонки, ніж до надання pods/log, і воно заслуговує на окрему роль, коли лише підмножині відповідальних потрібен цей доступ.
# FRAGILE (worked for kubectl's WebSocket path before v1.35):- apiGroups: [""] resources: ["pods/exec"] verbs: ["get"]
# CORRECT (required for SPDY and WebSocket, enforced everywhere in v1.35+):- apiGroups: [""] resources: ["pods/exec", "pods/attach", "pods/portforward"] verbs: ["get", "create"]Потокові субресурси завжди передбачали create як авторизаційне дієслово: застарілий транспорт SPDY завжди його вимагав. Шлях оновлення WebSocket, на який kubectl за замовчуванням переходить в останніх версіях, історично перевіряв лише get — невідповідність, що дозволяла ролі лише з get виконувати exec у поди. Kubernetes v1.35 закриває цю прогалину (перемикач можливостей AuthorizePodWebsocketUpgradeCreatePermission, бета й увімкнено за замовчуванням), тож надавайте create для цих субресурсів замість того, щоб покладатися на get.
Сценарії іспиту зазвичай поєднують помилки області видимості та суб’єкта, а не екзотичну поведінку авторизатора. Спершу пропрацюйте цільову дію: хто викликає, яке дієслово запитується, які група API та ресурс задіяні, і чи ресурс належить простору імен. Щойно ви зможете чітко вимовити це речення, потрібна Role, ClusterRole, RoleBinding чи ClusterRoleBinding часто стає очевидною.
# Create namespacekubectl create namespace development
# Create ServiceAccountkubectl create serviceaccount developer -n development
# Bind edit ClusterRole (read/write most resources)kubectl create rolebinding developer-edit \ --clusterrole=edit \ --serviceaccount=development:developer \ -n developmentЦей сценарій доступу розробника використовує вбудовану ClusterRole edit через RoleBinding простору імен. Надання широке всередині development, тож воно прийнятне для навчального простору імен чи довіреного пісочного середовища розробки, але воно було б надто широким для контролера, що лише оновлює Деплойменти. Дизайнерське питання не в тому, чи працює edit; питання в тому, чи відповідають його включені ресурси ризику ідентичності, що його отримує.
# ServiceAccount for monitoring toolskubectl create serviceaccount monitoring -n monitoring
# Cluster-wide read accesskubectl create clusterrolebinding monitoring-view \ --clusterrole=view \ --serviceaccount=monitoring:monitoringСценарій моніторингу використовує ClusterRoleBinding, бо сервісному акаунту потрібен доступ для читання в усіх просторах імен. Це все одно менш небезпечно, ніж cluster-admin, але воно не автоматично ідеальне, бо view включає багато читабельних ресурсів. Суворіший продакшен-дизайн може створити кастомну ClusterRole лише для подів, нод, просторів імен і ресурсів, пов’язаних із метриками, які інструмент моніторингу насправді використовує.
# Create role for deployments onlykubectl create role deployer \ --verb=get,list,watch,create,update,patch,delete \ --resource=deployments,services,configmaps \ -n production
# Bind to CI/CD ServiceAccountkubectl create rolebinding cicd-deployer \ --role=deployer \ --serviceaccount=cicd:pipeline \ -n productionПриклад CI/CD навмисно прив’язує сервісний акаунт із cicd у простір імен production. Це валідне міжпросторове надання суб’єкта, бо простір імен RoleBinding контролює, де застосовується дозвіл, тоді як простір імен суб’єкта визначає, який сервісний акаунт його отримує. Якщо конвеєру також потрібно створювати Job у batch, Role потребує правильної групи API та ресурсу, а не ширшої прив’язки.
# Task: Create a Role that can get, list, and watch pods and services in namespace "app"
kubectl create role app-reader \ --verb=get,list,watch \ --resource=pods,services \ -n app
# Task: Bind the role to user "john"kubectl create rolebinding john-app-reader \ --role=app-reader \ --user=john \ -n app
# Verifykubectl auth can-i get pods -n app --as=john# yeskubectl auth can-i delete pods -n app --as=john# noЦей швидкий патерн створення зручний для іспиту, бо він доводить і позитивний, і негативний випадки. Одне yes може приховати надто широку роль, тоді як парне no підтверджує, що роль випадково не включила мутацію. Коли час дозволяє, перевірте також межу простору імен, бо багато помилок RBAC виникають через створення правильної Role в неправильному просторі імен.
# Task: Create ServiceAccount "dashboard" that can list pods across all namespaces
kubectl create serviceaccount dashboard -n kube-system
kubectl create clusterrole pod-list \ --verb=list \ --resource=pods
kubectl create clusterrolebinding dashboard-pod-list \ --clusterrole=pod-list \ --serviceaccount=kube-system:dashboardСценарій дашборда потребує доступу рівня кластера до ресурсу, що належить простору імен, тож ClusterRoleBinding доречна. Сама ClusterRole навмисно мала: вона надає list для подів, а не get для Secret’ів, не delete для робочих навантажень і не широкий view, якщо тільки дашборду справді не потрібен кожен ресурс, який включає view. Це той тип мінімальної кастомної ролі, що перетворює RBAC із позначки в чек-листі на засіб контролю безпеки.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Використовуйте придатні для повторного використання ClusterRole разом із RoleBinding простору імен, коли багатьом просторам імен потрібен той самий профіль дозволів, але різні суб’єкти. Цей патерн дає вам один набір правил для супроводу й багато обмежених областю видимості надань для аудиту. Він особливо добре працює для ролей розробників команд, ролей підтримки лише для читання та локальної для простору імен автоматизації, що має поводитися послідовно в усіх середовищах.
Використовуйте спеціальні сервісні акаунти для кожного робочого навантаження чи межі автоматизації. Контролер розгортання, збирач моніторингу та інтерактивний под для діагностики мають різні причини викликати API, тож вони не повинні ділити сервісний акаунт default. Спеціальні ідентичності роблять помилки Forbidden легшими для читання й дають змогу відкликати дозволи одного робочого навантаження, не ламаючи кожен под у просторі імен.
Використовуйте kubectl auth can-i як дизайнерський тест, а не лише як аварійну діагностику. Після створення ролі перевірте принаймні один очікуваний дозвіл, одну очікувану заборону та одну межу простору імен. Ця звичка ловить поширені помилки, де роль надає правильний ресурс, але прив’язка націлюється на неправильний суб’єкт, або де ClusterRoleBinding випадково перетворює вимогу простору імен на надання рівня кластера.
Уникайте прив’язування cluster-admin до сервісних акаунтів застосунків. Команди часто роблять це, коли контролер дає збій під час встановлення, а документація чарта пропонує широку роль заради зручності. Краща альтернатива — дослідити фактичні виклики API контролера, почати з виявлення лише для читання за потреби та додати лише ті ресурси й дієслова, які потрібні для узгодження.
Уникайте правил із символами підстановки для довгоживучих продакшен-ідентичностей, якщо тільки ви не маєте навмисної причини на рівні платформи. Символ підстановки для дієслів чи ресурсів надає майбутню поверхню API в міру розвитку кластера, зокрема CRD, встановлені пізніше. Якщо вам потрібен тимчасовий символ підстановки для діагностики, зафіксуйте його як тимчасову роботу, швидко видаліть його та замініть явними дієсловами й ресурсами, перш ніж вважати інцидент закритим.
Уникайте ручного редагування ClusterRole system:. Автоматичне узгодження може відновити відсутні усталені дозволи, а неправильна зміна може зламати компоненти площини управління до того, як її буде скасовано. Якщо вам потрібно розширити ролі для користувачів для кастомних ресурсів, використовуйте мітки агрегації ClusterRole; якщо вам потрібна роль компонента для конкретної платформи, створіть окрему іменовану ClusterRole й прив’яжіть її явно.
Уникайте розгляду RBAC як межі мережевої безпеки. RBAC контролює дії API-сервера, а не трафік між подами, привілеї процесу всередині контейнера чи доступ до файлової системи всередині змонтованого тому. Поєднуйте його з NetworkPolicy, Pod Security, засобами контролю допуску, політикою образів і керуванням секретами, бо под без дозволів RBAC усе одно може завдати шкоди через інші шляхи, якщо цих шарів немає.
Структура прийняття рішень
Розділ «Структура прийняття рішень»Починайте кожне рішення RBAC із написання речення запиту: суб’єкт, дієслово, група API, ресурс, простір імен та ім’я ресурсу, якщо доречно. Наприклад, system:serviceaccount:cicd:pipeline потребує create для deployments.apps у production. Це речення каже вам, чи має роль належати простору імен, чи має прив’язка перетинати простір імен сервісного акаунта і чи вбудована роль надто широка.
Обирайте Role, коли дозвіл унікальний для одного простору імен і навряд чи буде повторно використаний. Обирайте ClusterRole, коли дозвіл стосується ресурсів кластерного рівня, URL без ресурсів чи придатного для повторного використання профілю дозволів для ресурсів простору імен. Обирайте RoleBinding, коли надання має застосовуватися в одному просторі імен, навіть якщо вказана роль є ClusterRole, та обирайте ClusterRoleBinding лише тоді, коли надання має застосовуватися на рівні всього кластера.
Коли суб’єкт — це людина, віддавайте перевагу прив’язкам груп від провайдера автентифікації над багатьма окремими прив’язками користувачів. Прив’язки груп дають змогу системам керування ідентичностями опрацьовувати процеси приєднання й вибуття, тоді як Kubernetes тримає стабільний об’єкт політики. Окремі прив’язки користувачів усе ще корисні для завдань іспиту, короткочасного аварійного доступу та малих кластерів, але вони погано старіють, коли команди змінюються.
Коли суб’єкт — це робоче навантаження, прив’язуйте точний сервісний акаунт, який використовується подом чи контролером. Не припускайте, що RoleBinding у цільовому просторі імен автоматично посилається на сервісний акаунт у цьому просторі імен чи в просторі імен конвеєра. Простір імен суб’єкта визначає ідентичність; простір імен прив’язки визначає, де застосовується Role чи надання простору імен.
Коли запит стосується pods/exec, pods/attach, pods/portforward, pods/log, deployments/scale чи будь-якого іншого субресурсу, називайте субресурс явно. Субресурси — це окремі цілі авторизації, бо вони надають інші можливості, ніж звичайні читання об’єктів. У Kubernetes 1.35 та новіших пам’ятайте, що субресурси потокового з’єднання потребують create для інтерактивної операції, а не лише дієслова читання для подів.
Коли наявна вбудована роль виглядає близькою, дослідіть її, перш ніж прив’язувати. Роль view уникає Secret’ів, edit може мутувати багато ресурсів простору імен і може дозволяти подам працювати як потужні сервісні акаунти, а admin ще ширша всередині простору імен. Правильне рішення базується на операційному завданні суб’єкта запиту, а не на дружньому імені вбудованої ролі.
Чи знали ви?
Розділ «Чи знали ви?»- RBAC увійшов у бета-стадію в Kubernetes v1.6 й досяг загальної доступності в Kubernetes v1.8, випущеному у вересні 2017 року.
- API RBAC використовує чотири види об’єктів: Role, ClusterRole, RoleBinding та ClusterRoleBinding.
- Поведінка токенів ServiceAccount суттєво змінилася після Kubernetes v1.24, де короткоживучі проєктовані токени замінили автоматичні довгоживучі токени-Secret для звичайних подів.
- Авторизація Node — це спеціалізований авторизатор kubelet, що є стабільним починаючи з Kubernetes v1.8; пізніше уточнення,
AuthorizeNodeWithSelectors, досягло GA в Kubernetes v1.33 й посилює доступ кожного kubelet лише до тих нод і подів, що стосуються його.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це стається | Як це виправити |
|---|---|---|
Неправильна apiGroup | Role виглядає правильно, але запит використовує іншу групу API | Перевірте kubectl api-resources і використовуйте apps для Деплойментів, batch для Job та "" для основних ресурсів |
| Відсутній простір імен у прив’язці | Прив’язку створено в неправильному просторі імен або вона надає доступ десь несподівано | Завжди перевіряйте -n <namespace> для RoleBinding і тестуйте передбачений простір імен за допомогою kubectl auth can-i |
| Забутий простір імен ServiceAccount | Суб’єкт RoleBinding посилається на неправильну ідентичність робочого навантаження | Використовуйте строгий формат namespace:name у командах та поле namespace: у YAML-суб’єктах |
| Використання Role для кластерних ресурсів | Role простору імен не можуть авторизувати запити до Node, PersistentVolume чи URL без ресурсів | Використовуйте ClusterRole для ресурсів кластерного рівня й прив’язуйте її найвужчою придатною прив’язкою |
| Порожня apiGroup без лапок | YAML чи інструменти перевірки приховують різницю між основною та іменованою групами API | Використовуйте apiGroups: [""] з явними лапками для основних ресурсів |
Відсутнє дієслово create для субресурсів exec/attach | Потокова авторизація Kubernetes 1.35+ вимагає більшого, ніж старі правила лише з get | Додавайте create до правил pods/exec, pods/attach та pods/portforward, коли передбачено інтерактивний доступ |
Надто широкий cluster-admin | Команди використовують найшвидше надання, щоб контролер чи дашборд запрацював | Замініть його кастомною ClusterRole, потім перевірте очікувані дозволи й заборони |
Використання AlwaysAllow,RBAC | Прапорець згадує RBAC, але попередній авторизатор спершу схвалює все | Видаліть AlwaysAllow з продакшен-ланцюжків авторизації й перевірте активну конфігурацію API-сервера |
Тест
Розділ «Тест»1. У вашій компанії п'ять команд розробки, кожна зі своїм простором імен. Усім командам потрібен доступ для читання-запису до Деплойментів, Сервісів і ConfigMap, але не до Secret'ів. Який найзручніший для супроводу дизайн RBAC?
Створіть одну придатну для повторного використання ClusterRole, що надає спільні дозволи для ресурсів простору імен, потім створіть RoleBinding у кожному просторі імен, яка посилається на цю ClusterRole й націлюється на правильну групу команди. ClusterRole централізує набір правил, тоді як кожна RoleBinding тримає надання в межах простору імен. П’ять окремих Role можуть працювати, але вони створюють розбіжності, коли профіль дозволів змінюється. ClusterRoleBinding була б надто широкою, бо вона надала б дозволи в усіх просторах імен одразу.
2. Сервісному акаунту CI/CD у `cicd` потрібно створювати Деплойменти в `production`, але `kubectl auth can-i` повертає `no`. Role існує в `production`. Що ви досліджуєте першим?
Дослідіть RoleBinding у production, особливо простір імен суб’єкта-ServiceAccount і групу API Role. Суб’єкт має визначати namespace: cicd і name: pipeline, тоді як правило Role для Деплойментів має використовувати apiGroups: ["apps"]. Якщо простір імен суб’єкта пропущено або встановлено в production, прив’язка посилається на іншу ідентичність. Якщо група API — "", правило не збігається з Деплойментами.
3. Сервісний акаунт моніторингу має ClusterRoleBinding до `cluster-admin`, але йому потрібно лише читати інформацію про поди й ноди. Як ви оцінюєте й заміняєте цей ризик?
cluster-admin дає поду моніторингу повний контроль над RBAC, Secret’ами, робочими навантаженнями та об’єктами кластерного рівня, тож компрометація пода моніторингу стає компрометацією кластера. Замініть його кастомною ClusterRole, що надає лише потрібні дієслова читання й ресурси, потім прив’яжіть цю ClusterRole до сервісного акаунта моніторингу. Перевірте за допомогою kubectl auth can-i --as=system:serviceaccount:monitoring:monitoring для потрібних і заборонених дій. Це оцінює ризик підвищення привілеїв від вбудованих ролей і надто широких прив’язок.
4. Після оновлення до Kubernetes 1.35+ розробник може отримувати список подів, але не може запустити `kubectl exec`. Його Role має `get`, `list` та `watch` для подів і `pods/exec`. Що змінилося?
Інтерактивні потокові субресурси на кшталт pods/exec, pods/attach та pods/portforward вимагають дозволу create для операції з’єднання в Kubernetes 1.35 та новіших. Отримання списку подів усе ще працює, бо звичайні читання подів — це окремі перевірки авторизації. Додайте create до відповідного правила субресурсу, зберігаючи надання обмеженим передбаченим простором імен. Не виправляйте це наданням широкого edit чи cluster-admin, якщо тільки користувачу справді не потрібні ці ширші дозволи.
5. Користувач отримує Forbidden під час доступу до `/metrics` через API-сервер, і ви знаходите Role простору імен, що надає `get` для цього шляху. Чому це не спрацьовує?
/metrics — це URL без ресурсу, а не об’єкт Kubernetes, що належить простору імен. Role не можуть надавати nonResourceURLs; це поле належить ClusterRole, бо шлях — це поверхня API-сервера кластерного рівня. Створіть ClusterRole з nonResourceURLs: ["/metrics"] та verbs: ["get"], потім прив’яжіть її до точного суб’єкта, якому потрібен доступ до метрик. Тримайте прив’язку вузькою, бо кінцеві точки метрик можуть розкривати операційні деталі.
6. Розробник може створювати RoleBinding, але не може прив'язати вбудовану ClusterRole `admin`. Який запобіжник ескалації RBAC блокує запит?
Kubernetes перевіряє, чи суб’єкт запиту вже володіє дозволами у вказаній ролі у відповідній області видимості, або чи має суб’єкт особливе дієслово bind для цієї ролі. Дозволу створювати ресурс rolebindings самого по собі недостатньо, щоб прив’язати потужнішу роль. Це не дає користувачу підвищити привілеї, прив’язавши себе до admin чи cluster-admin. Безпечне виправлення — надати вузький дозвіл bind лише для тих ролей, які цьому користувачу дозволено делегувати.
7. Ви маєте порівняти авторизацію RBAC, Node та Webhook для нової вимоги платформи. Який режим опрацьовує звичайний доступ команди, який опрацьовує запити kubelet, а який делегує зовнішньому сервісу?
RBAC опрацьовує звичайні дозволи команд, робочих навантажень, просторів імен і ресурсів кластера через об’єкти API Kubernetes. Авторизація Node призначена для запитів API kubelet й має бути поєднана з NodeRestriction, щоб kubelet’и залишалися прив’язаними до власної ноди та запланованих подів. Авторизація Webhook делегує рішення зовнішньому HTTP-сервісу, що корисно для спеціалізованої інтеграції політик, але додає синхронну залежність до запитів API. Сильний дизайн використовує кожен режим для того класу запитів, для оцінювання якого його було створено.
Практична вправа
Розділ «Практична вправа»У цій вправі ви побудуєте локальну для простору імен ідентичність розробника, доведете, що вона може й не може робити, потім розширите патерн кількома короткими практичними дрилами. Команди припускають, що у вас доступний кластер Kubernetes v1.35 чи новіший і що ваша поточна ідентичність kubeconfig може створювати об’єкти RBAC для лабораторії. Якщо ви використовуєте спільний кластер, використовуйте тимчасові простори імен і запускайте команди очищення.
Основне завдання: RBAC команди розробників
Розділ «Основне завдання: RBAC команди розробників»- Створіть простір імен, що міститиме ідентичність робочого навантаження.
kubectl create namespace dev-team- Створіть спеціальний сервісний акаунт замість використання усталеного для простору імен.
kubectl create serviceaccount dev-sa -n dev-team- Створіть Role для повсякденних дій розробника в цьому просторі імен.
kubectl create role developer \ --verb=get,list,watch,create,update,delete \ --resource=pods,deployments,services,configmaps \ -n dev-team- Прив’яжіть Role до спеціального сервісного акаунта.
kubectl create rolebinding dev-sa-developer \ --role=developer \ --serviceaccount=dev-team:dev-sa \ -n dev-team- Перевірте очікувані дозволи й заборони, перш ніж запускати под.
# Test as the ServiceAccountkubectl auth can-i get pods -n dev-team \ --as=system:serviceaccount:dev-team:dev-sa# yes
kubectl auth can-i delete pods -n dev-team \ --as=system:serviceaccount:dev-team:dev-sa# yes
kubectl auth can-i get secrets -n dev-team \ --as=system:serviceaccount:dev-team:dev-sa# no (we didn't grant access to secrets)
kubectl auth can-i get pods -n default \ --as=system:serviceaccount:dev-team:dev-sa# no (role only applies in dev-team namespace)- Створіть под, що використовує сервісний акаунт, і зачекайте, доки він стане готовим.
cat > dev-pod.yaml << 'EOF'apiVersion: v1kind: Podmetadata: name: dev-shell namespace: dev-teamspec: serviceAccountName: dev-sa containers: - name: shell image: bitnami/kubectl command: ["sleep", "infinity"]EOF
kubectl apply -f dev-pod.yaml
# Wait for the pod to be runningkubectl wait --for=condition=Ready pod/dev-shell -n dev-team --timeout=60s- Тестуйте зсередини пода, щоб ви побачили дозволи, прикріплені до ідентичності робочого навантаження, що працює.
kubectl exec dev-shell -n dev-team -- kubectl get pods # Should workkubectl exec dev-shell -n dev-team -- kubectl get secrets # Should fail (forbidden)kubectl exec dev-shell -n dev-team -- kubectl get pods -n default # Should fail (forbidden)- Додайте доступ для читання рівня кластера як навмисне розширення, потім перевірте зміну області видимості.
kubectl create clusterrolebinding dev-sa-view \ --clusterrole=view \ --serviceaccount=dev-team:dev-sa
# Now the ServiceAccount can read resources cluster-widekubectl auth can-i get pods -n default \ --as=system:serviceaccount:dev-team:dev-sa# yes (but read-only)- Очистіть ресурси лабораторії.
kubectl delete namespace dev-teamkubectl delete clusterrolebinding dev-sa-viewrm dev-pod.yamlПрактичні дрили
Розділ «Практичні дрили»Запускайте ці дрили після основного завдання, якщо хочете швидкості й практики усунення несправностей у стилі CKA. Кожен дрил навмисно короткий, але міркування має залишатися тим самим: ідентифікуйте суб’єкта, оберіть найвужчу область видимості ролі, прив’яжіть у передбаченій області видимості, потім перевірте і дозвіл, і заборону.
Дрил 1: швидкісний тест RBAC
Розділ «Дрил 1: швидкісний тест RBAC»# Create namespacekubectl create ns rbac-drill
# Create ServiceAccountkubectl create sa drill-sa -n rbac-drill
# Create Role (read pods)kubectl create role pod-reader --verb=get,list,watch --resource=pods -n rbac-drill
# Create RoleBindingkubectl create rolebinding drill-binding --role=pod-reader --serviceaccount=rbac-drill:drill-sa -n rbac-drill
# Testkubectl auth can-i get pods -n rbac-drill --as=system:serviceaccount:rbac-drill:drill-sa
# Cleanupkubectl delete ns rbac-drillДрил 2: тестування дозволів
Розділ «Дрил 2: тестування дозволів»kubectl create ns perm-testkubectl create sa test-sa -n perm-test
# Create limited rolekubectl create role limited --verb=get,list --resource=pods,services -n perm-testkubectl create rolebinding limited-binding --role=limited --serviceaccount=perm-test:test-sa -n perm-test
# Test various permissionsecho "=== Testing as test-sa ==="kubectl auth can-i get pods -n perm-test --as=system:serviceaccount:perm-test:test-sa # yeskubectl auth can-i create pods -n perm-test --as=system:serviceaccount:perm-test:test-sa # nokubectl auth can-i get secrets -n perm-test --as=system:serviceaccount:perm-test:test-sa # nokubectl auth can-i get pods -n default --as=system:serviceaccount:perm-test:test-sa # nokubectl auth can-i get services -n perm-test --as=system:serviceaccount:perm-test:test-sa # yes
# Cleanupkubectl delete ns perm-testДрил 3: ClusterRole проти Role
Розділ «Дрил 3: ClusterRole проти Role»# Create namespaceskubectl create ns ns-akubectl create ns ns-bkubectl create sa cross-ns-sa -n ns-a
# Option 1: Role (namespace-scoped) - only works in ns-akubectl create role ns-a-reader --verb=get,list --resource=pods -n ns-akubectl create rolebinding ns-a-binding --role=ns-a-reader --serviceaccount=ns-a:cross-ns-sa -n ns-a
# Testkubectl auth can-i get pods -n ns-a --as=system:serviceaccount:ns-a:cross-ns-sa # yeskubectl auth can-i get pods -n ns-b --as=system:serviceaccount:ns-a:cross-ns-sa # no
# Option 2: ClusterRole + RoleBinding (still namespace-scoped binding)kubectl create clusterrole pod-reader-cluster --verb=get,list --resource=podskubectl create rolebinding ns-b-binding -n ns-b --clusterrole=pod-reader-cluster --serviceaccount=ns-a:cross-ns-sa
# Now can read ns-b tookubectl auth can-i get pods -n ns-b --as=system:serviceaccount:ns-a:cross-ns-sa # yes
# Cleanupkubectl delete ns ns-a ns-bkubectl delete clusterrole pod-reader-clusterДрил 4: усунення несправностей — відмова в доступі
Розділ «Дрил 4: усунення несправностей — відмова в доступі»# Setup: Create SA with intentionally wrong bindingkubectl create ns debug-rbackubectl create sa debug-sa -n debug-rbackubectl create role secret-reader --verb=get,list --resource=secrets -n debug-rbac# WRONG: binding role to different SA namekubectl create rolebinding wrong-binding --role=secret-reader --serviceaccount=debug-rbac:other-sa -n debug-rbac
# User reports: "I can't read secrets!"kubectl auth can-i get secrets -n debug-rbac --as=system:serviceaccount:debug-rbac:debug-sa# no
# YOUR TASK: Diagnose and fixРішення
# Check what the rolebinding referenceskubectl get rolebinding wrong-binding -n debug-rbac -o yaml | grep -A5 subjects# Shows: other-sa, not debug-sa
# Fix: Create correct bindingkubectl delete rolebinding wrong-binding -n debug-rbackubectl create rolebinding correct-binding --role=secret-reader --serviceaccount=debug-rbac:debug-sa -n debug-rbac
# Verifykubectl auth can-i get secrets -n debug-rbac --as=system:serviceaccount:debug-rbac:debug-sa# yes
# Cleanupkubectl delete ns debug-rbacДрил 5: агреговані ClusterRole
Розділ «Дрил 5: агреговані ClusterRole»# Create aggregated rolecat << 'EOF' | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: aggregate-reader labels: rbac.authorization.k8s.io/aggregate-to-view: "true"rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list"]EOF
# The built-in 'view' ClusterRole automatically includes rules from# any ClusterRole with label aggregate-to-view: "true"# Note: 'view' already grants get/list/watch on configmaps, so this example# proves the mechanism rather than adding new access; to see a brand-new rule# appear, aggregate a resource 'view' lacks by default (e.g. a CRD).
# Check what 'view' includeskubectl get clusterrole view -o yaml | grep -A20 "rules:"
# Cleanupkubectl delete clusterrole aggregate-readerДрил 6: RBAC для користувача
Розділ «Дрил 6: RBAC для користувача»# Create role for hypothetical user "alice"kubectl create ns alice-nskubectl create role alice-admin --verb='*' --resource='*' -n alice-nskubectl create rolebinding alice-is-admin --role=alice-admin --user=alice -n alice-ns
# Test as alicekubectl auth can-i create deployments -n alice-ns --as=alice # yeskubectl auth can-i delete pods -n alice-ns --as=alice # yeskubectl auth can-i get secrets -n default --as=alice # no (different ns)kubectl auth can-i create namespaces --as=alice # no (cluster scope)
# List what alice can dokubectl auth can-i --list -n alice-ns --as=alice
# Cleanupkubectl delete ns alice-nsДрил 7: виклик — налаштування найменших привілеїв
Розділ «Дрил 7: виклик — налаштування найменших привілеїв»Створіть RBAC для deployment-manager, який може створювати, оновлювати й видаляти Деплойменти в просторі імен app, переглядати, але не змінювати Сервіси в просторі імен app, та переглядати Поди в будь-якому просторі імен.
kubectl create ns app# YOUR TASK: Create the necessary Role, ClusterRole, and bindingsРішення
# Role for deployment management in 'app' namespacekubectl create role deployment-manager \ --verb=create,update,delete,get,list,watch \ --resource=deployments \ -n app
# Role for service viewing in 'app' namespacekubectl create role service-viewer \ --verb=get,list,watch \ --resource=services \ -n app
# ClusterRole for cluster-wide pod viewingkubectl create clusterrole pod-viewer \ --verb=get,list,watch \ --resource=pods
# Create ServiceAccountkubectl create sa deployment-manager -n app
# Bind all roleskubectl create rolebinding dm-deployments \ --role=deployment-manager \ --serviceaccount=app:deployment-manager \ -n app
kubectl create rolebinding dm-services \ --role=service-viewer \ --serviceaccount=app:deployment-manager \ -n app
kubectl create clusterrolebinding dm-pods \ --clusterrole=pod-viewer \ --serviceaccount=app:deployment-manager
# Testkubectl auth can-i create deployments -n app --as=system:serviceaccount:app:deployment-manager # yeskubectl auth can-i delete services -n app --as=system:serviceaccount:app:deployment-manager # nokubectl auth can-i get pods -n default --as=system:serviceaccount:app:deployment-manager # yes
# Cleanupkubectl delete ns appkubectl delete clusterrole pod-viewerkubectl delete clusterrolebinding dm-podsКритерії успіху
Розділ «Критерії успіху»- Спроєктувати області видимості RBAC на рівні простору імен і кластера для доступу команд за принципом найменших привілеїв.
- Впровадити Role, ClusterRole, RoleBinding, ClusterRoleBinding та прив’язки сервісних акаунтів.
- Діагностувати помилки авторизації Forbidden за допомогою
kubectl auth can-iта перевірки прив’язок. - Оцінити ризики підвищення привілеїв через символи підстановки, вбудовані ролі,
bind,escalate,impersonateта Secret’и. - Порівняти режими авторизації RBAC, Node та Webhook, пояснюючи свій вибір дизайну.
Джерела
Розділ «Джерела»- https://kubernetes.io/docs/reference/access-authn-authz/rbac/
- https://kubernetes.io/docs/reference/access-authn-authz/authorization/
- https://kubernetes.io/docs/reference/access-authn-authz/node/
- https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/
- https://kubernetes.io/docs/concepts/security/service-accounts/
- https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_reconcile/
- https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#role-v1-rbac-authorization-k8s-io
- https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#clusterrole-v1-rbac-authorization-k8s-io
- https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#rolebinding-v1-rbac-authorization-k8s-io
- https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#clusterrolebinding-v1-rbac-authorization-k8s-io
- https://github.com/kubernetes/kubernetes/pull/134577
Наступний модуль
Розділ «Наступний модуль»Модуль 1.7: Основи kubeadm — Розкрийте початкове завантаження кластера, процедури приєднання вузлів та керування життєвим циклом площини управління.