MAATRIX / Блог / Регламент работы с секретами: где лежат, кто знает, что делать при утечке

Регламент работы с секретами: где лежат, кто знает, что делать при утечке

MAATRIX

Пароль от базы лежит в переписке в Telegram, API-ключ — в закреплённом сообщении в общем чате, а доступ к панели хостинга помнит только один человек, который сейчас в отпуске. Знакомая картина — и она не про лень, а про отсутствие регламента: никто заранее не решил, где секреты должны жить, кто может их смотреть и что делать, если один из них засветился не там. Разберём все три части такого регламента на конкретных инструментах и командах, а не на абстрактных принципах «храните пароли надёжно».

Почему текстовый файл и переписка — это не хранилище

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

Признаки того, что в компании секреты «разбросаны», а не хранятся:

  • пароль от продакшен-базы существует в виде скриншота или сообщения, отправленного полгода назад;
  • один и тот же .env-файл копируют вручную на каждый новый сервер через scp;
  • API-ключ подрядчика выдан «навсегда» без даты пересмотра;
  • никто не может быстро ответить, у скольких людей есть доступ к панели DNS-провайдера.

Централизованный менеджер секретов закрывает это одним решением: секрет хранится в одном месте, выдаётся по запросу, а не копируется, и каждое обращение к нему оставляет запись. Для команды с ограниченным бюджетом вариантов немного, и каждый решает разную задачу:

ИнструментДля чегоПорог входа
Vaultwarden (self-hosted Bitwarden)Пароли людей: панели, SaaS-аккаунты, root-доступыНизкий, разворачивается за вечер
HashiCorp VaultДинамические секреты приложений: токены БД, API-ключи с TTLВысокий, нужна отдельная эксплуатация
SOPS + ageСекреты в git-репозитории (конфиги, CI/CD) в зашифрованном видеСредний, встраивается в существующий workflow
Docker secrets / systemd credentialsСекреты для контейнеров и сервисов на одном хостеНизкий, но без централизации между серверами

Для большинства небольших команд достаточно связки Vaultwarden (человеческие пароли) и SOPS (секреты в конфигурации приложений). Vault оправдан, когда секретов десятки на приложение и нужна автоматическая ротация без участия человека.

Пример: файл secrets.enc.yaml, зашифрованный SOPS с ключом age, можно спокойно коммитить в приватный репозиторий — расшифровать его без ключа невозможно:

# Генерация ключа age (делается один раз, приватный ключ хранится отдельно от репозитория)
age-keygen -o key.txt

# Шифрование файла с секретами перед коммитом
sops --encrypt --age $(cat key.txt | grep -oP 'public key: \K.*') secrets.yaml > secrets.enc.yaml

# Расшифровка на сервере при деплое (ключ передаётся через переменную окружения)
export SOPS_AGE_KEY_FILE=/etc/sops/key.txt
sops --decrypt secrets.enc.yaml > /run/secrets/app-secrets.yaml

Расшифрованный файл кладите в tmpfs (например, /run/secrets), а не на диск — после перезагрузки он исчезнет сам, и не придётся отдельно чистить.

Кто имеет доступ и на каком основании

Второй пункт регламента — не техническое хранилище, а правило, отвечающее на вопрос «почему у этого человека есть этот доступ». Базовый принцип — минимально необходимые права (least privilege): доступ выдаётся под конкретную задачу, а не «на всякий случай, пригодится».

На практике это оформляется как матрица доступа, а не как список «у кого какой пароль»:

СекретКто имеет доступОснованиеСрок пересмотра
root на боевом сервере2 инженера DevOpsПостоянная эксплуатацияРаз в квартал
API-ключ платёжного шлюзаBackend-лидЕдинственный, кто деплоит платёжный сервисРаз в квартал
Доступ к панели хостингаВладелец, DevOps-лидБиллинг и аварийное восстановлениеРаз в полгода
Ключ доступа подрядчика к stagingПодрядчик (временно)Контракт на разработку фичи XДо конца контракта, но не более 30 дней

