Модуль 3.1: AppArmor для контейнерів
Складність:
[MEDIUM]- Основа безпеки LinuxЧас на виконання: 45-50 хвилин
Передумови: Основи Linux, знання середовища виконання контейнерів
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете:
- Створити профілі AppArmor, що обмежують доступ контейнерів до файлів та мережеві операції
- Розгорнути Pod з профілями AppArmor, застосованими через анотації контексту безпеки
- Діагностувати відмови AppArmor, інтерпретуючи журнали аудиту ядра
- Аудитувати запущені контейнери для перевірки правильного застосування профілю AppArmor
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»AppArmor — це модуль безпеки Linux, який обмежує можливості застосунків: до яких файлів вони можуть звертатися, які мережеві операції можуть виконувати, які можливості (capabilities) можуть використовувати. При застосуванні до контейнерів AppArmor додає рівень безпеки поверх середовища виконання контейнерів.
CKS перевіряє вашу здатність створювати профілі AppArmor та застосовувати їх до Pod.
Що таке AppArmor?
Розділ «Що таке AppArmor?»┌─────────────────────────────────────────────────────────────┐│ ОГЛЯД APPARMOR │├─────────────────────────────────────────────────────────────┤│ ││ AppArmor = Application Armor ││ ───────────────────────────────────────────────────────── ││ • Система обов'язкового контролю доступу (MAC) ││ • Обмежує можливості кожної програми ││ • За замовчуванням на Ubuntu, Debian ││ • Альтернатива SELinux (RHEL/CentOS) ││ ││ Як це працює: ││ ││ ┌─────────────────┐ ┌─────────────────┐ ││ │ Застосунок │────►│ Системний │ ││ │ (Контейнер) │ │ виклик │ ││ └─────────────────┘ └────────┬────────┘ ││ │ ││ ▼ ││ ┌─────────────────┐ ││ │ Перевірка │ ││ │ профілю │ ││ │ AppArmor │ ││ └────────┬────────┘ ││ │ ││ ┌────────────┴────────────┐ ││ ▼ ▼ ││ ┌─────────┐ ┌─────────┐ ││ │ДОЗВОЛЕНО│ │ЗАБОРОНЕНО│ ││ └─────────┘ └─────────┘ ││ │└─────────────────────────────────────────────────────────────┘Режими AppArmor
Розділ «Режими AppArmor»┌─────────────────────────────────────────────────────────────┐│ РЕЖИМИ ПРОФІЛЮ APPARMOR │├─────────────────────────────────────────────────────────────┤│ ││ Режим примусу (Enforce) ││ └── Політика застосовується, порушення блокуються ТА ││ журналюються ││ aa-enforce /path/to/profile ││ ││ Режим скарги (Complain) ││ └── Порушення політики журналюються, але НЕ блокуються ││ aa-complain /path/to/profile ││ (Корисно для тестування нових профілів) ││ ││ Вимкнено/Без обмежень (Disabled/Unconfined) ││ └── Жодних обмежень не застосовується ││ │└─────────────────────────────────────────────────────────────┘Перевірка статусу AppArmor
Розділ «Перевірка статусу AppArmor»# Перевірити, чи увімкнено AppArmorcat /sys/module/apparmor/parameters/enabled# Вивід: Y (увімкнено) або N (вимкнено)
# Перевірити статус AppArmorsudo aa-status
# Приклад виводу:# apparmor module is loaded.# 47 profiles are loaded.# 47 profiles are in enforce mode.# /usr/bin/evince# /usr/sbin/cupsd# docker-default# 0 profiles are in complain mode.# 10 processes have profiles defined.
# Список завантажених профілівsudo aa-status --profiles
# Перевірити, чи підтримує середовище виконання контейнерів AppArmordocker info | grep -i apparmor# Вивід: Security Options: apparmorСтандартний профіль контейнера
Розділ «Стандартний профіль контейнера»# Docker/containerd використовують профіль 'docker-default'# Цей профіль:# - Забороняє монтування файлових систем# - Забороняє доступ до /proc/sys# - Забороняє прямий доступ до мережі# - Дозволяє звичайні операції контейнера
# Перевірити стандартний профільcat /etc/apparmor.d/containers/docker-default 2>/dev/null || \ cat /etc/apparmor.d/docker 2>/dev/nullСтворення власних профілів AppArmor
Розділ «Створення власних профілів AppArmor»Розташування профілів
Розділ «Розташування профілів»# Профілі AppArmor зберігаються в:/etc/apparmor.d/
# Для Kubernetes, створюйте в:/etc/apparmor.d/# Профіль повинен бути завантажений на кожному вузлі, де може запуститися PodСтруктура профілю
Розділ «Структура профілю»#include <tunables/global>
profile my-container-profile flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base>
# Правила доступу до файлів /etc/passwd r, # Читання /etc/passwd /var/log/myapp/** rw, # Читання/запис у каталог журналів /tmp/** rw, # Читання/запис у tmp
# Мережеві правила network inet tcp, # Дозволити TCP network inet udp, # Дозволити UDP
# Правила можливостей (capabilities) capability net_bind_service, # Дозволити прив'язку до портів < 1024
# Правила заборони deny /etc/shadow r, # Заборонити читання shadow deny /proc/sys/** w, # Заборонити запис у /proc/sys}Синтаксис правил
Розділ «Синтаксис правил»┌─────────────────────────────────────────────────────────────┐│ СИНТАКСИС ПРАВИЛ APPARMOR │├─────────────────────────────────────────────────────────────┤│ ││ Доступ до файлів: ││ ───────────────────────────────────────────────────────── ││ /path/to/file r, # Читання ││ /path/to/file w, # Запис ││ /path/to/file rw, # Читання і запис ││ /path/to/file a, # Додавання (append) ││ /path/to/file ix, # Виконання, успадкування профілю ││ /path/to/dir/ r, # Читання каталогу ││ /path/to/dir/** rw, # Рекурсивне читання/запис ││ ││ Мережа: ││ ───────────────────────────────────────────────────────── ││ network, # Дозволити всю мережу ││ network inet, # IPv4 ││ network inet6, # IPv6 ││ network inet tcp, # Тільки IPv4 TCP ││ network inet udp, # Тільки IPv4 UDP ││ ││ Можливості (Capabilities): ││ ───────────────────────────────────────────────────────── ││ capability dac_override, # Обхід дозволів файлів ││ capability net_admin, # Адміністрування мережі ││ capability sys_ptrace, # Трасування процесів ││ ││ Заборона: ││ ───────────────────────────────────────────────────────── ││ deny /path/file w, # Явна заборона (журналюється) ││ │└─────────────────────────────────────────────────────────────┘Створення профілю для Kubernetes
Розділ «Створення профілю для Kubernetes»Крок 1: Написати профіль
Розділ «Крок 1: Написати профіль»# Створити профіль на кожному вузліsudo tee /etc/apparmor.d/k8s-deny-write << 'EOF'#include <tunables/global>
profile k8s-deny-write flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base>
# Дозволити більшість операцій читання file,
# Заборонити всі операції запису, крім /tmp deny /** w, /tmp/** rw,
# Дозволити мережу network,}EOFКрок 2: Завантажити профіль
Розділ «Крок 2: Завантажити профіль»# Розібрати та завантажити профільsudo apparmor_parser -r /etc/apparmor.d/k8s-deny-write
# Переконатися, що він завантаженийsudo aa-status | grep k8s-deny-write
# Щоб видалити профільsudo apparmor_parser -R /etc/apparmor.d/k8s-deny-writeКрок 3: Застосувати до Pod
Розділ «Крок 3: Застосувати до Pod»apiVersion: v1kind: Podmetadata: name: secured-pod annotations: # Формат: container.apparmor.security.beta.kubernetes.io/<ім'я-контейнера>: <профіль> container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-deny-writespec: containers: - name: app image: nginxЗначення посилань на профілі AppArmor
Розділ «Значення посилань на профілі AppArmor»# Формат анотації:container.apparmor.security.beta.kubernetes.io/<ім'я-контейнера>: <посилання-на-профіль>
# Варіанти посилань на профіль:# runtime/default - Використовувати стандартний профіль середовища виконання# localhost/<ім'я> - Використовувати профіль, завантажений на вузлі з <ім'я># unconfined - Без обмежень AppArmor (небезпечно!)Поширені профілі для контейнерів
Розділ «Поширені профілі для контейнерів»Заборона запису в кореневу файлову систему
Розділ «Заборона запису в кореневу файлову систему»#include <tunables/global>
profile k8s-readonly flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base>
# Читати все /** r,
# Записувати тільки у конкретні шляхи /tmp/** rw, /var/tmp/** rw, /run/** rw,
# Заборонити запис в інші місця deny /** w,
network,}Заборона мережевого доступу
Розділ «Заборона мережевого доступу»#include <tunables/global>
profile k8s-deny-network flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base>
file,
# Заборонити весь мережевий доступ deny network,}Заборона доступу до чутливих файлів
Розділ «Заборона доступу до чутливих файлів»#include <tunables/global>
profile k8s-deny-sensitive flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base>
file, network,
# Заборонити доступ до чутливих файлів deny /etc/shadow r, deny /etc/gshadow r, deny /etc/sudoers r, deny /etc/sudoers.d/** r, deny /root/** rwx,}Реальні сценарії іспиту
Розділ «Реальні сценарії іспиту»Сценарій 1: Застосування наявного профілю
Розділ «Сценарій 1: Застосування наявного профілю»# Перевірити, чи завантажено профільsudo aa-status | grep my-profile
# Застосувати до Podcat <<EOF | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: test-pod annotations: container.apparmor.security.beta.kubernetes.io/nginx: localhost/my-profilespec: containers: - name: nginx image: nginxEOFСценарій 2: Створення та застосування профілю
Розділ «Сценарій 2: Створення та застосування профілю»# Створити профіль, що забороняє запис у /etcsudo tee /etc/apparmor.d/k8s-deny-etc-write << 'EOF'#include <tunables/global>
profile k8s-deny-etc-write flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base> file, network, deny /etc/** w,}EOF
# Завантажити профільsudo apparmor_parser -r /etc/apparmor.d/k8s-deny-etc-write
# Застосувати до Podcat <<EOF | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: secured-nginx annotations: container.apparmor.security.beta.kubernetes.io/nginx: localhost/k8s-deny-etc-writespec: containers: - name: nginx image: nginxEOF
# Перевіритиkubectl exec secured-nginx -- touch /etc/test# Повинно завершитися невдачею через AppArmorСценарій 3: Налагодження проблем AppArmor
Розділ «Сценарій 3: Налагодження проблем AppArmor»# Перевірити події Podkubectl describe pod secured-pod | grep -i apparmor
# Перевірити, чи завантажено профіль на вузліssh node1 'sudo aa-status | grep k8s'
# Перевірити журнали аудиту на відмовиsudo dmesg | grep -i apparmor | tail -10
# Або перевірити журнал аудитуsudo journalctl -k | grep -i apparmorЧи знали ви?
Розділ «Чи знали ви?»-
Профілі AppArmor повинні бути завантажені на кожному вузлі, де може запуститися Pod. DaemonSet допомагають розповсюджувати профілі.
-
Частина ‘flags=(attach_disconnected,mediate_deleted)’ є необхідною для профілів контейнерів, оскільки контейнери можуть мати від’єднані шляхи та видалені файли.
-
AppArmor є стандартним для Ubuntu/Debian, тоді як SELinux є стандартним для RHEL/CentOS. Іспит CKS використовує Ubuntu, тому фокус на AppArmor.
-
Ви можете генерувати профілі за допомогою
aa-genprofабоaa-logprof, які моніторять поведінку застосунку та створюють профілі на основі спостережуваних дій.
Поширені помилки
Розділ «Поширені помилки»| Помилка | Чому це шкодить | Рішення |
|---|---|---|
| Профіль не завантажено на вузлі | Pod не може запуститися | Завантажте на всі вузли |
| Неправильний формат анотації | Профіль не застосовується | Перевірте точний ключ анотації |
| Відсутні абстракції | Профіль занадто обмежувальний | Включіть базові абстракції |
| Використання ‘unconfined’ | Без захисту | Використовуйте мінімум runtime/default |
| Тестування без режиму скарги | Ламає застосунок | Спочатку тестуйте з aa-complain |
Тест
Розділ «Тест»-
Яка анотація застосовує профіль AppArmor до контейнера?
Відповідь
`container.apparmor.security.beta.kubernetes.io/<ім'я-контейнера>: localhost/<ім'я-профілю>` — ім'я контейнера повинно збігатися з контейнером у специфікації Pod. -
Як завантажити профіль AppArmor на вузлі?
Відповідь
`sudo apparmor_parser -r /etc/apparmor.d/<файл-профілю>` — прапорець -r перезавантажує, якщо вже завантажено. -
Для чого використовується режим скарги (complain)?
Відповідь
Для тестування профілів без блокування. У режимі скарги AppArmor журналює порушення, але дозволяє їх, що дає змогу вдосконалити профіль перед примусовим застосуванням. -
Що відбувається, якщо вказаний профіль AppArmor не існує на вузлі?
Відповідь
Pod не запуститься з помилкою, що вказує на неможливість знайти профіль. Kubelet перевіряє наявність профілю перед запуском контейнера.
Практична вправа
Розділ «Практична вправа»Завдання: Створити та застосувати профіль AppArmor, що забороняє мережевий доступ.
# Крок 1: Перевірити, що AppArmor увімкнено (виконати на вузлі)cat /sys/module/apparmor/parameters/enabled# Повинно вивести: Y
# Крок 2: Створити профільsudo tee /etc/apparmor.d/k8s-deny-network << 'EOF'#include <tunables/global>
profile k8s-deny-network flags=(attach_disconnected,mediate_deleted) { #include <abstractions/base>
# Дозволити файлові операції file,
# Заборонити мережевий доступ deny network,}EOF
# Крок 3: Завантажити профільsudo apparmor_parser -r /etc/apparmor.d/k8s-deny-network
# Крок 4: Переконатися, що він завантаженийsudo aa-status | grep k8s-deny-network
# Крок 5: Створити Pod з профілемcat <<EOF | kubectl apply -f -apiVersion: v1kind: Podmetadata: name: no-network-pod annotations: container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-deny-networkspec: containers: - name: app image: curlimages/curl command: ["sleep", "3600"]EOF
# Крок 6: Дочекатися Podkubectl wait --for=condition=Ready pod/no-network-pod --timeout=60s
# Крок 7: Тестувати, що мережа заблокованаkubectl exec no-network-pod -- curl -s https://kubernetes.io --connect-timeout 5# Повинно завершитися невдачею через заборону мережі AppArmor
# Крок 8: Створити Pod без обмеження для порівнянняkubectl run network-allowed --image=curlimages/curl --rm -it --restart=Never -- \ curl -s https://kubernetes.io -o /dev/null -w "%{http_code}"# Повинно працювати (200)
# Очищенняkubectl delete pod no-network-podКритерії успіху: Pod з профілем AppArmor не може встановлювати мережеві з’єднання.
Підсумок
Розділ «Підсумок»Основи AppArmor:
- Обов’язковий контроль доступу Linux
- Обмеження на рівні програми
- Профілі завантажуються на вузлах
Застосування профілю:
annotations: container.apparmor.security.beta.kubernetes.io/<контейнер>: localhost/<профіль>Поширені правила профілю:
deny /path w,— заборона записуdeny network,— заборона мережіcapability X,— дозвіл можливості
Поради для іспиту:
- Знайте формат анотації
- Практикуйте завантаження профілів
- Розумійте розташування профілів
Наступний модуль
Розділ «Наступний модуль»Модуль 3.2: Профілі Seccomp — Фільтрація системних викликів для контейнерів.