Модуль 3.1: Безпека Подів
Складність:
[СЕРЕДНЯ]— базові знання для інженерів, яким потрібно оцінювати ризики під час виконання Подів та поведінку допускуЧас на проходження: 40–50 хвилин читання, перегляду маніфестів і практичної роботи з усунення проблем
Передумови: Модуль 2.4: PKI та сертифікати, а також базова впевненість у читанні YAML Подів і міток просторів імен
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете переглядати реальні маніфести Подів, діагностувати поведінку Pod Security Admission та пояснювати компроміси безпеки, що стоять за кожною рекомендованою зміною:
- Оцінювати налаштування
securityContextна рівні Пода й контейнера, щоб відокремити прийнятні рішення з посилення безпеки від конфігурацій, що уможливлюють підвищення привілеїв, доступ до хоста чи закріплення зловмисника. - Порівнювати профілі Pod Security Standards
privileged,baselineтаrestrictedі рекомендувати найменш дозвільний профіль, що підходить для класу робочого навантаження. - Діагностувати відмови та попередження Pod Security Admission, зіставляючи відповідь API з точним полем, що порушує політику простору імен.
- Проєктувати посилену специфікацію Пода, яка працює не від імені root, відкидає непотрібні можливості Linux, використовує seccomp і зберігає працездатність застосунку завдяки явно заданим шляхам для запису.
- Визначати, коли виняток для робочого навантаження виправданий, а потім обмежувати цей виняток мітками простору імен, ізоляцією навантаження та задокументованими компенсувальними засобами контролю.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Платформена команда успадковує кластер, де кожен простір імен застосунків дозволяє привілейовані Поди, бо одному агенту моніторингу багато років тому знадобився доступ до хоста. Через місяці вразливий вебзастосунок зазнає компрометації, і зловмисник виявляє, що контейнер може працювати від імені root, додавати широкі можливості Linux, писати у свою файлову систему та спільно використовувати мережу вузла. Початкова помилка застосунку була звичайною; радіус ураження став небезпечним, бо Поду дозволили поводитися як частина хоста.
Безпека Подів — це межа між «зловмисник контролює один процес» і «зловмисник може взаємодіяти з вузлом». Kubernetes не робить кожен Под безпечним за замовчуванням, бо багатьом легітимним системним компонентам потрібен потужний доступ до мережі, пристроїв чи просторів імен хоста. Така гнучкість корисна для операторів кластера, але це означає, що командам застосунків доводиться вчитися розрізняти, які поля є рутинним посиленням безпеки, які поля є винятками, а які поля мають запускати перегляд дизайну.
Вплив на бізнес не є теоретичним. Під час розборів інцидентів дорогою частиною часто виявляється не початкова помилка віддаленого виконання коду; це розслідування, ротація облікових даних, перебудова вузлів, термінова робота з міжмережевими екранами та простій, помітний для клієнтів, спричинений нечіткою локалізацією загрози. Якщо скомпрометований Под може писати лише до /tmp і спілкуватися через мережевий шлях застосунку, у відповідальних осіб одна ніч. Якщо той самий Под може досліджувати процеси хоста, монтувати чутливі шляхи хоста чи завантажувати інструменти, що взаємодіють із ядром, відповідальні особи мусять припустити, що межу вузла зламано, і розширити інцидент.
Цей модуль навчає безпеки Подів як процесу прийняття рішень, а не як контрольного списку. Спершу ви побудуєте ментальну модель того, де застосовуються засоби контролю Подів, потім дослідите поширені небезпечні поля, а далі пов’яжете ці поля з Pod Security Standards та Pod Security Admission. Наприкінці ви маєте вміти подивитися на маніфест Пода й пояснити не лише те, чи він дозволений, а й чому існує ризик і як його зменшити, не зламавши робоче навантаження.
Безпека Подів починається з меж
Розділ «Безпека Подів починається з меж»Контейнер ізольовано засобами ядра Linux, такими як простори імен, cgroups, можливості (capabilities) та фільтри seccomp. Kubernetes надає багато цих засобів контролю через специфікацію Пода, тож команди можуть вирішувати, наскільки робочому навантаженню дозволено бачити хост чи впливати на нього. Важлива ідея полягає в тому, що безпека Пода — це не один перемикач; це набір рівнів, які або зберігають, або послаблюють ізоляцію.
┌───────────────────────────────────────────────────────────────┐│ POD SECURITY LAYERS │├───────────────────────────────────────────────────────────────┤│ ││ POD-LEVEL SETTINGS ││ Apply to the whole pod unless a container overrides them ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ securityContext: │ ││ │ runAsUser, runAsGroup, fsGroup │ ││ │ seccompProfile │ ││ │ hostNetwork, hostPID, hostIPC │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ CONTAINER-LEVEL SETTINGS ││ Apply to one container and can be more specific ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ securityContext: │ ││ │ runAsUser, runAsNonRoot │ ││ │ readOnlyRootFilesystem │ ││ │ allowPrivilegeEscalation │ ││ │ capabilities, privileged, seccompProfile │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ ADMISSION ENFORCEMENT ││ Decides whether the API server accepts the pod ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Pod Security Standards │ ││ │ Pod Security Admission │ ││ │ Optional policy engines such as Kyverno or Gatekeeper │ ││ └─────────────────────────────────────────────────────────┘ ││ │└───────────────────────────────────────────────────────────────┘Корисний спосіб міркувати про Под — поставити по черзі три запитання. По-перше, від чийого імені працює процес усередині контейнера? По-друге, які додаткові привілеї ядра отримує цей процес? По-третє, які частини хоста Под спільно використовує чи монтує? Більшість небезпечних конфігурацій Подів ризиковані саме тому, що надто щедро відповідають на одне з цих запитань.
Наприклад, Под, що працює під UID 0, не є автоматично компрометацією хоста, але це більша стартова позиція для зловмисника. Под, що працює під UID 0, зберігає типові можливості, дозволяє підвищення привілеїв і монтує шляхи хоста, набагато ближчий до проблеми рівня вузла. Безпека Kubernetes часто полягає в тому, щоб не дати цим дрібним дозволам скластися в серйозний шлях для виходу за межі.
Уявіть ці налаштування як ключі, видані підряднику, що входить до захищеної будівлі. Перепустка до одного офісу відрізняється від перепустки до серверної, і обидві відрізняються від майстер-ключа разом із дозволом вимикати сигналізацію. Безпека Подів працює так само: під час перегляду потрібно враховувати поєднання ідентичності, можливостей, просторів імен, томів і міток допуску. Поле, що виглядає керованим саме по собі, може стати небезпечним у парі з іншим полем, яке прибирає окремий рівень ізоляції.
Зупиніться та подумайте: Розробник стверджує, що його контейнеру потрібен
privileged: true, бо той має слухати порт80. Перш ніж читати далі, вирішіть, чи це виправдання слушне, і назвіть найменший дозвіл, що розв’язав би зазначену проблему.
Відповідь у дусі мінімальних привілеїв — це зазвичай NET_BIND_SERVICE, а не privileged: true. Прив’язування до портів нижче 1024 контролюється конкретною можливістю Linux, тож надати всі можливості та пристрої хоста було б поганим обміном. Цей патерн часто з’являється під час оглядів безпеки: робоче навантаження має реальну потребу, але запропонований дозвіл значно ширший за неї.
Ця різниця важлива на іспиті KCSA та в реальних оглядах, бо Kubernetes дає кілька способів задовольнити одну й ту саму вимогу застосунку. Сервіс може надавати порт 80, поки контейнер слухає на 8080. Образ, що не працює від імені root, може володіти каталогами, які йому насправді потрібні. emptyDir може надати тимчасовий простір, не роблячи файлову систему образу змінною. Уміння полягає не в запам’ятовуванні кожного можливого поля; уміння полягає в зіставленні потреби з найменшим механізмом Kubernetes чи Linux, що її задовольняє.
SecurityContext: головна поверхня контролю
Розділ «SecurityContext: головна поверхня контролю»Поле securityContext — це місце, де Kubernetes дозволяє задати ідентичність користувача, поведінку файлової системи, правила підвищення привілеїв, можливості Linux та вибір профілю seccomp. Воно може з’являтися на рівні Пода й на рівні контейнера. Налаштування рівня Пода — це зручні типові значення, тоді як налаштування рівня контейнера корисні, коли init-контейнеру чи sidecar потрібне щось відмінне від основного застосунку.
Посилена специфікація контейнера зазвичай починається з прибирання широких дозволів перед додаванням вузьких винятків. Наведений маніфест навмисно достатньо малий, щоб вивчати його поле за полем. Приклади команд використовують повну назву бінарника kubectl, тож вони залишаються придатними для копіювання в неінтерактивних оболонках, завданнях CI та скриптах лабораторних робіт.
kubectl create namespace pod-security-demoapiVersion: v1kind: Podmetadata: name: secure-web namespace: pod-security-demospec: securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 2000 seccompProfile: type: RuntimeDefault containers: - name: web image: nginx:1.27 ports: - containerPort: 8080 securityContext: runAsNonRoot: true readOnlyRootFilesystem: true allowPrivilegeEscalation: false privileged: false capabilities: drop: - ALL volumeMounts: - name: cache mountPath: /var/cache/nginx - name: run mountPath: /var/run - name: tmp mountPath: /tmp volumes: - name: cache emptyDir: {} - name: run emptyDir: {} - name: tmp emptyDir: {}Цей маніфест відокремлює намір щодо безпеки від потреб застосунку. Коренева файлова система доступна лише для читання, але NGINX усе одно отримує каталоги з можливістю запису для файлів часу виконання через томи emptyDir. Процес працює під UID, що не є root, підвищення привілеїв вимкнено, а можливості Linux відкинуто. Профіль seccomp встановлено на RuntimeDefault, що дає середовищу виконання контейнерів змогу блокувати небезпечні системні виклики, не змушуючи учня писати власний профіль.
Зверніть увагу, що securityContext рівня Пода виражає типові значення, спільні для Пода, тоді як блок рівня контейнера виражає обмеження, специфічні для процесу web. Цей поділ — більше ніж стиль. Налаштування ідентичності рівня Пода зменшують повторення й роблять маніфест легшим для перегляду, але налаштування рівня контейнера все ще потрібні для таких засобів контролю, як readOnlyRootFilesystem, allowPrivilegeEscalation, privileged та можливості. Тому рецензенти мають читати обидва рівні як одну спільну політику, а не вважати жоден блок повним сам по собі.
Томи з можливістю запису також є частиною дизайну безпеки, а не зручністю, доданою постфактум. Багато образів припускають, що можуть створювати кеш-файли, PID-файли, тимчасові файли чи сокети за шляхами, що лежать у файловій системі образу. Коли ви робите цю файлову систему доступною лише для читання, ці припущення стають видимими. Уважний інженер використовує невдачу, щоб дізнатися, яким саме шляхам потрібен запис, а потім явно надає ці шляхи. Поспішний інженер вимикає налаштування «лише для читання» й втрачає корисний засіб контролю.
| Поле | Безпечний напрямок | Чому це важливо | Поширений компроміс |
|---|---|---|---|
runAsNonRoot | Установіть true | Запобігає випадковому виконанню від імені root, коли типове значення образу змінюється | Образ має працювати під UID, що не є root |
runAsUser | Використовуйте ненульовий UID | Робить ідентичність часу виконання явною та придатною для перегляду | Може знадобитися коригування власника файлів |
runAsGroup | Використовуйте ненульовий GID | Уникає поведінки типової групи root | Спільним томам можуть знадобитися групові дозволи |
fsGroup | Використовуйте лише там, де томам це потрібно | Дозволяє групі робочого навантаження писати в змонтовані томи | Може сповільнювати запуск тому на деяких типах сховища |
readOnlyRootFilesystem | Установіть true | Зменшує закріплення та підміну в файловій системі образу контейнера | Застосункам потрібні явні томи для запису |
allowPrivilegeEscalation | Установіть false | Блокує setuid та подібні шляхи отримання привілеїв | Деякі застарілі інструменти перестають працювати |
privileged | Залишайте false або опускайте | Уникає широкого доступу до пристроїв хоста та можливостей | Системним агентам може знадобитися окремий виняток |
capabilities.drop | Спершу відкидайте ALL | Прибирає навколишні привілеї Linux, що можуть бути не потрібні застосунку | Повертайте вузькі можливості лише за обґрунтування |
seccompProfile | Використовуйте RuntimeDefault | Фільтрує ризиковані системні виклики через типові значення середовища виконання | Дуже спеціалізованим застосункам може знадобитися власний профіль |
Опрацьований приклад: припустімо, вебконтейнер відмовляє після того, як ви ввімкнули readOnlyRootFilesystem: true. Слабкою реакцією було б вимкнути цей засіб контролю, бо «застосунку потрібен запис». Сильніша реакція — знайти точні шляхи, до яких пише застосунок, і явно змонтувати ці шляхи. Це зберігає незмінну файлову систему застосунку захищеною, водночас даючи процесу контрольовану тимчасову зону.
kubectl apply -f secure-web.yamlkubectl -n pod-security-demo describe pod secure-webkubectl -n pod-security-demo logs secure-webЯкщо в логах згадується шлях на кшталт /var/cache/nginx чи /var/run, додайте монтування emptyDir для цього шляху й спробуйте знову. Це приклад звички старшого інженера з безпеки: зберігайте засіб контролю, коли це можливо, і робіть виняток достатньо точним, щоб його можна було переглянути.
Зробіть паузу й передбачте: Якщо на рівні Пода задано
runAsUser: 1000, але один контейнер задаєrunAsUser: 0, яке значення застосовується до цього контейнера? Поясніть, чому така поведінка перевизначення важлива під час перегляду маніфесту.
securityContext рівня контейнера є більш специфічним, тож він перевизначає типове значення рівня Пода для цього контейнера. Під час перегляду це означає, що ви не можете зупинитися на блоці рівня Пода й припустити, що кожен контейнер безпечний. Init-контейнери, sidecar та контейнери застосунку — усі потребують перевірки, бо один контейнер, що перевизначає налаштування, може послабити Под.
Практична звичка перегляду — прочитати маніфест двічі. На першому проході шукайте широкі ознаки небезпеки: простори імен хоста, privileged, hostPath, додані можливості та виконання від імені root. На другому проході шукайте узгодженість: чи всі контейнери успадковують потрібного користувача, чи перевизначають якісь init-контейнери типові значення, і чи відповідають томи для запису реальним шляхам запису застосунку. Цей другий прохід ловить багато помилок, бо платформені команди часто посилюють основний контейнер, але забувають про допоміжний контейнер, що працює перед ним.
Можливості Linux: менше за root, але все ще потужні
Розділ «Можливості Linux: менше за root, але все ще потужні»Можливості Linux розбивають стару модель «root може все» на вужчі привілеї. Це корисно, бо застосунку може знадобитися одна особлива дія, наприклад прив’язування до порту з малим номером, без потреби мати дозвіл адмініструвати мережевий стек чи монтувати файлові системи. Kubernetes дозволяє відкидати можливості й повертати лише ті, що обґрунтовані.
┌───────────────────────────────────────────────────────────────┐│ LINUX CAPABILITIES │├───────────────────────────────────────────────────────────────┤│ ││ TRADITIONAL MODEL ││ ││ ┌───────────────┐ ┌───────────────────────┐ ││ │ UID 0 root │ ────────────▶ │ Broad system powers │ ││ └───────────────┘ └───────────────────────┘ ││ ││ CAPABILITY MODEL ││ ││ ┌───────────────┐ ┌───────────────────────┐ ││ │ Process │ ────────────▶ │ Specific permissions │ ││ └───────────────┘ └───────────────────────┘ ││ ││ HIGH-RISK CAPABILITIES ││ ││ ┌───────────────────┬─────────────────────────────────────┐ ││ │ SYS_ADMIN │ Mounts, namespaces, broad admin use │ ││ │ NET_ADMIN │ Network configuration and routing │ ││ │ SYS_PTRACE │ Inspect or manipulate processes │ ││ │ DAC_OVERRIDE │ Bypass file permission checks │ ││ │ SYS_RAWIO │ Raw I/O access │ ││ └───────────────────┴─────────────────────────────────────┘ ││ ││ SAFER REVIEW PATTERN ││ ││ capabilities: ││ drop: ││ - ALL ││ add: ││ - NET_BIND_SERVICE ││ │└───────────────────────────────────────────────────────────────┘Найважливіше правило перегляду — ставитися до SYS_ADMIN як до запиту, майже рівносильного привілейованому. Її назва звучить вузько, але на практиці вона відкриває багато операцій ядра, що можуть зламати ізоляцію. Розробник, який каже «ми не привілейовані, бо privileged: true відсутній», усе одно може запитувати небезпечний Под, якщо додано широкі можливості.
Хороший перегляд можливостей запитує про операцію, а не про назву можливості. Якщо робочому навантаженню потрібен порт 80, NET_BIND_SERVICE може бути достатньо. Якщо йому потрібно змінювати маршрути чи правила iptables, NET_ADMIN може бути технічно доречним, але це зазвичай має штовхати робоче навантаження до суворо контрольованого системного простору імен, а не до загального простору імен застосунків. Якщо йому потрібен SYS_ADMIN, команда має ставитися до цього як до винятку, що потребує перегляду архітектури.
Можливості легко недооцінити, бо їхні назви виглядають точними, але операційні наслідки залежать від навколишнього робочого навантаження. NET_ADMIN у демоні CNI, яким володіє платформена команда, що розгорнутий із перевіреного образу й ізольований у системному просторі імен, — це дуже інший ризик, ніж NET_ADMIN у вебзастосунку, зверненому до клієнтів. Поле однакове; межа довіри — ні. Саме тому перегляд безпеки Подів поєднує технічну перевірку полів із власністю та дизайном простору імен.
| Можливість | Типовий запит | Рівень ризику | Краще запитання під час перегляду |
|---|---|---|---|
NET_BIND_SERVICE | Прив’язування до портів нижче 1024 | Низький, якщо ізольовано | Чи може застосунок слухати на високому порту за Сервісом? |
CHOWN | Зміна власника файлів | Середній | Чи можна виправити власника в образі чи під час налаштування тому? |
SETUID / SETGID | Зміна ідентичності процесу | Середній | Чи це застарілий патерн образу, який можна прибрати? |
NET_ADMIN | Зміна маршрутів, iptables, інтерфейсів | Високий | Чи це справді системний агент, а не навантаження застосунку? |
SYS_PTRACE | Налагодження чи дослідження процесів | Високий | Чи може налагодження відбуватися в окремому тимчасовому процесі? |
SYS_ADMIN | Широке адміністрування ядра | Критичний | Чи навантаження фактично просить довіру рівня хоста? |
Розгляньте цей небезпечний фрагмент. Він уникає privileged: true, але все ж надає широку можливість і дозволяє підвищення привілеїв. Це поєднання — саме той випадок, який рецензент має ставити під сумнів, бо воно послаблює одразу більш ніж один рівень ізоляції.
apiVersion: v1kind: Podmetadata: name: risky-capabilityspec: containers: - name: app image: busybox:1.36 command: ["sh", "-c", "sleep 3600"] securityContext: allowPrivilegeEscalation: true capabilities: add: - SYS_ADMINБезпечніший патерн починається без жодних можливостей і додає лише найменший дозвіл, що відповідає поведінці застосунку. Коли немає вузької можливості, яка підходить, відповідь не зводиться автоматично до надання широкої. Відповіддю може бути переробка робочого навантаження, переміщення його до окремого простору імен або використання спеціально призначеної функції Kubernetes замість доступу рівня хоста.
Один тонкий момент для середовищ Kubernetes 1.35+ полягає в тому, що типова поведінка середовища виконання й політика допуску — це окремі речі. Середовище виконання може вже застосовувати типовий профіль seccomp, а образ контейнера може вже працювати під користувачем, що не є root, але ці факти не такі придатні для перегляду, як явний намір у маніфесті. Явні налаштування роблять дрейф видимим під час перегляду коду, оцінювання політики та реагування на інциденти. Коли майбутнє оновлення образу змінює користувача образу чи пише до нового шляху, засоби контролю рівня маніфесту допомагають перетворити цей дрейф на чітку відмову замість тихого послаблення.
Простори імен хоста: де ізоляція може зникнути
Розділ «Простори імен хоста: де ізоляція може зникнути»Простори імен — це один із механізмів, завдяки яким контейнер відчуває себе ізольованим від хоста. Коли Под використовує hostNetwork, hostPID чи hostIPC, він навмисно спільно використовує частину простору імен вузла. Це іноді необхідно для інфраструктури кластера, але рідко доречно для звичайних навантажень застосунків.
┌───────────────────────────────────────────────────────────────┐│ HOST NAMESPACE RISKS │├───────────────────────────────────────────────────────────────┤│ ││ hostPID: true ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Container can see processes from the host PID namespace │ ││ │ Risk: process discovery, signals, ptrace-style attacks │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ hostNetwork: true ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Container uses the node network namespace │ ││ │ Risk: port conflicts, traffic visibility, spoofing │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ hostIPC: true ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Container shares host inter-process communication │ ││ │ Risk: shared memory leakage and process interference │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ secure default: omit these fields or set them to false ││ │└───────────────────────────────────────────────────────────────┘Налаштування просторів імен хоста небезпечні, бо вони змінюють те, що контейнер може спостерігати чи на що впливати. З hostPID процес усередині контейнера може мати змогу перелічувати процеси хоста, дізнаватися командні рядки й намагатися надсилати сигнали процесам, якщо це дозволяють інші дозволи. З hostNetwork контейнер оминає звичайний мережевий простір імен Пода й може конфліктувати з портами хоста чи поводитися як локальний для вузла сервіс. З hostIPC спільна пам’ять і механізми IPC стають проблемою розкриття даних.
Правильне запитання — не «чи підтримує Kubernetes це поле?». Правильне запитання — «який довірений компонент цього потребує і чому він мусить працювати на межі хоста?». Плагіни CNI, агенти моніторингу вузлів, плагіни пристроїв і деякі компоненти зберігання можуть мати слушні відповіді. Вебзастосунок, обробник черги чи API-сервіс зазвичай ні.
Простори імен хоста заслуговують на особливу увагу, бо вони можуть зробити звичайне усунення проблем оманливо легким. Якщо контейнер не бачить процес, hostPID робить процес видимим. Якщо мережева перевірка поводиться інакше зсередини Пода, hostNetwork прибирає частину мережевої абстракції. Ці швидкі виправлення навчають хибного уроку, коли вони залишаються у виробничих маніфестах. Тимчасовий діагностичний доступ слід обробляти через контрольований процес, тоді як Поди застосунків у сталому стані мають зберігати власні простори імен, якщо немає вагомої причини рівня вузла.
| Налаштування хоста | Що воно спільно використовує | Типове легітимне використання | Типове значення для простору імен застосунків |
|---|---|---|---|
hostNetwork: true | Мережевий простір імен вузла | CNI, локальний для вузла DNS, окремі агенти моніторингу | Блокувати або вимагати винятку |
hostPID: true | Простір імен процесів вузла | Глибока діагностика вузла чи агенти безпеки | Блокувати |
hostIPC: true | Простір імен IPC вузла | Рідкісні застарілі чи спеціалізовані навантаження вузла | Блокувати |
Том hostPath | Файли чи каталоги з вузла | Плагіни пристроїв, збирачі логів, агенти, звернені до kubelet | Блокувати чутливі шляхи |
Що сталося б, якби команда перемістила агента моніторингу вузлів і публічний вебзастосунок до одного простору імен, а потім позначила цей простір імен
pod-security.kubernetes.io/enforce: privileged, щоб агент міг працювати? Опишіть ризик, створений для вебзастосунку.
Вебзастосунок успадковує послаблену політику допуску простору імен, хоча йому не потрібен доступ до хоста. Якщо цей застосунок скомпрометовано, зловмисник може подавати чи змінювати Поди, які використовують ті самі широкі дозволи, дозволені для агента моніторингу. Кращий дизайн — ізолювати довірені системні навантаження в окремому просторі імен і тримати простори імен застосунків на рівні baseline чи restricted.
Це головна причина, чому компонування просторів імен є рішенням щодо безпеки. Простір імен — це не лише організаційна тека; для PSA це межа, де мітки вирішують, які специфікації Подів допускаються. Якщо платформена команда змішує агентів вузлів, пакетні завдання, публічні API та навантаження орендарів в одному просторі імен, найсуворіше навантаження може бути обмежене найдозвільнішим винятком. Розділення класів навантажень дозволяє команді захищати звичайні застосунки, не вдаючи, ніби довірені компоненти вузла завжди можуть працювати під одним профілем.
Pod Security Standards: три профілі, різні призначення
Розділ «Pod Security Standards: три профілі, різні призначення»Pod Security Standards, які зазвичай скорочують до PSS, визначають три профілі політики для специфікацій Подів. Вони не є повною програмою безпеки й не замінюють сканування образів, RBAC, NetworkPolicy чи виявлення під час виконання. Це вбудований словник для вирішення того, які функції Подів слід дозволяти під час допуску.
┌───────────────────────────────────────────────────────────────┐│ POD SECURITY STANDARDS │├───────────────────────────────────────────────────────────────┤│ ││ PRIVILEGED ││ ┌─────────────────────────────────────────────────────────┐ ││ │ No meaningful restrictions on pod security fields │ ││ │ Use only for trusted system workloads that need host │ ││ │ access, devices, or broad kernel interaction │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ BASELINE ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Blocks common privilege-escalation paths │ ││ │ Suitable as a minimum bar for many application teams │ ││ │ Still allows some settings that Restricted forbids │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ RESTRICTED ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Enforces stronger hardening expectations │ ││ │ Requires non-root behavior and tighter runtime controls │ ││ │ Best target for sensitive or mature application teams │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ PRACTICAL STARTING POINT ││ Use Restricted when workloads are ready. Use Baseline as a ││ minimum guardrail while teams remediate Restricted warnings. ││ │└───────────────────────────────────────────────────────────────┘Назви профілів описують позицію політики, а не цінність робочого навантаження. Простір імен із міткою privileged не є важливішим за той, що має мітку restricted; він менш обмежений. Це важливо, бо команди іноді просять «privileged», ніби це знак старшинства. У зрілому кластері привілейовані простори імен мають бути рідкісними, чітко названими й обмеженими довіреними системними компонентами.
baseline корисний, коли кластеру потрібен негайний захист від очевидних шляхів підвищення привілеїв, не ламаючи багато наявних образів. Він блокує такі поля, як privileged, простори імен хоста та небезпечні можливості, але не вимагає, щоб кожне навантаження працювало не від імені root. restricted суворіший, бо він очікує виконання не від імені root, вимкненого підвищення привілеїв, відкинутих можливостей і seccomp. Перехід від baseline до restricted часто потребує очищення образу та файлової системи, а не лише зміни мітки.
Профілі найкраще розуміти як драбину міграції. privileged каже, що простір імен перебуває поза звичайною межею застосунків і має керуватися компенсувальними засобами контролю. baseline каже, що платформа блокуватиме найпоширеніші маршрути підвищення привілеїв, водночас даючи застарілим образам простір продовжувати працювати. restricted каже, що робоче навантаження спроєктовано для роботи з вузькою ідентичністю, вузькою файловою системою, вузькими можливостями та запобіжниками часу виконання. Команди, що ставляться до профілів як до міток для суперечок, зазвичай мають труднощі; команди, що ставляться до них як до інженерних цілей, можуть планувати роботу.
| Засіб контролю | Privileged | Baseline | Restricted |
|---|---|---|---|
hostNetwork | Дозволено | Заблоковано | Заблоковано |
hostPID | Дозволено | Заблоковано | Заблоковано |
hostIPC | Дозволено | Заблоковано | Заблоковано |
privileged: true | Дозволено | Заблоковано | Заблоковано |
| Небезпечні можливості | Дозволено | Заблоковано | Заблоковано |
Чутливе використання hostPath | Дозволено | Заблоковано | Заблоковано |
Виконання під UID 0 | Дозволено | Дозволено | Заблоковано |
allowPrivilegeEscalation: true | Дозволено | Іноді дозволено | Заблоковано |
| Відсутній профіль seccomp | Дозволено | Дозволено | Заблоковано |
| Необмежені типи томів | Дозволено | Обмежено | Обмежено суворіше |
Обираючи профіль, починайте з класу робочого навантаження. Простори імен застосунків мають прагнути до restricted, особливо для сервісів, звернених до інтернету чи орендарів. Застарілі застосунки, яким усе ще потрібен root, можуть тимчасово підійти під baseline, поки команда виправляє власника образу та шляхи запису. Інфраструктура кластера не повинна спільно використовувати простір імен із застосунками лише тому, що їй потрібен привілейований доступ.
Немає нічого ганебного у використанні baseline як тимчасового кроку, але він не повинен ставати постійним виправданням. Розумний план міграції називає блокери: які образи все ще працюють від імені root, яким шляхам усе ще потрібні томи для запису, які контейнери все ще покладаються на типові можливості, і які команди володіють виправленнями. Без цього переліку простір імен може роками сидіти на baseline, поки всі припускають, що хтось інший зробить його готовим до restricted. Попередження допуску, події аудиту та контрольні списки перегляду розгортань перетворюють цей нечіткий намір на роботу, з якою можна щось зробити.
Наведений нижче шлях прийняття рішень — це практичний інструмент перегляду. Він навмисно консервативний: він штовхає звичайні застосунки до restricted, дає застарілим навантаженням шлях усунення проблем через baseline і резервує privileged для навантажень, що діють на самому вузлі.
┌───────────────────────────────────────────────────────────────┐│ PROFILE SELECTION PATH │├───────────────────────────────────────────────────────────────┤│ ││ Does the workload administer node networking, devices, ││ storage, process visibility, or other host-level features? ││ ││ yes ──▶ dedicated system namespace ──▶ privileged ││ │ ││ no ││ ▼ ││ Can the image run as non-root with explicit writable mounts, ││ dropped capabilities, no privilege escalation, and seccomp? ││ ││ yes ────────────────────────────────▶ restricted ││ │ ││ no ││ ▼ ││ Is there a time-boxed remediation plan to remove root, ││ mutable filesystem assumptions, or legacy privileges? ││ ││ yes ────────────────────────────────▶ baseline + warn ││ │ ││ no ││ ▼ ││ Escalate for architecture review before admitting workload ││ │└───────────────────────────────────────────────────────────────┘Pod Security Admission: примусове застосування стандартів через мітки простору імен
Розділ «Pod Security Admission: примусове застосування стандартів через мітки простору імен»Pod Security Admission, який зазвичай скорочують до PSA, — це вбудований контролер допуску Kubernetes, що застосовує Pod Security Standards. У Kubernetes 1.35 та поточних підтримуваних версіях він є стандартною вбудованою заміною вилученої функції PodSecurityPolicy. PSA навмисно простіший за повноцінний рушій політик: він оцінює Поди за мітками профілю на просторі імен.
┌───────────────────────────────────────────────────────────────┐│ PSA ENFORCEMENT MODES │├───────────────────────────────────────────────────────────────┤│ ││ ENFORCE ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Blocks pods that violate the selected profile │ ││ │ Use when the namespace is ready for hard enforcement │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ WARN ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Allows the pod but returns warnings to the API client │ ││ │ Use to teach developers before raising enforcement │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ AUDIT ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Allows the pod but records violations in audit events │ ││ │ Use to measure readiness and find hidden violations │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ COMMON COMBINATION ││ enforce baseline, warn restricted, audit restricted ││ │└───────────────────────────────────────────────────────────────┘Три режими дозволяють командам піднімати планку, не спричиняючи збою. Простір імен може примусово застосовувати baseline, тож очевидно небезпечні Поди блокуються, водночас попереджаючи та проводячи аудит проти restricted. Розробники можуть продовжувати постачати сумісні навантаження, але вони бачать попередження, що показують, які поля треба змінити, перш ніж простір імен зможе перейти до суворішого примусового застосування.
Цей поділ між enforce, warn та audit — одна з найкорисніших операційних функцій PSA. Примусове застосування захищає кластер негайно, попередження навчають особу, що подає маніфест, а записи аудиту дозволяють платформеним командам вимірювати роботу, що відбувається поза інтерактивним терміналом. У здоровому розгортанні режими попередження та аудиту йдуть попереду примусового застосування. Вони виявляють, які навантаження зламалися б під наступним суворішим профілем, перш ніж платформена команда перемкне блокувальну мітку.
apiVersion: v1kind: Namespacemetadata: name: production labels: pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/enforce-version: latest pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: latest pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/audit-version: latestМітка версії latest означає, що політика дотримується визначення профілю поточним сервером Kubernetes. Деякі організації фіксують версії профілів під час оновлень, щоб уникнути несподіваних змін у поведінці допуску. Для розуміння на рівні KCSA знайте, що мітка профілю обирає стандарт, мітка режиму обирає поведінку, а мітка версії контролює, яка версія Kubernetes стандарту використовується.
Зафіксовані версії — це інструмент керування змінами, а не спосіб назавжди уникати оновлень. Якщо кластер фіксує версію політики під час оновлення Kubernetes, платформена команда має запланувати наступний перегляд, щоб порівняти зафіксований профіль із новим типовим профілем. Інакше організація може випадково заморозити старі припущення й пропустити поліпшення у стандарті. Для цілей іспиту важливий патерн полягає в тому, що кожен режим може мати відповідну мітку *-version, і сама лише назва профілю не є цілою політикою.
kubectl label namespace pod-security-demo \ pod-security.kubernetes.io/enforce=baseline \ pod-security.kubernetes.io/enforce-version=latest \ pod-security.kubernetes.io/warn=restricted \ pod-security.kubernetes.io/warn-version=latest \ --overwriteТепер уявіть, що розробник подає Под, який працює від імені root, але не використовує privileged: true, простори імен хоста чи небезпечні можливості. З enforce: baseline Под може бути допущено, бо baseline зосереджується на відомих шляхах підвищення привілеїв і не повністю вимагає виконання не від імені root. З warn: restricted розробник усе одно отримує зворотний зв’язок, бо restricted очікує налаштувань, що не є root, та інших засобів посилення.
Зробіть паузу й передбачте: Ваш кластер примусово застосовує
baselineі попереджає проrestricted. Команда подає Под, що працює під UID0, задаєallowPrivilegeEscalation: false, відкидає всі можливості й використовує seccompRuntimeDefault. Под буде заблоковано, попереджено, і те, і те, чи нічого? Поясніть, який профіль зумовлює кожен результат.
Хороша відповідь відокремлює примусове застосування від попередження. Под не блокується лише за роботу від імені root під baseline, якщо він уникає полів, що baseline забороняє. Він усе одно має отримати попередження restricted, бо restricted очікує, що навантаження працюватиме не від імені root. Саме тому поєднання режимів PSA корисні: вони дозволяють платформеним командам примусово застосовувати мінімум, водночас сигналізуючи про наступну ціль.
Під час налагодження реальних попереджень скопіюйте текст попередження до pull request чи тікета й перекладіть його на зміни в маніфесті. «Порушує restricted» менш корисне, ніж «контейнер api має задати runAsNonRoot: true, використати ненульовий UID, відкинути всі можливості й задати allowPrivilegeEscalation: false». Цей крок перекладу допомагає власникам застосунку засвоїти правило й дає рецензентам конкретний спосіб перевірити наступну ревізію.
Опрацьований приклад: налагодження відмови PSA
Розділ «Опрацьований приклад: налагодження відмови PSA»Помилка Pod Security Admission корисна, якщо читати її як мапу назад до полів у маніфесті. Сервер API зазвичай повідомляє порушений профіль і називає поля-порушники. Замість того щоб гадати, скопіюйте кожне порушення до невеликого списку усунення, а потім вирішіть, чи виправляти навантаження, чи перенести його до простору імен, де виняток виправданий.
Цей процес особливо важливий під час реагування на інциденти чи міграційної роботи, бо повідомлення PSA можуть перелічувати кілька порушень одразу. Команди іноді виправляють перше назване поле, повторюють спробу, а потім виявляють наступний блокер, що марнує час і викликає роздратування політикою. Краща звичка — зібрати всю відмову, визначити кожну категорію полів і вирішити, чи описує маніфест звичайний застосунок, чи компонент рівня хоста. Це рішення визначає, чи ви посилюєте Под, чи ізолюєте його як виняток.
Почніть із простору імен, що примусово застосовує baseline, бо це дає вам чітку відмову щоразу, коли маніфест перетинає мінімальну межу безпеки застосунку.
kubectl create namespace psa-debugkubectl label namespace psa-debug \ pod-security.kubernetes.io/enforce=baseline \ pod-security.kubernetes.io/enforce-version=latest \ --overwriteЗастосуйте Под, що порушує baseline кількома способами, а потім прочитайте відповідь як структуровані докази, а не як загальне повідомлення про невдачу.
apiVersion: v1kind: Podmetadata: name: blocked-debug namespace: psa-debugspec: hostNetwork: true hostPID: true containers: - name: app image: busybox:1.36 command: ["sh", "-c", "sleep 3600"] securityContext: privileged: true capabilities: add: - NET_ADMIN - SYS_ADMINkubectl apply -f blocked-debug.yamlТочне повідомлення може відрізнятися залежно від версії Kubernetes, але структура є послідовною: воно каже, що Под порушує примусово застосований профіль, і перелічує поля на кшталт просторів імен хоста, привілейованих контейнерів чи заборонених можливостей. Ваше завдання — перекласти це повідомлення на виправлений дизайн. У цьому випадку Под не описує нормальний застосунок; він просить мережу хоста, видимість процесів хоста, повний привілей і широкі можливості.
| Підказка про відмову | Поле для перевірки | Імовірне виправлення | Коли виняток може бути слушним |
|---|---|---|---|
| Використовує мережу хоста | spec.hostNetwork | Прибрати поле й надавати через Сервіс | Локальні для вузла мережеві компоненти |
| Використовує простір імен PID хоста | spec.hostPID | Прибрати поле | Агенти безпеки чи глибока діагностика |
| Привілейований контейнер | securityContext.privileged | Установити false або опустити | Плагіни пристроїв чи окремі агенти вузлів |
| Додає заборонену можливість | securityContext.capabilities.add | Відкинути ALL, додати вузьку можливість лише за потреби | Компоненти CNI чи мережі вузлів |
| Працює від імені root під restricted | runAsUser, USER образу | Задати ненульовий UID і runAsNonRoot: true | Тимчасова міграція застарілого під baseline |
Виправлений звичайний Под застосунку прибрав би спільне використання просторів імен хоста та широкі привілеї. Він також використовував би посилені типові значення, які ви бачили раніше. Якщо власник навантаження каже, що Под насправді є мережевим агентом вузла, то виправлення полягає не в послабленні простору імен застосунків; виправлення полягає в розміщенні агента в окремому системному просторі імен із явною власністю, моніторингом і переглядом.
apiVersion: v1kind: Podmetadata: name: corrected-app namespace: psa-debugspec: securityContext: runAsUser: 1000 runAsGroup: 1000 seccompProfile: type: RuntimeDefault containers: - name: app image: busybox:1.36 command: ["sh", "-c", "sleep 3600"] securityContext: runAsNonRoot: true allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {}Зверніть увагу на послідовність перегляду. По-перше, визначте, що навантаження має робити. По-друге, зіставте кожне відхилене поле з ризиком. По-третє, приберіть поле чи замініть його вужчим механізмом. По-четверте, якщо поле справді потрібне, ізолюйте навантаження замість того, щоб змінювати політику для непов’язаних застосунків.
Виправлений Под навмисно нудний. Він спить, працює під користувачем, що не є root, відкидає можливості, використовує профіль seccomp середовища виконання й пише лише до названого тимчасового тому. Ця нудна форма — саме те, чого ви хочете для більшості навантажень застосунків, бо нудні маніфести легше переглядати, легше шаблонізувати та легше примусово застосовувати послідовно. Якщо застосунок не може вписатися в цю форму, перегляд має виявити конкретну причину, а не нечітке твердження, що «безпека ламає застосунок».
Привілейовані контейнери: ставтеся до них як до рішень про довіру вузла
Розділ «Привілейовані контейнери: ставтеся до них як до рішень про довіру вузла»privileged: true — одна з найчіткіших ознак небезпеки в маніфесті Пода. Він надає контейнеру широкий доступ до пристроїв хоста й можливостей, що може змусити контейнер поводитися радше як процес на вузлі, ніж як ізольований процес застосунку. Деякій інфраструктурі кластера ця сила потрібна, але більшості навантажень застосунків — ні.
┌───────────────────────────────────────────────────────────────┐│ PRIVILEGED CONTAINERS │├───────────────────────────────────────────────────────────────┤│ ││ privileged: true grants ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Access to host devices │ ││ │ Broad Linux capability set │ ││ │ Weakened runtime isolation │ ││ │ Much larger node-compromise blast radius │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ legitimate examples ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ CNI plugins that configure node networking │ ││ │ Device plugins that expose hardware │ ││ │ Selected node monitoring or security agents │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ review expectation ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Dedicated namespace │ ││ │ Narrow service account and RBAC │ ││ │ Clear owner and documented justification │ ││ │ No co-location with ordinary application workloads │ ││ └─────────────────────────────────────────────────────────┘ ││ │└───────────────────────────────────────────────────────────────┘Поширена помилка початківця — розглядати privileged як інструмент усунення проблем. Щось відмовляє, команда задає privileged: true, і застосунок запускається. Цей результат доводить лише те, що початкова проблема стосувалася дозволів; він не доводить, що широкий дозвіл був необхідним. Старший перегляд наполягає на найменшому успішному дозволі й запитує, чи може дизайн застосунку взагалі уникнути залежності від хоста.
Наприклад, сервіс, якому потрібен малий порт, може використати зіставлення Сервісу Kubernetes порту 80 до високого containerPort. Процес, якому потрібен тимчасовий запис, може використати emptyDir. Процес, якому потрібно читати конфігурацію, може використати ConfigMap чи Secret. Под, що просить привілейований режим, має вміти пояснити, чому абстракцій, нативних для Kubernetes, недостатньо.
Існує також проблема підзвітності з постійними привілейованими налаштуваннями. Через шість місяців після термінового виправлення особа, що додала privileged: true, могла перейти до іншої команди, застосунок міг змінитися, а початкова причина могла більше не існувати. Якщо маніфест не містить задокументованого шляху для винятку поза YAML, майбутні рецензенти бачать лише потужне налаштування без контексту. Ставлення до привілейованого доступу як до рішення про довіру вузла змушує команду фіксувати власність, технічну необхідність та очікування щодо переоцінювання.
| Заявлена потреба | Уникайте privileged, спробувавши | Чому це безпечніше |
|---|---|---|
Прив’язування до порту 80 | Сервіс port: 80 до targetPort: 8080 або NET_BIND_SERVICE | Тримає пристрої хоста та широкі можливості подалі |
| Запис тимчасових файлів | emptyDir, змонтований за конкретним шляхом | Зберігає кореневу файлову систему лише для читання |
| Читання конфігурації застосунку | Том ConfigMap чи Secret | Уникає монтувань файлової системи хоста |
| Збір метрик застосунку | Патерн sidecar чи ServiceMonitor | Уникає мережі хоста та видимості процесів |
| Налагодження процесу | Ефемерний процес налагодження з контрольованим RBAC | Уникає постійних підвищених налаштувань часу виконання |
Зупиніться та подумайте: Якщо Под відхилено через
baseline, бо він задаєprivileged: true, які докази переконали б вас, що він належить до привілейованого простору імен, а не має бути переспроєктований? Напишіть докази так, ніби ви залишаєте коментар до огляду.
Сильний коментар до огляду називає операцію рівня хоста, пояснює, чому вужча можливість чи абстракція Kubernetes не може її задовольнити, визначає команду-власника й підтверджує, що навантаження ізольоване від звичайних застосунків. Слабкий коментар каже лише «потрібно для моніторингу» чи «воно так працює». Привілейований доступ — це рішення про довіру вузла, тож обґрунтування має бути достатньо конкретним, щоб майбутні супровідники могли його перевірити.
Той самий стандарт стосується агентів від постачальників. Чарт від поважного постачальника все одно може запитувати дозволи, надто широкі для моделі ризику вашого кластера. Перш ніж встановлювати його до привілейованого простору імен, прочитайте згенеровані маніфести, зрозумійте, якому DaemonSet потрібен доступ до хоста, та обмежте права на розгортання навколо цього простору імен. Довіра до постачальника зменшує деякі питання щодо ланцюга постачання; вона не прибирає потреби обмежувати потужні Поди.
Seccomp та підвищення привілеїв: запобіжники часу виконання
Розділ «Seccomp та підвищення привілеїв: запобіжники часу виконання»Seccomp фільтрує системні виклики — інтерфейс, який процеси використовують, щоб попросити ядро виконати роботу. Контейнеру може бути не потрібен кожен можливий syscall, щоб обслуговувати HTTP, обробляти повідомлення чи виконувати пакетне завдання. Типовий профіль seccomp середовища виконання блокує окремі небезпечні чи незвичні системні виклики, водночас зберігаючи сумісність для нормальних навантажень.
┌───────────────────────────────────────────────────────────────┐│ SECCOMP PROFILES │├───────────────────────────────────────────────────────────────┤│ ││ Unconfined ││ ┌─────────────────────────────────────────────────────────┐ ││ │ No seccomp syscall filtering from the container runtime │ ││ │ Highest compatibility, weakest syscall restriction │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ RuntimeDefault ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Uses the container runtime's default seccomp profile │ ││ │ Good default for most application workloads │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ Localhost ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Uses a custom profile installed on the node │ ││ │ Useful for specialized hardening with operational care │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ recommended application setting ││ ││ securityContext: ││ seccompProfile: ││ type: RuntimeDefault ││ │└───────────────────────────────────────────────────────────────┘allowPrivilegeEscalation: false — це ще один запобіжник часу виконання. Він не дає процесу здобути більше привілеїв, ніж має його батьківський процес, через механізми на кшталт бінарників setuid. Це особливо корисно, коли образ містить застарілі інструменти, не потрібні застосунку. Якщо допоміжний бінарник setuid несподівано перестає працювати після застосування цього налаштування, це сигнал дизайну: або допоміжний інструмент непотрібний і має бути прибраний, або навантаження потребує явного винятку, який треба переглянути.
Seccomp, відкинуті можливості та вимкнене підвищення привілеїв найсильніші, коли використовуються разом. Відкидання можливостей прибирає широкі сили ядра. Вимкнення підвищення привілеїв не дає процесу здобути нові сили пізніше. Seccomp зменшує набір операцій ядра, доступних навіть якщо процес скомпрометовано. Жоден із цих засобів контролю не є досконалим окремо, але разом вони ускладнюють переміщення після компрометації.
Корисно відокремлювати проблеми сумісності від проблем безпеки, коли ці засоби контролю виявляють старі припущення. Якщо допоміжний бінарник відмовляє через вимкнене підвищення привілеїв, команда має запитати, чи взагалі належить цей помічник до образу. Якщо syscall заблоковано типовим профілем seccomp середовища виконання, команда має визначити syscall і функцію, що його потребує, а не одразу перемикатися на Unconfined. Мета — не змусити кожну невдачу зникнути; мета — зробити вимогу до дозволу точною.
| Засіб контролю | Блокує чи зменшує | Симптом невдачі, коли застосунок від цього залежить | Реакція під час перегляду |
|---|---|---|---|
seccompProfile: RuntimeDefault | Деякі ризиковані syscall | Логи застосунку згадують «operation not permitted» для дії на кшталт syscall | Підтвердити потребу, потім розглянути власний профіль лише за обґрунтування |
allowPrivilegeEscalation: false | setuid та подібне підвищення | Застарілий допоміжний бінарник не може здобути підвищені дозволи | Прибрати помічника чи задокументувати виняток |
capabilities.drop: ["ALL"] | Навколишні можливості Linux | Прив’язування до малого порту чи операція зі зміни власника відмовляє | Додати вузьку можливість чи переспроєктувати |
readOnlyRootFilesystem: true | Запис до файлової системи образу | Застосунок не може писати кеш, pid, тимчасові файли чи логи | Змонтувати явні томи для запису |
Що сталося б, якби ви задали
allowPrivilegeEscalation: false, але залишилиprivileged: trueна тому самому контейнері? Поясніть, чому суперечливі налаштування ускладнюють перегляди безпеки.
Маніфест передає змішаний намір. Одне поле каже, що навантаження не повинне здобувати додаткові привілеї, тоді як інше надає широкий привілей рівня хоста від самого початку. Рецензенти не повинні вважати одне поле посилення доказом безпеки, коли сильніше поле послаблює межу. Перегляд безпеки полягає в сукупному ефекті специфікації Пода, а не в наявності окремих гарних на вигляд налаштувань.
Це правило сукупного ефекту — наскрізна тема в безпеці Подів. runAsNonRoot: true цінне, але менш переконливе, якщо той самий контейнер додає широкі можливості. Коренева файлова система лише для читання цінна, але менш переконлива, якщо Под монтує чутливий шлях хоста для читання-запису. Seccomp цінний, але менш переконливий, якщо контейнер працює привілейовано. Звичка рівня KCSA — читати маніфест як систему дозволів, а не як контрольний список окремих хороших і поганих полів.
Проєктування винятків без послаблення для всіх
Розділ «Проєктування винятків без послаблення для всіх»Реальні кластери містять винятки. Мета — не вдавати, ніби кожен Под можна негайно обмежити; мета — не дати одному винятку стати типовим для непов’язаних навантажень. Простори імен є головною межею PSA, тож дизайн винятків починається з розділення просторів імен.
Зрілий виняток має п’ять властивостей. Він має конкретну назву й власника навантаження. Він має заявлену технічну причину, прив’язану до операції рівня хоста. Він використовує найменш дозвільний профіль і поля, що все ще працюють. Він ізольований від звичайних застосунків. Він має шлях для перегляду, щоб виняток можна було прибрати чи переоцінити пізніше.
Дизайн винятків — це місце, де безпека й операції або співпрацюють, або конфліктують. Якщо команда безпеки просто каже «жодних привілейованих Подів», платформені команди обходитимуть правило, бо деяким агентам рівня вузла справді потрібен підвищений доступ. Якщо платформена команда позначає широкі простори імен як привілейовані без перегляду, команди застосунків успадковують ризик, про який не просили. Придатний процес називає виняток, звужує простір імен, обмежує тих, хто може там розгортати, і тримає типовий шлях застосунку якомога ближчим до restricted.
apiVersion: v1kind: Namespacemetadata: name: node-agents labels: pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/enforce-version: latest pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/audit-version: latestСамої лише цієї мітки простору імен недостатньо для безпеки. Привілейований простір імен має також мати вузький RBAC, контрольовані дозволи на розгортання, чітку власність і моніторинг. PSA вирішує, чи допускаються специфікації Подів; він не вирішує, хто може створювати Поди, які образи довірені й чи навантаження поводиться правильно під час виконання.
| Засіб контролю винятку | Призначення | Приклад запитання для перегляду |
|---|---|---|
| Окремий простір імен | Запобігає перетіканню дозволів до застосунків | Чи заборонено непов’язаним навантаженням бути в цьому просторі імен? |
| Вузький RBAC | Обмежує тих, хто може створювати потужні Поди | Які ідентичності можуть створювати чи оновлювати Поди тут? |
| Власник навантаження | Створює підзвітність | Яка команда реагує, якщо агента скомпрометовано? |
| Контроль образів | Зменшує ризик ланцюга постачання | Чи зафіксовано образ і взято з затвердженого реєстру? |
| Моніторинг під час виконання | Виявляє зловживання після допуску | Чи видимі події привілейованого навантаження командам безпеки? |
| Перегляд з обмеженням у часі | Запобігає постійним випадковим виняткам | Коли виняток буде переоцінено? |
Для цілей іспиту KCSA знайте, що PSA є обмеженим простором імен і базованим на профілях. Для реальних операцій ідіть на рівень глибше: мітки простору імен — лише одна частина площини управління. RBAC, політика образів, NetworkPolicy, ізоляція вузлів, логування та реагування на інциденти — усі визначають, чи залишається привілейований виняток обмеженим.
Один практичний патерн — вести реєстр винятків поза маніфестами. Реєстр не має бути вишуканим, але він має фіксувати простір імен, навантаження, власника, причину, запитані поля, дату затвердження та дату наступного перегляду. Під час оновлень кластера чи інцидентів безпеки цей реєстр допомагає відповідальним особам визначити, які навантаження мають довіру рівня хоста та які команди можуть їх пояснити. Без нього привілейовані простори імен стають інституційною пам’яттю, прихованою в мітках.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Патерни безпеки Подів найкорисніші, коли вони пов’язують клас навантаження з повторюваною формою перегляду. Платформена команда не повинна змушувати кожного розробника наново винаходити той самий маніфест із виконанням не від імені root, лише для читання та відкиданням можливостей, і не повинна затверджувати кожен виняток як разову розмову. Хороші патерни роблять безпечний шлях легким шляхом, водночас залишаючи контрольований маршрут для навантажень, що справді перебувають на межі вузла.
| Патерн | Коли його використовувати | Чому він працює | Міркування щодо масштабування |
|---|---|---|---|
| Простори імен застосунків із restricted за замовчуванням | Нові сервіси, навантаження, звернені до інтернету, та команди із сучасними образами | Він робить виконання не від імені root, відкидання можливостей, seccomp і явні шляхи запису нормальним очікуванням | Надавайте шаблони та перевірки CI, щоб розробники отримували зворотний зв’язок до того, як допуск відхилить Под |
| Примусовий baseline із попередженням restricted під час міграції | Застарілі простори імен, що все ще містять образи з root чи припущення про змінну файлову систему | Він блокує найризикованіші поля негайно, водночас показуючи залишок роботи до готовності restricted | Відстежуйте кількість попереджень за власником, інакше міграція застрягне на baseline |
| Окремі привілейовані системні простори імен | Агенти CNI, зберігання, пристроїв та безпеки вузлів, яким потрібен доступ рівня хоста | Він не дає винятками довіри вузла перетікати до звичайних навантажень застосунків | Обмежуйте права на розгортання та переглядайте маніфести постачальників перед наданням доступу до простору імен |
| Явний дизайн шляхів для запису | Застосунки, яким потрібні розташування для кешу, PID, сокетів чи тимчасових файлів | Він зберігає файлову систему образу лише для читання, водночас даючи процесу мінімальний тимчасовий простір | Тримайте шляхи запису задокументованими в чарті чи маніфесті, щоб майбутні зміни образу залишалися придатними для перегляду |
Антипатерни зазвичай починаються як швидкі рішення. Команда хоче виправити невдале розгортання, чарту моніторингу потрібен доступ до хоста, або старий образ припускає скрізь власника root. Швидке рішення стає небезпечним, коли його копіюють до шаблонів, спільних просторів імен чи постійних винятків. Лікування — це не лише суворіше налаштування; це процес перегляду, що запитує про фактичну операцію навантаження, найменший дозвіл, що її уможливлює, і межу, що її обмежує.
| Антипатерн | Що йде не так | Чому команди в це впадають | Краща альтернатива |
|---|---|---|---|
| Privileged як перемикач налагодження | Под отримує широку довіру рівня хоста для невідомої проблеми | Це швидко, часто змушує симптом зникнути й уникає вивчення точного відсутнього дозволу | Відтворіть невдачу, визначте операцію та надайте вузьку можливість чи том для запису лише за потреби |
| Один простір імен для застосунків і агентів вузлів | Поди застосунків успадковують послаблений допуск, бо системному агенту потрібен доступ до хоста | Компонування простору імен слідує власності команди, а не межам безпеки | Розділіть класи навантажень на простори імен із різними мітками PSA та засобами контролю RBAC |
| Посилений основний контейнер зі слабким init-контейнером | Под усе одно порушує політику чи стартує з ризикованим шляхом помічника | Перегляди зосереджуються на довготривалому контейнері застосунку й пропускають логіку налаштування | Перевіряйте securityContext кожного контейнера, включно з init-контейнерами та sidecar |
| Попередження без власності | Попередження restricted накопичуються, поки ніхто їм не довіряє й не читає | Режим попередження ввімкнено як галочку, а не як програму міграції | Спрямовуйте попередження до власників сервісів, створюйте тікети усунення та піднімайте примусове застосування лише після тестування |
Структура прийняття рішень
Розділ «Структура прийняття рішень»Використовуйте цю структуру під час перегляду нового навантаження, оновлення чарту чи відмови PSA. Почніть із класифікації навантаження, потім оберіть найменш дозвільний профіль, що підтримує його реальну поведінку, а потім вирішіть, чи будь-який виняток достатньо вузький, щоб його затвердити. Структура навмисно консервативна, бо більшість Подів застосунків не повинні торкатися просторів імен хоста, пристроїв хоста, широких можливостей чи змінних файлових систем образу.
| Запитання для перегляду | Якщо відповідь «так» | Якщо відповідь «ні» |
|---|---|---|
| Чи навантаження конфігурує мережу вузла, зберігання, пристрої, видимість процесів чи іншу функцію рівня хоста? | Ставтеся до нього як до системного навантаження, розмістіть його в окремому просторі імен і переглядайте привілейовані чи baseline-винятки з RBAC та засобами контролю власності | Продовжуйте переглядати його як навантаження застосунку, що має прагнути до restricted |
Чи може кожен контейнер працювати під ненульовим UID із runAsNonRoot: true? | Збережіть чи вимагайте сумісні з restricted налаштування ідентичності | Використовуйте baseline тимчасово лише з планом усунення проблем образу та власником |
| Чи може коренева файлова система бути лише для читання з явними томами для запису? | Задайте readOnlyRootFilesystem: true та назвіть шляхи запису | Визначте точні записи перед послабленням засобу контролю; уникайте широких змінних файлових систем |
| Чи всі можливості Linux непотрібні чи достатньо вузькі для обґрунтування? | Відкиньте ALL і додайте лише переглянуту можливість, якщо немає кращого дизайну | Відхиляйте широкі додавання на кшталт SYS_ADMIN для звичайних застосунків і ескалюйте випадки рівня хоста |
| Чи можна розв’язати попередження PSA перед зміною примусового застосування? | Перемістіть простір імен до примусового застосування restricted після тестування | Тримайте enforce на baseline, попереджайте про restricted і відстежуйте залишкові блокери |
Остаточне рішення має читатися як інженерна нотатка, а не як гасло. «Затверджено для restricted, бо всі контейнери працюють під UID 1000, відкидають можливості, використовують RuntimeDefault і пишуть лише до /tmp та /var/cache/app» — корисне. «Затверджено, бо пройшло безпеку» — ні. Чіткі рішення навчають майбутніх рецензентів, які докази мали значення, і полегшують виявлення дрейфу, коли навантаження змінюється.
Чи знали ви?
Розділ «Чи знали ви?»-
Pod Security Admission замінив PodSecurityPolicy після того, як PodSecurityPolicy було визнано застарілим і вилучено з Kubernetes. PSA простіший, бо використовує стандартні профілі та мітки простору імен замість власних об’єктів політики.
-
Restricted не означає непридатний для нормальних застосунків. Більшість HTTP-сервісів, обробників і пакетних завдань можуть працювати під налаштуваннями restricted, щойно образи уникнуть припущень про власника root і пишуть лише до явно змонтованих шляхів.
-
Под може виглядати частково посиленим і все одно бути небезпечним, якщо одне поле надає широкий доступ. Наприклад,
allowPrivilegeEscalation: falseне робить привілейований контейнер звичайним контейнером застосунку. -
Попередження — це інструмент міграції, бо
warn: restrictedможе навчити розробників, які поля виправити, перш ніж платформена команда змінитьenforceзbaselineнаrestricted.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона трапляється | Як її виправити |
|---|---|---|
| Виконання контейнерів застосунку від імені root за замовчуванням | Скомпрометований процес стартує з більшими повноваженнями над файловою системою та процесами всередині контейнера | Задайте runAsNonRoot: true і ненульовий runAsUser, який образ підтримує |
Задання privileged: true для виправлення непоясненої невдачі | Воно надає широкий доступ рівня хоста й приховує реальну вимогу до дозволу | Визначте операцію, що відмовляє, потім використайте вужчу можливість, том чи абстракцію Kubernetes |
| Забування відкинути можливості Linux | Типові чи додані можливості можуть дозволяти дії, не потрібні застосунку | Використовуйте capabilities.drop: ["ALL"] і додавайте лише переглянуту вузьку можливість |
Примусове застосування privileged у змішаному просторі імен застосунків | Кожне навантаження в просторі імен успадковує послаблену межу допуску | Перемістіть системних агентів до окремого простору імен і тримайте простори імен застосунків на baseline чи restricted |
Увімкнення readOnlyRootFilesystem без томів для запису | Застосунок може відмовити, коли пише кеш, pid, тимчасові файли чи файли часу виконання | Тримайте кореневу файлову систему лише для читання й монтуйте emptyDir за явними шляхами запису |
| Ставлення до попереджень PSA як до нешкідливого шуму | Попередження часто показують саме те, що блокує майбутню міграцію до суворішого примусового застосування | Відстежуйте попередження, призначайте власників і усувайте їх перед підняттям примусового застосування |
Перегляд лише securityContext рівня Пода | Перевизначення рівня контейнера може послабити один контейнер, навіть коли типові значення Пода виглядають безпечними | Перевіряйте кожен контейнер застосунку, sidecar та init-контейнер на перевизначення |
| Використання просторів імен хоста для звичайного усунення проблем | Доступ до мережі чи PID хоста розкриває інформацію рівня вузла й може створювати шляхи підвищення привілеїв | Використовуйте контрольовані процеси налагодження й прибирайте налаштування просторів імен хоста зі специфікацій застосунків |
Тест
Розділ «Тест»-
Ваша команда розгортає API-Под у простір імен із
enforce: baselineтаwarn: restricted. Под працює під UID0, відкидає всі можливості, використовує seccompRuntimeDefaultі не використовує простори імен хоста. Розгортання вдається, але виводить попередження. Як вам інтерпретувати результат, і що команда має змінити, перш ніж простір імен перейде до примусового застосування restricted?Відповідь
Под проходить baseline, бо він уникає головних полів підвищення привілеїв, що baseline блокує, як-от привілейований режим, простори імен хоста та небезпечні можливості. Він попереджає під restricted, бо restricted очікує виконання не від імені root і сильнішого посилення. Команда має оновити образ чи специфікацію Пода, щоб процес працював під ненульовим UID, задати
runAsNonRoot: true, підтвердити дозволи файлів і томи для запису та зберегти наявні відкинуті можливості й налаштування seccomp. Головне — ставитися до попередження як до зворотного зв’язку міграції, а не як до помилки, яку треба ігнорувати. -
Розробник каже, що його сервісу потрібен
privileged: true, бо той має слухати на порту80. Ви переглядаєте маніфест для простору імен застосунків, що прагне до безпеки restricted. Який альтернативний дизайн ви порекомендували б і чому він безпечніший?Відповідь
Порекомендуйте слухати на високому порту контейнера, як-от
8080, і надавати його через Сервіс Kubernetes ізport: 80таtargetPort: 8080. Якщо процес справді має прив’язуватися до малого порту всередині контейнера, розгляньте додавання лишеNET_BIND_SERVICEпісля відкидання всіх можливостей. Обидва варіанти безпечніші за привілейований режим, бо вони уникають надання пристроїв хоста, широких можливостей і послабленої ізоляції часу виконання заради вузької мережевої потреби. -
Агент моніторингу відмовляє після того, як платформена команда змінює його простір імен із
privilegedнаbaseline. Відмова згадуєhostNetworkтаhostPID. Агент збирає метрики рівня вузла, тоді як звичайні вебзастосунки також працюють у тому самому просторі імен. Який найкращий план усунення проблеми?Відповідь
Не послаблюйте спільний простір імен застосунків назад до privileged. Створіть окремий простір імен для довірених агентів вузлів, застосуйте найменш дозвільні мітки, що дозволяють агента, обмежте тих, хто може там розгортати, за допомогою RBAC і тримайте звичайні вебзастосунки в просторі імен baseline чи restricted. Агент моніторингу може мати легітимну потребу рівня хоста, але його спільне розміщення зі звичайними застосунками поширює виняток на навантаження, яким він не потрібен.
-
Под відхилено примусовим застосуванням restricted після того, як ви додали
readOnlyRootFilesystem: true. Застосунок пише тимчасові файли під/tmpі файли часу виконання під/var/run/app. Колега пропонує задатиreadOnlyRootFilesystem: false. Як ви виправили б Под, зберігши засіб контролю безпеки?Відповідь
Збережіть
readOnlyRootFilesystem: trueі змонтуйте явні томи для запису за шляхами, потрібними застосунку, як-от томиemptyDirдля/tmpта/var/run/app. Це задовольняє вимогу застосунку, не дозволяючи запис у всю файлову систему образу. Результат придатніший для перегляду, бо розташування для запису названі в маніфесті, а зловмисник має менше місць для зміни бінарників чи створення закріплення. -
Під час перегляду ви знаходите Под із
capabilities.add: ["SYS_ADMIN"],allowPrivilegeEscalation: falseтаprivileged: false. Власник стверджує, що Под безпечний, бо він не привілейований і підвищення вимкнено. Який ризик залишається, і що вам запитати далі?Відповідь
SYS_ADMINзалишається можливістю високого ризику навіть безprivileged: true; вона охоплює широкі операції ядра й може підірвати ізоляцію контейнера.allowPrivilegeEscalation: falseзапобігає здобуттю нових привілеїв пізніше, але не прибирає вже наданого широкого привілею. Запитайте, яка саме операція потребуєSYS_ADMIN, чи може вужча можливість чи абстракція Kubernetes її замінити, і чи належить навантаження до окремого системного простору імен, якщо потреба справді рівня хоста. -
securityContextрівня Пода задаєrunAsUser: 1000таseccompProfile: RuntimeDefault. Один init-контейнер перевизначаєrunAsUser: 0й додаєNET_ADMIN. Основний контейнер застосунку виглядає сумісним із restricted. Як вам оцінити цей Под?Відповідь
Оцінюйте кожен контейнер, включно з init-контейнерами та sidecar, бо контекст безпеки рівня контейнера може перевизначати типові значення рівня Пода. Init-контейнер послаблює Под, працюючи від імені root і додаючи
NET_ADMIN, що може порушувати restricted і, можливо, baseline залежно від точної політики. Перегляд має запитати, чому init-контейнеру потрібне адміністрування мережі, чи можна перенести цю роботу за межі Пода, і чи може Под послідовно зберігати виконання не від імені root в усіх контейнерах. -
Команда хоче перемістити застарілий простір імен від відсутніх міток PSA одразу до
enforce: restricted. Пробний запуск показує, що багато Подів відмовляє, бо образи працюють від імені root і пишуть під/var/cache. Яка поетапна міграція зменшила б ризик, не залишаючи простір імен незахищеним?Відповідь
Почніть із
enforce: baseline, щоб заблокувати найнебезпечніші функції Подів, і додайтеwarn: restrictedплюсaudit: restricted, щоб визначити залишок роботи. Потім усуньте проблеми образів, задаючи користувачів, що не є root, виправляючи власника файлів і монтуючи явні шляхи для запису, як-отemptyDirдля/var/cache. Після розв’язання попереджень і тестування розгортань підніміть примусове застосування до restricted. Цей поетапний підхід поліпшує безпеку негайно, водночас уникаючи великого збою. -
Розбір інциденту виявляє, що скомпрометований Под застосунку міг створювати файли всередині своєї файлової системи образу контейнера, працювати від імені root і використовувати типові можливості. Застосунок не використовував простори імен хоста чи привілейований режим. Які засоби посилення ви додали б першими, і як вони зменшують вплив після компрометації?
Відповідь
Додайте виконання не від імені root із
runAsNonRoot: trueта ненульовимrunAsUser, задайтеreadOnlyRootFilesystem: trueз явними томами для запису, відкиньте всі можливості, задайтеallowPrivilegeEscalation: falseі використайтеseccompProfile: RuntimeDefault. Ці засоби контролю не виправляють початкову вразливість застосунку, але вони зменшують те, що зловмисник може зробити після виконання коду. Зловмисник має менше повноважень над процесами, менше привілеїв ядра, менше розташувань для закріплення з можливістю запису та вужчу поверхню syscall.
Практична вправа: аналіз безпеки та усунення проблем
Розділ «Практична вправа: аналіз безпеки та усунення проблем»Сценарій: Команда просить вас затвердити наведений Под для простору імен застосунків. Простір імен наразі примусово застосовує baseline і попереджає про restricted. Ваше завдання — проаналізувати маніфест, передбачити, які налаштування створюють проблеми допуску чи попередження, а потім створити безпечнішу заміну, що зберігає вимогу застосунку писати тимчасові файли.
apiVersion: v1kind: Podmetadata: name: web-app namespace: productionspec: hostNetwork: true hostPID: true containers: - name: app image: myapp:latest ports: - containerPort: 80 securityContext: runAsUser: 0 privileged: true readOnlyRootFilesystem: false allowPrivilegeEscalation: true capabilities: add: - SYS_ADMINКрок 1: класифікуйте кожен ризик
Розділ «Крок 1: класифікуйте кожен ризик»Прочитайте маніфест згори донизу й класифікуйте кожне ризиковане поле як одну з трьох категорій: ризик межі хоста, ризик підвищення привілеїв або ризик операційної гігієни. Не переходьте одразу до фінального YAML. Уміння, яке ви практикуєте, — це міркування під час перегляду: визначте механізм, поясніть шкоду й лише потім оберіть виправлення.
| Проблема | Категорія | Ризик | Безпечніший напрямок |
|---|---|---|---|
hostNetwork: true | Межа хоста | Спільно використовує мережевий простір імен вузла й може створювати ризики видимості трафіку чи конфлікту портів | Прибрати для звичайних застосунків; використати Сервіс |
hostPID: true | Межа хоста | Розкриває інформацію про процеси хоста й можливі шляхи втручання в процеси | Прибрати для звичайних застосунків |
runAsUser: 0 | Привілей | Працює від імені root усередині контейнера | Використати ненульовий UID і runAsNonRoot: true |
privileged: true | Привілей | Надає широкий доступ до пристроїв хоста й можливостей | Установити false або опустити |
readOnlyRootFilesystem: false | Закріплення | Дозволяє запис до файлової системи образу | Установити true й змонтувати явні шляхи для запису |
allowPrivilegeEscalation: true | Привілей | Дозволяє підвищення в стилі setuid | Установити false |
SYS_ADMIN | Привілей | Надає широку можливість адміністрування ядра | Відкинути всі можливості; уникати, якщо немає глибокого обґрунтування |
image: myapp:latest | Гігієна | Змінний тег робить перегляд і відкат менш передбачуваними | Використати незмінний тег версії чи дайджест |
containerPort: 80 | Тиск дизайну | Може заохочувати непотрібні привілеї малого порту | Слухати на 8080 й надавати порт 80 через Сервіс |
Крок 2: передбачте результат PSA
Розділ «Крок 2: передбачте результат PSA»У просторі імен із enforce: baseline цей Под має бути відхилено, бо він використовує простори імен хоста, привілейований режим і небезпечну можливість. У просторі імен лише з warn: restricted він також видавав би попередження про виконання від імені root та інші прогалини посилення. Запишіть, які поля є блокерами baseline, перш ніж перевіряти відповідь, бо це передбачення — та частина, що будує іспитове й операційне судження.
Крок 3: створіть посилений Под
Розділ «Крок 3: створіть посилений Под»Виправлена версія нижче припускає, що застосунок може слухати на 8080 і потребує запису до /tmp плюс /var/cache/app. Якщо вашому реальному застосунку потрібні інші шляхи для запису, збережіть той самий патерн і змініть лише шляхи монтування. Важливий дизайн полягає в тому, що записи є явними, а не розкиданими по файловій системі образу.
apiVersion: v1kind: Podmetadata: name: web-app namespace: productionspec: securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 2000 seccompProfile: type: RuntimeDefault containers: - name: app image: myapp@sha256:abc123def456 ports: - containerPort: 8080 securityContext: runAsNonRoot: true privileged: false readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: - ALL volumeMounts: - name: tmp mountPath: /tmp - name: app-cache mountPath: /var/cache/app volumes: - name: tmp emptyDir: {} - name: app-cache emptyDir: {}Крок 4: додайте Сервіс замість прив’язування контейнера до малого порту
Розділ «Крок 4: додайте Сервіс замість прив’язування контейнера до малого порту»Якщо клієнтам потрібен порт 80, надавайте цей порт на рівні Сервісу, а контейнер нехай слухає на високому порту. Так ви уникаєте надання дозволів на прив’язування до малого порту всередині контейнера й зберігаєте сумісність Пода із суворішими налаштуваннями безпеки.
apiVersion: v1kind: Servicemetadata: name: web-app namespace: productionspec: selector: app: web-app ports: - name: http port: 80 targetPort: 8080Крок 5: контрольний список перевірки
Розділ «Крок 5: контрольний список перевірки»- Я визначив щонайменше вісім проблем безпеки чи гігієни в оригінальному маніфесті й зіставив кожну з конкретним ризиком.
- Я пояснив, які оригінальні поля було б заблоковано примусовим застосуванням
baselineі які все одно мали б значення для міграції доrestricted. - Я прибрав спільне використання просторів імен хоста з Пода застосунку замість переміщення всього простору імен застосунку до
privileged. - Я замінив виконання від імені root ненульовим UID і додав
runAsNonRoot: true. - Я зберіг
readOnlyRootFilesystem: trueі надав явні томи для запису для шляхів часу виконання застосунку. - Я відкинув усі можливості Linux і не додавав широких можливостей на кшталт
SYS_ADMIN. - Я задав
allowPrivilegeEscalation: falseтаseccompProfile.type: RuntimeDefault. - Я використав Сервіс для надання порту
80, тримаючи контейнер на високому порту.
Проблеми безпеки та виправлення
| Проблема | Ризик | Виправлення |
|---|---|---|
runAsUser: 0 | Процес працює від імені root усередині контейнера | Використати runAsUser: 1000 та runAsNonRoot: true |
privileged: true | Контейнер отримує широкий доступ рівня хоста | Установити privileged: false або опустити поле |
readOnlyRootFilesystem: false | Зловмисник може змінювати файли всередині файлової системи образу | Установити readOnlyRootFilesystem: true й змонтувати явні томи для запису |
allowPrivilegeEscalation: true | Шляхи підвищення в стилі setuid залишаються доступними | Установити allowPrivilegeEscalation: false |
hostNetwork: true | Под спільно використовує мережевий простір імен вузла | Прибрати його й надавати трафік через Сервіс |
hostPID: true | Под може бачити процеси хоста | Прибрати його для звичайних застосунків |
capabilities.add: ["SYS_ADMIN"] | Под отримує широку можливість високого ризику | Відкинути всі можливості (ALL) і уникати широких додавань |
image: myapp:latest | Переглянутий образ може змінитися без зміни маніфесту | Використати незмінну версію чи дайджест |
| Відсутній профіль seccomp Пода | Поду може бракувати фільтрації syscall часу виконання, яку очікує restricted | Задати seccompProfile.type: RuntimeDefault |
| Відсутні явні томи для запису | Увімкнення кореневої файлової системи лише для читання може зламати записи часу виконання | Додати emptyDir лише там, де застосунок мусить писати |
Безпечна версія не є «безпечною назавжди» лише тому, що маніфест виглядає краще. Їй усе одно потрібні звичайні операційні засоби контролю, як-от сканування образів, RBAC, NetworkPolicy, логування та оновлення. Безпека Подів зменшує радіус ураження, коли щось інше відмовляє.
Підсумок
Розділ «Підсумок»Безпека Пода — це практика збереження ізоляції контейнера за умови надання лише тих дозволів часу виконання, які робоче навантаження може обґрунтувати. Найважливіша звичка перегляду — оцінювати сукупний ефект специфікації Пода: ідентичність користувача, можливості, підвищення привілеїв, змінюваність файлової системи, seccomp, простори імен хоста та політика допуску — усе це взаємодіє. Под з одним посиленим полем усе одно може бути ризикованим, якщо інше поле надає широкий доступ до хоста.
| Засіб контролю | Призначення | Безпечне налаштування |
|---|---|---|
runAsNonRoot | Запобігти випадковому виконанню від імені root | true |
runAsUser | Зробити ідентичність часу виконання явною | Ненульовий UID |
readOnlyRootFilesystem | Зменшити втручання та закріплення | true з явними томами для запису |
allowPrivilegeEscalation | Блокувати підвищення в стилі setuid | false |
privileged | Уникати широкого доступу рівня хоста | false або опущено |
capabilities | Обмежити привілеї Linux | drop: ["ALL"], додавати лише вузькі винятки |
seccompProfile | Фільтрувати ризиковані syscall’и | RuntimeDefault |
hostNetwork, hostPID, hostIPC | Уникати спільного використання просторів імен хоста | false або опущено |
Використовуйте Pod Security Standards як спільну мову. privileged — для довірених системних робочих навантажень, яким справді потрібен доступ рівня хоста. baseline — корисна мінімальна планка, що блокує поширені шляхи підвищення привілеїв. restricted — ціль для добре посилених робочих навантажень застосунків. Використовуйте мітки Pod Security Admission, щоб застосовувати, попереджати та проводити аудит цих стандартів на межі простору імен.
Хід рівня сеньйора — це не запам’ятовування ідеального блоку YAML. Це запитання, чому дозвіл потрібен, вибір найменшого механізму, що задовольняє потребу, та обмеження винятків так, щоб вони не ставали типовими для всіх інших.
Джерела
Розділ «Джерела»- Документація Kubernetes: Pod Security Standards, https://kubernetes.io/docs/concepts/security/pod-security-standards/
- Документація Kubernetes: Pod Security Admission, https://kubernetes.io/docs/concepts/security/pod-security-admission/
- Документація Kubernetes: Configure a Security Context for a Pod or Container, https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
- Документація Kubernetes: Linux kernel security constraints for Pods and containers, https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/
- Документація Kubernetes: Seccomp, https://kubernetes.io/docs/tutorials/security/seccomp/
- Документація Kubernetes: Admission Controllers, https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
- Документація Kubernetes: Namespaces, https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
- Документація Kubernetes: Volumes, https://kubernetes.io/docs/concepts/storage/volumes/
- Документація Kubernetes: Debug running Pods, https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/
- Документація Kubernetes: Kubernetes API reference for Pod security context fields, https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/
- Linux manual pages: capabilities, https://man7.org/linux/man-pages/man7/capabilities.7.html
- Linux manual pages: seccomp, https://man7.org/linux/man-pages/man2/seccomp.2.html
- kubernetes.io: security context — Завдання про контекст безпеки Kubernetes прямо зазначає, що налаштування безпеки контейнера перевизначають налаштування рівня Пода в разі перетину.
- kubernetes.io: service — Документація Service прямо показує зіставлення
portіtargetPortта зазначає, що Service може зіставити будь-який вхідний порт із targetPort. - kubernetes.io: linux kernel security constraints — Сторінка про обмеження безпеки ядра Linux прямо каже, що привілейовані контейнери працюють без обмежень seccomp, ігнорують обмеження AppArmor і SELinux та отримують усі можливості Linux.
- kubernetes.io: pod security standards — Сторінка Pod Security Standards каже, що стандарти визначають три політики і що ці політики є кумулятивними.
- kubernetes.io: pod security admission — Документація PSA каже, що Kubernetes пропонує вбудований контролер допуску Pod Security і що обмеження безпеки Подів застосовуються на рівні простору імен.
- kubernetes.io: pod security policy — Документація PodSecurityPolicy прямо позначає PSP як застарілу у v1.21, видалену у v1.25 і скеровує читачів до PSA та сторонніх плагінів допуску.
- kubernetes.io: images — Документація про образи каже, що теги можна переміщати, щоб вони вказували на інші образи, тоді як дайджести фіксовані й унікально ідентифікують конкретну версію.
Наступний модуль
Розділ «Наступний модуль»Продовжуйте з Модуля 3.2: Основи RBAC, щоб пов’язати засоби контролю допуску Подів із рішеннями авторизації Kubernetes та проєктуванням ідентичності робочих навантажень.