DevSecOps для самых маленьких. 4\n. Харденинг: как надеть незеритовую броню на свой кластер
В прошлый раз мы разобрались с секретами. Теперь следующий слой — харденинг. И тут мне в голову пришла метафора из Minecraft, которая, кажется, объясняет всё лучше любых терминов.
В Minecraft есть несколько уровней брони. Кожаная, железная, золотая, алмазная. Алмазная долго считалась лучшей, пока не добавили незеритовую. И вот в чём фокус: незеритовую броню нельзя скрафтить с нуля. Ты не делаешь её из незерита, как железную из железа. Ты берёшь готовую алмазную броню и улучшаешь её на специальном столе. Для этого нужно найти в аду редкие древние обломки, переплавить их, найти шаблон улучшения в бастионе и соединить всё это вместе.
Харденинг работает точно так же. Ты не переписываешь систему с нуля. Ты берёшь то, что уже работает, и улучшаешь. Закрываешь дыры, убираешь лишнее, делаешь крепче.
Что такое харденинг — это приведение системы к безопасному состоянию. Убрать лишнее, закрыть лишнее, оставить только необходимое.
Звучит просто. Но на практике большинство кластеров по умолчанию настроены так, чтобы было удобно разработчику, а не безопаснику. Контейнеры бегают под root. Образы весят по гигабайту и тащат в себе компиляторы, которых в проде быть не должно. У подов нет лимитов, и один утечный цикл может положить всю ноду. Privileged-режим включён, потому что «так исторически сложилось».
Всё это — алмазная броня без зачарований. Работает, но уязвимо.
Почему дефолт — это плохо
В Kubernetes безопасных настроек по умолчанию почти нет. Pod Security Standards существуют, но их надо включить. NetworkPolicy есть, но по умолчанию весь трафик разрешён. RBAC есть, но cluster-admin выдают направо и налево, потому что «иначе не работает».
Дефолт — это когда ты заходишь в новый кластер и видишь: контейнеры под root, нет лимитов, нет политик, секреты в переменных окружения. И это не потому что кто-то злой. Это потому что так проще запустить.
Харденинг начинается с того, что ты признаёшь: дефолт — это не безопасно. И начинаешь улучшать.
Что конкретно харденить
Первое и самое важное — non-root. Контейнер не должен запускаться от имени root. Если злоумышленник попадёт внутрь, он получит минимум прав. В Kubernetes это настраивается через securityContext.
Второе — read-only filesystem. Контейнеру не нужно писать в свою файловую систему. Если нужно — пусть пишет в volume. Это усложняет жизнь атакующему.
Третье — запрет privileged. Privileged-контейнер — это фактически root на хосте. В проде такого быть не должно, кроме редких системных случаев.
Четвёртое — минимальные образы. Distroless, alpine, scratch. Чем меньше внутри, тем меньше уязвимостей. Компилятор, bash и curl в проде не нужны.
Пятое — capabilities. По умолчанию контейнер получает набор Linux capabilities, которые ему не нужны. Их надо дропать. Оставить только те, без которых никак.
Шестое — Pod Security Standards. Это встроенный механизм Kubernetes, который позволяет задать уровень безопасности для namespace. Есть три уровня: privileged, baseline, restricted. В проде обычно restricted.
Седьмое — resource limits. Не совсем безопасность, но харденинг. Если у пода нет лимитов, один утечный цикл может положить ноду. Лимиты — это про устойчивость.
Восьмое — запрет hostPath, hostNetwork, hostPID. Контейнер не должен видеть хост напрямую, если это не системный под.
И девятое — обновления. Регулярно обновлять зависимости, базовые образы, сам Kubernetes. Старая версия — это известные CVE.
Зачарования для брони
В Minecraft на броню можно наложить зачарования. Защита снижает урон. Прочность увеличивает срок службы. Починка автоматически восстанавливает броню за счёт опыта. Шипы наносят урон атакующему.
В харденинге то же самое. Базовые настройки — это незеритовая броня. А зачарования — это дополнительные политики:
Pod Security Standards уровня restricted. Базовый уровень защиты от всех источников.
Resource limits. Не защищает напрямую, но не даёт системе упасть от перегрузки.
Автоматическое обновление зависимостей. Система сама себя чинит, не дожидаясь, пока кто-то вспомнит про CVE.
Запрет лишних capabilities. Если кто-то пытается сделать то, что ему не положено, — получит отказ.
Инструменты
Open source: kube-bench прогоняет CIS Kubernetes Benchmark по живому кластеру. Kubescape шире — RBAC, образы, posture score, готовые фреймворки NSA и CISA. kubesec анализирует pod-спеки статически. Trivy умеет IaC-сканирование.
Российские решения: Deckhouse Kubernetes Platform сертифицирован ФСТЭК и включает харденинг из коробки. Kaspersky Container Security закрывает контейнерные среды, в реестре. Luntry защищает контейнеры на всём жизненном цикле. PT Container Security от Positive Technologies — ещё один игрок.
Что не входит в харденинг
Важный момент. NetworkPolicy, Cilium, Istio, микросегментация — это отдельный слой. Мы разберём его в следующий раз. В харденинге мы говорим только о самой системе: под, контейнер, нода. Не о связях между ними. Сделал такое разделение целенаправленно, что бы в голове каши не было.
С чего начать
Первое — запустить kube-bench на тестовом кластере. Посмотреть, что он найдёт. Обычно находит много интересного.
Второе — добавить kubesec в CI. Пусть плохие манифесты не доезжают до прода.
Третье — включить Pod Security Standards в namespace. Начать с baseline, потом перейти на restricted.
Четвёртое — убрать root из контейнеров. Если не получается сразу — хотя бы для новых.
Пятое — добавить resource limits. Всем.
Шестое — настроить регулярное обновление базовых образов.
Не пытайтесь сделать всё сразу. Незеритовую броню тоже не добывают за одну ночь. Начните с одного шага.
Главное
Харденинг — это не переписывание системы с нуля. Это улучшение того, что уже есть. Как алмазная броня становится незеритовой: ты не создаёшь новое, ты делаешь существующее крепче.
Без харденинга остальные практики DevSecOps работают вполсилы. Секреты можно спрятать в Vault, но если контейнер бегает под root, толку мало. Микросегментация защитит сеть, но если в поде privileged, атакующий и так дойдёт до хоста.
Начните с non-root. Потом read-only fs. Потом Pod Security. Через месяц ваш кластер будет не узнать.
