Модуль 2.1: Поглиблене вивчення RBAC
Складність:
[СЕРЕДНЯ]— основна навичка безпекиЧас на проходження: 40-45 хвилин
Передумови: знання RBAC рівня CKA, основи ServiceAccount
Що ви зможете зробити
Розділ «Що ви зможете зробити»Після завершення цього модуля ви зможете:
- Проводити аудит Kubernetes-об’єктів RBAC — Role, ClusterRole, RoleBinding, ClusterRoleBinding та ServiceAccount, щоб виявити права з символом підстановки (wildcard), доступ до Secret та шляхи підвищення привілеїв.
- Впроваджувати Role, ClusterRole, RoleBinding та ClusterRoleBinding за принципом найменших привілеїв для потреб робочих навантажень, не надаючи зайвого доступу в межах усього кластера.
- Простежувати ефективні права користувачів та ServiceAccount, ідучи зв’язками RoleBinding і ClusterRoleBinding крізь ланцюжок авторизації.
- Діагностувати відмови доступу RBAC та усувати їх найменшою безпечною зміною ролі чи прив’язки, а не широкими резервними правами.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Гіпотетичний сценарій: конвеєр розгортання починає падати після того, як платформенна команда прибрала cluster-admin із CI-сервісного акаунта (ServiceAccount). Команда застосунку просить повернути стару прив’язку, бо релізи заблоковано, але перевірка безпеки показує, що той самий токен міг би також читати кожен Secret, патчити кожен ClusterRole та видаляти робочі навантаження за межами простору імен застосунку. Інженер рівня CKS має зберегти працездатність шляху релізу, водночас довівши, які саме операції API дійсно потрібні конвеєру.
RBAC — це місце, де безпека Kubernetes стає операційно конкретною. Мережеві політики, Pod Security Admission та посилення безпеки під час виконання мають значення, але саме API-сервер усе одно вирішує, чи може суб’єкт створити под, прочитати Secret, прив’язати роль чи видати себе за іншого користувача. Коли RBAC надто широкий, радіус ураження (blast radius) одного скомпрометованого контейнера розширюється з одного простору імен до всієї площини управління; коли RBAC надто вузький, реальні оператори втрачають можливість безпечно діагностувати інциденти.
Цей модуль переписує звичний урок «створи Role та RoleBinding» у робочий процес аудиту. Ви дізнаєтеся, як авторизатор збирає права докупи, чому деякі дієслова (verbs) чутливі до підвищення привілеїв, як порівняти вимогу робочого навантаження з наявною роллю та як зменшити доступ, не зламавши при цьому навантаження, яке вас попросили захистити. Мета — не запам’ятати поля YAML; мета — ухвалювати обґрунтовані рішення про авторизацію під тиском іспиту та промислової експлуатації.
Огляд RBAC: як збираються права
Розділ «Огляд RBAC: як збираються права»RBAC здається заплутаним, доки ви не розділите дві половини моделі. Role або ClusterRole відповідає на питання «які дії дозволено», тоді як RoleBinding або ClusterRoleBinding відповідає на питання «хто отримує ці дії». Цей поділ зроблено навмисно, бо він дозволяє повторно використовувати той самий набір прав для різних суб’єктів, але водночас це означає, що ви не можете оцінити ризик, прочитавши лише один об’єкт. Безневинна на вигляд Role стає небезпечною, коли її прив’язано до широкої групи, а безневинний на вигляд ServiceAccount стає небезпечним, коли ClusterRoleBinding скеровує його на потужну роль.
┌─────────────────────────────────────────────────────────────┐│ RBAC COMPONENTS │├─────────────────────────────────────────────────────────────┤│ ││ Role/ClusterRole ││ └── Defines WHAT actions are allowed ││ ├── apiGroups: ["", "apps", "batch"] ││ ├── resources: ["pods", "deployments"] ││ └── verbs: ["get", "list", "create", "delete"] ││ ││ RoleBinding/ClusterRoleBinding ││ └── Defines WHO gets the permissions ││ ├── subjects: [users, groups, serviceaccounts] ││ └── roleRef: [Role or ClusterRole] ││ ││ Scope: ││ ├── Role + RoleBinding = namespace-scoped ││ ├── ClusterRole + ClusterRoleBinding = cluster-wide ││ └── ClusterRole + RoleBinding = reusable in namespace ││ │└─────────────────────────────────────────────────────────────┘Область дії (scope) — це друга ідея, яка має бути автоматичною ще до того, як ви щось аудитуєте. Role завжди живе всередині одного простору імен, тоді як ClusterRole має кластерну область дії й може охоплювати або ресурси в межах простору імен, або ресурси кластерного рівня, або і ті, і ті. RoleBinding завжди надає права всередині одного простору імен, навіть коли він посилається на ClusterRole; ClusterRoleBinding надає вказаний ClusterRole у кластерній області дії. Саме ця остання відмінність породжує багато кластерів із надмірними правами.
Уявіть ClusterRole як заготовку для ключа багаторазового використання, а прив’язку — як двері, де ключ встановлюють. ClusterRole на ім’я pod-reader може бути безпечним, коли його встановлено через RoleBinding в одному просторі імен, бо він відкриває лише двері читання подів у цьому просторі імен. Той самий ClusterRole, встановлений через ClusterRoleBinding, відкриває двері читання подів по всьому кластеру, включно з просторами імен, про які початковий запитувач, можливо, ніколи й не згадував.
Поле групи API (API group) також легко недооцінити. Базові ресурси, як-от Pod, Secret, ConfigMap та ServiceAccount, використовують порожню групу API "", тоді як Deployment використовує apps, Job використовує batch, а об’єкти RBAC використовують rbac.authorization.k8s.io. Якщо роль надає resources: ["*"] для apiGroups: ["*"], вона охоплює не лише ті ресурси, які ви мали на думці сьогодні. Вона також охоплює майбутні API та встановлені користувацькі ресурси, що відповідають символу підстановки.
Дієслова (verbs) не є рівнозначними. get, list та watch орієнтовані на читання, але list на Secret може розкрити багато секретних значень одразу. create, update, patch та delete змінюють стан кластера, але create pods чутливіший, ніж здається на перший погляд, бо новий под може запуститися під обраним ServiceAccount та запросити небезпечні налаштування контексту безпеки, якщо інші засоби контролю цьому не завадять. Тому RBAC слід читати разом із засобами контролю допуску робочих навантажень, а не сприймати як ізольовану таблицю.
Авторизатор RBAC є адитивним, тобто Kubernetes не має нативного правила «заборони» (deny) в RBAC, яке могло б відняти право від широкого надання. Якщо суб’єкт отримує get secrets з однієї прив’язки та вузьку роль лише для подів з іншої прив’язки, ефективна відповідь усе одно включає get secrets. Саме тому аудиторська робота починається з ефективних прав і потім простежує назад до прив’язки, що надала ризиковане дієслово.
Зробіть паузу та спрогнозуйте: якщо ServiceAccount має один RoleBinding до вузької Role читача подів і ще один ClusterRoleBinding до широкого моніторингового ClusterRole, який об’єкт визначає остаточну відповідь, коли ви виконуєте kubectl auth can-i get secrets --as=system:serviceaccount:team:app? Важлива звичка — припинити мислити в категоріях останнього об’єкта, який ви редагували. Kubernetes обчислює об’єднання кожного застосовного надання, тож неочікуване «так» часто походить зі старішої прив’язки, яку ніхто не прибрав.
У Kubernetes 1.35 RBAC усе ще використовує стабільний API rbac.authorization.k8s.io/v1 для Role, ClusterRole, RoleBinding та ClusterRoleBinding. Ця стабільність корисна на іспиті, бо форма об’єктів передбачувана, але вона також може породжувати самозаспокоєння. Складна частина — не запам’ятовування назв полів; складна частина — рішення, чи повинен суб’єкт мати це дієслово на цьому ресурсі в цій області дії, а потім доведення цього рішення за допомогою kubectl auth can-i.
Небезпечні патерни RBAC
Розділ «Небезпечні патерни RBAC»Найлегше помітна помилка RBAC — це роль із символом підстановки (wildcard). Її також найлегше виправдати під час міграції, зламаного розгортання чи поспішного реагування на інцидент. Wildcard каже «усі групи API, усі ресурси, усі дієслова», а це означає, що суб’єкт може читати Secret, змінювати RBAC, створювати робочі навантаження, видаляти їх та використовувати API, встановлені вже після написання ролі. На практиці ClusterRole з wildcard, прив’язаний у межах усього кластера, функціонально близький до cluster-admin.
# DANGEROUS: Allows everythingapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: too-permissiverules:- apiGroups: ["*"] resources: ["*"] verbs: ["*"]
# WHY IT'S BAD:# - Equivalent to cluster-admin# - Can access secrets, modify RBAC, delete anything# - Violates least privilegeСимволи підстановки інколи з’являються тому, що запитувач не може описати свою реальну залежність від API. Це проблема процесу, а не привід надавати wildcard назавжди. Безпечніший робочий процес — надати тимчасовий, обмежений у часі шлях для діагностики поза межами ServiceAccount застосунку, поспостерігати за потрібними викликами API, а потім перетворити результат на явні ресурси та дієслова. У завданні на іспиті крок спостереження зазвичай не потрібен; умова дає вам достатньо інформації про намір робочого навантаження, щоб одразу написати вузьку роль.
Доступ до Secret — наступний патерн, бо Secret часто містять облікові дані, що переживають под, у якому їх було змонтовано. RBAC ставиться до Secret як до звичайних ресурсів API, але операційно це матеріал ідентичності — паролі баз даних, облікові дані для завантаження з реєстру, ключі TLS та токени застосунків. Суб’єкт із list secrets у просторі імен може зібрати кожен Secret цього простору імен одним викликом API, а суб’єкт із доступом до Secret у межах усього кластера може перетворити одну компрометацію ServiceAccount на безліч компрометацій застосунків.
# DANGEROUS: Can read all secretsapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: secret-readerrules:- apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "watch"]
# WHY IT'S BAD:# - Secrets contain passwords, tokens, certificates# - One secret can compromise entire applications# - Should be tightly scoped to specific secretsІснують легітимні читачі Secret, але вони мають бути рідкісними та свідомо обмеженими за областю дії. Контролер, що синхронізує іменований TLS-сертифікат, може потребувати get на цьому одному Secret через resourceNames, тоді як система резервного копіювання може потребувати окремого перегляду дизайну, бо вона торкається багатьох чутливих об’єктів. Практичне аудиторське питання — не «чи згадує цей інструмент Secret хоч десь»; воно звучить так: «які саме імена Secret цей суб’єкт має читати, у якому просторі імен та що станеться, якщо токен витече».
Права на зміну RBAC є ще чутливішими, бо вони дозволяють суб’єкту змінювати сам граф авторизації. Розробник, який може створювати ClusterRoleBinding, може спробувати прив’язати суб’єкта до потужного ClusterRole, а суб’єкт із дієсловом bind може обійти звичайну перевірку, що не дає прив’язувати ролі з правами, яких він сам ще не має. Суб’єкт із дієсловом escalate може створювати або оновлювати ролі, що надають права понад його власні поточні права. Ці дієслова — не рутинні помічники адміністрування; це навмисні межі привілеїв.
# DANGEROUS: Can modify RBACapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: rbac-modifierrules:- apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles", "clusterrolebindings"] verbs: ["create", "update", "patch"]
# WHY IT'S BAD:# - Can mutate RBAC objects cluster-wide# - Dangerous combined with bind/escalate or existing broad grants# - Only tightly controlled admins should modify RBACПідступна версія цієї помилки — надання адміністраторам простору імен надто широкого доступу на запис RBAC через те, що кластер погано користується спільними просторами імен. Роль простору імен, що може оновлювати Role та RoleBinding, усе одно потужна всередині цього простору імен, особливо коли там уже існують привілейовані ServiceAccount. Перш ніж надавати права на запис RBAC, перевірте, чи може суб’єкт прив’язуватися до наявних ролей, чи обмежує політика допуску ті ServiceAccount, якими він може користуватися, і чи містить простір імен облікові дані для робочих навантажень поза зоною відповідальності запитувача.
Створення подів — патерн, що дивує багатьох учнів, бо create pods не схоже на право в межах усього кластера. Специфікація пода може обрати ServiceAccount, монтувати проєктовані токени, запитувати томи hostPath, встановлювати поля контексту безпеки та запускати контейнери, що роблять виклики API. Сам по собі RBAC не оцінює, чи безпечний цей под; рішення про авторизацію лише питає, чи може суб’єкт створити об’єкт пода. Pod Security Admission, політика простору імен, політика образів та дизайн ServiceAccount вирішують, наскільки небезпечним може стати цей об’єкт.
# DANGEROUS: Can create pods (potential escalation)apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: pod-creatorrules:- apiGroups: [""] resources: ["pods"] verbs: ["create"]
# WHY IT'S BAD:# - Can create pods that request privileged settings or stronger ServiceAccounts# - Can mount service account tokens into the workload# - Node-level escape depends on admission controls (Pod Security Admission, etc.)# - RBAC alone does not evaluate whether the pod spec is safeЗупиніться та подумайте: розробник має Role, що дозволяє create на pods, але більше нічого, і він стверджує, що не може зробити нічого небезпечного. Якщо простір імен містить потужніший ServiceAccount, а допуск дозволяє поду використовувати його, розробник може створити под, що запуститься з токеном цього ServiceAccount. На папері надання RBAC виглядало вузьким, але об’єкт робочого навантаження став мостом до іншої ідентичності.
Уособлення (impersonation) належить до того самого ментального кошика. Kubernetes підтримує заголовки уособлення, щоб адміністратори та інструменти могли перевіряти авторизацію від імені іншого користувача, групи чи ServiceAccount. Це корисно для діагностики, але дієслово impersonate слід вважати чутливим, бо воно дозволяє суб’єкту попросити API-сервер оцінювати запити так, ніби їх робить хтось інший. Вузьке надання уособлення може бути безпечним для процесів підтримки; широке може стерти межу між ідентичністю підтримки та цільовою ідентичністю.
Коли ви аудитуєте небезпечні патерни, тримайте в полі зору ланцюжок наслідків. Широке надання на читання може розкрити облікові дані, широке надання на запис може змінити робочі навантаження, надання на створення подів може дотягнутися до потужніших ServiceAccount, надання на запис RBAC може переписати авторизацію, а надання уособлення може оминути межі ідентичності. Правильне виправлення залежить від того, який ланцюжок існує, а не від загального правила, що кожне дієслово create погане або кожен ClusterRole заборонений.
Приклади найменших привілеїв
Розділ «Приклади найменших привілеїв»Найменші привілеї — це не найкоротший файл YAML, який ви можете написати. Це найменший набір прав, що підтримує відому поведінку з чіткою межею відповідальності. У Kubernetes це означає починати з викликів API робочого навантаження, обирати найвужчу область дії, уникати символів підстановки та перевіряти результат як той самий користувач чи ServiceAccount, що працюватиме в промисловому середовищі. Роль, яка ламає робоче навантаження, — не безпечна роль; це неповна роль, яку обійдуть під тиском.
Найпростіша добра роль надає видимість подів лише для читання всередині одного простору імен. Це корисно для дашборда, скрипта підтримки чи компонента застосунку, якому потрібно інспектувати власні поди та отримувати логи, не змінюючи стану кластера. Зверніть увагу, що pods/log є підресурсом (subresource), тож він з’являється як окремий запис ресурсу. Суб’єкт може мати доступ до логів, не отримуючи широкого права на оновлення чи видалення подів.
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-viewer namespace: productionrules:- apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]- apiGroups: [""] resources: ["pods/log"] verbs: ["get"]Ця Role навмисно прив’язана до простору імен, бо потреба є локальною для простору імен. Якщо інструмент підтримки обслуговує лише простір імен production, ClusterRoleBinding зробив би доведення складнішим, а радіус ураження — більшим. Ви все одно можете визначити багаторазовий ClusterRole для перегляду подів, але прив’язуйте його за допомогою RoleBinding у кожному просторі імен, де цей доступ затверджено. Цей патерн дає вам повторне використання без тихого перетворення запиту однієї команди на видимість у межах усього кластера.
Обмеження за іменами ресурсів корисні, коли запит до API може назвати точний об’єкт наперед. Поле resourceNames нижче дозволяє читання двох ConfigMap і блокує читання інших ConfigMap у тому самому просторі імен. Це добре підходить для контролерів чи застосунків, що завантажують іменовані об’єкти конфігурації, але це не загальна заміна дизайну простору імен, бо поведінка list та watch має важливі обмеження з resourceNames.
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: specific-configmap-reader namespace: apprules:- apiGroups: [""] resources: ["configmaps"] resourceNames: ["app-config", "feature-flags"] # Only these! verbs: ["get"]Використовуйте resourceNames лише тоді, коли робоче навантаження природно знає ім’я об’єкта. Якщо застосунку потрібно знайти кожен ConfigMap із певною міткою, йому потрібен доступ list, і resourceNames не виразить цей патерн виявлення чисто. Якщо ж оператору потрібен лише один Secret, тоді resourceNames може стати різницею між контрольованим читанням облікових даних та зливом облікових даних у межах усього простору імен. Це той тип компромісу, який відповідь рівня CKS має пояснювати, а не лише кодувати.
Підресурси — ще один спосіб звузити намір. Підресурс pods/exec відрізняється від основного ресурсу pods, і дієсловом зазвичай є create, бо сесію exec створюють проти наявного пода. Спершу це може здаватися дивним, але це дозволяє надати доступ для діагностики, не надаючи водночас права створювати, оновлювати чи видаляти об’єкти подів. Точність підресурсу — поширена ознака того, що роль спроєктовано від операції API, а не скопійовано з широкого прикладу.
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-executor namespace: debugrules:- apiGroups: [""] resources: ["pods/exec"] # Only exec, not full pod access verbs: ["create"]Перш ніж запускати це в реальному просторі імен — який результат ви очікуєте від kubectl auth can-i create pods --as=<subject> після надання лише pods/exec? Безпечна відповідь — «ні», бо доступ exec не є доступом на створення подів. Питання-прогнози на кшталт цього допомагають вам ловити ролі, що надають правильне на вигляд дієслово на неправильному ресурсі, а це один із найшвидших способів надати зайвий доступ для процесів діагностики.
Повний дизайн найменших привілеїв також перевіряє суб’єкта прив’язки. Користувачі та групи часто походять із зовнішнього постачальника ідентичності, тоді як ServiceAccount — це ідентичності Kubernetes, що використовуються робочими навантаженнями. Якщо роль призначено для пода застосунку, прив’язуйте її до ServiceAccount цього застосунку, а не до default ServiceAccount простору імен. default ServiceAccount легко використати, але він стає спільним кошиком прав, коли на нього покладається кілька подів.
Найменші привілеї є ітеративними, бо робочі навантаження змінюються. Нова версія контролера може потребувати створення Event, спостереження за Lease чи оновлення підресурсу Status. Правильна реакція — не панікувати й надавати edit; вона полягає в тому, щоб визначити відхилений виклик API, вирішити, чи належить цей виклик до зони відповідальності робочого навантаження, додати найменше правило, що його підтримує, та перевірити, що непов’язані операції все ще зазнають невдачі. Саме ця звичка відрізняє операційне виправлення RBAC від зливу прав.
Аудит і простеження прав
Розділ «Аудит і простеження прав»Аудит RBAC починається з двох питань: які ролі небезпечні та які суб’єкти їх отримують. Пошук лише прив’язок cluster-admin необхідний, але неповний, бо користувацькі ClusterRole можуть бути так само потужними. Перший прохід має знайти правила з символами підстановки, читачів Secret, тих, хто пише RBAC, надання уособлення, тих, хто створює поди в чутливих просторах імен, та прив’язки, що приєднують ці ролі до широких груп чи ідентичностей робочих навантажень. Другий прохід має перевірити ефективні права як фактичний суб’єкт.
# List all ClusterRoles with wildcard permissionskubectl get clusterroles -o json | jq -r ' .items[] | select(.rules[]? | (.verbs[]? == "*") or (.resources[]? == "*") or (.apiGroups[]? == "*") ) | .metadata.name'
# Find roles that can read secretskubectl get clusterroles -o json | jq -r ' .items[] | select(.rules[]? | (.resources[]? | contains("secrets")) and ((.verbs[]? == "get") or (.verbs[]? == "*")) ) | .metadata.name'
# Find roles that can modify RBACkubectl get clusterroles -o json | jq -r ' .items[] | select(.rules[]? | (.apiGroups[]? == "rbac.authorization.k8s.io") and ((.verbs[]? == "create") or (.verbs[]? == "update") or (.verbs[]? == "*")) ) | .metadata.name'Ці запити навмисно прості, бо вони навчають формі розслідування. У промисловому перегляді ви також перевірили б Role у межах простору імен, дієслова на кшталт patch, delete, bind, escalate та impersonate, а також ресурси на кшталт serviceaccounts/token, pods/exec, pods/attach, nodes/proxy та підресурси робочих навантажень. Простота прийнятна для першого проходу, доки ви розумієте, що він пропускає. Чистий перший прохід не доводить, що кластер безпечний.
Перевірки ефективних прав — найшвидший спосіб підтвердити, що Kubernetes насправді дозволить. Прапорець --as просить API-сервер оцінити запит як певного користувача чи ServiceAccount, тобто ваша поточна адміністративна ідентичність використовується для виконання тестового запиту, тоді як рішення про авторизацію обчислюється для цільового суб’єкта. Ця відмінність важлива, бо успішний виклик kubectl auth can-i не означає, що було використано токен цілі; він означає, що API-сервер відповів на питання авторизації для цієї цільової ідентичності.
# What can a specific user do?kubectl auth can-i --list --as=system:serviceaccount:default:myapp
# Can user create privileged pods?kubectl auth can-i create pods --as=developer
# Can user read secrets?kubectl auth can-i get secrets --as=system:serviceaccount:app:backend
# In specific namespacekubectl auth can-i delete deployments -n production --as=developerВивід --list корисний, але він може бути зашумленим, коли суб’єкт успадковує права від кількох прив’язок. Для аудиторських доказів поєднуйте широкий перелік із точковими перевірками «так чи ні», що відповідають ризику, який ви досліджуєте. Якщо хвилює розкриття Secret, перевірте get, list та watch на Secret у просторі імен та в кластерній області дії. Якщо хвилює підвищення привілеїв через робоче навантаження, перевірте створення подів у просторі імен, де вже існують потужні ServiceAccount.
Використовуйте простори імен як лінзи для аудиту, а не лише як фільтри в командах. Ідентичність ServiceAccount включає її простір імен, але ClusterRoleBinding усе одно може надати цій ідентичності права в межах усього кластера, тож простір імен в імені суб’єкта не гарантує доступу, обмеженого простором імен. Коли ви перевіряєте ідентичність робочого навантаження, виконайте принаймні одну перевірку всередині її домашнього простору імен та одну перевірку в сусідньому просторі імен. Контраст підкаже вам, чи відповідає тип прив’язки бажаній межі.
Відокремлюйте доведення авторизації від виявлення об’єктів. kubectl get rolebindings каже вам, які об’єкти прив’язок існують, тоді як kubectl auth can-i каже вам, що дозволить авторизатор після врахування кожної застосовної прив’язки. Обидва необхідні, бо один відповідає «звідки це може походити», а інший відповідає «що станеться, якщо суб’єкт запитає». У нотатці перегляду записуйте і ризикований об’єкт, і ефективне право, яке він породив.
Звертайте увагу на підресурси під час простеження. Роль, що дозволяє get pods, не дозволяє автоматично get pods/log, а роль, що дозволяє create pods/exec, не дозволяє автоматично create pods. Ця точність корисна для найменших привілеїв, але вона також може приховати відсутні чи надмірні права, якщо ви аудитуєте лише батьківський ресурс. Коли процес підтримки згадує логи, exec, attach, status чи scale, включіть підресурс у перевірку авторизації.
Простеження потім рухається від відповіді назад до прив’язки. Відповідь «так» означає, що якийсь RoleBinding чи ClusterRoleBinding надає це право — напряму чи опосередковано через групу. Почніть із широких пошуків прив’язок, потім інспектуйте зазначену роль, потім інспектуйте список суб’єктів. Якщо задіяний ServiceAccount, пишіть повний рядок ідентичності як system:serviceaccount:<namespace>:<name>, бо багато аудиторських помилок походять зі сплутування двох ServiceAccount з однаковим іменем у різних просторах імен.
# Who has cluster-admin?kubectl get clusterrolebindings -o json | jq -r ' .items[] | select(.roleRef.name == "cluster-admin") | "\(.metadata.name): \(.subjects[]?.name // "unknown")"'
# List all ClusterRoleBindingskubectl get clusterrolebindings -o wide
# Describe suspicious bindingkubectl describe clusterrolebinding suspicious-bindingСценарій вправи: вам дано ServiceAccount на ім’я backend у просторі імен app, і верифікатор показує, що він може видаляти поди, хоча застосунку потрібно лише читати стан подів. Ваш перший крок — не редагувати випадковий YAML; це довести, звідки походить право на видалення. Виконайте kubectl auth can-i delete pods --as=system:serviceaccount:app:backend -n app, перелічіть RoleBinding у app, інспектуйте кожну зазначену Role чи ClusterRole та шукайте правило, що надає delete на pods.
# Given: ServiceAccount with too many permissions# Task: Reduce to only get/list pods
# Check current permissionskubectl auth can-i --list --as=system:serviceaccount:app:backend -n app
# Find the rolebindingkubectl get rolebindings -n app -o wide
# Check the rolekubectl get role backend-role -n app -o yaml
# Create restricted rolecat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: backend-role namespace: apprules:- apiGroups: [""] resources: ["pods"] verbs: ["get", "list"]EOF
# Verifykubectl auth can-i delete pods --as=system:serviceaccount:app:backend -n app# Should return "no"Цей опрацьований приклад перезаписує наявну Role, бо умова каже, що бажаний результат — лише get та list на поди. У реальному перегляді ви перевірили б, чи не використовують backend-role інші суб’єкти, перш ніж змінювати її на місці. Якщо спільна Role підтримує кілька робочих навантажень, безпечнішим виправленням може бути створення нової вузької Role для ServiceAccount backend та перенесення лише цієї прив’язки. Іспит часто дає контрольоване середовище; промислова експлуатація — рідко.
Прив’язки cluster-admin заслуговують на окрему перевірку, бо вони мають високий ризик навіть тоді, коли ім’я суб’єкта виглядає специфічним для сервісу. Прив’язка з іменем developer-admin чи monitoring-admin не стає безпечною через те, що ім’я описує вузьку функцію. roleRef контролює набір прав, і roleRef, що вказує на cluster-admin, надає повний контроль над кластером. Список суб’єктів контролює, хто його отримує, включно з групами та ServiceAccount.
# Find who has cluster-adminkubectl get clusterrolebindings -o json | jq -r ' .items[] | select(.roleRef.name == "cluster-admin") | .metadata.name'
# Remove inappropriate bindingkubectl delete clusterrolebinding developer-adminВидалення небезпечної прив’язки доречне, коли ви підтвердили, що вона недоречна, і існує шлях заміни. Якщо ви видаляєте спочатку, а аналізуєте потім, ви можете зламати контролери, моніторинг чи аварійний доступ так, що це створить інший збій. Краща операційна послідовність — визначити суб’єкта, окреслити потрібні операції API, створити вузьку заміну, перевірити за допомогою kubectl auth can-i і лише потім прибрати небезпечну прив’язку. Іспит може стиснути цю послідовність, але міркування все одно мають значення.
Багатьом робочим навантаженням потрібен більш ніж один ресурс. Приклад нижче читає ConfigMap та створює Event, що є поширеним патерном для застосунків чи контролерів, які завантажують конфігурацію та звітують про стан. Роль не включає Secret, ресурси RBAC, створення подів чи ресурси кластерного рівня, бо жодна з цих можливостей не є частиною заявленої вимоги. Цей пропуск і є суттю: найменші привілеї — це здебільшого рішення про те, чого не включати.
# Requirement: App needs to read configmaps and create eventscat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: app-role namespace: myapprules:- apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"]- apiGroups: [""] resources: ["events"] verbs: ["create"]---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: app-binding namespace: myappsubjects:- kind: ServiceAccount name: myapp-sa namespace: myapproleRef: kind: Role name: app-role apiGroup: rbac.authorization.k8s.ioEOFЗробіть паузу та спрогнозуйте: ви виконуєте kubectl auth can-i --list --as=system:serviceaccount:default:default і бачите права на get, list та watch Secret у межах усього кластера, але ви не створювали жодних RoleBinding для default ServiceAccount. Найімовірніше пояснення — що ClusterRoleBinding, прив’язка до групи чи раніше встановлене доповнення приєднали широкі права до цієї ідентичності або до групи, до якої вона належить. Наступний крок — інспектувати прив’язки, а не припускати, що default ServiceAccount чарівний.
Діагностика відмов RBAC використовує ту саму логіку у зворотному напрямку. Відповідь «ні» каже вам, що ефективному набору прав бракує запитаного дієслова, ресурсу, групи API, області дії чи імені ресурсу. Не виправляйте це наданням широкої вбудованої ролі, якщо вимога справді не відповідає цій ролі. Натомість визначте відсутню операцію, додайте вузьке правило та перевірте і щойно дозволену дію, і принаймні одну дію, яка все ще має бути заборонена.
# Test as specific userkubectl auth can-i create pods --as=jane
# Test as ServiceAccountkubectl auth can-i get secrets --as=system:serviceaccount:default:myapp
# List all permissionskubectl auth can-i --list --as=jane
# Why can/can't user do something?kubectl auth can-i create pods --as=jane -v=5
# Check who can do somethingkubectl auth who-can create podskubectl auth who-can delete secrets -n productionДеякі кластери надають who-can через плагін чи специфічне для дистрибутива розширення, тоді як портативна практика Kubernetes завжди має включати kubectl auth can-i, бо це частина стандартного робочого процесу авторизації kubectl. Якщо who-can недоступний під час іспиту чи перегляду, поверніться до переліку RoleBinding та ClusterRoleBinding, простежте кожен roleRef та порівняйте правила вручну. Цей повільніший метод цінний, бо він змушує вас зрозуміти, який саме об’єкт надає це право.
Запобігання підвищенню привілеїв RBAC
Розділ «Запобігання підвищенню привілеїв RBAC»Запобігання підвищенню привілеїв полягає в блокуванні шляхів, а не лише очевидних адміністративних ролей. Суб’єкт може стати потужнішим, напряму змінивши RBAC, опосередковано створивши под, що використовує потужніший ServiceAccount, прочитавши Secret, що містить інші облікові дані, видавши себе за привілейовану ідентичність чи дотягнувшись до API рівня вузла, що розкриває облікові дані. Граф авторизації та граф робочих навантажень зустрічаються на ServiceAccount, подах та токенах, тож перегляд RBAC має досліджувати ці зв’язки разом.
┌─────────────────────────────────────────────────────────────┐│ RBAC ESCALATION PATHS │├─────────────────────────────────────────────────────────────┤│ ││ Direct Escalation: ││ ───────────────────────────────────────────────────────── ││ 1. Create/update ClusterRoleBindings ││ → Attach powerful roles (bind guardrail applies) ││ ││ 2. bind / escalate on RBAC resources ││ → Expand permissions beyond current grants ││ ││ Indirect Escalation: ││ ───────────────────────────────────────────────────────── ││ 3. Create pods in any namespace ││ → Mount privileged ServiceAccount ││ ││ 4. Create pods with node access ││ → Read kubelet credentials ││ ││ 5. Impersonate users ││ → Act as cluster-admin ││ ││ Prevention: ││ ───────────────────────────────────────────────────────── ││ • Never give RBAC modification rights loosely ││ • Use Pod Security Admission ││ • Audit escalation verbs regularly ││ │└─────────────────────────────────────────────────────────────┘Прямий шлях найлегше пояснити. Якщо суб’єкт може створювати чи оновлювати ClusterRoleBinding, а API-сервер дозволяє цьому суб’єкту прив’язувати потужну роль, суб’єкт може приєднати себе чи контрольований ServiceAccount до cluster-admin. Kubernetes має запобіжники проти підвищення привілеїв, але ці запобіжники теж виражені через авторизацію. Спеціальні дієслова bind та escalate існують саме тому, що запис об’єктів RBAC сам по собі є привілейованою операцією.
Що сталося б, якби ви знайшли ClusterRoleBinding, що надає cluster-admin ServiceAccount на ім’я monitoring-agent у просторі імен monitoring, а команда моніторингу каже, що їй це потрібно, щоб «бачити все»? Якщо зловмисник скомпрометує под, що використовує цей ServiceAccount, він зможе скористатися змонтованим токеном, щоб викликати API як cluster-admin. Вимогою моніторингу може бути широка видимість на читання, але прив’язка надає також широкі повноваження на запис та на RBAC.
# The 'bind' verb allows creating bindings to roles# even without permissions the role grants- apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterrolebindings"] verbs: ["create"] # Plus...- apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["bind"] # ...this allows binding to any role!
# The 'escalate' verb allows granting permissions# that the user doesn't have- apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["escalate"] # Can add any permissions to roles!Опосередкований шлях через под складніший, бо RBAC та контроль допуску ділять відповідальність. RBAC може дозволити create pods, але Pod Security Admission може відхилити привілейовані поля, простори імен хоста чи томи hostPath відповідно до стандарту, що його застосовує простір імен. Налаштування ServiceAccount також можуть зменшити ризик, уникаючи спільних default-ідентичностей та вимикаючи автоматичне монтування токена, коли застосунку не потрібен доступ до API. Жоден із цих засобів не замінює RBAC, але вони знижують імовірність того, що створення пода перетвориться на крадіжку ідентичності.
Доступ до Secret — ще один опосередкований шлях, бо облікові дані Kubernetes часто зберігаються як Secret чи розкриваються через проєктовані токени. Читання не того Secret може розкрити пароль бази даних, обліковий запис реєстру, приватний ключ TLS чи токен застосунку, що дає доступ за межі кластера. Строга роль для застосунку, що читає один іменований ConfigMap, не повинна випадково включати Secret через те, що слова «конфігурація» та «облікові дані» звучать схоже у тікеті. Ставтеся до Secret як до об’єктів, що несуть повноваження, а не нешкідливих текстових блоків.
Уособлення слід надавати лише ідентичностям, що мають конкретну потребу в підтримці чи автоматизації. Наприклад, процесу служби підтримки можна дозволити видавати себе за невеликий набір користувачів для перевірок авторизації, але йому не слід уособлювати system:masters, кожну групу чи кожен ServiceAccount. Коли ви бачите impersonate в ролі, спитайте, які цілі дозволено та чому оператор не може скористатися kubectl auth can-i --as з наявної адміністративної ідентичності замість цього.
Права, спрямовані на вузли, також заслуговують на увагу в посилених кластерах. Деякі ресурси та підресурси можуть розкривати функціональність kubelet, проксі-доступ до вузла чи дані робочого навантаження, що є потужнішими, ніж натякає ім’я ресурсу. Вам не потрібно запам’ятовувати кожен маловідомий шлях підвищення привілеїв для цього модуля, але ви маєте розпізнавати патерн: будь-яке право, що переходить від метаданих API до облікових даних, доступу до вузла, виконання робочого навантаження чи зміни RBAC, потребує сильнішого обґрунтування, ніж звичайна видимість застосунку лише для читання.
Тому запобігання підвищенню привілеїв використовує багаторівневе доведення. По-перше, підтвердьте, що суб’єкт не може змінювати RBAC чи прив’язувати потужніші ролі. По-друге, підтвердьте, що суб’єкт не може читати широкі Secret чи уособлювати потужніші ідентичності. По-третє, підтвердьте, що створення подів поєднано з Pod Security Admission рівня простору імен та належними межами ServiceAccount. Нарешті, перевірте заплановану дозволену дію та принаймні дві заборонені дії, щоб ваше виправлення не просто виглядало вузьким у YAML.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Патерни й антипатерни корисні лише тоді, коли вони допомагають вам обрати під обмеженнями. Іспит рідко питає: «чи добрі найменші привілеї?». Він дає вам робоче навантаження, команду, що падає, надто широку роль чи підозрілу прив’язку та просить змінити кластер, не створюючи нового шляху підвищення привілеїв. Патерни нижче — це звички ухвалення рішень: вони пов’язують суб’єкта, ресурс, дієслово, область дії та крок перевірки.
┌─────────────────────────────────────────────────────────────┐│ RBAC BEST PRACTICES │├─────────────────────────────────────────────────────────────┤│ ││ 1. Least Privilege ││ └── Only grant what's needed ││ └── Prefer Roles over ClusterRoles ││ └── Use resourceNames when possible ││ ││ 2. No Wildcards ││ └── Never use "*" in production ││ └── List specific resources and verbs ││ ││ 3. Audit Regularly ││ └── Review cluster-admin bindings ││ └── Check for secret access ││ └── Monitor RBAC changes ││ ││ 4. Namespace Isolation ││ └── One ServiceAccount per application ││ └── Roles scoped to namespace ││ ││ 5. Protect RBAC Resources ││ └── Only cluster admins modify RBAC ││ └── Audit bind/escalate verbs ││ │└─────────────────────────────────────────────────────────────┘| Підхід | Коли використовувати | Чому це працює | Аспект масштабування |
|---|---|---|---|
| Role плюс RoleBinding | Робоче навантаження потребує ресурсів простору імен в одному просторі імен | Область дії відповідає межі ресурсу й обмежує випадкові надання в межах усього кластера | Повторюйте на кожен простір імен або шаблонізуйте через GitOps, коли той самий патерн навантаження з’являється знову |
| ClusterRole плюс RoleBinding | Той самий набір правил простору імен слід повторно використати в кількох просторах імен | Набір прав багаторазовий, але кожна прив’язка залишається в межах простору імен | Тримайте відповідальність чіткою, щоб одна зміна спільного ClusterRole не здивувала кожен простір імен |
| Імена ресурсів | Робоче навантаження читає чи оновлює конкретні іменовані об’єкти | Правило блокує доступ до сусідніх об’єктів того самого виду | Уникайте для процесів виявлення, що потребують list чи watch по динамічних наборах об’єктів |
| Окремі ServiceAccount | Кілька робочих навантажень працюють в одному просторі імен із різними потребами в API | Кожен токен несе лише власні права робочого навантаження | Потребує дисципліни розгортання, щоб поди тихо не відкочувалися до default ServiceAccount |
Перший антипатерн — використання вбудованих ролей замість збирання вимог. view, edit, admin та cluster-admin зручні, але зручність не є доказом того, що роль відповідає робочому навантаженню. Зокрема, edit може бути надто потужним для багатьох ServiceAccount застосунків, бо зміна робочих навантажень може взаємодіяти з обліковими даними та політикою допуску. Надавайте перевагу користувацьким ролям, коли вимога достатньо мала, щоб сформулювати її точно.
Другий антипатерн — виправлення відмови додаванням ClusterRoleBinding, бо він працює всюди. Цей підхід часто приховує початкову помилку області дії та ускладнює майбутні аудити. Якщо відхилений запит обмежений простором імен, виправляйте його за допомогою RoleBinding у просторі імен, якщо робоче навантаження справді не потребує ресурсів кластерного рівня чи всіх просторів імен. Успішна команда після широкого надання не є доказом доброго виправлення; вона лише доказ того, що широке надання включило відсутнє право.
Третій антипатерн — спільне використання потужного default ServiceAccount між непов’язаними подами. Це зазвичай стається, бо маніфести пропускають serviceAccountName, default простору імен з часом накопичує права, і ніхто не знає, яке робоче навантаження їх досі потребує. Краща альтернатива — один ServiceAccount на застосунок чи контролер, із automountServiceAccountToken: false, коли под не викликає API. Цей дизайн перетворює аудит із загадки простору імен на перегляд, специфічний для робочого навантаження.
Четвертий антипатерн — ігнорування заборонених дій після успішної зміни. Якщо ви надаєте конвеєру право патчити Deployment, також перевірте, що він не може читати Secret, створювати ClusterRoleBinding чи видаляти робочі навантаження в сусідньому просторі імен. Негативні тести — не церемонія; це те, як ви доводите, що виправлення не протягнуло повноважень, яких запит ніколи не обґрунтовував. На іспиті CKS пара точкових перевірок can-i може запобігти широкій, але прохідній відповіді.
Фреймворк прийняття рішень
Розділ «Фреймворк прийняття рішень»Використовуйте фреймворк прийняття рішень, коли ви під тиском часу й кожне поле YAML виглядає правдоподібним. Почніть із суб’єкта, бо ідентичність контролює радіус ураження: людина-користувач, зовнішня група, ServiceAccount контролера та ServiceAccount застосунку мають різні строки життя й моделі компрометації. Потім визначте потрібну операцію API в термінах Kubernetes: групу API, ресурс чи підресурс, дієслово, простір імен та ім’я об’єкта, якщо доречно. Лише після того, як ці факти прояснені, варто обирати між Role та ClusterRole і типом прив’язки.
| Точка рішення | Обирайте вужчий варіант, коли | Обирайте ширший варіант лише коли |
|---|---|---|
| Role чи ClusterRole | Ресурси належать простору імен, а правило унікальне для одного простору імен | Правило включає ресурси кластерного рівня або має бути узгоджено повторно використане |
| RoleBinding чи ClusterRoleBinding | Доступ має діяти всередині одного простору імен | Доступ має діяти в межах усього кластера, а суб’єкту довіряють для цієї області дії |
get чи list/watch | Робоче навантаження знає точне ім’я об’єкта | Робоче навантаження має виявляти чи безперервно спостерігати набір об’єктів |
| Користувацька чи вбудована роль | Вимога називає невеликий набір ресурсів та дієслів | Вбудовану роль переглянуто, і вона відповідає всій вимозі |
| Токен ServiceAccount змонтовано чи вимкнено | Под не викликає API Kubernetes | Робоче навантаження потребує доступу до API й має роль, спроєктовану для цієї ідентичності |
Найбезпечніший робочий процес — вимога, роль, прив’язка, перевірка та негативна перевірка. По-перше, напишіть одне речення, що описує потрібну поведінку, наприклад «ServiceAccount backend читає поди та логи подів у просторі імен app». Далі перекладіть це речення в Role чи ClusterRole. Потім прив’яжіть її до точного суб’єкта. Нарешті, перевірте дозволену операцію та принаймні одну заборонену операцію, що вказувала б на перевищення.
Якщо ви знайдете наявне широке надання, вирішіть, чи редагувати, замінювати чи розділяти його. Редагуйте роль лише тоді, коли ви знаєте, що кожен суб’єкт, прив’язаний до неї, повинен отримати нові вужчі права. Замінюйте прив’язку, коли одному суб’єкту потрібен інший набір прав, ніж іншим суб’єктам. Розділяйте роль, коли спільна роль змішує непов’язані можливості, як-от читання ConfigMap та запис RBAC, якими мають володіти різні ідентичності.
Коли робоче навантаження зламано через RBAC, протистійте спокусі стрибнути просто від повідомлення про помилку до готової ролі. Помилка forbidden зазвичай включає спробуване дієслово, ресурс, групу API та простір імен, чого достатньо, щоб накидати вузьке правило. Відсутнє правило все одно потребує політичного рішення: застосунок, що просить оновити власний підресурс Status, відрізняється від застосунку, що просить перелічити кожен Secret. Діагностика каже вам, що було заборонено, а не чи слід це дозволяти.
Для перегляду підвищення привілеїв розверніть фреймворк. Спитайте, що скомпрометований суб’єкт міг би зробити далі, якби поточне право було використано неналежно. get pods зазвичай розкриває метадані, get secrets може розкрити облікові дані, create pods може створити нове середовище виконання, patch deployments може змінити запущений код, а дієслова запису RBAC можуть змінити граф авторизації. Це мислення «спершу наслідок» допомагає вам пріоритезувати, які знахідки слід виправити, перш ніж PR чи відповідь на іспиті вважатиметься завершеною.
Останнє правило рішення — це відповідальність. Платформена команда може володіти ClusterRole, команди простору імен можуть володіти RoleBinding усередині своїх просторів імен, а команди застосунків можуть володіти ServiceAccount лише тоді, коли запобіжники не дають їм прив’язувати потужніші ролі чи оминати допуск. Якщо відповідальність нечітка, RBAC дрейфує до широких спільних ідентичностей, бо ніхто не хоче зламати чуже робоче навантаження. Чітка відповідальність є засобом контролю безпеки, бо вона робить вузькі права підтримуваними.
Чи знали ви?
Розділ «Чи знали ви?»-
RBAC у Kubernetes став стабільним в API
rbac.authorization.k8s.io/v1під час лінії релізів 1.8. Саме ця стабільність є причиною того, що та сама базова структура Role та RoleBinding досі з’являється в навчанні та промислових аудитах Kubernetes 1.35. -
Групу
system:mastersтрактують як статичну ідентичність суперкористувача, а не як право, яке ви надаєте через RoleBinding. Авторизатор API-сервера надає цій групі доступ, еквівалентний cluster-admin, напряму, тож видалення прив’язок RBAC не звузить клієнтський сертифікат чи ідентичність, що все ще належить до неї. -
Агреговані ClusterRole розширюють вбудовані ролі через мітки на кшталт
rbac.authorization.k8s.io/aggregate-to-view. Це дозволяє користувацьким ресурсам додавати правила читання доview, але це також означає, що поведінка вбудованої ролі може змінитися, коли встановлюються нові помічені ClusterRole. -
Значення Secret закодовано в base64, а не зашифровано для читача, що має право API на їх отримання. Шифрування в стані спокою (at rest) захищає носії зберігання, але RBAC усе одно вирішує, чи може користувач чи ServiceAccount запитати в API-сервера розкодовані дані об’єкта.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це трапляється | Як це виправити |
|---|---|---|
Надання cluster-admin розробникам | Широка прив’язка змушує зламані команди працювати негайно, тож це здається ефективним розблокуванням | Окресліть фактичні операції розгортання, діагностики чи читання та прив’яжіть користувацьку Role чи переглянуту вбудовану роль у найвужчій області дії |
| Використання ClusterRole, коли працює Role | Інженери обирають багаторазові об’єкти, перш ніж вирішити, чи має доступ перетинати межі простору імен | Використовуйте Role для одного простору імен або поєднуйте багаторазовий ClusterRole з RoleBinding у просторі імен замість ClusterRoleBinding |
| Символи підстановки в промисловому середовищі | Команди копіюють завантажувальний YAML з експериментів, де швидкість важила більше за межі авторизації | Замініть * явними групами API, ресурсами та дієсловами, потім перевірте очікувані дозволи й важливі заборони |
| Відсутність аудиту прив’язок | Рецензенти інспектують Role, але пропускають суб’єктів, що їх фактично отримують | Простежуйте RoleBinding та ClusterRoleBinding, включно з групами та ServiceAccount, перш ніж оцінювати ефективний доступ |
| Ігнорування налаштувань ServiceAccount за замовчуванням | Поди без serviceAccountName успадковують default-ідентичність простору імен, яка може накопичити старі права | Створюйте ServiceAccount, специфічні для робочого навантаження, та вимикайте автомонтування токена для подів, що не викликають API Kubernetes |
| Надання доступу list до Secret заради зручності | Застосунки часто просять доступ до «конфігурації», і Secret потрапляють разом із ConfigMap | Відокремте облікові дані від конфігурації та використовуйте resourceNames для читання іменованих Secret, коли робоче навантаження справді цього потребує |
Виправлення відмов через edit | Вбудована роль знайома й зазвичай прибирає миттєву помилку | Додавайте відсутнє дієслово та ресурс лише після рішення, що відхилена операція належить робочому навантаженню |
| Забування про негативні тести | Перевірка успіху доводить, що бажана дія працює, але не виявляє випадкових зайвих повноважень | Поєднуйте кожну дозволену перевірку kubectl auth can-i із забороненими перевірками для Secret, запису RBAC та сусідніх просторів імен |
Тест
Розділ «Тест»1. Ваш CI-сервісний акаунт може патчити Deployment у просторі імен `payments`, але аудит показує, що його прив'язано до ClusterRole з символом підстановки через ClusterRoleBinding. Як впровадити безпечнішу заміну, не зламавши релізи?
Створіть Role у межах простору імен payments, що надає лише ті дієслова й ресурси, які потрібні конвеєру, наприклад патчинг Deployment та читання стану розгортання, якщо потрібно. Прив’яжіть цю Role до CI-сервісного акаунта за допомогою RoleBinding, перевірте дозволену операцію розгортання за допомогою kubectl auth can-i та перевірте, що запис до Secret і RBAC заборонено. ClusterRoleBinding із символом підстановки слід прибрати лише після того, як доведено, що вузька прив’язка підтримує процес релізу. Це впроваджує найменші привілеї, зберігаючи бізнес-функцію.
2. Скомпрометований под використав токен свого ServiceAccount, щоб перелічити Secret у кількох просторах імен. Що ви аудитуєте першим і чому перевірки лише маніфесту пода недостатньо?
Почніть із простеження ефективних надань RBAC для цього ServiceAccount, особливо ClusterRoleBinding та будь-яких Role чи ClusterRole, що включають get, list чи watch на Secret. Маніфест пода каже вам, який ServiceAccount було змонтовано, але він не показує кожну прив’язку, що надає цій ідентичності право. Потім вам слід замінити широкий доступ до Secret на читання іменованих Secret або прибрати його цілком, якщо робоче навантаження не потребує читання Secret через API. Перевірка як system:serviceaccount:<namespace>:<name> доводить, чи змінило виправлення відповідь авторизації.
3. Розробник має `create pods` у просторі імен, що містить ServiceAccount, прив'язаний до `cluster-admin`. Він не може напряму оновлювати RBAC. Поясніть ризик підвищення привілеїв та засоби контролю, які ви перевірили б.
Розробник може мати змогу створити под, що працює як потужний ServiceAccount, а потім скористатися змонтованим токеном, щоб викликати API з цією потужнішою ідентичністю. RBAC не надав права запису RBAC напряму, але створення пода стало опосередкованим шляхом до інших облікових даних. Перевірте, чи обмежує політика допуску вибір ServiceAccount, чи блокує Pod Security Admission небезпечні налаштування пода та чи існують у цьому просторі імен потужні ServiceAccount. Безпечніший дизайн розділяє робочі навантаження, звужує ServiceAccount та надає створення подів лише там, де ці запобіжники на місці.
4. Ваша команда отримує помилку `forbidden`, коли оператор намагається створити Event, а колега пропонує прив'язати оператора до `edit`. Як точніше діагностувати й усунути цю відмову?
Прочитайте повідомлення forbidden, щоб визначити дієслово, ресурс, групу API та простір імен, потім перевірте ту саму дію за допомогою kubectl auth can-i create events --as=<subject> -n <namespace>. Якщо створення Event є частиною відповідальності оператора, додайте вузьке правило для create на events у базовій групі API чи відповідній групі API Events, що використовується версією кластера. Уникайте edit, бо він надає багато непов’язаних прав на зміну робочих навантажень. Після зміни перевірте, що створення Event працює, а непов’язані дії на кшталт читання Secret усе ще зазнають невдачі.
5. Role містить `resourceNames: ["app-config"]` із `verbs: ["get"]` на ConfigMap, але застосунок падає, коли намагається спостерігати (watch) за ConfigMap за міткою. Роль неправильна, чи вимога застосунку інша?
Role коректна для читання відомого ConfigMap за іменем, але вона не відповідає процесу виявлення, що спостерігає за динамічним набором ConfigMap. resourceNames працює найкраще, коли клієнт називає об’єкт у запиті, тоді як операції list та watch зазвичай потребують ширшого доступу, щоб спостерігати набори. Вам слід вирішити, чи справді застосунку потрібне виявлення; якщо так, надайте найвужче правило list чи watch у межах простору імен, що підтримує цю поведінку. Якщо ні, змініть конфігурацію застосунку так, щоб він запитував іменований ConfigMap напряму.
6. Під час перегляду ви знаходите ClusterRole із `bind` та `escalate` на ресурсах RBAC, призначений акаунту автоматизації простору імен. Чим це відрізняється від звичайного доступу create чи update?
Дієслово bind дозволяє суб’єкту створювати прив’язки до ролей, прав яких він може й не мати, а escalate дозволяє зміни ролей, що надають права понад поточні повноваження суб’єкта. Ці дієслова стосуються саме перетинання меж авторизації, тож вони чутливіші за рутинний запис до звичайних ресурсів простору імен. Акаунту автоматизації простору імен вони рідко потрібні, бо роботу з розгортання в межах простору імен зазвичай можна виконати вузькими Role та RoleBinding. Приберіть чи ізолюйте ці дієслова, якщо акаунт не є строго контрольованою адміністративною ідентичністю з явною відповідальністю за управління RBAC.
7. Ви простежуєте підозріле «так» від `kubectl auth can-i get secrets --as=system:serviceaccount:default:default`, але не можете знайти RoleBinding у просторі імен `default`. Що слід перевірити далі?
Перевірте ClusterRoleBinding, бо вони можуть надавати ServiceAccount права в межах усього кластера навіть тоді, коли не існує жодного RoleBinding у просторі імен. Також інспектуйте суб’єктів-груп, якщо постачальник ідентичності чи завантажувальний процес зіставив суб’єкта з привілейованою групою, хоча ServiceAccount зазвичай найлегше простежити за їхнім повним іменем system:serviceaccount. Щойно ви знайдете прив’язку, інспектуйте зазначений ClusterRole на правила щодо Secret та замініть надання на RoleBinding у просторі імен, лише якщо доступ до Secret справді потрібен. Ключове — простежувати ефективне право назад, а не припускати, що джерело міститься в просторі імен.
Практична вправа
Розділ «Практична вправа»У цій вправі ви проведете аудит та виправите навмисно надмірно привілейований ServiceAccount. Налаштування надає ServiceAccount простору імен ClusterRole із символом підстановки через ClusterRoleBinding, що є саме тим типом обхідного шляху, який ви маєте вміти розпізнавати й прибирати. Виконуйте команди в одноразовому кластері чи лабораторному середовищі, бо вправа створює об’єкти RBAC, а потім видаляє їх під час очищення.
# Setup: Create overpermissive configurationkubectl create namespace rbac-testkubectl create serviceaccount admin-app -n rbac-test
cat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: overpermissiverules:- apiGroups: ["*"] resources: ["*"] verbs: ["*"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: admin-app-bindingsubjects:- kind: ServiceAccount name: admin-app namespace: rbac-testroleRef: kind: ClusterRole name: overpermissive apiGroup: rbac.authorization.k8s.ioEOF
# Task 1: Audit the permissionskubectl auth can-i --list --as=system:serviceaccount:rbac-test:admin-app
# Task 2: Confirm it can read secrets (expected with the wildcard grant)kubectl auth can-i get secrets --as=system:serviceaccount:rbac-test:admin-app
# Task 3: Create a restricted role (only pods in namespace)cat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-manager namespace: rbac-testrules:- apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch", "create", "delete"]EOF
# Task 4: Replace the ClusterRoleBinding with RoleBindingkubectl delete clusterrolebinding admin-app-binding
cat <<EOF | kubectl apply -f -apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: admin-app-binding namespace: rbac-testsubjects:- kind: ServiceAccount name: admin-app namespace: rbac-testroleRef: kind: Role name: pod-manager apiGroup: rbac.authorization.k8s.ioEOF
# Task 5: Verify permissions are now restrictedkubectl auth can-i get secrets --as=system:serviceaccount:rbac-test:admin-app# Should return "no"
kubectl auth can-i get pods --as=system:serviceaccount:rbac-test:admin-app -n rbac-test# Should return "yes"
kubectl auth can-i get pods --as=system:serviceaccount:rbac-test:admin-app -n default# Should return "no" (namespace-scoped)
# Cleanupkubectl delete namespace rbac-testkubectl delete clusterrole overpermissiveВаше перше завдання — зафіксувати небезпечний базовий стан, перш ніж щось виправляти. Збережіть вивід kubectl auth can-i --list десь, де ви зможете подумки порівняти його з кінцевим станом, та виконайте точкові перевірки для Secret, доступу до подів у rbac-test та доступу до подів в іншому просторі імен. Суть — довести і наявність ризикованого надання, і точну область дії виправленого надання.
- Створіть простір імен
rbac-test, ServiceAccountadmin-app, ClusterRole з символом підстановки та ClusterRoleBinding із блоку налаштування. - Проведіть аудит ефективних прав для
system:serviceaccount:rbac-test:admin-appта визначте принаймні одну небезпечну дозволену дію. - Підтвердьте, що ServiceAccount може читати Secret до виправлення, потім запишіть, чому це неприйнятно для ідентичності, що управляє подами.
- Замініть ClusterRoleBinding із символом підстановки на RoleBinding у просторі імен до Role
pod-manager. - Перевірте, що управління подами працює в
rbac-testі зазнає невдачі вdefault. - Перевірте, що читання Secret заборонено після застосування прив’язки-заміни.
Підказка до рішення
Важливе виправлення — зміна і набору прав, і області дії прив’язки. Role pod-manager належить простору імен, а RoleBinding-заміна живе в rbac-test, тож ServiceAccount більше не отримує прав у межах усього кластера з символом підстановки. Ваші фінальні перевірки мають показати no для читання Secret, yes для доступу до подів у rbac-test та no для доступу до подів у default. Якщо будь-яка з цих відповідей відрізняється, інспектуйте решту ClusterRoleBinding, бо старе широке надання все ще може діяти.
Після базового виправлення розширте вправу, зробивши роль реалістичнішою. Вирішіть, чи справді застосунку потрібні create та delete на Pod, чи йому потрібно лише get, list, watch та get на pods/log. Потім оновіть Role відповідно та повторіть позитивні й негативні перевірки. Цей другий прохід важливий, бо надана Role pod-manager безпечніша за wildcard, але вона все одно може бути ширшою, ніж насправді потрібно застосунку лише для читання.
Рішення челенджу
Для робочого навантаження лише для читання приберіть create та delete із правила pods та додайте окреме правило pods/log із get, якщо потрібні логи. Перевірте, що kubectl auth can-i delete pods --as=system:serviceaccount:rbac-test:admin-app -n rbac-test повертає no, тоді як kubectl auth can-i get pods --as=system:serviceaccount:rbac-test:admin-app -n rbac-test повертає yes. Це демонструє, що найменші привілеї — це не лише заміна області дії в межах усього кластера; це також прибирання непотрібних дієслів усередині простору імен.
Успіх — це не просто прохідна команда. Безпечна відповідь має докази того, що ServiceAccount зберіг призначену здатність працювати з подами в просторі імен, втратив досяжність у межах усього кластера, втратив доступ до Secret та більше не залежить від прав із символом підстановки. Саме ці докази ви помістили б у pull request, нотатку до інциденту чи відповідь на іспиті, щоб показати, що виправлення є контрольованим, а не випадковим.
Перевірка засвоєння
Розділ «Перевірка засвоєння»ClusterRole із символом підстановки, прив’язаний через ClusterRoleBinding, дозволяє ServiceAccount простору імен читати Secret у межах усього кластера; практична вправа доводить цей надмірно широкий базовий стан за допомогою
kubectl auth can-iще до того, як ви заміните прив’язку на RoleBinding у межах простору імен.
Перш ніж рухатися далі, поясніть, чому зміна ClusterRoleBinding не є автоматично еквівалентною наданню собі cluster-admin, та які дієслова RBAC роблять цю різницю явною. Ґрунтовна відповідь називає запобіжники bind та escalate, протиставляє пряму зміну RBAC опосередкованому підвищенню привілеїв через под та включає принаймні одну негативну перевірку kubectl auth can-i після вашого виправлення.
Джерела
Розділ «Джерела»- 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/authentication/
- https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
- https://kubernetes.io/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i/
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
- https://kubernetes.io/docs/concepts/security/pod-security-admission/
- https://kubernetes.io/docs/concepts/security/pod-security-standards/
- https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/role-v1/
- https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/role-binding-v1/
- https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-v1/
- https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-binding-v1/
Наступний модуль
Розділ «Наступний модуль»Модуль 2.2: Безпека ServiceAccount — посилення безпеки ServiceAccount, монтування токенів та ідентичностей робочих навантажень, щоб надання RBAC не перетворювалися на багаторазові облікові дані.