Безопасность по умолчанию: секреты, доступы, соответствие требованиям
Платформенная команда получила задачу от службы безопасности: «закрыть уязвимости в образах». Сделали быстро и правильно, как казалось: сканер в конвейере, блокировка деплоя при находках уровня High и Critical, дашборд с прогрессом.
В первый день сборка упала у тридцати восьми сервисов из сорока одного. Причина — уязвимость в системной библиотеке базового образа, которую нельзя починить со стороны приложения. Через два часа в чат платформы пришёл директор по продукту с вопросом, почему встал релиз. Через четыре часа появилась метка security-exception: true, которая пропускает проверку, — как временное решение на неделю.
Через полгода метку несут 74 % деплоев. Дашборд показывает 91 % покрытия сканированием и ноль незакрытых Critical — потому что всё, что не закрыли, помечено исключением, а исключения в отчёт не попадают. Служба безопасности отчитывается о результате. Платформа получила репутацию тормоза. Реальный уровень защищённости не изменился ни на процент: единственное, что изменилось, — теперь в компании есть общий, всем известный и социально одобренный способ обойти любую проверку.
Это не история про плохой сканер. Это история про то, что безопасность в платформе — это продуктовая работа с теми же законами, что и всё остальное в этом треке. У неё есть пользователи — инженеры продуктовых команд. У пользователей есть альтернатива. Если контроль дороже обхода, будет обход, и вопрос лишь в том, оформят его меткой или сделают молча.
В этой главе — три предметные области, в которых платформа реально может дать больше, чем регламент в вики: секреты и идентичность, доступы, доказательства соответствия. И к каждой — цена: во времени платформенной команды, во времени продуктовых команд и в стоимости владения инструментами.
Почему безопасность в платформе — про принятие, а не про полноту
Служба безопасности и платформа считают разными единицами, и в этом корень большинства конфликтов.
Служба безопасности измеряет покрытие: сколько контролей внедрено, сколько находок закрыто, сколько политик написано. Это её локальный оптимум — и он честно оптимизируется, вплоть до состояния, когда покрытие 100 %, а работать невозможно. Классическая локальная оптимизация, разобранная в systems-thinking: каждый участник улучшает свой показатель, а система в целом деградирует.
Платформа обязана измерять другое — долю потока, который проходит через защищённый путь:
- сколько продовых нагрузок ходит в базу по короткоживущему токену, а не по паролю из конфига;
- сколько деплоев прошло без метки исключения;
- сколько доказательств для аудита собралось автоматически, а не руками накануне.
Разница принципиальная. Контроль, который покрывает 100 % сервисов, но обходится в 74 % случаев, защищает 26 % флота. Контроль, который покрывает 60 % сервисов и не обходится никогда, защищает 60 %. Второй лучше, хотя в отчёте выглядит хуже.
Отсюда рабочее определение, вокруг которого построена вся глава:
Безопасность по умолчанию — это состояние, при котором безопасный вариант оказывается самым дешёвым по времени и когнитивной нагрузке. Не единственным доступным, а самым дешёвым.
«Не единственным» — важная оговорка. Как только безопасный путь становится единственным, он перестаёт быть золотым путём и превращается в забор, а забор порождает подкопы. Про то, как выглядит легальный съезд с пути, разговор будет в разделе про исключения.
Есть и вторая причина, по которой платформа — правильное место для безопасности, и она чисто экономическая. Платформа уже стоит на пути каждого изменения: конвейер, реестр образов, выдача инфраструктуры, приёмка. Добавить контроль в место, через которое поток и так идёт, стоит на порядок дешевле, чем поставить сорок команд перед сорока чек-листами. Это прямое применение точек воздействия: изменение значения по умолчанию — рычаг сильнее, чем добавление правила поверх старого умолчания.
40 наборов скриншотов"] A4 --> A5["Дрейф: через квартал
половина реализаций сгнила"] end subgraph B["Модель «умолчание платформы»"] direction TB B1["Политика в шаблоне,
конвейере, приёмке"] --> B2["Команда получает
её, ничего не делая"] B2 --> B3["1 реализация,
1 место для правки"] B3 --> B4["Аудит: выгрузка
из одной системы"] B4 --> B5["Дрейф виден как
метрика: доля на версии"] end A5 -.->|"цена растёт линейно
по числу команд"| C["Стоимость безопасности"] B5 -.->|"цена почти не зависит
от числа команд"| C
Именно этот график расхождения — единственный честный аргумент за платформенную безопасность. Он же говорит, когда её строить не надо: при пяти командах линия «чек-лист» дешевле, и никакая архитектурная красота этого не перевешивает. К расчёту вернёмся отдельно.
Секреты: проблема не в шифровании, а в числе живых копий
Начнём с первых принципов. Секрет — это данные, обладание которыми даёт доступ. Всё, что о нём важно, следует из одного свойства: секрет копируется без следа. Вы не узнаете, что копия сделана, и не сможете её найти.
Из этого следуют два вывода, которые переворачивают привычную постановку задачи.
Вывод первый: шифрование хранилища решает наименее важную часть проблемы. Секрет в покое почти никогда не утекает — утекает копия в пути: в переменной окружения CI, в логе сборки, в слое образа, в дампе памяти, в тикете, в чате, в .env на ноутбуке уволившегося подрядчика. Хранилище с шифрованием нужно, но это гигиена, а не решение.
Вывод второй: главная метрика секрета — не «где лежит», а «сколько стоит отозвать». Если отзыв стоит недель координации, ротации не будет. Не потому что люди ленивы, а потому что цена реальна и её никто не оплатит.
Лестница зрелости: от пароля в конфиге до отсутствия секрета
| Ступень | Как выглядит | Время жизни | Цена отзыва | Что происходит при утечке |
|---|---|---|---|---|
| 0. Секрет в репозитории | пароль в config.yaml |
вечность | недели | утечка навсегда, история git её хранит |
| 1. Секрет в переменных CI | вписан руками в настройки | годы | дни | доступен всем, кто может запустить job |
| 2. Хранилище с ручной выдачей | Vault, инженер копирует значение | месяцы | дни | копия уже разошлась, отзыв неполный |
| 3. Хранилище с автоподстановкой | оператор кладёт в под при старте | недели | часы | окно ограничено сроком жизни секрета |
| 4. Короткоживущий токен по идентичности | обмен идентичности на токен на 15 мин | минуты | минуты | утечка есть, доступа нет |
| 5. Секрета не существует | mTLS-сертификат, выданный автоматически | минуты | минуты | нечего красть в статике |
Ступени 0–2 отличаются от 3–5 качественно, а не количественно. На ступенях 0–2 секрет — это значение, которым владеет человек. На ступенях 3–5 это производная от идентичности, и человек его не видит вовсе.
Практический перевод: цель платформы — не «завести Vault», а убрать долгоживущие ключи с путей, где ходит поток. Порядок работ, который окупается быстрее всего:
- Убить долгоживущие облачные ключи в CI. Это одна конфигурация и самая большая разовая победа. GitHub Actions, GitLab CI и большинство систем умеют выдавать OIDC-токен, который облако обменивает на временную роль (документация GitHub про OIDC). После этого в настройках репозиториев не остаётся ни одного ключа доступа к облаку — самой опасной категории.
- Дать нагрузкам идентичность. В Kubernetes это service account, привязанный к облачной роли; в общем виде — SPIFFE/SPIRE с проверяемым идентификатором нагрузки (spiffe.io).
- Перевести на неё базы и внутренние вызовы. Большинство managed-СУБД умеют аутентификацию по IAM-токену; внутренние вызовы — по mTLS.
- Оставшееся — в хранилище с автоподстановкой, без ручного копирования.
# Обмен идентичности рабочей нагрузки на короткоживущий доступ к базе.
# Ключевая деталь: в коде нет ни пароля, ни пути к файлу с паролем —
# есть только имя роли и утверждение о том, кто мы такие.
import time
import boto3
class DbCredentials:
"""Токен живёт 15 минут; обновляем заранее, чтобы не ловить отказ в пике."""
REFRESH_MARGIN_SEC = 120 # обновляем за 2 минуты до истечения
def __init__(self, host: str, port: int, user: str, region: str):
self._host, self._port, self._user = host, port, user
self._client = boto3.client("rds", region_name=region)
self._token: str | None = None
self._expires_at: float = 0.0
def token(self) -> str:
now = time.monotonic()
if self._token is None or now > self._expires_at - self.REFRESH_MARGIN_SEC:
# Вызов подписывается идентичностью, которую среда выдала процессу
# (в Kubernetes — проецируемый service account token).
# Секрета, который можно было бы украсть из образа, здесь нет.
self._token = self._client.generate_db_auth_token(
DBHostname=self._host, Port=self._port, DBUsername=self._user
)
self._expires_at = now + 15 * 60
return self._token
Обратите внимание на то, чего в этом коде нет: чтения файла, переменной окружения, обращения к внешнему хранилищу секретов. Ступень 4 убирает не только секрет, но и целый класс кода вокруг него — и вместе с ним класс инцидентов «сервис не поднялся, потому что не смог достучаться до хранилища».
Жизненный цикл секрета и почему «ротация раз в 90 дней» — плохая цель
Календарная ротация — это ритуал, а не контроль. Она не отвечает на вопрос, который задают в момент инцидента: за сколько мы сможем отозвать и заменить конкретный ключ прямо сейчас?
Правильная величина — время до полного отзыва (по сути MTTR для секрета). Её надо измерять учением, а не декларировать: выбрать один продовый секрет, объявить его скомпрометированным и провести полную замену, засекая время. Это тот же жанр, что и учения из SRE, и результат первого прогона обычно отрезвляет: там, где ожидали час, получается три дня, и половина времени уходит на поиск владельца.
Два состояния в этой схеме обычно отсутствуют в реальных системах, и оба дорого стоят.
«Осиротел». Секрет, у которого нет живого владельца, — это ресурс, который никто не решится отозвать. Лечится связкой с каталогом владения из главы про инфраструктуру как API: у секрета обязано быть поле владельца, ссылающееся на живую группу, и автоматическая проверка, что группа существует и в ней есть люди.
«Подозрение утечки». Когда сканер находит ключ в коммите, типовая реакция — переписать историю и закрыть тикет. Это неверно: любой секрет, попавший в репозиторий, считается скомпрометированным независимо от того, удалили вы коммит или нет. Форки, зеркала, кэши CI, локальные клоны — всё это копии. Единственный корректный сценарий — ротация. Платформа обязана сделать этот сценарий дешёвым: кнопка «ротировать» рядом с находкой, иначе процесс не выполнится ни разу.
Технически стоит ставить два барьера, а не один: блокировка push на стороне хостинга (у GitHub это push protection) — она ловит до попадания в историю, и периодический скан всей истории (gitleaks) — он ловит то, что уже там. Первый барьер лучше, потому что даёт обратную связь за секунды и не требует ротации. Детали устройства самих хранилищ разобраны в треке безопасности: управление секретами.
Цена владения хранилищем секретов
Тут пора назвать цифры, потому что «поставьте Vault» звучит как одна задача, а является постоянным обязательством.
Самостоятельно развёрнутый HashiCorp Vault в отказоустойчивой конфигурации — это: кворум узлов и понимание Raft, процедура распечатывания (unseal) и хранение ключей от неё вне самого Vault, резервное копирование с проверкой восстановления, обновления версий без простоя, аудит-лог с ротацией, интеграция с каждым потребителем, отдельная строка в дежурстве. Vault в проде — компонент уровня «упал он — не деплоится и не стартует ничего», то есть его SLO обязано быть строже, чем у сервисов, которые от него зависят (про SLO зависимостей). Реалистичная оценка: 0,3–0,5 постоянного человека на поддержание плюс разовые 1–2 месяца на внедрение.
Managed-альтернатива (secret manager облака) снимает почти всю эту работу и стоит денег за операцию чтения — что тоже надо посчитать, потому что наивная реализация с чтением секрета на каждый запрос выдаёт неожиданный счёт. Промежуточный вариант — External Secrets Operator, который синхронизирует секреты из облачного хранилища в кластер и снимает с приложений знание о хранилище.
Правило выбора простое и скучное: если у вас нет требования, которое managed-хранилище не закрывает, берите managed. Своё разворачивают, когда есть жёсткое требование к размещению данных, работа в нескольких облаках сразу или потребность в динамических секретах для СУБД, которых нет у провайдера. Это ровно тот случай, где применим Choose Boring Technology.
Доступы: три разных вопроса, которые постоянно смешивают
Слово «доступ» покрывает три задачи с несовпадающими требованиями. Смешение — источник самых уродливых платформенных абстракций.
| Доступ нагрузки | Доступ человека | Доступ самой платформы | |
|---|---|---|---|
| Кто субъект | сервис, job | инженер, аналитик | контроллеры платформы |
| Частота | миллионы раз в день | десятки раз в неделю | постоянно |
| Требование | нулевая задержка, без участия человека | быстро выдать, обязательно отозвать | минимальные права, максимальный аудит |
| Основной риск | избыточные права навсегда | забытый доступ у уволенного | компрометация = компрометация всего |
| Механизм | идентичность нагрузки, mTLS | SSO, короткая сессия, JIT | отдельные роли на контроллер, а не одна root-роль |
Третья колонка — та, о которой забывают. Платформа по устройству обладает правами создавать инфраструктуру и раздавать доступы, то есть является самой привлекательной целью в компании. Минимум, который здесь обязателен: у каждого контроллера своя роль с правами только на свой класс ресурсов, права платформы на продовые данные отсутствуют (создавать базу — да, читать из неё — нет), и все действия платформы от чужого имени логируются с указанием инициатора. Подробный разбор моделей авторизации — в security.
Наименьшие привилегии как процесс, а не как состояние
Написать минимальную политику доступа заранее невозможно: никто не знает полного списка вызовов, которые сервису понадобятся. Поэтому на практике первая версия политики всегда содержит "*", и там же навсегда остаётся.
Рабочий выход — выводить политику из наблюдений, а не из воображения:
- Сервис стартует с широкой политикой, помеченной как временная, со сроком.
- Платформа собирает фактически использованные действия (в AWS это Access Advisor и генерация политики по журналам).
- Через месяц наблюдений платформа сама открывает пул-реквест с суженной политикой и отчётом «за 30 дней использовано 7 действий из 240 разрешённых».
- Команда либо сливает PR, либо добавляет обоснование — и то и другое занимает минуты.
Именно так это работает у Netflix: их инструменты Aardvark и RepoKid автоматически урезают неиспользуемые права в ролях. Ключевое в этом подходе — работу делает платформа, а команде остаётся решение. Обратный порядок (платформа заводит тикет «сузьте свои права») даёт нулевой результат, потому что у команды нет ни данных, ни мотива.
Доступ человека в прод: JIT и аварийный доступ
Постоянный доступ инженера к проду — это долгоживущий секрет в человеческой форме, со всеми теми же свойствами. Замена — выдача по требованию с коротким сроком.
причина: разбор INC-4417 P->>C: инженер входит в команду-владельца orders? C-->>P: да, роль developer Note over P: правило известно заранее:
чтение своего сервиса — автоодобрение,
запись или чужой сервис — второй человек P->>A: выдать роль db-reader на 60 минут A-->>I: сессия открыта, обратный отсчёт виден P->>J: кто, что, зачем, на сколько, по какому тикету I->>S: работа под записываемой сессией Note over S,J: по истечении срока доступ снимается сам,
отзывать вручную нечего P-->>I: за 5 минут до конца: продлить с указанием причины?
Три детали делают эту схему рабочей, и без любой из них она не взлетит.
Скорость важнее строгости. Если выдача занимает больше 2–3 минут, инженеры добудут постоянный доступ — через тикет, через знакомого, через сервисную учётку с паролем в чате. Автоодобрение для доступа на чтение к своему сервису — не послабление, а условие того, что схемой будут пользоваться.
Аварийный доступ (break-glass) обязателен и обязан быть быстрым. В три часа ночи при лежащем проде дежурный не будет ждать второго одобряющего. Правильная конструкция: аварийная роль выдаётся мгновенно и без одобрения, но её использование поднимает громкий сигнал, пишет полную сессию и автоматически создаёт задачу на разбор. Разбор — не наказание, а вопрос «почему штатного пути не хватило»; каждое использование break-glass — это баг в платформе. Тон разговора здесь ровно такой же, как в постмортемах: ищем причину в системе, а не виноватого.
Отзыв при уходе человека обязан быть в одном месте. Единственный надёжный вариант — все доступы производны от членства в группе в каталоге сотрудников; удаление человека из каталога снимает всё. Если хоть один доступ выдан «напрямую этому человеку», у вас в компании навсегда останется набор неизвестных живых доступов.
Инструментов для записи сессий и брокеринга доступа хватает (Teleport, боры доступа облаков, собственный SSH-CA). Все они стоят денег и требуют обслуживания; на масштабе меньше пары десятков инженеров дешевле обходится связка «SSO + короткие роли облака + журнал», без отдельного продукта.
Соответствие требованиям: доказательства как побочный продукт
Здесь платформенные команды теряют больше всего времени зря — потому что неправильно понимают вопрос.
Аудитор не спрашивает «у вас безопасно?». Он спрашивает: «покажите, что заявленный контроль работал непрерывно в течение периода, и дайте выборку доказательств». Ключевые слова — «непрерывно» и «доказательства». Доказательство — это артефакт с меткой времени, субъектом и содержанием: запись в журнале, подписанный отчёт конвейера, история одобрений пул-реквеста.
Отсюда следует главное утверждение раздела: платформа — самый дешёвый производитель доказательств в компании, потому что она и так стоит на пути потока. Один общий конвейер даёт доказательство «код прошёл ревью и тесты перед выкладкой» сразу для всех сорока команд, автоматически и без единого интервью. Сорок разных конвейеров дают сорок интервью и сорок папок со скриншотами.
| Типовой контроль | Где реализован в платформе | Что становится доказательством |
|---|---|---|
| Изменения проходят ревью | защита ветки, обязательное одобрение | история PR: автор, ревьюер, время |
| Разделение обязанностей | автор PR не может его одобрить | тот же журнал; выкладку делает автоматика, а не человек |
| В прод попадает только собранное в CI | приёмка требует подписи образа | подпись cosign и отчёт о происхождении |
| Известен состав ПО | генерация SBOM в конвейере | SBOM, привязанный к цифровому отпечатку образа |
| Доступ по принципу минимальных прав | роли из каталога владения | выгрузка «кто к чему имел доступ» на любую дату |
| Доступ отзывается при уходе | производность от каталога сотрудников | журнал синхронизации |
| Данные шифруются при передаче и хранении | mTLS по умолчанию, шифрование томов | конфигурация в git плюс проверка на приёмке |
| Уязвимости устраняются в срок | конвейер обновления зависимостей | распределение времени от появления CVE до выката |
| Действия в проде журналируются | брокер доступа, аудит облака | журнал сессий |
Практический вывод, который экономит кварталы: не стройте «портал соответствия», в который люди руками загружают скриншоты. Это самый частый вид платформенного продукта, которым не пользуются: он не даёт пользователю ничего, а требует работы. Если доказательство нельзя собрать автоматически из системы, которая и так работает, — вопрос не в портале, а в том, что контроль на самом деле не реализован.
Про сами стандарты стоит знать ровно одно: они говорят о процессе и доказательствах, а не о технологиях. Ни SOC 2, ни ISO/IEC 27001 не требуют конкретного инструмента; PCI DSS более предметен, а GDPR и 152-ФЗ добавляют требования к обработке персональных данных и местам их хранения — там начинаются архитектурные ограничения, которые платформа обязана уметь выражать (например, «эти данные не выходят из региона» как политика, проверяемая на приёмке). Содержательный разбор — в security. Полезные инженерные ориентиры, на которые можно опереться, не изобретая свой список: NIST SSDF (SP 800-218), SLSA, OWASP ASVS, CIS Benchmarks.
И честная оговорка про мотив. Часто настоящая причина заниматься соответствием — не риск, а продажи: без отчёта SOC 2 не подписывается контракт с крупным клиентом. Это нормальный, измеримый бизнес-аргумент, и его надо называть вслух. Он же задаёт правильный объём работ: закрыть требования аудита, а не построить идеальную безопасность.
Точки контроля: где ставить проверку и во что она обходится
У любого контроля есть место установки, и от места зависят три вещи: задержка обратной связи, цена исправления и вероятность того, что контроль обойдут.
Правило одно: контроль ставится в самой левой точке, где его можно проверить детерминированно. Правее — только то, что левее в принципе не проверяется. Проверка «образ подписан» невозможна в редакторе, потому что образа ещё нет, — ей место на приёмке. Проверка «в манифесте нет привилегированного контейнера» прекрасно делается в редакторе схемой и в PR политикой; выносить её только на приёмку — значит специально ронять деплой в момент, когда команда уже под давлением срока.
Когда контроль имеет право блокировать
Блокирующая проверка — это обещание пользователю. Нарушенное обещание стоит доверия, которое возвращается кварталами. Критериев права на блокировку три, и нужны все:
- Детерминированность. Одинаковый вход даёт одинаковый результат. Проверка, зависящая от внешней базы уязвимостей, которая обновилась ночью, недетерминирована: вчера собиралось, сегодня нет, код не менялся.
- Действие в сообщении. Отказ обязан содержать: что нарушено, где именно (файл, строка), как починить, и ссылку на исключение, если починить нельзя. «Policy violation: PSP-0042» — это не сообщение, это оскорбление.
- Низкий уровень ложных срабатываний. Порог здесь жёстче, чем кажется: при 5 % ложных срабатываний и десяти проверках на деплой каждый второй деплой ловит ложный отказ, и через месяц проверкам перестают верить в принципе.
Не проходящее по критериям остаётся предупреждением и метрикой. Это не поражение: метрика с именем владельца работает лучше блокировки без него, потому что попадает в бэклог, а не в обход.
Отдельно про верхний правый угол — «CVE Critical в базовом образе». Это ровно тот случай из начала главы. Цена пропуска высокая, но ложных и неустранимых срабатываний столько, что блокировка не работает. Рабочее решение не «блокировать» и не «забить», а изменить умолчание: платформа сама поставляет и обновляет базовые образы, сама открывает пул-реквесты с обновлением, и тогда проверка ловит уже единицы случаев, а не тридцать восемь сервисов сразу.
Как вводить новую политику, не устроив забастовку
Мгновенное включение блокировки — самый надёжный способ получить метку security-exception на 74 % деплоев. Работает поэтапная раскатка с публичным графиком, ровно как в главе про миграции.
Что здесь принципиально:
- Отчёт до включения. Вы обязаны знать список затронутых сервисов и команд до того, как что-то сломается. Если такого отчёта нет — вы не готовы к раскатке.
- Платформа чинит большинство случаев сама. Автоматический PR с исправлением превращает «сделайте работу» в «нажмите слить». Это то самое различие между продуктом и налогом, которое проходит через весь трек.
- Блокировка сначала для новых. Новый сервис ничего не ломает, а поток новых сервисов постепенно сдвигает распределение.
- Исключения со сроком и владельцем. Не «метка в конфиге», а запись в реестре: сервис, причина, кто разрешил, до какой даты, ссылка на задачу по устранению. Автопродление запрещено; истечение срока создаёт задачу. Пустой реестр исключений — не признак порядка, а признак того, что исключения оформляют мимо вас.
Типовые провалы
Обёртка над IAM облака, которая только мешает
Платформа заводит свой формат описания прав и транслирует его в политики облака. Мотив понятен: «спрятать сложность IAM». Результат: чтобы отладить отказ в доступе, инженер обязан понимать и IAM, и вашу схему, и правила трансляции между ними. Сообщение об ошибке приходит от облака в терминах облака, а написано было в терминах платформы — сопоставить их некому.
Признак того, что вы в этой ловушке: на каждое обращение в поддержку платформы вы отвечаете переводом с языка облака на свой язык. Это чистая косвенность, за которую платят чужим временем; подробный критерий — в главе про абстракции.
Обёртка оправдана в двух случаях. Первый: вы даёте не другой синтаксис, а другой уровень — «сервис A читает из очереди B», из чего выводятся все нужные политики. Второй: вам реально нужна переносимость между облаками, и это подтверждено решением, а не мечтой. Во всех остальных случаях лучше дать готовые именованные наборы прав на родном языке облака и хороший инструмент диагностики отказов.
Портал соответствия, которым никто не пользуется
Двести контролей в вики, красивый дашборд, ручная загрузка подтверждений раз в квартал. Пользуются им два человека из службы безопасности перед аудитом. Инженеры не открывали его ни разу.
Диагноз простой: инструмент не даёт пользователю ничего, что нужно ему самому. Работающая альтернатива — показывать состояние соответствия там, где инженер и так находится: в пул-реквесте, в описании сервиса, в CLI. И собирать доказательства из систем, а не из людей. Это в чистом виде платформа как продукт: если никто не пользуется, продукта нет, независимо от вложенных усилий.
Одна абстракция поверх трёх разных потребностей
Самый дорогой провал в этой главе, потому что он выглядит как хорошая инженерия. Платформа делает единый интерфейс secrets.get("имя") и накрывает им три вещи:
| Пароль к внешнему API | Сертификат mTLS | Ключ подписи артефактов | |
|---|---|---|---|
| Время жизни | месяцы, ротация по договорённости с партнёром | часы, ротация автоматическая | годы, ротация — событие |
| Кто выдаёт | человек, вручную, вне вашего контура | внутренний удостоверяющий центр | церемония с несколькими участниками |
| Как используется | при каждом вызове | при установке соединения | редко, при выпуске релиза |
| Требование к аудиту | факт чтения | не нужен, объём слишком велик | каждое использование, поимённо |
| Где обязан жить | хранилище | память процесса, на диск не пишется | HSM или keyless-схема |
Общего у них — только слово «секрет». Единый интерфейс либо опускается до наименьшего общего знаменателя (и тогда для сертификатов не хватает автоматической ротации, а для ключа подписи — аудита каждого использования), либо обрастает флагами до состояния, в котором его невозможно ни объяснить, ни поменять. Правильный ответ — три разных механизма с честными именами: хранилище секретов, cert-manager или его аналог, keyless-подпись через Sigstore. Три простых механизма дешевле одного универсального.
Безопасность как налог: политику пишет один, платят другие
Служба безопасности выпускает требование. Платформа реализует. Продуктовые команды тратят на приведение в соответствие по несколько дней каждая. Ни у кого нет строки «сколько это стоило», потому что затраты распределены по сорока бэклогам и не видны ни в одном отчёте.
Лекарство административное, а не техническое: у каждого требования обязана быть оценка совокупной стоимости внедрения до принятия решения. Формулировка для разговора: «это требование стоит примерно 34 команды × 6 часов = 204 часа плюс 3 недели платформенной работы; какой риск оно снимает и есть ли вариант дешевле?». Часто выясняется, что вариант дешевле есть — обычно это изменение умолчания вместо добавления проверки. Про то, как ведут такие разговоры и почему граница ответственности команд здесь ключевая, — в engineering-leadership.
Культ инструментов
Ни один инструмент из этой области не бесплатен, и цену стоит называть вслух.
- Движки политик (OPA Gatekeeper, Kyverno). Дают декларативные правила на приёмке. Цена: у OPA — собственный язык Rego с непривычной моделью вычисления и нетривиальной отладкой; у обоих — вебхук в критическом пути кластера. Вебхук с
failurePolicy: Failпри недоступности останавливает создание подов во всём кластере — это реальный способ устроить полный отказ платформы политикой. Обязательны: исключение системных пространств имён, запас реплик, режимIgnoreна время раскатки, тесты политик в CI (документация Kubernetes про admission-вебхуки). Прежде чем ставить движок, проверьте, хватает ли встроенных Pod Security Standards — часто хватает. - Vault. Разобран выше: 0,3–0,5 человека постоянно, критичность выше, чем у сервисов-потребителей.
- Service mesh ради mTLS. Даёт шифрование и идентичность между сервисами без изменения кода. Цена: sidecar у каждого пода (память и задержка), собственный слой отказов, отдельная экспертиза, болезненные обновления. Если mTLS нужен только на периметре или между тремя сервисами, mesh — избыточен.
- Сканеры. Полезны; вредны, когда включены на блокировку без работы с базовыми образами и без автопатчей.
- Backstage и порталы. Витрина не создаёт безопасности. Если контроль не реализован в конвейере и на приёмке, красивая карточка в каталоге показывает статус несуществующего контроля.
Общий принцип, который стоит держать при выборе: инструмент решает задачу «как выразить правило», а не задачу «как сделать так, чтобы правило соблюдали». Вторая задача — продуктовая, и никакой инструмент её за вас не решит.
Сколько это стоит и когда окупается
Платформенная команда не пишет продукт. Значит, её работа обязана возвращаться сэкономленным временем других — или снятым риском, выраженным в деньгах. Посчитаем честно, включая неприятную часть.
Возьмём компанию: 40 продуктовых команд, около 200 инженеров. Экономия на одной команде в год при работающем платформенном контуре безопасности:
| Статья | Без платформы, ч/год на команду | С платформой | Экономия |
|---|---|---|---|
| Возня с секретами и доступами | 18 | 4 | 14 |
| Подготовка к аудиту (интервью, выгрузки, скриншоты) | 8 | 1 | 7 |
| Кампании массового обновления (2 в год) | 12 | 3 | 9 |
| Ожидание доступа при инцидентах | 6 | 1 | 5 |
| Итого | 44 | 9 | 35 |
40 команд × 35 ч = 1400 часов в год.
Теперь цена. Платформенный контур безопасности — это примерно 1,2 постоянного человека (выдача идентичности, хранилище, политики, автопатчи, поддержка) ≈ 1900 рабочих часов, плюс лицензии и инфраструктура в эквиваленте ещё 0,3 человека ≈ 480 часов. Итого около 2400 часов.
1400 меньше 2400. Экономия на рутине покрывает примерно 58 % затрат, и на этом месте надо остановиться и сказать вслух неприятное: если считать только сэкономленную рутину, платформенная безопасность обычно не окупается. Это отличает её от конвейера или окружений, где счёт сходится на прямой экономии.
Остаток закрывают три слагаемых, и их надо считать явно, а не подразумевать.
Ожидаемый ущерб. Вероятность серьёзного инцидента с утечкой долгоживущего ключа — величина, которую можно оценить по собственной истории и по отраслевым данным. Пусть 15 % в год. Стоимость такого инцидента для компании этого размера — расследование, тотальная ротация, простой, юридическая работа, отчёт клиентам — эквивалент 2500–4000 часов. Ожидаемая величина: 0,15 × 3000 ≈ 450 часов в год, и она снижается кратно при переходе на короткоживущие доступы.
Скорость массового обновления. Это, пожалуй, главный продукт платформенной безопасности. Когда выходит уязвимость уровня Log4Shell (предупреждение CISA по CVE-2021-44228), вопрос стоит так: за сколько вы обновите 95 % флота? Компания с общими базовыми образами и автопатчами делает это за дни; компания с сорока своими сборками — за недели, при этом инженеры работают ночами, а окно эксплуатации открыто всё это время. Разница и в прямых часах, и в вероятности ущерба.
Возможность продавать. Отчёт SOC 2 или аналог как условие сделки — это не «безопасность», это выручка. Если такой контракт есть, он один закрывает весь расчёт, и тогда объём работ надо определять от требований аудита, а не от идеала.
С учётом всех слагаемых картина обычно сходится в диапазоне 25–40 команд. Ниже — не сходится, и это не повод «внедрять на вырост».
Когда не строить. 5 команд, 25 инженеров, один аудит в год. Тут выигрывает скучный набор: SSO с обязательным вторым фактором, managed secret manager облака, OIDC-федерация вместо ключей в CI, включённая защита от push с секретом, одна страница правил и раз в квартал общая ревизия доступов на час. Совокупно — примерно 0,2 человека, покрывает подавляющее большинство реального риска и не создаёт ни одного нового компонента, который может упасть. Это полностью соответствует логике последней главы трека.
Что измерять
Метрики этой главы делятся на две группы, и путать их нельзя.
Метрики принятия — отвечают на вопрос «пользуются ли безопасным путём»:
| Метрика | Как считать | Целевое поведение |
|---|---|---|
| Доля нагрузок без долгоживущих ключей | по инвентарю секретов и ролей | главная метрика; растёт медленно, падает при каждом новом легаси |
| Доля деплоев с меткой исключения | из журнала конвейера | больше 5 % — контроль не работает, а имитируется |
| Число активных исключений и медианный возраст | из реестра | возраст важнее числа: старые исключения — это отказ от контроля |
| Доля доступов в прод, выданных по требованию | против постоянных | постоянные доступы обязаны стремиться к нулю |
| Использование break-glass | случаев в месяц | не ноль (иначе им побоятся пользоваться) и не десятки |
| Доля доказательств, собранных автоматически | из подготовки к аудиту | ниже 70 % — вы будете тратить недели перед каждым аудитом |
Метрики результата — отвечают на вопрос «стало ли безопаснее»:
| Метрика | Как считать | Почему важна |
|---|---|---|
| Время до полного отзыва секрета | учением, не оценкой | реальная готовность к инциденту |
| Время от выхода CVE до 95 % обновлённого флота | по инвентарю версий | главный продукт платформенной безопасности |
| Доля секретов старше 12 месяцев | по метаданным хранилища | прокси для «ротация не работает» |
| Число доступов у уволившихся спустя сутки | сверкой с каталогом сотрудников | любое ненулевое значение — дефект процесса |
| Медианное число разрешённых действий на роль против использованных | из журналов | показывает, движетесь ли вы к минимальным правам |
| Доля сервисов с известным владельцем | из каталога | без владельца не работает ни один контроль |
Отдельно стоит смотреть на поток обращений в поддержку с формулировкой «не понял, почему не пустило». Это лучший ранний индикатор того, что контроль скоро начнут обходить: непонятный отказ рождает не исправление, а поиск обхода. Про то, как собирать такие сигналы честно, — в главе про опыт разработчика.
План на квартал, если начинать с нуля
Порядок здесь не произвольный: каждый следующий шаг опирается на предыдущий, и первые три дают львиную долю эффекта.
- Инвентарь и владение (2 недели). Список продовых нагрузок, у каждой — живая группа-владелец. Без этого не работает ничего дальше. Побочный результат: вы найдёте сервисы, о которых никто не помнил.
- Убить облачные ключи в CI (2 недели). OIDC-федерация вместо статических ключей доступа. Самая большая разовая победа за самые скромные деньги.
- Защита от push с секретом плюс скан истории (1 неделя). Плюс написанный и опробованный сценарий ротации при находке.
- Идентичность нагрузок и первый сервис на короткоживущем доступе к базе (3–4 недели). Один сервис целиком, до конца, с честным замером трудозатрат — это ваш образец и ваша оценка для остальных.
- Базовые правила приёмки в режиме предупреждения (2 недели). Пять-шесть правил, не пятьдесят. Отчёт «кого затронет» публикуется сразу.
- Автосбор доказательств (2 недели). Выгрузка по трём-четырём контролям, которые аудитор спросит наверняка.
- Только потом — движок политик, свой портал, mesh и всё остальное, что стоит постоянных людей.
Пункты 1–3 занимают около пяти недель и снимают, по опыту, большую часть реального риска. Пункты 4–6 — это уже платформа. Пункт 7 требует ответа на вопрос про окупаемость из предыдущего раздела.
Мини-итог
- У безопасности в платформе те же законы, что у остальной платформы: есть пользователи, есть альтернатива, и контроль дороже обхода будет обойдён. Метрика — доля потока через защищённый путь, а не число внедрённых контролей.
- Проблема секрета — не шифрование, а количество живых копий и цена отзыва. Лестница ведёт от «значения, которым владеет человек» к «производной от идентичности»; ступени 4–5 меняют природу риска, а не его величину.
- Календарная ротация — ритуал. Осмысленная величина — время до полного отзыва, и её надо измерять учением. Секрет, попавший в репозиторий, скомпрометирован независимо от переписывания истории.
- «Доступ» — это три разные задачи: нагрузки, человека и самой платформы. У платформы самые опасные права в компании, и её собственная модель доступа обязана быть строже всех прочих.
- Минимальные привилегии достигаются наблюдением и автоматическим PR от платформы, а не тикетом «сузьте свои права».
- Аварийный доступ обязателен, обязан быть мгновенным и обязан вызывать разбор, а не наказание. Каждое его использование — баг в платформе.
- Соответствие требованиям — это доказательства с меткой времени. Платформа дёшево производит их как побочный продукт; портал с ручной загрузкой скриншотов не производит ничего.
- Контроль ставится в самой левой точке, где проверяется детерминированно. Право блокировать даётся только при детерминированности, действии в сообщении и низком уровне ложных срабатываний; остальное — метрика с владельцем.
- Новая политика раскатывается этапами: наблюдение, отчёт «кого затронет», автопатч от платформы, блокировка для новых, потом для всех. Исключения — со сроком, владельцем и задачей.
- На одной сэкономленной рутине безопасность в платформе обычно не окупается. Считать надо вместе с ожидаемым ущербом, скоростью массового обновления флота и возможностью продавать. Точка окупаемости — около 25–40 команд; ниже дешевле скучный набор из SSO, managed-хранилища и федерации без единого нового компонента.
Источники
- H. Adkins, B. Beyer, P. Blankinship, P. Lewandowski, A. Oprea, A. Stubblefield. Building Secure and Reliable Systems, O’Reilly, 2020 — доступна бесплатно; главы про наименьшие привилегии, аварийный доступ и восстановление особенно применимы к платформам.
- NIST. SP 800-207 Zero Trust Architecture, SP 800-218 Secure Software Development Framework.
- Google. BeyondCorp: A New Approach to Enterprise Security, BeyondProd — доступ человека и доступ нагрузки как две разные задачи.
- SPIFFE и SPIRE — переносимая идентичность рабочей нагрузки. SLSA, Sigstore — происхождение и подпись артефактов.
- GitHub. Security hardening with OpenID Connect, push protection. gitleaks.
- Netflix. Aardvark и RepoKid — автоматическое сужение прав по наблюдениям. Scaling Appsec at Netflix — безопасность как «мощёная дорога», а не как ворота.
- Kubernetes. Pod Security Standards, admission-вебхуки, шифрование данных в etcd. Kyverno, OPA Gatekeeper, cert-manager, External Secrets Operator.
- OWASP. Application Security Verification Standard. CIS. Benchmarks. CISA. Руководство по CVE-2021-44228.
- CNCF TAG App Delivery. Platforms White Paper. DORA Research 2024 — про неоднозначное влияние платформ на скорость поставки. D. McKinley. Choose Boring Technology.
Что дальше
Безопасность оказалась не техническим слоем, а продуктовым: она работает ровно настолько, насколько безопасный путь дешевле обхода, и её ценность приходится доказывать числами, а не пугалками. Ровно та же логика ждёт нас в разговоре о деньгах — с одним отличием: там счёт видит бухгалтерия, а значит, разговор начнётся сам, независимо от того, готовы вы к нему или нет. Платформа тратит чужой бюджет, показывает его командам и обязана уметь объяснить, за что именно.
Стоимость: учёт расходов, лимиты и разговор с командами о деньгах