Kubernetes v1.37 приносить важливі функції безпеки зберігання: режими дозволів emptyDir та параметри bind mount. Вони допомагають розробникам застосунків та фахівцям з безпеки впроваджувати суворі політики безпеки, наприклад, забороняти видалення файлів між контейнерами або виконання довільних бінарних файлів із томів з правами запису, безпосередньо в Kubernetes без будь-яких складних обхідних шляхів.
Перш ніж заглибитись у нові функції Kubernetes, коротко оглянемо низькорівневі механізми безпеки Linux, які роблять їх можливими.
Коли Linux монтує або повторно монтує теку, прапорці Virtual File System (VFS) контролюють, які дії дозволені в цій файловій системі:
noexec: Не дозволяє безпосереднє виконання будь-яких бінарних файлів у змонтованій файловій системі.nosuid: Не дозволяє бітам set-user-identifier або set-group-identifier діяти.nodev: Не інтерпретує символічні або блокові спеціальні пристрої у файловій системі.Стандартні Unix-дозволи регулюють доступ у трьох областях: Власник, Група та Інші (наприклад, 0755 або 0777).
Окрім стандартних бітів читання, запису та виконання, Linux підтримує sticky-біт (як у режимі 01777). Коли sticky-біт застосовується до теки, він гарантує, що файл у цій теці може бути видалений або перейменований лише власником файлу або root. Це є необхідним для спільних тек з правом на запис, таких як /tmp.
Чому Kubernetes потребує параметри bind mount та дозволів emptyDir?
Основна мета цих функцій — підвищити безпеку робочих навантажень Kubernetes, дозволяючи параметри bind mount, повʼязані з безпекою, при монтуванні томів. Стандартно том монтується як bind mount у контейнери середовищем виконання контейнерів та kubelet без прапорців noexec, nosuid або nodev. Це стандартне значення може підривати безпеку. Наприклад, без noexec, скомпрометований процес може використовувати будь-який том з правами на запис (emptyDir, PersistentVolume тощо) для завантаження, chmod +x та виконання довільних бінарних файлів, навіть коли контейнер має право тільки для читання кореневої файлової системи (readOnlyRootFilesystem: true). Підтримка noexec, nodev та nosuid надає користувачам вбудований спосіб посилення монтування томів відповідно до стандартів безпеки та політик.
Проблема найбільш помітна з томами emptyDir, які є найпоширенішим типом тому з правом на запис та були предметом кількох повідомлень про проблеми з безпекою:
emptyDir була виявлена під час аудиту, але залишилася невирішеною до теперішнього часу.emptyDir з noexec являє собою збій в безпеці.Однак та ж прогалина стосується всіх типів томів. У PersistentVolumes є поле mountOptions, але ці параметри є прапорцями рівня файлової системи, які застосовуються CSI-драйвером на вузлі, тому вони не надійно перетворюються на прапорці bind mount всередині контейнера. Раніше не було механізму для встановлення noexec, nosuid або nodev на bind mount, який створює середовище виконання контейнерів для будь-якого типу тому.
Крім того, тип тому emptyDir зазвичай створює теки з жорстко заданим режимом 0777. Раніше це означало, що будь-який процес, який може знайти том, може читати, записувати та видаляти все в томі, незалежно від того, хто його створив.
Ви могли, і все ще можете, використовувати init-контейнер для встановлення іншого режиму доступу, але це складніше і важче перевірити на відповідність вимогам.
Це викликає реальні проблеми:
emptyDir, не можуть запобігти видаленню файлів одного контейнера іншим. Sticky-біт (01777) вирішує цю проблему, але не було вбудованого способу його встановити./tmp мають встановлений sticky-біт (режим 01777). Без вбудованої підтримки встановлення режиму emptyDir користувачам доводилося використовувати init-контейнери або альтернативні типи томів, щоб задовольнити це вимогу.0750 лише для власника та групи), доводилося використовувати init-контейнери з chmod, що додає зайву складність.Тип тому emptyDir був помітною прогалиною. Як один із найпоширеніших типів томів з можливістю запису у Kubernetes, він не мав жодного способу контролювати свої дозволи створення.
Розробники застосунків, працюючи тісно з інженерами з безпеки, несуть відповідальність за підтримку профілю безпеки своїх застосунків та забезпечення того, щоб робочі навантаження не створювали ризиків для загальної інфраструктури. Ці функції дозволяють командам розробників з впевненістю вирішати критичні сценарії безпеки:
Запобігання розширенню прав доступу на монтованих розділах із можливістю запису: Розробник застосунку, який налаштовує тимчасові робочі томи (як emptyDir або монтування /tmp), може переконатися, що вони монтуються з nosuid та noexec. Це гарантує, що навіть якщо застосунок скомпрометовано та завантажено зловмисне навантаження, робоче навантаження не може виконати це навантаження або використати його для підвищення привілеїв на вузлі.
Захист спільного тимчасового простору в Podʼах з кількома контейнерами: Розробник, який налаштовує Podʼи CI/CD конвеєри, часто потребує кількох контейнерів (наприклад, контейнера збірки та sidecar логгера) для спільного робочого простору. Встановивши mode: 01777 на emptyDir, розробник гарантує, що спільний робочий простір працює як традиційна Unix-тека /tmp. Кожен контейнер може незалежно записувати файли, але скомпрометований процес в одному контейнері не може видалити артефакти збірки, створені іншим.
Впровадження принципу найменшого привілею для даних застосунку: Розробник застосунку, який розгортає Pod бази даних, може заблокувати доступ до тимчасового сховища бази даних. Встановивши mode: 0750 на emptyDir, розробник гарантує, що лише конкретний користувач та група бази даних можуть читати або записувати до тому, явно відмовляючи в доступі до будь-яких інших процесів або sidecar контейнерів у тому самому Podʼі.
Примітка: Обидві функції знаходяться за Alpha-функціональними можливостями в Kubernetes v1.37. Для їх використання увімкніть VolumeBindMountOptions та EmptyDirVolumeMode на API-сервері та kubelet.
Цей повний маніфест Podʼа монтує том emptyDir у /tmp з bindMountOptions: [noexec, nosuid].
apiVersion: v1
kind: Pod
metadata:
name: hardened-bindmount-pod
namespace: default
spec:
os:
name: linux
containers:
- name: hardened-app
image: alpine:latest
command: ["sleep", "3600"]
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: temp-storage
mountPath: /tmp
bindMountOptions:
- noexec
- nosuid
volumes:
- name: temp-storage
emptyDir: {}
emptyDir зі sticky-бітомЦей повний маніфест Podʼа створює том emptyDir із використанням mode: 01777 для впровадження стандартних захисних механізмів Unix sticky-біту /tmp між контейнерами.
apiVersion: v1
kind: Pod
metadata:
name: hardened-emptydir-pod
namespace: default
spec:
os:
name: linux
containers:
- name: app-container
image: alpine:latest
command: ["sleep", "3600"]
volumeMounts:
- name: shared-tmp
mountPath: /tmp
volumes:
- name: shared-tmp
emptyDir:
mode: 01777
Щоб перевірити, що ці функції активно впроваджують обмеження, ви можете виконати kubectl exec у контейнері. Наведені нижче приклади імітують спроби виконати дії, які ці функції успішно блокують.
Спроба запису та виконання скрипту на тому, змонтованому з noexec:
# 1. Виконайте exec у podʼі
kubectl exec -it hardened-bindmount-pod -- sh
# 2. Створіть виконуваний скрипт на змонтованому томі
cd /tmp
echo '#!/bin/sh' > test.sh
echo 'echo "Executing untrusted code..."' >> test.sh
chmod +x test.sh
# 3. Спроба виконати скрипт
./test.sh
Очінуваний результат:
sh: ./test.sh: Permission denied
Навіть якщо виконуваний файл створено, ядро Linux відмовляє у виконанні, оскільки MS_NOEXEC впроваджується на рівні bind mount.
Спроба видалення файлу іншого користувача в emptyDir із режимом дозволів 01777:
# 1. Виконайте exec у podʼі
kubectl exec -it hardened-emptydir-pod -- sh
# 2. Перевірте дозволи теки /tmp
ls -ld /tmp
# Вивід: drwxrwxrwt 2 root root ... /tmp (Зверніть увагу на 't', що вказує на sticky-біт)
# 3. Створіть файл як користувач guest
su -s /bin/sh -c "touch /tmp/guest_file" guest
# 4. Спроба видалити цей файл як nobody
su -s /bin/sh -c "rm /tmp/guest_file" nobody
Очікуваний результат:
rm: can't remove '/tmp/guest_file': Operation not permitted
Ядро блокує видалення, оскільки sticky-біт (01777) обмежує видалення файлів суворо власником файлу.
Починаючи користуватися цими функціями, майте на увазі ці ключові моменти. Повні деталі доступні в офіційній документації для параметрів bind mount, режиму тому emptyDir та томів emptyDir.
bindMountOptions або не встановлюєте mode для emptyDir, ви отримуєте стандартну поведінку (як-от дозволи 0777) точно так само, як і раніше.bindMountOptions працює з emptyDir, PersistentVolumes, CSI-томами, проєкційними томами, ConfigMap, Secret та іншими. Єдиним винятком є томи образів, які явно не підтримуються. Поле mode працює з усіма типами середовища emptyDir: default (на основі диска), Memory (tmpfs) та HugePages.bindMountOptions): Контейнерне середовище виконання повинно підтримувати поле CRI mount_options та оголошувати це через runtimeFeatures. Планувальник використовує оголошені вузлом можливості, щоб уникати розміщення Podʼів на несумісних вузлах. Якщо Pod все ж досягає такого вузла, kubelet відхиляє його. Немає мовчазного зниження якості. Однак використання mode для emptyDir не потребує підтримки середовища виконання.mountOptions PersistentVolume застосовуються на рівні сховища через CSI-драйвер. Нові bindMountOptions контролюють прапорці bind mount, які застосовуються всередині контейнера середовищем виконання. Вони працюють на різних рівнях і не конфліктують.fsGroup встановлено в контексті безпеки Podʼа, дозволи групи, які застосовуються fsGroup, перевищать mode, вказаний для тому emptyDir. Це та сама поведінка, що існує для defaultMode на томах Secret та ConfigMap.noexec, nosuid, nodev та Unix-дозволи є концепціями Linux. bindMountOptions не має ефекту на вузлах Windows. На Windows поле mode також пропускається для томів emptyDir, оскільки Windows не підтримує Unix-дозволи на файли.emptyDir mode: якщо API-сервер має цвімкнуті функціональні можливості, але kubelet — ні, поле приймається, але ігнорується — kubelet повертається до 0777. Для bindMountOptions: планувальник використовує Node Declared Features, щоб запобігти розміщенню Podʼів на вузлах без підтримки середовища виконання; якщо Pod досягає такого вузла, kubelet відхиляє його, а не ігнорує параметри мовчки.VolumeBindMountOptions: Контролює прапорці bind mount при монтуванні томів.EmptyDirVolumeMode: Контролює режими дозволів створення на томах emptyDir.Ці нові функції розробляють SIG Node та SIG Storage. Ви можете знайти більше деталей у KEP для цих покращень: KEP-5855 (параметри bind mount) та KEP-5502 (режим дозволів emptyDir).
Звʼяжіться з SIG Node:
Звʼяжіться з SIG Storage: