← Журнал

Передавать секреты, не компрометируя их

"Ключи API, доступы к базам данных, сертификаты: практики передачи секретов между командами, подрядчиками и клиентами так, чтобы не найти их в истории три года спустя."

БезопасностьСекретыКомандные практикиКомплаенс

Лучший переданный секрет тот, который не передавали

Каждый проект начинается с одного и того же ритуала: «пришли доступы?». И каждая команда импровизирует ответ, чаще всего неверный. Пароль в письме, ключ API в канале Slack, файл .env во вложении: секрет только что покинул всякий периметр контроля, навсегда.

Прежде чем искать канал получше, задайте главный вопрос: должен ли этот секрет вообще существовать в такой форме? Механизмы федеративной идентичности (OIDC между CI и облаком, роли IAM, идентичности рабочих нагрузок) заменяют статический секрет эфемерным доказательством личности. Нечего передавать, нечему утекать, нечего ротировать. Когда такая возможность есть, она побеждает: остальная часть статьи касается только секретов, которым действительно нужно перемещаться между людьми.

Каналы, которые дисквалифицируют сами себя

Некоторые каналы отпадают сразу, без обсуждений:

  • электронная почта: реплицируется на серверах, которые никто не контролирует, индексируется, архивируется, пересылается;
  • командный мессенджер: историю читают администраторы, её экспортируют при миграциях и хранят долго после ухода участников;
  • тикет или общий документ: переживёт проект и всплывёт в полнотекстовом поиске три года спустя;
  • SMS и личные мессенджеры: смешивают частный и рабочий периметры.

Общая черта: неуправляемая персистентность. Приемлемый канал обмена гарантирует ровно обратное, то есть сквозное шифрование и исчезновение.

Что работает: от простого к оснащённому

Для разовой передачи достаточно одноразовой короткоживущей ссылки, созданной аудируемым инструментом: получатель открывает, секрет самоуничтожается. Получение подтверждают по второму каналу (звонок, сообщение), что заодно подтверждает: ссылку использовал нужный человек.

Для длительного сотрудничества разовых передач уже мало: нужно общее пространство. Командный менеджер паролей с хранилищами по периметрам остаётся самым доступным вариантом; централизованный менеджер секретов (с журналом доступов и ролевыми политиками) становится уместным, как только инфраструктура это оправдывает. Критерий выбора один и тот же: можно ли узнать, кто к чему обращался, и отозвать доступ одним действием?

ПолучательОбщее хранилищеОтправительПолучательОбщее хранилищеОтправительОтзыв одним действием при уходе участникаКладёт секрет в хранилище проектаДоступ записан в журналУведомляет по другому каналу (в сообщении нет секрета)Аутентифицируется и читает секретДоступ записан в журнал

Схему стоит повторить: уведомление никогда не содержит секрета. Оно лишь говорит, где его забрать, со своими собственными правами.

Минимальные привилегии не паранойя, а бюджет

Каждый переданный секрет, долг: кому-то придётся о нём помнить, ротировать его, отзывать. Этот долг сокращают у источника:

  • секреты по окружениям: никогда один и тот же токен в стейджинге и продакшене;
  • секреты по людям и сервисам: никаких общих аккаунтов «team», за которые никто не отвечает;
  • минимальные права: ключ только на чтение для задачи только на чтение;
  • короткие сроки жизни по умолчанию: истечение срока лучшая из ротаций.

История Git не забывает никогда

Самая частая утечка не проходит ни по одному каналу обмена: её коммитят. .env, добавленный «временно», строка подключения в конфиге, ключ в тесте. История вечная и распределённая память: каждый клон уносит копию.

Защита строится слоями. Строгий .gitignore для файлов окружения. Сканер секретов в pre-commit и в CI, блокирующий до публикации. И одно абсолютное правило на день, когда секрет всё же попал в историю: чистки никогда не достаточно, секрет считается скомпрометированным и немедленно ротируется. Переписывание истории ограничивает будущую экспозицию, но не отменяет утечку.

Выход, часть обмена

Процесс обмена секретами оценивается по офбордингу. Уход участника команды, конец контракта, расторжение с подрядчиком запускают одну и ту же механику: отозвать именные доступы, ротировать общие секреты, к которым человек имел доступ, проверить журнал. Если этот список больно составлять, значит секреты раздавались без инвентаря, а инвентарь ровно то, что хранилище даёт бесплатно.

Чек-лист, который мы применяем

  • Можно ли заменить секрет эфемерной идентичностью? Если да, заменить.
  • Ни одного секрета открытым текстом в письме, чате, тикете, документе.
  • Разовая передача: одноразовая ссылка, уведомление по другому каналу.
  • Длительная работа: общее хранилище, ролевой доступ, журнал.
  • Секрет на окружение и на человека, с минимальными правами и сроком.
  • Сканер секретов в pre-commit и CI.
  • Секрет в истории = скомпрометированный секрет: немедленная ротация.
  • Офбординг по сценарию: отозвать, ротировать, проверить журнал.

Ничто из этого не дорого. Дорог забытый в Slack токен, который всё ещё открывает продакшен через два года после конца проекта.