«Прячем» секреты от cluster admin

«Прячем» секреты от cluster admin

Vitaliy Likhachev

Вопрос, который вам могут задать на собеседовании, чтобы почеленджить на тему понимания работы механизмов безопасности в k8s и в Linux.

Представьте, что вам нужно обеспечить недоступность секретов приложения для cluster admin. Концептуально это возможно, конечно, идеальной защиты не существует. На то он и cluster admin. Однако защита может быть не только технической, но и юридической, особенно в зарегулированных сферах типа банковской или медицинской. Для этого понадобятся аудит-логи и алерты на них, которые один человек без доп. апрувов просто поменять не сможет.

Приступим к разбору.

Зашифрованный etcd и RBAC на доступ к секретам — это база. Не секрет, что секреты (такая тавтология) хранятся в base64, и cluster admin может заглянуть куда угодно.

Наша задача — сделать процесс доступа сильно сложнее, так, чтобы по аудит-логам (с настроенными алертами на службу безопасности) можно было понять, что cluster admin целенаправленно полез туда, куда не надо.

Проблема: где текут секреты?

Обычно всё ломается на двух этапах:

  • API Server: любой kubectl get secret -o yaml или describe pod вываливает всё содержимое.
  • Runtime: если админ может сделать kubectl exec, он просто посмотрит env или залезет в /proc/1/environ.

Поэтому «не давать exec» — это база RBAC. Но админ всё равно сможет создать под, подменив либо образ, либо cmd, либо что-то ещё, чтобы посмотреть env, даже без exec.

Добавляем паранойи: Vault Agent + execve()

Забудьте про envFrom. Мы будем использовать Vault Agent Injector и фокус с подменой процесса через vault-env.

При этом важно, чтобы либо в Vault так же был настроен аудит, либо Vault был недоступен для управления тем же самым админом.

Секреты вообще не должны попадать в Kubernetes как объекты. Под аутентифицируется в Vault через свой ServiceAccount. Админ может обсмотреться на манифест пода — там будут только аннотации.

Подмена процесса

Это киллер-фича. Мы не прописываем переменные окружения в манифесте Deployment. Мы используем утилиту-враппер (например, vault-env) как ENTRYPOINT.

Как это работает на уровне ядра:

  1. Стартует vault-env. Он лезет в Vault, забирает секреты и кладёт их в свой массив environ.
  2. Далее он делает системный вызов execve("/app/binary", args, envp).
  3. Ядро Linux полностью заменяет образ процесса vault-env вашим приложением, но передаёт ему обогащённый секретами стек окружения напрямую в память.

Итог: kubectl describe pod покажет чистый список переменных. Секреты не проходили через API-сервер, их нет в etcd, и они не светятся в логах.

Помним: аудит и «правило четырёх глаз»

Допустим, админ настойчивый. Он лезет в логи или пытается перехватить запросы.

  • Vault Audit Logs (External): логи Vault должны уходить сразу в изолированный SIEM, к которому у админа куба нет доступа. Любая попытка пода (или того, кто им притворился) достать лишний секрет должна триггерить алерт.
  • Control Groups (rule of two keys): для самых критичных штук (например, ключи расшифровки БД) включаем в Vault control_groups. Даже если под попросит секрет, Vault его не отдаст, пока второй человек (Security Officer) не нажмёт кнопку «Одобрить» у себя. Конечно, это доступно только в enterprise-версии и не подойдёт для автоматической разблокировки, когда Vault неожиданно перезапустится. Но тут уже отдельная история, как делать vault unseal, если всё упало, включая падение кластера Vault.

Добиваем выживших: hardening

Чтобы kubectl exec превратился для админа в тыкву:

  • Distroless/Scratch: выкиньте из образа sh, ls и env. Нет бинарников — нет простого способа посмотреть окружение.
  • Drop Capabilities: сносите CAP_SYS_PTRACE через securityContext. Да и вообще все capabilities дропайте. Без этого даже root внутри контейнера не сможет легко сделать дамп памяти процесса или прочитать чужой /proc/[pid]/environ.
  • Dynamic Credentials: используйте динамические секреты Vault для БД. Пароль живёт 5 секунд и умирает вместе с подом. Даже если админ его украл — через 5 секунд это просто мусор.

Итог

Админ видит пустые конфиги, пустой env в манифестах и заблокированный ptrace. Любая его попытка пошпионить залетает во внешний аудит, который он не может почистить


Ещё больше полезных материалов по K8s на ресурсах:

K8s для junior: t.me/Kubernetes_Minkin

K8s для middle и senior: t.me/Kubernetes_Likhachev

Траблшутер-бот в Телеграм: t.me/simulator_kub_bot

Анонсы мероприятий и вебинаров по K8s: t.me/KubWebBot

Беседа-сообщество по K8s: t.me/K8s_and_you




Report Page