Профили AppArmor для Podman и Docker на Linux
Контейнеры обеспечивают нам изоляцию, но по умолчанию они используют ядро хоста напрямую. А это значит, что общая поверхность атаки остается куда шире, чем многие думают. AppArmor (и его родственник SELinux, о котором мы поговорим как-нибудь позже) позволяет применять мандатный контроль доступа (MAC) на уровне приложений. Используя его связке с Podman или Docker, вы можете кардинально урезать возможности скомпрометированного процесса внутри контейнера по отношению к хост-системе.
В этом посте разберем процесс генерации рабочего профиля, его принудительного применения, отладки нарушений и чистой интеграции с вашей средой выполнения контейнеров - и всё это на базе типичной системы Debian/Ubuntu.
Зачем нужен AppArmor для контейнеров?
Казалось бы, ну ведь стандартные среды выполнения контейнеров уже дропают возможности (capabilities) и используют seccomp, нафига AppArmor? Но AppArmor добавляет к этому правила на основе путей и отслеживания возможностей, которые легко аудировать. Профиль может:
Запретить запись в чувствительные пути хоста, даже если внутри контейнера процесс запущен от root.
Ограничить разрешенные системные вызовы и операции с файлами сверх того, что предоставляет рантайм.
Выдавать вам понятные человеку логи, когда что-то пытается выбраться из своей «песочницы».
В Ubuntu AppArmor включен по умолчанию, а в Debian и Arch его активация - дело пары пустяков.
Генерируем первый профиль
Для начала установим инструменты (пример для Debian/Ubuntu):
sudo apt update && sudo apt install apparmor apparmor-utils apparmor-profiles
Переведем целевое приложение в режим обучения (complain mode), чтобы понаблюдать за его реальным поведением:
sudo aa-genprof podman # или docker, или имя вашего бинарника
Утилита aa-genprof запускает программу в режиме обучения и следит за логами. Теперь запустите ваш контейнер в обычном рабочем режиме:
podman run --rm -it nginx:alpine sh
Погоняйте контейнер в хвост и в гриву (поустанавливайте пакеты, позаписывайте файлы и т.д.). Затем выйдете из него и позвольте утилите aa-logprof провести вас по процессу создания правил.
Минимальный готовый профиль (/etc/apparmor.d/podman-nginx) может выглядеть примерно так:
#include <tunables/global>
profile podman-nginx flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
#include <abstractions/nameservice>
capability net_bind_service,
capability setuid,
capability setgid,
network inet stream,
network inet6 stream,
/var/log/nginx/** rw,
/var/cache/nginx/** rw,
/etc/nginx/** r,
/usr/share/nginx/** r,
# Запрещаем доступ на запись к большей части /proc и /sys по умолчанию
deny /proc/** w,
deny /sys/** w,
# Разрешаем только конкретное чтение при необходимости
/proc/cpuinfo r,
/proc/meminfo r,
# Бинарник вашего приложения и библиотеки
/usr/sbin/nginx mr,
/usr/lib/nginx/** mr,
# Обработка сигналов
signal (receive) set=term,
# Запрещаем всё остальное по умолчанию
deny /** wl,
}
Инструмент aa-logprof шаг за шагом проведет вас по каждому залогированному событию и позволит выбрать: разрешить его, запретить или проигнорировать.
Принудительное применение профиля в Podman
У Podman отличная интеграция с AppArmor. Запустите контейнер следующим образом:
podman run --security-opt apparmor=podman-nginx -p 8080:80 nginx:alpine
Убедитесь, что профиль действительно загружен:
sudo aa-status | grep podman-nginx
Вы должны увидеть его в режиме enforce (принудительное исполнение).
Для Docker (если вы всё еще его используете):
docker run --security-opt apparmor=podman-nginx nginx:alpine
Отладка и итерация
Если что-то ломается, проверьте логи ядра:
sudo dmesg | grep apparmor
# или
sudo journalctl -xe | grep apparmor
Затем снова воспользуйтесь интерактивным профилировщиком:
sudo aa-logprof
Он покажет, какого именно правила не хватало. Типичный сценарий: нужно добавить конкретный путь вида /run/… или /tmp/…, который легитимно требуется вашему приложению.
В продакшене вы можете временно переключить профиль в режим обучения (complain):
sudo aa-complain /etc/apparmor.d/podman-nginx
После настройки верните всё обратно в режим принудительного исполнения:
sudo aa-enforce /etc/apparmor.d/podman-nginx
С чего начать изучение
Запускайте каждый новый образ контейнера с автоматически сгенерированным профилем в режиме обучения (complain) на протяжении недели.
Храните профили в Git рядом с вашими манифестами развертывания.
Сочетайте это с флагом --cap-drop=ALL и строгим профилем seccomp для эшелонированной защиты.
Периодически используйте утилиту aa-unconfined, чтобы находить процессы, которые работают без ограничений.
Что почитать по теме
Документация Ubuntu по AppArmor: https://ubuntu.com/server/docs/how-to/security/apparmor/
Страница AppArmor на Arch Wiki (отличные примеры): https://wiki.archlinux.org/title/AppArmor
Параметры безопасности Podman: man podman-run (ищите по ключевому слову apparmor)
Man-страницы для aa-genprof(8), aa-logprof(8) и apparmor(7)
Профили AppArmor относятся к той категории инструментов, которые настраиваются один раз и довольно долго не меняются (если конечно хорошо к этому подойти в первый раз). Первоначальные вложения времени в изучение aa-logprof окупятся в первый же раз, когда вы поймаете контейнер на попытке сделать то, чего он делать не должен.
Если вы уже гоняете Podman или Docker в продакшене без кастомных профилей AppArmor, то это одно из самых высокодоходных (с точки зрения ROI) улучшений безопасности, которые вы можете сделать на этой неделе. Начните с одного критически важного сервиса и двигайтесь дальше.


















