По Секрету Всему Свету Или Всё, Что Случается В Git Остаётся В Git (Не Совсем)
Intro
Представим себе ситуацию: мы что-то в спешке коммитим в git и по какой-то причине в наш коммит попадает пароль, файл с токенами или какой-то иной секрет. И кажется, что логичное решение это удалить последний коммит.
|
|
Но git push --force
может быть запрещен (как минимум для ветки main), да и в целом это не совсем верный подход, даже если вы работаете над своим небольшим проектом в гордом одиночестве. И это в целом не про удаление секретов, а про отмену последнего коммита и его применение в удаленном репозитории, через git reflog
доступ к коммитам остаётся.
Например:
|
|
Захардкоженый секрет == скомпроментированный секрет, так что его не только стоит удалить (тут скорей больше для сканеров, чтобы не фолзили), но и менять секрет.
Где искать эти ваши секреты?
Где в git можно найти секреты:
- в CI/CD
- в самом коде и конфигах Это мы можем покрыть обычными сканерами секретов, так у нас всё как код.
На каких этапах взаимодействия с git мы можем обнаружить захардкоженные секреты:
- При коммите (pre-commit)
- При пуше (pre-push)
- При получении изменений (pre-receive)
Из хуков пожалуй будет интересен pre-commit, его и рассмотрим. Но для любопытных есть GitGuardian есть документация по использованию ggshield в pre-push и pre-receive.
Pre-commit hook
Наиболее удобный вариант, но применим либо к разработчикам-одиночкам, либо к зрелым командам. Для этого можно использовать различные инструменты, но из-за простоты возьму для примера Trufflehog:
|
|
Теперь при коммите Trufflehog будет проверять на наличие секретов.
Это не является единственным решением или точкой проверки, так как при необходимости проверку можно обойти.
Так же для pre-commit хуков можно использовать фреймворк pre-commit или Husky.
Trufflehog так же не лучшее решение, но об этом чуть ниже.
Поиск секретов в кодовой базе
Pre-commit hook это отлично, но не гарантирует полное отсутствие секретов в коде. Для этого есть множество как OSS так и платных инструментов. Что-то можно так же использовать в Pre-commit hook, что-то в CI/CD, а что-то как sidecar-сервис.
Сами инструменты в целом похожи могут сканировать как локально (код, репозитории, конфиги), так и удалённые репозитории.
Инструменты
- Gitleaks - Лёгкий и быстрый сканер для обнаружения токенов в Git-репозиториях. Идеально подходит для интеграции в CI/CD.
- ggshield CLI-инструмент, которое запускается в локальной среде или в среде CI, обнаруживает более 400+ типов секретов. Но привязан к GitGuardian.
- Detect Secrets - Инструмент от Yelp с гибкой настройкой и системой плагинов.
- Talisman - Инструмент от ThoughtWorks, предотвращающий случайную отправку данных в репозиторий.
- Secretlint - Линтер секретов для
.env
, JSON, YAML и др. без зависимости от Git. Лучше запускать в Docker. - TruffleHog - Мощный инструмент для поиска, классификации и анализа утечек ключей и токенов в коде. Поддерживает более 800 типов секретов и может проверять их актуальность.
Warning
Сейчас OSS-версия Trufflehog имеет значительные ограничения по источникам сканирования. Из 21 источника в OSS поддерживается только 9. Подробнеей смотрите в документации.
Название | git | CI/CD | Local |
---|---|---|---|
TruffleHog | ✅ | ✅ | ✅ |
Gitleaks | ✅ | ✅ | ❌ |
ggshield | ✅ | ✅ | ✅ |
Detect Secrets | ✅ | ✅ | ❌ |
Talisman | ✅ | ✅ | ✅ |
Secretlint | ✅ | ✅ | ✅ |
Сервисы
- GitGuardian - обнаруживает более 350 типов секретов как в публичных, так и в приватных репозиториях. Предлагает подробные отчёты и интеграции с различными платформами. Платный, но есть демо на 30 дней.
- TruffleHog Enterprise - 20+ интеграций, 800+ типов секретов, демо нет.
Рекомендации
- Интеграция в CI/CD:
Gitleaks
,ggshield
,detect-secrets
. - Pre-commit хуки:
detect-secrets
,talisman
,gitleaks
. - Сканирование файлов вне Git:
detect-secrets
,secretlint
,ggshield
.
Из-за ограничений сейчас Trufflehog рекомендовать не буду. Но на общем фоне вполне интересно выглядитdetect-secrets
, хоть он и требует особого подхода, но обновлялся он почти год назад. Так же неплохо работаетggshield
, если вас не смущает привязка к GitGuardian.
Удаляем неудаляемое
Секреты в коде найдены, заменены, но что делать, если их все в коде надо удалить? Удалять коммиты решение плохое, а если секретов больше чем 1, то задача кажется не выполнимой. Но и для этого уже есть решения.
- git filter-branch - встроенный в git инструмент для изменения истории. Требует хорошего знания git и работает довольно медленно.
- git-filter-repo - инструмент для удаления секретов в коде.
- BFG Repo-Cleaner - более простая и быстрая альтернатива git-filter-branch для очистки истории Git-репозитория.
Возьмем для примера BFG Repo-Cleaner. Для начала нам нужен список секретов
|
|
Далее нам потребуется bare repo,что означает, что ваши обычные файлы не будут видны, но это полная копия базы данных Git вашего репозитория. И на данном этапе стоит сделать бэкап репозитория.
Так же для простоты использования bfg
используется алиас для java -jar bfg.jar
(например: alias bfg='java -jar ~/.local/bin/bfg.jar'
)
|
|
BFG изменит ваши коммиты и все ветки и теги.
После чего проведём небольшую уборку с git reflog
и git gc
.
|
|
Если всё в порядке, можем запушить изменения (обратите внимание, что поскольку мы использовали --mirror
флаг, этот push обновит все ссылки в репозитории) :
|
|
Outro
Как можно заметить, удаление коммита не является решением проблемы, а удаление секрета это недостаточная мера, его в любом случае необходимо ротировать.
Покрыть только инструментами поиск секретов довольно сложно. Да и с увеличением количества репозиториев задача становится сложнее. Нельзя всё решить хуками или проверками в CI/CD. Вариант с живущим параллельным сканером в целом неплоха, но лучше применять всё в комплексе.
Секреты в принципе удаляемы, но всё же есть риск что-нибудь сломать.
Не храните секреты в коде и конфигах (есть же встроенные средства Gitlab и Github, или даже Vault) и будет вам счастье.
Github Docs: Removing sensitive data from a repository
Git-SCM: Customizing Git - Git Hooks
TruffleHog Docs: Pre-commit hooks
Git-SCM: git-reflog
Habr: Коммитить нельзя сканировать: как мы боремся с секретами в коде