Kubernetes AppArmor
![](https://habrastorage.org/getpro/habr/upload_files/851/40d/702/85140d702b32fd17af39d01e89af7624.jpg)
Автор статьи: Рустем Галиев
IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM
Привет Хабр!
Сперва небольшая вводная:
AppArmor — это модуль безопасности ядра Linux, который дополняет стандартные разрешения Linux для пользователей и групп, ограничивая программы набором ресурсов. AppArmor можно настроить для любого приложения, чтобы уменьшить потенциальную поверхность атаки и обеспечить более глубокую защиту. Он настраивается с помощью профилей, настроенных так, чтобы разрешить доступ, необходимый для конкретной программы или контейнера, например возможности Linux, доступ к сети, права доступа к файлам и т. д. Каждый профиль можно запускать либо в принудительном режиме, который блокирует доступ к запрещенным ресурсам, либо в режиме жалобы - режим, который сообщает только о нарушениях.
AppArmor может помочь вам выполнить более безопасное развертывание, ограничив возможности контейнеров и/или предоставив лучший аудит с помощью системных журналов. Однако важно иметь в виду, что AppArmor не является серебряной пулей и может сделать очень мало для защиты от эксплойтов в коде вашего приложения.
AppArmor обеспечивает контроль доступа к программам, работающим в системе Linux. Инструмент реализует дополнительный уровень безопасности между приложениями, вызываемыми в пользовательском пространстве и базовой функциональностью системы. Например, мы можем ограничить сетевые вызовы или взаимодействие с файловой системой. Многие дистрибутивы Linux (например, Debian, Ubuntu, openSUSE) уже поставляются с AppArmor. Поэтому AppArmor не нужно устанавливать вручную.
Важная концепция в AppArmor - это профили
Правила определяющие, что программа может или не может делать, определяются в профиле AppArmor. Каждый профиль должен быть загружен в AppArmor, прежде чем он начнет действовать. AppArmor предоставляет инструмент командной строки для проверки загруженных профилей. Мы можем выполнить команду aa-status
, чтобы увидеть сводку всех загруженных профилей. Увидим, что AppArmor уже поставляется с набором профилей приложений по умолчанию для защиты служб Linux:
Режим профиля определяет обработку правил во время выполнения, если произойдет соответствующее событие. AppArmor различает два типа режимов профиля:
Enforce: Система применяет правила, сообщает о нарушении и записывает его в системный журнал. Мы используем этот режим, чтобы запретить программе выполнять определенные вызовы.
Complain: Система не применяет правила, но записывает нарушения в журнал. Этот режим полезен, если мы хотим обнаружить вызовы, которые делает программа.
Например это определяет пользовательский профиль в файлеk8s-deny-write
для ограничения доступа к файлу на запись. Файл должен быть помещен в директорию/etc/apparmor.d
каждого рабочего узла, выполняющего рабочую нагрузку.
#include <tunables/global>
profile k8s-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
deny /** w,
}
Чтобы загрузить профиль в AppArmor, мы запускаем следующую команду на рабочем узле: sudo apparmor_parser /etc/apparmor.d/k8s-deny-write
По умолчанию команда использует enforce режим. Чтобы загрузить профиль в режиме complain, используйте параметр -C
. Команда aa-status
теперь будет отображать профиль в дополнение к профилям по умолчанию. Как вы можете видеть в выводе, профиль указан в принудительном режиме:
С теорией разобрались, давайте теперь поработаем с ним.
Мы создадим профиль AppArmor с именем network-deny в текущей директории, который предотвращает любой входящий и исходящий сетевой трафик и добавим профиль в набор правил AppArmor в принудительном режиме на node01
.
Также у нас будет под со следующим дескриптором:
apiVersion: v1
kind: Pod
metadata:
name: network-call
spec:
containers:
- name: network-call
image: alpine/curl:3.14
command: ["sh", "-c", "while true; do ping -c 1 google.com; sleep 5; done"]
Создадим его и проверим
Окей, приступим.
Перейдем на рабочий узел node01
.
$ ssh node01
Создадим профиль AppArmor в /etc/apparmor.d/network-deny
. Содержимое файла должно выглядеть следующим образом:
#include <tunables/global>
profile network-deny flags=(attach_disconnected) {
#include <abstractions/base>
network,
}
Применим профиль AppArmor, выполнив следующую команду:apparmor_parser /etc/apparmor.d/network-deny
Ну и вернемся на controlplane
Прежде чем использовать правила AppArmor в дескрипторе пода, необходимо выполнить несколько предварительных условий. Во-первых, среда выполнения контейнера должна поддерживать AppArmor, чтобы правила вступили в силу. Кроме того, AppArmor необходимо установить на рабочем узле, на котором работает под.
Мы не можем изменить существующий объект Pod, чтобы добавить аннотацию для AppArmor. Сначала вам нужно удалить объект.
Чтобы применить профиль к контейнеру, нам нужно будет установить определенную аннотацию. Ключ аннотации должен использовать ключ в формате container.apparmor.security.beta.kubernetes.io/<container-name>
Редактируем файл pod.yaml
в текущей директории. Добавляем аннотацию AppArmor. Для соответствующей аннотации мы используем имя контейнера network-call
как часть ключевого суффикса и localhost/network-deny
в качестве значения. Суффикс network-deny
относится к имени профиля AppArmor. Окончательное содержание файла будет выглядеть следующим образом:
apiVersion: v1
kind: Pod
metadata:
name: network-call
annotations:
container.apparmor.security.beta.kubernetes.io/network-call: localhost/network-deny
spec:
containers:
- name: network-call
image: alpine/curl:3.14
command: ["sh", "-c", "while true; do ping -c 1 google.com; sleep 5; done"]
Создадим под
AppArmor не позволяет поду совершать сетевые вызовы. Но мы проверим логи, чтобы убедиться в этом:
Напоследок хочу порекомендовать бесплатный вебинар, на котором вы узнаете из каких компонентов состоит Kubernetes, как они взаимодействуют и для чего нужны, а также подробно познакомитесь с базовыми объектами, которые существуют внутри любого кластера Kubernetes.