Удаление конфиденциальных данных из репозиторияNew
Удаление конфиденциальных данных из репозитория — это двухэтапный процесс, который включает в себя действия как локально, так в удаленном репозитории:
-
Локальная очистка истории. На этом этапе используйте
git-filter-repo
для перезаписи истории репозитория на локальной машине. Процесс включает удаление файлов, замену текста в содержимом файлов и/или сообщениях коммитов. После этого локальная копия вашей истории уже не будет содержать конфиденциальных данных. -
Обновление удаленного репозитория и последующая очистка на сервере. После локальной очистки вы принудительно отправляете (
git push --force
) измененную историю на удаленный репозиторий. Однако этого часто недостаточно, так как удаленные платформы могут кэшировать старые версии данных или сохранять ссылки на них в запросах на слияние. Поэтому второй критически важный шаг — это обращение в службу поддержки GitVerse для окончательной очистки кэшей и удаления всех оставшихся ссылок на конфиденциальные данные на стороне сервера.
Локальная очистка истории
Программные средства для очистки истории локального репозитория
Известное ПО для очистки истории локального репозитория:
-
git-filter-repo
(opens in a new tab) — современный инструмент для перезаписи истории Git, рекомендуем использовать его. -
git filter-branch
— старый, медленный и имеет более сложный синтаксис.
Основные команды очистки локального репозитория
Основные команды для очистки истории локального репозитория:
-
--invert-paths
и--invert-paths --path
. Удаление определенного файла из истории:git-filter-repo --invert-paths --path ПУТЬ-К-ВАШЕМУ-ФАЙЛУ-С-КОНФИДЕНЦИАЛЬНЫМИ-ДАННЫМИ
Дополнительный аргумент
--path
используется, когда файл существовал по другим путям из-за перемещений или переименований. Иначе для для удаления файла может потребоваться повторный запуск с альтернативным путем. -
--replace-text
. Замена текста, перечисленного в подготовленном файле, в небинарных файлах истории. Замена текста применяется и к сообщениям коммитов, если не указывать конкретные пути:git-filter-repo --replace-text path/to/file/file_with_passwords.txt
Файл, который вы передаете в качестве аргумента
--replace-text
, должен содержать строки в форматеsearch_string==>replacement_string
. Каждая строка должна содержать искомый текст, затем два знака равенства (==>
), а затем текст для замены.Пример подготовленного файла со строками для замены:
моя_старая_функция==>моя_новая_функция устаревшая_переменная==>актуальная_переменная секретный_ключ_А==>скрытый_ключ_B
Если не указывать текст для замены, то вместо замены найденный текст будет удален.
Подготовленный файл должен содержать список строк для удаления:
моя_секретная_строка_123 API_KEY_ТОКЕН пароль_пользователя
-
--message-callback
. Очистка текста в сообщениях коммитов. Этот метод позволяет выполнять более гибкую очистку или замену текста непосредственно в сообщениях коммитов, используя Python-скрипт:
git-filter-repo --message-callback '
import re
secret_to_find = r"секрет" # Переменная для текста с конфиденциальными данными
replacement_text = b"Сообщение очищено от конфиденциальных данных" # Сообщение на месте замены
if re.search(secret_to_find, message.decode("utf-8")):
return replacement_text
return message
'
В данном примере, чтобы конфиденциальный текст был стерт без замены, переменной replacement_text
следует присвоить пустую байтовую строку replacement_text = b""
.
-
Проверка запросов на слияние, затронутых перезаписью истории:
После перезаписи истории
git-filter-repo
вы можете узнать, сколько запросов на слияние потенциально затронуты, используя командуgrep
. Это важно, так как GitVerse может продолжать ссылаться на старые, содержащие конфиденциальные данные, коммиты.grep -c '^refs/pull/.*/head$' .git/filter-repo/changed-refs
Эта команда выводит количество строк, соответствующих шаблону
^refs/pull/.*/head$
, в файле .git/filter-repo/changed-refs. Каждая такая строка указывает на то, что связанный с ней запрос на слияние может ссылаться на старую историю до очистки.Чтобы увидеть список затронутых запросов на слияние вместо их количества, уберите флаг
-c
:grep '^refs/pull/.*/head$' .git/filter-repo/changed-refs
Если при очистке не был создан файл .git/filter-repo/changed-refs, то команда вернет вернет сообщение grep: .git/filter-repo/changed-refs: No such file or directory
.
Обновление удаленного репозитория и последующая очистка на сервере
После того как вы успешно очистили историю репозитория локально, необходимо перенести эти изменения в удаленный репозиторий и убедиться, что все следы конфиденциальных данных удалены на сервере. Этот процесс включает принудительную отправку изменений и, при необходимости, взаимодействие со службой поддержки.
Принудительная отправка изменений
Команда позволяет перезаписать всю историю удаленного репозитория вашей локальной, уже очищенной версией:
git push --force --mirror origin
где:
-
--force
— флаг принудительной отправки изменений для перезаписи истории изменений на удаленном сервер. -
--mirror
— флаг гарантирует, что отправятся все ссылки (ветки, теги и другие специальные ссылки, такие какrefs/pull/
) из вашего локального репозитория в удаленный. Это обеспечивает точное соответствие удаленного репозитория вашей очищенной локальной копии, включая удаление ссылок на старые, содержащие конфиденциальные данные коммиты; -
origin
— указывает на удаленный репозиторий, куда вы отправляете изменения. Обычно это основной удаленный репозиторий по умолчанию.
Перед выполнением этой команды обязательно согласуйте действия со всеми участниками проекта. Все соавторы должны удалить свои локальные клоны репозитория и создать их заново, либо выполнить жесткий сброс (git reset --hard
) и синхронизировать свои ветки с новой историей.
Если у вас включена защита веток, то команда git push --force --mirror
может быть отклонена. В этом случае вам придется временно отключить защиту веток, выполнить отправку изменений, а затем снова включить защиту.
Пример очистки репозитория от конфиденциальных данных
Подготовительные действия
- Установите
git-filter-repo
, например:
sudo apt update
sudo apt install git-filter-repo
-
Сохраните все изменения. Если есть непомеченные (unstaged) или незакомиченные (uncommitted) изменения, команда
git-filter-repo
не сработает корректно. -
Сделайте резервную копию вашего репозитория. Это критически важно, так как
git-filter-repo
необратимо изменяет историю.
Идентификация и подготовка конфиденциальных данных
Предположим, вы случайно закоммитили API-ключ MY_SECRET_API_KEY_123
в файл config.js
и также упомянули его в сообщении коммита.
Создайте файл для замены/удаления текста, например, sensitive_data_to_clean.txt
:
MY_SECRET_API_KEY_123==>***API_KEY_REMOVED***
Если вы хотите просто удалить, то:
MY_SECRET_API_KEY_123
Очистка файлов и сообщений коммитов локально
Выполните git-filter-repo
для удаления API-ключа из содержимого файлов и сообщений коммитов:
git-filter-repo --replace-text path/to/sensitive_data_to_clean.txt
Если бы API-ключ был в отдельном файле, который нужно полностью удалить:
git-filter-repo --invert-paths --path path/to/your/config.js
Если бы вы хотели только удалить ключ из сообщений коммитов:
git-filter-repo --message-callback '
import re
secret_key = r"MY_SECRET_API_KEY_123"
replacement = b"***KEY_REMOVED_FROM_FROM_MESSAGE***"
decoded_message = message.decode("utf-8")
new_message = re.sub(secret_key, replacement.decode("utf-8"), decoded_message)
return new_message.encode("utf-8")
'
Проверка затронутых запросов на слияние
Проверьте, сколько запросов на слияние ссылаются на старые коммиты, содержащие API-ключ:
grep -c '^refs/pull/.*/head$' .git/filter-repo/changed-refs
Если результат больше нуля, вам потребуется связаться со службой поддержки GitVerse.
Принудительная отправка изменений в удаленный репозиторий
git push --force --mirror origin
Перед выполнением убедитесь, что все коллеги осведомлены, и временно отключите защиту веток, если она есть.
Связь со службой поддержки GitVerse (при необходимости)
Если запросы на слияние были затронуты (шаг 4), свяжитесь со службой поддержки GitVerse и предоставьте им необходимую информацию, чтобы они могли очистить серверные кэши и ссылки.