Автор статьи: Рустем Галиев

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.kuber⁠netes.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.

Комментарии (2)


  1. vasyakrg
    14.06.2023 00:39

    Не очень понял, зачем задачу прав в кубе решать нативно средствами операционки ?

    А если у меня 100 нод в кубе - ансом профили раскатывать каждый раз ?

    А если куб из мульти-нод ? Часть нод на винде вообще, часть в облаке, где по ssh на ноду просто так не сходишь и нужно городить шелл-поды.

    В кубах есть куча инструментов, правил и политик: и сетевых и на выполнение действий, которые прекрасно с этим справляются, абстрагируя хождение в операционку (и имеющие собственно все это самое под капотом)


    1. Numen_Divinum
      14.06.2023 00:39

      В кубах есть куча инструментов, правил и политик

      ..и AppArmor - один из них
      Входит в требования CIS и программу сертификации CKS, если что