Файлы проиндексированы, написано сообщение коммита, данные отправлены на сервер… И вдруг хочется повернуть время вспять. В коммит попал файл, которого там быть не должно. Когда такое случается, приходит время обращаться к поисковику.
Каждый разработчик когда-то по ошибке коммитил в общедоступный репозиторий файлы с конфиденциальной информацией. Как справиться с такой проблемой? Как сделать так, чтобы ничего подобного больше не случилось бы?
В этой статье я расскажу о том, что делать в том случае, если в репозиторий случайно попал файл, которому там совершенно нечего делать. Здесь же я приведу команды Git, которые позволят подправить историю, и поделюсь некоторыми рекомендациями по организации безопасной работы с конфиденциальной информацией.
Удаление файлов с конфиденциальной информацией из Git-репозитория (изображение большого размера)
Минимизация ущерба
Итак, вы случайно закоммитили файл с конфиденциальной информацией. Назовём этот файл .env
. Сразу после того, как это случилось, надо задать себе пару вопросов:
- Отправлен ли коммит в удалённый репозиторий?
- Является ли удалённый репозиторий общедоступным?
▍Коммит пока не отправлен в удалённый репозиторий
Если вы пока не отправили коммит в репозиторий, то, в общем-то, возникшая ситуация никакой угрозы не несёт. Для того чтобы всё исправить, достаточно просто вернуться к предыдущему коммиту:
git reset HEAD^ --soft
Файлы останутся в рабочей копии репозитория, вы сможете внести в проект необходимые изменения.
Если же вы хотите сохранить коммит и вам нужно просто удалить из него определённые файлы, тогда поступите так:
git rm .env --cached
git commit --amend
Параметр --amend
можно использовать только для работы с самым свежим коммитом. Если вы, после неудачного коммита, добавили ещё несколько, воспользуйтесь такой командой:
git rebase -i HEAD~{на сколько коммитов нужно вернуться?}
Это позволит исправить неправильный коммит и поможет не потерять изменения, внесённые в проект остальными коммитами.
▍Коммит отправлен в удалённый репозиторий
Если вы уже отправили коммит в удалённый репозиторий, то, в первую очередь, вам нужно знать о том, чем отличаются публичные и приватные репозитории.
Если ваш репозиторий является приватным, и при этом он не доступен ботам или людям, которым вы не доверяете, вы можете просто внести поправки в последний коммит, воспользовавшись парой вышеприведённых команд.
Если вы отправили в репозиторий, после проблемного коммита, и другие коммиты, это не помешает вам убрать файлы с конфиденциальными данными из истории Git, воспользовавшись командой git filter-branch или инструментом BFG Repo-Cleaner.
Вот пример использования git filter-branch
:
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch .env" --prune-empty --tag-name-filter cat -- --all
Но, делая это, учитывайте два важных аспекта подобных изменений, вносимых в репозиторий:
- Вы меняете историю Git. Если на текущее состояние репозитория полагаются другие люди, если от этого состояния зависят какие-то ветки того же репозитория, его форки, открытые PR, то это нарушит их работу. В подобных случаях относитесь к репозиторию как к общедоступному и постарайтесь не вносить изменения в его историю.
- Вам нужно будет очистить кеш. Вам понадобится обратиться в службу поддержки платформы, на которой хранится ваш репозиторий, и попросить очистить его кеш. Несмотря на то, что вы исправили проблемный коммит или переписали историю репозитория, старый коммит, содержащий конфиденциальные данные, останется в кеше. Для того чтобы к нему обратиться, нужно будет знать его ID, но к нему можно будет получить доступ до тех пор, пока кеш не очистят.
Нужно ли создавать новые секретные ключи в том случае, если их актуальные версии попали в публичный репозиторий?
Если кратко ответить на вопрос, вынесенный в заголовок, то — нужно. Если ваш репозиторий общедоступен, или если вы, по любой причине, полагаете, что он — не место для хранения секретных данных, вам необходимо будет счесть попавшие в него конфиденциальные данные скомпрометированными.
Даже если вы удалили эти данные из репозитория, вы ничего не сможете сделать с ботами и с форками репозитория. Как же поступить?
- Деактивируйте все ключи или пароли. Это надо сделать в первую очередь. После того, как вы деактивируете ключи, конфиденциальные сведения, ушедшие в общий доступ, оказываются бесполезными.
- Настройте файл
.gitignore
. Сделайте в.gitignore
записи о файлах с конфиденциальной информацией для того чтобы Git не отслеживал бы состояние этих файлов. - Подготовьте коммит, в котором нет файлов с конфиденциальной информацией.
- Отправьте изменения в репозиторий, снабдите коммит пояснениями о возникшей ситуации. Не пытайтесь скрыть ошибку. Все программисты, работающие над проектом, включая вас, по достоинству оценят наличие в репозитории коммита с разъяснениями ситуации и с описанием того, что именно было исправлено с помощью данного коммита.
Рекомендации по хранению конфиденциальных файлов в проектах, в которых для контроля версий применяется Git
Для того чтобы не допустить утечек конфиденциальной информации стоит придерживаться следующих рекомендаций.
▍Храните секретные данные в файле .env (или в другом подобном файле)
Ключи к API и другие подобные сведения стоит хранить в единственном файле .env
. При таком подходе, если Git не отслеживает состояние файла .env
, вы, добавив в этот файл новый ключ, не отправите его случайно в репозиторий.
Ещё одно преимущество такого подхода заключается в том, что так у вас будет доступ ко всем ключам через глобальную переменную process
.
▍Используйте, если это возможно, ключи API
Скомпрометированные ключи API легко деактивировать, такие ключи легко создать заново. Если это возможно — используйте именно их, а не нечто вроде логинов и паролей.
▍Храните ключи API, пользуясь средствами вашего инструмента для сборки проектов
Ключи API обычно нужны при сборке приложений. Инструменты для сборки проектов, вроде Netlify, позволяют держать ключи в защищённых хранилищах. Такие ключи автоматически внедряются в приложение с использованием глобальной переменной process
.
Управление переменными окружения
▍Добавьте запись о файле .env в файл .gitignore
Сделайте так, чтобы Git не отслеживал бы файлы, содержащие конфиденциальную информацию.
▍Подготовьте шаблонный файл .env.template
Наличие подобного шаблонного файла помогает тем, кто работает над проектом, добавлять в проект ключи API, избавляя их от необходимости чтения документации.
▍Не меняйте историю Git в удалённых репозиториях
Постарайтесь строго придерживаться этого правила. Если вы следовали вышеприведённым рекомендациям, то историю Git вам менять и не потребуется.
Итоги
Надеюсь, мой материал поможет вам в безопасной работе с конфиденциальными данными.
А вам случалось отправлять в общедоступный репозиторий что-то такое, что туда попадать не должно?
Автор: ru_vds