Три правила, которые превращают эту таблицу из формальности в рабочий инструмент:

  1. Именные учётки, не общие. Общий root-пароль на всю команду — это классический антипаттерн, который убивает саму идею аудита: если инцидент случился, узнать, кто именно выполнил команду, невозможно. У каждого свой SSH-ключ, свой аккаунт в менеджере паролей, своя запись в матрице.
  2. Доступ подрядчика и временных сотрудников — со сроком годности. Выдавайте доступ с явной датой окончания, а не полагайтесь на то, что кто-то вспомнит его отозвать. Если платформа не поддерживает TTL нативно — ставьте напоминание в календарь на дату пересмотра.
  3. Журналирование обращений, а не только выдачи. Мало знать, кому выдан доступ — нужно видеть, когда им пользовались. У Vaultwarden это история событий организации, у Vault — встроенный audit log, у SSH — системный журнал входов:
# Кто и когда заходил по SSH за последние 7 дней
journalctl -u ssh --since "-7 days" | grep "Accepted publickey"

# Активные сессии прямо сейчас
who -u

# Audit log Vault: кто читал конкретный секрет
vault audit list
tail -f /var/log/vault_audit.log | jq 'select(.request.path == "secret/data/payment-api")'

Регулярная ревизия — не разовое мероприятие, а календарная задача. Многие команды делают это раз в квартал: выгружают список активных доступов и по каждому отвечают на вопрос «эта причина ещё актуальна?». Отдельно стоит завести чек-лист на увольнение сотрудника — первые действия после ухода должны включать отзыв SSH-ключей, смену общих паролей, которые он мог знать, и удаление из менеджера секретов.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Как оформить регламент документом, а не устной договорённостью

Регламент бесполезен, если он существует только в голове DevOps-инженера. Минимальный документ — это не многостраничная политика, а таблица и три коротких раздела, которые реально открывают в момент, когда нужно быстро понять, что делать.

Структура, которая работает на практике:

# Регламент работы с секретами — [название компании]

1. Классификация секретов

  • Уровень 1 (критичные): root-доступы, платёжные ключи, ключи шифрования бэкапов
  • Уровень 2 (важные): API-ключи внешних сервисов, доступы к БД
  • Уровень 3 (рабочие): токены CI/CD, staging-доступы

2. Где хранится каждый уровень

  • Уровень 1 — Vault с обязательным MFA, доступ только у двух именных ролей
  • Уровень 2 — Vaultwarden, организация "infra", папка по проекту
  • Уровень 3 — переменные окружения CI, secrets самого CI/CD (GitHub Actions Secrets и т.п.)

3. Кто выдаёт и отзывает доступ

  • Выдача — по заявке в трекере с указанием причины и срока
  • Отзыв — автоматически по истечении срока, вручную — в день увольнения/окончания контракта

4. План действий при утечке

[см. следующий раздел]

5. Ответственный за регламент

  • Актуальную версию поддерживает: [имя/роль]
  • Дата последнего пересмотра: [дата]

Этого достаточно, чтобы новый сотрудник за пять минут понял, куда идти за доступом, а не писал в общий чат «а где у нас пароль от...». Держите файл там же, где остальная инженерная документация — в репозитории с инфраструктурой, не в отдельном малодоступном месте.

Плановая ротация: секрет с истёкшим сроком не нужно взламывать

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

Ориентировочные интервалы, которые стоит закрепить в регламенте (это отправная точка, не догма — под вашу инфраструктуру сроки могут отличаться):

  • SSH-ключи сотрудников — раз в 6–12 месяцев;
  • API-ключи внешних сервисов без встроенной ротации — раз в 3–6 месяцев;
  • Пароли от административных панелей — раз в квартал;
  • Ключи шифрования бэкапов — реже, но с обязательной проверкой, что старые бэкапы всё ещё расшифровываются новым ключом.

Слепая смена пароля каждые 90 дней по календарю без анализа риска — практика с известной обратной стороной: люди начинают использовать предсказуемые вариации одного и того же пароля. Осмысленнее автоматизировать ротацию там, где это возможно (динамические секреты Vault с TTL, ssh-keygen по расписанию), и оставить ручные интервалы только там, где автоматизация пока не окупается.

План действий при утечке: три шага без паузы на раздумья

