Keeping secrets out of logs (2024)
Коротко:
Секреты в логах — это не «одним фиксом» решить нельзя. Ни 80/20, ни чудо-инструмента нет. Есть 10 «свинцовых пуль» — несовершенных, но при правильной раскладке работают.
Почему течёт
Причина | Пример |
---|---|
Прямой логинг | log.info(user) вместо log.info(user.id) |
«Мусорные» дампы | logger.debug(req.headers) |
Конфиги | debug=true выводит весь env |
Зашитые секреты | JSON-поле password внутри структуры |
Телеметрия | APM-сборщик хватает всё подряд |
Пользователь | Вводит пароль в поле «имя» |
10 «пуль»
-
Архитектура данных
Разделяем «чувствительное» и «остальное» на уровне схемы; в логи идёт только последнее. -
Трансформации
Сериализуем черезsanitize()
илиtoLog()
— явно выбрасываем секретные поля. -
Domain-primitives
- Компиляция:
SecretString
не реализуетDisplay
. - Рантайм:
Redactable
интерфейс,toString() → "***"
.
- Компиляция:
-
Read-once
Пароль читается 1 раз, дальше объект пустой — логировать нечего. -
Taint-tracking
Помечаем вход как «грязный»; если доходит до логгера — exception. Дорого, но точно. -
Форматтеры логов
Пишем свойLayout
/Encoder
, который режет заранее заданные ключи рекурсивно. -
Unit-тесты
ПроверяемassertThat(log).doesNotContain(secret)
; запускаем на каждый PR. -
Сканеры
Regex-правила + entropy-фильтры в CI и в production-потоке. Сэмплируем, чтобы не умереть от CPU. -
Pre-processors
Vector / Logstash / Cribl вырезают поля ещё до попадания в Elasticsearch. -
Люди
Code-review чек-лист: «есть ли тут .toString / JSON.stringify / printf без фильтров?».
Стратегия
- Фундамент: классификация данных, единый словарь «что считать секретом».
- Карта потока: от источника до хранилища логов.
- Контрольные точки: валидация, sanitize, redact.
- Защита в глубину: 2-3 слоя из списка выше.
- План на инцидент: ротация, оповещение, forensics.
Итог:
Нет волшебства — только дисциплина и много мелких фиксов. Начните с 2-3 «пуль», которые дешёвле всего у вас, и двигайтесь дальше.
Комментарии (42)
- Отличный пост: чёткий разбор проблемы «секреты в логах» и конкретные техники борьбы.
- Основные идеи: taint-tracking, in-band метки, GuardedString/SecureString, доменные примитивы
new Secret(...)
. - Сложности: стектрейсы, JSON, core-dumps, динамически создаваемые секреты, человеческий фактор.
- Защита в глубину: маскировать, ограничивать доступ к логам, не писать всё подряд, валидировать маски (Kingfisher).
Rug pulls, forks, and open-source feudalism
Rug-pull и вилки: кто кого в OSS
- В облаке всё решают гиганты (AWS, GCP, Azure); разработчики и пользователи — без прав.
- Компания-владелец проекта может «рвануть коврик»: сменить лицензию на закрытую, чтобы загнать облачных конкурентов.
- Пример: Elastic → SSPL, MongoDB → SSPL, Sentry → новая лицензия.
- Ответ — вилка (fork), но она требует людей и денег; без спонсора умирает.
- AWS форкнул Elasticsearch → OpenSearch: набрал контрибьюторов с нуля, теперь живёт.
- Puppet ушёл в Perforce и закрыл код → родилась OpenVox.
- Вывод: однокомпаночные проекты рискованны; выбирайте те, где власть распределена, или сразу готовьтесь вилковать.
Комментарии (115)
- CLA = право перелицензировать → «rug pull» возможен; DCO такого не даёт.
- Elasticsearch, Redis, Mongo и др. перелицензировались не от банкротства, а чтобы ограничить конкурентов и поднять доход.
- Пользователи чувствуют «предательство»: проект начинали под FOSS-лицензией, привлекли вклад и клиентов, потом закрыли код.
- Форки (OpenSearch, Valkey) спасают, но требуют новой инфраструктуры и сообщества; большинство просто делают «снапшот» и уходят.
- Проблема устойчивости: без денег проект умрёт, но нынешняя модель дарения дарит прибыль крупным облакам, а не разработчикам.