[Перевод] Как убрать из Git-репозитория файлы с конфиденциальной информацией

Файлы проиндексированы, написано сообщение коммита, данные отправлены на сервер… И вдруг хочется повернуть время вспять. В коммит попал файл, которого там быть не должно. Когда такое случается, приходит время обращаться к поисковику.

Каждый разработчик когда-то по ошибке коммитил в общедоступный репозиторий файлы с конфиденциальной информацией. Как справиться с такой проблемой? Как сделать так, чтобы ничего подобного больше не случилось бы?

В этой статье я расскажу о том, что делать в том случае, если в репозиторий случайно попал файл, которому там совершенно нечего делать. Здесь же я приведу команды Git, которые позволят подправить историю, и поделюсь некоторыми рекомендациями по организации безопасной работы с конфиденциальной информацией.

650caab838eb2f6c8ad5653692a85c45.png


Удаление файлов с конфиденциальной информацией из 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.

a9cd8c919a32f554f8c8b02767eea626.png


Управление переменными окружения

▍Добавьте запись о файле .env в файл .gitignore


Сделайте так, чтобы Git не отслеживал бы файлы, содержащие конфиденциальную информацию.

▍Подготовьте шаблонный файл .env.template


Наличие подобного шаблонного файла помогает тем, кто работает над проектом, добавлять в проект ключи API, избавляя их от необходимости чтения документации.

▍Не меняйте историю Git в удалённых репозиториях


Постарайтесь строго придерживаться этого правила. Если вы следовали вышеприведённым рекомендациям, то историю Git вам менять и не потребуется.

Итоги


Надеюсь, мой материал поможет вам в безопасной работе с конфиденциальными данными.

А вам случалось отправлять в общедоступный репозиторий что-то такое, что туда попадать не должно?

oug5kh6sjydt9llengsiebnp40w.png

3piw1j3wd_cgmzq9sefgferaumu.png

© Habrahabr.ru