DockerSeniorTechnical
Чем capabilities отличаются от full root? Какие capabilities обычно дропают?
Linux capabilities делят root на отдельные права (~40 штук). В контейнерах применяют cap_drop: ALL, затем добавляют минимально нужные. Обычно дропают SYS_ADMIN, NET_ADMIN, SYS_PTRACE, NET_RAW, DAC_OVERRIDE и другие неиспользуемые привилегии.
Что такое Linux capabilities
Традиционная Unix модель: процесс либо root (всё), либо не root (почти ничего). Linux capabilities делят привилегии root на ~40 независимых прав. Процесс может иметь только нужный capability, не получая полный root. В Docker это — основа least privilege для контейнеров.
Default capabilities в Docker
Docker по умолчанию оставляет ограниченный набор (из docker/engine):
CHOWN— смена владельца файловDAC_OVERRIDE— обход file permission checksFSETID— сохранение setuid/setgid битовFOWNER— обход ownership checks для операций с файламиMKNOD— создание device nodesNET_RAW— raw sockets (нужен для ping, ARP, ICMP)SETGID,SETUID— смена group/user IDSETFCAP— установка capabilities на файлыSETPCAP— передача capabilitiesNET_BIND_SERVICE— bind на порты < 1024SYS_CHROOT— chrootKILL— посылка сигналовAUDIT_WRITE— запись в audit log
Что дропают в production
# docker-compose.yml
services:
api:
image: my-api:1.0.0
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # только если нужен порт < 1024
read_only: true
user: "1000:1000"
# Kubernetes Pod spec
securityContext:
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
Наиболее опасные capabilities, которые дропают в первую очередь:
SYS_ADMIN— самый широкий, охватывает mount, namespace, device control. По сути почти весь root.NET_ADMIN— управление сетевыми интерфейсами, iptables, routing. Нужен только сетевым утилитам.SYS_PTRACE— introspection процессов,ptrace(). Нужен debugger'ам; в production не нужен.SYS_MODULE— загрузка kernel modules. Почти никогда не нужен в контейнере.DAC_OVERRIDE— обход ACL. Дропают если приложение правильно запускается под своим uid.NET_RAW— raw sockets. Нужен для ping внутри контейнера, но web-сервисам не нужен.
Диагностика нужных capabilities
# Запустить с cap_drop: ALL и найти что именно нужно
docker run --rm --cap-drop ALL my-app 2>&1 | grep -i 'operation not permitted'
# Проверить capabilities процесса внутри контейнера
docker run --rm --cap-drop ALL --cap-add NET_BIND_SERVICE my-app \
grep Cap /proc/1/status
# capsh decode
capsh --decode=00000000a80425fb
Подводные камни
- Запуск как uid 0 с дефолтными capabilities — это не «безопасный root»: процесс имеет
DAC_OVERRIDEиNET_RAW, что уже позволяет много лишнего. - Флаг
--privilegedдаёт все capabilities и отключает seccomp/AppArmor — никогда не используйте в production. - Legacy приложения могут требовать
SYS_ADMINдля mount-related операций — правильное решение переработать, а не дать capability. - Дропнуть
SETUID/SETGID— правильно, но проверьте что entrypoint и init-скрипты не меняют uid (tini, gosu). - В Kubernetes capabilities задаются в
securityContextна уровне pod и container; Pod Security Standards (Restricted) требуетdrop: ALL. NET_BIND_SERVICEнужен только для портов < 1024; для web-сервисов проще использовать порт 8080 за reverse proxy.- Docker Compose не проверяет корректность capability names — опечатка в
cap_dropмолча игнорируется. - Capabilities в контейнере ограничены bounding set namespace: даже с
cap_add: SYS_ADMINнекоторые операции недоступны без--privilegedиз-за user namespace ограничений.
Common mistakes
- Считать non-root user единственным нужным security control.
- Добавлять SYS_ADMIN как универсальный фикс.
- Оставлять NET_RAW и SYS_PTRACE без причины в web-service container.
What the interviewer is testing
- Объясняет capabilities как дробление root privileges.
- Знает cap_drop ALL and targeted cap_add model.
- Называет опасные capabilities and legitimate exceptions.