Локальный CLI-сервис для поиска утечек токенов, паролей и ключей в коде.
Ядро детектирования построено на detect-secrets, а поверх него реализованы:
- загрузка JSON-конфига;
- отдельный JSON-файл исключений;
- полное начальное сканирование;
- инкрементальное сканирование только изменённых файлов;
- текстовый отчёт с критичностью и рекомендациями;
- возможность подключать пользовательские фильтры и плагины.
secret_scanner/cli.py— точка входа CLIsecret_scanner/service.py— фоновый сервисsecret_scanner/scanner.py— интеграция с detect-secretssecret_scanner/reporter.py— текстовый отчётsecret_scanner/severity.py— критичность и рекомендацииconfig.json— основной конфигexcludes.json— исключенияcustom_filters.py— пример пользовательского фильтраcustom_plugins.py— пример пользовательского плагина
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtpython scanner_service.py --config ./config.json --oncepython scanner_service.py --config ./config.jsonОбязательные поля:
target_directory- целевая директория для сканированияexclude_file- файл с исключениямиdetect_secrets- используемые плагины detect_secretsreport_file- итоговый файл для отчета
Дополнительно:
state_file— файл состояния для инкрементального сканированияscan_interval_seconds— интервал проверки изменений
- Сервис читает
config.json - Загружает
excludes.json - Сканирует указанную директорию полностью
- Записывает находки в
report.txt - Сохраняет текущее состояние файлов в
state.json - Переходит в цикл и проверяет только изменённые файлы
- Новые результаты дозаписывает в тот же отчёт
В отчёт выводится:
- время сканирования;
- тип запуска (
FULL_SCAN,INCREMENTAL_SCAN); - список просканированных файлов;
- найденный детектор;
- файл и строка;
- хеш секрета;
- критичность;
- рекомендация по устранению.
detect-secretsлучше работает на текстовых файлах. Поэтому в проекте есть whitelist текстовых расширений.- Критичность (
CRITICAL,HIGH,MEDIUM,LOW) вычисляется нашей логикой вseverity.py. - Поле
filters_usedв конфиге поддерживает и встроенные фильтры, и кастомные черезfile://...::function_name. - Поле
plugins_usedподдерживает и встроенные плагины, и кастомные плагины черезfile://....
Если при запуске появляется ошибка вида No such ... plugin to initialize, это означает, что в установленной версии detect-secrets нет одного из плагинов из config.json. В проекте есть защита от этого: неизвестные встроенные плагины автоматически пропускаются с предупреждением в логах, а если не осталось ни одного поддерживаемого плагина, включается минимальный совместимый набор. На новых версиях detect-secrets список плагинов шире, на старых — уже.
Наличие качественного сканера на утечки является обязательным условием для обеспечения безопасной разработки. Однако, инструмент сам по себе не гарантирует безопасную разработку. Самое банальное - разработчику надоест каждый раз запускать сканер, разбираться в логах, он просто перестанет его использовать. "Да и всё равно скоро уволюсь, мне ничего не будет" - подумает он.
Для того, чтобы пуш на сервере прошел успешно, необходимо, чтобы коммиты, сделанные локально, имели подпись, которую выдает только сканер. Тогда что бы не сделал разработчик, он не сможет запушить никакие изменения в прод, если он не запустил сканер и не исправил обнаруженные проблемы.
На данный момент реализован основной функционал системы: невозможность запушить изменения в обход инструмента. В реальном сценарии для минимально безопасной работы система должна поддерживать:
- Закрепление и сокрытие программы и её компонентов от разработчика. Пути реализации: перехват системных вызовов, разграничение доступа к файлам и директориям, соблюдение принципа "запрещено всё, что не разрешено"
- Мониторинг попыток получения доступа к закрытому ключу сканера и другие зловредные действия. Пути реализации: SIEM-мониторинг, использование honey-pot, перехват системных вызовов, составления профиля нормального поведения.
- Ротация ключей, сертификатов. Создание PKI.
- Учет локальных политик и мощностей организации, ведение уровня доверия (trust score) к разным командам, разработчикам, проектам.
- Отдельная машина в локальной/корпоративной сети:
- git --bare сервер
- pre-recieve хук для проверки подписей коммитов
- отсутствие подписи/некорректная/поддельная подпись = отказ в пуше
- "некорректные" коммиты никогда не появляются в истории репозитория
- Машина разработчика
- локальный клиент kss-cli - командная оболочка, единственная входная точка для корректного подписания коммитов
- при попытке коммита через командную оболочку kss-cli происходит вызов описанного выше сканера утечек конфиденциальной информации. Далее, kss-cli парсит отчет, который вернул сканер:
- при отсутствии утечек kss-cli подписывает коммит и прикладывает в тело коммита сертификат с подписью
- при наличии утечек kss-cli блокирует коммит и предлагает на выбор:
- отказаться от комита
- посмотреть подробную информацию о находках
- переместить находки по инициативе разработчика в исключения (так называемый self-hosted вариант, применяемый при высоком trust score, при низком trust score должен быть реализован функционал по валидации исключений ответственным лицом)
- при потытке вызвать git commit без оболочки коммит будет успешен, но сервер при git push отклонит такой коммит
Предварительная настройка. Необходимо выполнить следующие команды:
cd ./kss-cli/
pip install -r requirements.txt
# Инициализация служебных структур
python3 -m cli.main init
# Генерация закрытого и открытого ключа подписи
python3 -m cli.main keygen "<your_name>" "<your_email>"
После генерации ключа появится информация, которую необходимо временно сохранить в блокнот, позже, информацию нужно будет вставить в файл на сервере.
Подключение к серверу git репозитория:
mkdir ~/test-reppo
cd ~/test-repo
git init
git remote add origin <user>@<server_ip_address>:~/git-server/test-repo.git
git remote -v # проверить
Для работы сканера необходимо настроить рабочий проект:
cd kss/
nano ./config.json
# изменить строчку
"target_directory": "",
# на строчку
"target_directory": "~/test-repo",
Для создания тестового репозитория необходимо выполнить следующие команды:
mkdir -p ~/git-server
cd ~/git-server
git init --bare test-repo.git
# Настроить пользователя, если нет
git config user.email "<your_email>"
git config user.name "<your_name>"
# Обязательно установить хук
cd ~/git-server/test-repo.git/hooks
nano pre-receive
# Вставить содержимое pre-receive hook из файла server/pre-receive
chmod +x pre-receive
После генерации ключа на машине разработчика, положить информацию о ключе на сервер:
# На сервере создать файл с публичным ключом
mkdir -p ~/.kss/ca/keys
nano ~/.kss/ca/keys/user_xxxxxxxxxxxx.pub
# Вставить JSON с публичным ключом от пользователя, полученным после вывода команды python3 -m cli.main keygen "<your_name>" "<your_email>"
Разработчик работает как обычно. При необходимости коммита запускает командную оболочку и делает необходимые действия:
python3 -m cli.main shell
### 3.2 Навигация в оболочке
🔒 KSS:kss-cli> cd ~/test-repo # перейти в проект
🔒 KSS:test-repo> ls # посмотреть файлы
### 3.3 Работа с Git через KSS
🔒 KSS:test-repo> git status # статус
🔒 KSS:test-repo> git add . # добавить файлы
🔒 KSS:test-repo> git commit -m "сообщение" # коммит с проверкой сканером и подписью
🔒 KSS:test-repo> git push origin master # пуш на сервер