
Как разобраться с AppArmor на Ubuntu Server
Проверяем профили AppArmor, находим причину DENIED в журнале, тестируем одно приложение в complain mode и возвращаем enforce без отключения защиты сервера.
Содержание
Обычные права Linux отвечают на вопрос, может ли пользователь открыть файл или выполнить действие. AppArmor добавляет второе ограничение: что разрешено конкретной программе, даже если её пользователь формально имеет нужные права.
Например, процесс может работать от root, но профиль разрешает ему читать только конфигурацию своей службы и писать в один каталог. Если в программе появится уязвимость, такое ограничение уменьшает набор файлов и системных возможностей, до которых доберётся чужой код.
На Ubuntu AppArmor обычно установлен и загружен по умолчанию. Его не нужно отключать при первой непонятной ошибке. Правильный порядок — найти решение DENIED в журнале, понять, какую операцию выполняло приложение, и изменить только профиль этой программы.
Проверьте, работает ли AppArmor
Начните с чтения фактического состояния, не меняя режимы защиты. Получите сводку загруженных профилей и процессов, к которым они применены:
sudo aa-status
В начале ожидается apparmor module is loaded. Ниже перечисляются профили в режимах enforce и complain, а также процессы, к которым они применены. Если команда не найдена, установите утилиты управления пакетом apparmor-utils; сам модуль при этом может уже работать.
Проверьте также службу загрузки профилей:
systemctl status apparmor.service --no-pager
Состояние показывает, были ли профили загружены при старте и возникли ли ошибки разбора. На новых выпусках Ubuntu связь AppArmor с ядром не сводится к обычному запуску одной службы, поэтому команда systemctl stop apparmor не является надёжным и безопасным способом «проверить без защиты».
Поймите два режима профиля
Профиль в режиме enforce реально блокирует доступ, которого нет в правилах, и пишет событие в системный журнал. Это рабочий защитный режим.
В режиме complain большинство неразрешённых действий не блокируется, но регистрируется. Такой режим нужен на короткое время для разработки и диагностики профиля. Он не защищает программу от этих действий, а явные правила deny могут продолжать блокировку.
Менять режим всего AppArmor ради одного приложения не следует. Если проблема относится к одному профилю, только его и переводят в диагностический режим, после чего обязательно возвращают в enforce.
Сначала воспроизведите ошибку и отметьте время
Запустите ровно ту функцию, которая не работает: загрузку файла, запуск дочерней программы, подключение к сокету или перезапуск службы. Сразу после ошибки запишите время:
date --iso-8601=seconds
Отметка со смещением часового пояса нужна, чтобы не искать событие среди сообщений за весь день. Если приложение не выдаёт понятной ошибки, посмотрите его systemd-статус и журнал; AppArmor может проявляться как обычный Permission denied, отказ открыть файл или неожиданное завершение.
Найдите решение DENIED в системном журнале
Сразу после воспроизведения ошибки покажите сообщения ядра AppArmor за последние десять минут. Узкий интервал помогает связать отказ именно с выполненным тестом:
sudo journalctl -k --since '10 minutes ago' --no-pager | grep 'apparmor="DENIED"'
journalctl -k ограничивает вывод сообщениями ядра, --since задаёт период, а grep оставляет записи AppArmor с отказом. Пустой результат означает, что за это время подходящей строки нет. Он не доказывает, что причина точно не в AppArmor: проверьте правильность времени, наличие auditd и журнал, принятый в конкретной системе.
Типичная запись содержит несколько полезных полей:
profile— профиль, который принял решение;operation— операция, например чтение файла или запуск программы;name— путь или ресурс, к которому обращались;commиpid— имя и номер процесса;requested_maskиdenied_mask— запрошенные и запрещённые права.
Не смотрите только на путь. Сначала убедитесь, что время совпадает с тестом, profile относится к нужной службе, а operation объясняет наблюдаемую ошибку.
Свяжите профиль с реальной программой
Узнайте команду запуска службы. Для примера ниже используется Nginx; замените имя unit на службу из своего события:
systemctl show nginx.service -p ExecStart -p User -p Group
ExecStart показывает запускаемый файл, а User и Group — учётную запись процесса, если она задана в unit. Сопоставьте путь с полем profile из журнала и перечнем aa-status. Пустые User и Group означают значения systemd по умолчанию, обычно root, но сама программа может затем понизить права рабочих процессов.
Профили пакетов находятся в /etc/apparmor.d/. Их имена часто получаются заменой / в пути программы на ., но угадывать не нужно: точное имя видно в profile и выводе aa-status.
Решите, нужен ли приложению этот доступ
Перед добавлением правила ответьте на три вопроса:
- Какая пользовательская функция вызвала обращение?
- Почему программе нужен именно этот путь или системная возможность?
- Можно ли разрешить более узкий файл, каталог или операцию?
Если веб-приложение пытается читать /etc/shadow, правильным исправлением почти наверняка будет не разрешение, а поиск причины обращения. Если после переноса каталога данных база не может открыть новый путь, узкое правило для этого каталога может быть оправдано.
Проверьте также обычные права Linux. AppArmor не отменяет владельца, группу и режим файла: после разрешения в профиле программа всё равно получит отказ, если её пользователь не имеет обычного доступа.
Временно переведите только один профиль в complain
Команды aa-complain и aa-enforce входят в пакет apparmor-utils. Если они отсутствуют, установите утилиты:
sudo apt update
sudo apt install apparmor-utils
Обновление индекса не меняет установленные пакеты, а установка добавляет средства диагностики. После этого подставьте реальный путь исполняемого файла, найденный в предыдущем разделе. Например, для программы /usr/sbin/exampled команда имела бы вид sudo aa-complain /usr/sbin/exampled; слова exampled на настоящем сервере, скорее всего, нет.
Снова выполните только известный сценарий и посмотрите новые события AppArmor. Не оставляйте приложение в complain во время обычной работы дольше, чем требуется для теста: нарушения разрешаются и могут быть вызваны посторонним трафиком.
Измените локальную часть профиля
Пакетные профили могут обновляться. Если для профиля предусмотрен файл в /etc/apparmor.d/local/, локальные дополнения удобнее хранить там, не смешивая их с исходным файлом пакета.
Откройте основной профиль и найдите строку #include <local/...>. Имя после local/ указывает на файл дополнений. Добавьте только правило, которое объясняется вашим тестом. Не используйте широкие шаблоны вроде /** rw, потому что они фактически отменяют смысл ограничения файловой системы.
Утилита aa-logprof может прочитать события и предложить варианты правил:
sudo aa-logprof
Просматривайте каждое предложение, а не принимайте всё подряд. Журнал фиксирует фактические обращения, но среди них могут быть необязательные проверки, ошибочные пути и действия, вызванные внешним запросом. Инструмент помогает написать синтаксис; решение о допустимом доступе остаётся за администратором.
Перезагрузите один профиль и повторите тест
После ручного изменения проверьте и загрузите конкретный файл профиля. В команде ниже путь условный — замените его точным путём из /etc/apparmor.d/:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.exampled
Параметр -r заменяет уже загруженный профиль. При синтаксической ошибке команда сообщает строку и не должна считаться успешной. Не перезагружайте все профили, если менялся один: узкое действие проще проверить и вернуть.
Верните профиль программы в защитный режим. Для того же условного пути это выглядело бы как sudo aa-enforce /usr/sbin/exampled. Затем повторите нормальный сценарий, перезапуск службы и одну заведомо запрещённую операцию, если у проекта есть безопасный тест.
Снова выполните aa-status и поиск DENIED за время теста. Результат считается успешным, когда нужная функция работает в enforce, профиль загружен, а лишний доступ по-прежнему не разрешён.
Как вернуть изменение
До редактирования сохраните копию локального файла профиля вне /etc/apparmor.d/ или держите конфигурацию в закрытом репозитории. Если новое правило ломает загрузку, верните предыдущую версию файла и снова выполните apparmor_parser -r.
Если срочно нужно восстановить одну службу, переведите только её профиль в complain, зафиксируйте причину и подготовьте узкое исправление. Не добавляйте параметр отключения AppArmor в загрузчик и не снимайте все профили ради одной ошибки.
После обновления приложения повторите его основные сценарии и проверьте журнал: новый путь к бинарному файлу, библиотеке или каталогу данных может потребовать осмысленного изменения профиля. AppArmor дополняет обычные права файлов и ограничения systemd-службы, а не заменяет их.
Первоисточники
Самопроверка
Проверьте, что материал усвоен
Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.
Разбираем коротко
Частые вопросы
Нужно ли отключать AppArmor, если служба перестала работать?
Нет. Сначала найдите событие DENIED и профиль, затем исправьте конкретное правило. Для диагностики можно временно перевести только этот профиль в complain mode, не отключая защиту остальных программ.
Чем complain отличается от enforce?
В enforce профиль блокирует неразрешённые действия. В complain большинство нарушений разрешается, но записывается в журнал для настройки профиля. Явные deny-правила могут продолжать действовать и в complain.
Почему нельзя автоматически разрешить всё из журнала?
В журнал могут попасть необязательные, ошибочные или вызванные атакой обращения. Каждое новое разрешение нужно связывать с известной функцией приложения и делать настолько узким, насколько возможно.