Когда есть подозрение, что секрет скомпрометирован — увидели чужой коммит с .env, нашли ключ в публичном access-логе, узнали, что бывший подрядчик всё ещё может зайти по SSH — регламент должен отвечать не «что вообще делать», а «что делать в первую минуту». Три шага именно в этом порядке:

1. Немедленная ротация скомпрометированного секрета. Не «оценим ущерб, потом сменим» — сначала смена, потом разбор. Секрет, который может использовать злоумышленник, должен перестать работать до того, как вы закончите анализ:

# SSH-ключ — отозвать немедленно
ssh-keygen -R hostname_or_ip   # убрать из known_hosts на своей стороне
# на сервере — удалить публичный ключ из authorized_keys
sed -i '/compromised-key-comment/d' ~/.ssh/authorized_keys

# API-ключ — отозвать через панель провайдера и выпустить новый
# (у большинства сервисов это делается в разделе API Keys / Access Tokens)

# Пароль от базы — сменить и перезапустить сервисы с новым значением
ALTER USER app_user WITH PASSWORD 'новый-длинный-пароль';

2. Оценка масштаба: что реально могло быть скомпрометировано. После того как секрет отозван, спокойно разберитесь, что он давал доступ. Часто утечка одного ключа — это на самом деле утечка доступа к нескольким системам сразу: ключ от S3-бакета с бэкапами может означать доступ к приватным ключам шифрования внутри самих бэкапов. Практический чек-лист на этом шаге:

  • Проверить логи доступа за период, когда секрет предположительно был доступен третьей стороне;
  • Найти, где ещё в конфигурации мог быть использован тот же секрет (частая ошибка — один пароль на несколько сервисов);
  • Найти по логам, кто и откуда конкретно использовал ключ — иногда это отвечает на вопрос сам факт утечки или уже эксплуатация, разбор такого случая есть в статье API-ключ утёк: как найти по логам, кто его жжёт;
  • Проверить, есть ли признаки, что секретом уже воспользовались (нетипичные запросы, новые записи, которые вы не создавали).

3. Коммуникация с затронутыми сторонами, если она нужна. Не каждая утечка требует внешнего уведомления — если ключ отозван до того, как им кто-то воспользовался, часто достаточно внутреннего разбора. Но если есть основания полагать, что данные клиентов затронуты, компания должна быть готова сообщить об этом — команде, руководству, а при определённых обстоятельствах и пострадавшим пользователям. Правило простое: решение о внешней коммуникации не принимается в одиночку и не откладывается на «подумаем позже» — оно должно быть частью регламента, а не импровизацией в моменте стресса. Общая структура первых действий при инциденте (не только утечка секретов) описана в материале про первые 15 минут инцидента.

Зафиксируйте эти три шага в самом документе регламента как чек-лист с чекбоксами — в момент утечки не время придумывать порядок действий, время — им следовать.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Нужен ли отдельный менеджер секретов для команды из трёх человек?

Да, но не обязательно Vault — для такой команды хватит self-hosted Vaultwarden или даже платного облачного менеджера паролей с общими коллекциями. Главное — не переписка и не общий текстовый файл.

Что делать, если секрет уже давно лежит в истории git и его нельзя просто удалить?

Ротировать сам секрет — переписывание истории git (git filter-repo, BFG) убирает его из будущих клонов, но не отменяет того, что он уже мог быть скачан. Единственная надёжная защита — сделать старое значение нерабочим.

Как автоматически проверять, что секреты не попадают в репозиторий?

Поставить pre-commit хук и CI-проверку с инструментом вроде gitleaks или trufflehog — они сканируют diff на характерные паттерны ключей и токенов до того, как коммит уйдёт в общую историю.

Обязательно ли использовать MFA для доступа к менеджеру секретов?

Для секретов уровня 1 (root, платёжные ключи) — да, это должно быть требованием регламента, а не рекомендацией. Один скомпрометированный пароль от менеджера секретов без MFA обнуляет всю систему хранения.

Как быть с секретами, которые нужны инфраструктуре как коду (Terraform, Ansible)?

Используйте бэкенд, который поддерживает шифрование состояния и получение секретов во время выполнения (Vault provider, SOPS-provider), а не хардкодьте значения в .tf-файлах — даже во «временных» ветках.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →