Как управлять вашими секретами с git-crypt

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Большинство программных проектов используют секреты – обычно, как ключи к удаленному API или данные для доступа к внешнему ресурсу, например к базе данных. Вашему приложению необходимы эти ключи во время работы, поэтому вам нужно предоставить их при развертывании приложения или на этапе подготовки окружения.
В данной статье я покажу вам, как использовать git-crypt так, чтобы вы могли безопасно хранить секреты ваших приложений в репозиториях исходного кода, даже публичных.


Проблема с секретами приложений


Большинство проектов имеют различные ключи или данные для входа. Например, если ваше приложение располагается на Heroku, вы можете предоставить ключ API приложению Heroku, используя команды вроде этих:


$ heroku config:set API_KEY=my-sooper-sekrit-api-key

Запуская эту команду до того, как вы (снова) развернете приложение, вы передаете переменную окружения с именем API_KEY и значением my-sooper-sekrit-api-key. Однако продолжать отслеживать значения этих переменных вне Heroku (или где бы вы ни развертывали свое приложение) все еще проблематично.


Я всегда стараюсь настроить мои проекты так, чтобы я мог запустить развертку с нуля одной командой, без каких-либо дополнительных шагов. В нашем примере это означает, что мне нужно хранить значение my-sooper-sekrit-api-key где-то для того, чтобы мой развертываемый код мог использовать его (в данном случае, для запуска heroku config:set… командой выше).


Исходный код моего проекта всегда хранится на git и обычно располагается на github.com или bitbucket.com или на другом сервисе хостинга. Я могу хранить значение API_KEY в своем репозитории исходного кода, однако есть и недостатки:


  • Я не могу поделиться репозиторием, и не дать доступа к моим секретам. Это значит, что репозиторий моего приложения с секретами должен быть приватным.
  • Предположительно многие участники Github/bitbucket/прочего тоже получили бы доступ к моим секретам, с чем я мог бы не согласиться (в зависимости от секрета).
  • Можно легко забыть о наличии секретов в приватных репозиториях, если позже решишь сделать его публичным. Это могло бы случайно раскрыть важный секрет.

Я могу хранить секреты отдельно от исходного кода приложения, но и это имеет проблемы:


  • Необходим способ доставать секреты, независимо от того, где они находятся, во время или после развертывания, и дать моему коду развертки доступ до них.
  • Мои секреты могут не храниться так же надежно, как исходный код. К примеру, можно хранить секреты в файлах типа .env на ноутбуке, и быть уверенным, что мне не придется сверяться с git репозиторием. Однако, если я потеряю этот файл (например, если ноутбук сломается\потеряется), то секрет пропадет вместе с ним.

git-crypt


Git-crypt позволяет решить эту проблему шифрованием ваших секретов, когда загружаете их в git репозиторий, и расшифровкой, когда необходимо их извлечь. С вашей точки зрения все происходит прозрачно. То есть секреты находятся в открытом виде как для вас, так и для вашего экземпляра развертывания, но никто кроме вас не сможет читать их, даже если исходный код располагается в публичном в репозитории GitHub.


Рассмотрим пример.


1. Установка git-crypt.


Инструкция для Linux, Mac, и Windows на странице установки git-crypt.


Если вы, как и я, используете Mac с установленным Homebrew, вы можете запустить:


$ brew install git-crypt

2. Создайте новый git репозиторий.


$ mkdir myproject 
$ cd myproject 
$ git init 
$ echo "This is some text" > file.txt 
$ git add file.txt 
$ git commit -m "Initial commit"

Теперь у нас есть репозиторий с одним текстовым файлом.


3. Настройка репозитория для git-crypt.


$ git-crypt init

Вы должны увидеть следующее:


Generating key...

Перед тем, как мы сделаем что-либо еще, пожалуйста, запустите следующую команду:


$ git-crypt export-key ../git-crypt-key

Эта команда создает копию симметричного ключа git-crypt, который сгенерирован для этого репозитория. Поместим его в директорию на уровень выше этого репозитория, так чтобы можно было использовать один ключ в нескольких git репозиториях.


По стандарту, git-crypt хранит все созданные ключи в файле .git/git-crypt/keys/default, так что вы можете достичь тех же результатов запустив cp .git/git-crypt/keys/default ../git-crypt-key

Файл git-crypt-key очень важен. Это ключ, который открывает все зашифрованные файлы в нашем репозитории. Дальше мы рассмотрим как использовать его.


4. Укажите git-crypt какой файл зашифровать.


Представим, что нашему приложению нужен API ключ, и мы собираемся хранить его в файле с именем api.key.


До того, как добавим этот файл в репозиторий, мы укажем git-crypt, что хотим, чтобы каждый раз при совершении коммита, api.key был зашифрован.


Мы делаем это, используя файл .gitattributes. Его можно использовать, чтобы добавить дополнительные метаданные в git репозиторий. Это не особенность git-crypt, так что файл .gitattributes может уже существовать в вашем репозитории. В таком случае просто добавьте актуальные строки, не заменяя весь файл.


У нас же .gitattributes нет, поэтому его необходимо создать. Файл должен содержать строки вида:


[file pattern] attr1=value1 attr2=value2

Для git-crypt, шаблон должен соответствовать всем файлам, которые должны быть зашифрованы. Атрибуты всегда одинаковы: filter и diff, которые мы установили в настройках git-crypt.


Так, наш .gitattributes должен содержать:


api.key filter=git-crypt diff=git-crypt

Создайте такой файл, добавьте и загрузите его в свой репозиторий:


$ echo "api.key filter=git-crypt diff=git-crypt" > .gitattributes 
$ git add .gitattributes 
$ git commit -m "Tell git-crypt to encrypt api.key"

Я использовал конкретное имя файла api.key в .gitattributes, но это может быть и любой шаблон, включающий в себя файлы для шифрования, так что я мог использовать, например, *.key. В качестве альтернативы, просто добавьте строку для каждого файла, который хотите зашифровать.


Легко совершить ошибку при создании .gitattributes, если вы пытаетесь защитить сразу несколько файлов с единственным шаблоном. Поэтому я настоятельно рекомендую прочесть раздел README из git-crypt, в котором выделено несколько распространенных ошибок.


5. Добавим секрет.


Теперь, когда мы указали git-crypt, что хотим зашифровать api.key, давайте добавим этот файл в репозиторий.


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

$ echo "dummy value" > api.key

Мы еще не добавили api.key в git, но можем проверить, что cделает git-crypt, запустив команду:


$ git-crypt status

Вывод должен быть следующим:


   encrypted: api.key 
not encrypted: .gitattributes 
not encrypted: file.txt

Итак, даже если api.key еще не был загружен в репозиторий, такое сообщение говорит о том, что при совершении коммита git-crypt зашифрует его.


Давайте выполним добавление и коммит файла:


$ git add api.key 
$ git commit -m "Added the API key file"

6. Подтвердим шифрование секрета.


Мы указали git-crypt файл для шифрования, добавили api.key в репозиторий, однако, если мы посмотрим, то не увидим разницы:


$ cat api.key 
dummy value

Причина в том, что git-crypt шифрует и дешифрует файлы прозрачно, как во время загрузки, так и во время извлечения. Поэтому api.key выглядит как обычный текстовый файл в открытом виде.


$ file api.key 
api.key: ASCII text

Один из способов подтвердить, что ваши файлы действительно зашифрованы – загрузить их в репозиторий GitHub. Когда вы будете просматривать api.key через интерфейс GitHub, то увидите зашифрованный двоичный файл, а не текст.


Более простой способ посмотреть, как репозиторий будет выглядеть для кого-нибудь без ключа дешифрования, это запустить команду:


$ git-crypt lock

Теперь, если мы прочитаем api.key, все будет выглядеть по другому:


$ file api.key 
api.key: data 

$ cat api.key 
GITCRYPTROܮ7y\R*^

Вы увидите отличающийся от моего мусор, но ясно, что файл зашифрован. Это то, что будет храниться на GitHub.


Чтобы вернуться к открытому виду файла api.key, выполните:


$ git-crypt unlock ../git-crypt-key

../git-crypt-key — это файл, который мы сохранили ранее с помощью git-crypt export-key...


Итак, что мы узнали?


Давайте сделаем быстрый обзор того, что уже известно


  • Инициализация git-crypt в git репозитории через git-crypt init
  • Использование шаблонов в .gitattributes, чтобы указать git-crypt какие файлы шифровать
  • git-crypt lock зашифрует все указанные файлы в нашем репозитории
  • git-crypt unlock [путь до файла ключа] расшифрует зашифрованные файлы

git-crypt-key очень важен. Без него будет невозможно дешифровать какие бы то ни было зашифрованные файлы в вашем репозитории. Кто угодно, получив копию этого файла, получит доступ ко всем зашифрованным секретам в репозитории. Поэтому необходимо держать его в безопасности.


Повторное использование ключа git-crypt


Мы использовали git-crypt init и git-crypt export-key, чтобы создать файл git-crypt-key. Но если бы нам нужно было использовать отдельные ключи для каждого репозитория, то это не очень-то и улучшило бы нашу систему управления секретами.


К счастью, можно довольно легко использовать один и тот же ключ git-crypt для нескольких git репозиториев.


Чтобы использовать уже существующий ключ, просто запустите git-crypt unlock вместо git-crypt init, когда настраиваете ваш репозиторий для git-crypt, вроде этого:


$ mkdir my-other-project   # At the same directory level as `myproject` 
$ cd my-other-project 
$ git init 
$ echo "Something" > file.txt 
$ git add file.txt 
$ git commit -m "initial commit" 
$ git-crypt unlock ../git-crypt-key

Если вы запустите git-crypt unlock не добавив ни одного файла в git репозиторий, то увидите сообщение вроде такого:

fatal: You are on a branch yet to be born 
Error: 'git checkout' failed 
git-crypt has been set up but existing encrypted files have not been decrypted

Это по-прежнему неплохо работает, но слегка сбивает с толку, поэтому я убедился, что добавил и совершил коммит как минимум одного файла, до запуска git-crypt unlock...

Повторное использование ключа git-crypt удобно, но это значит, что если кто-либо получит ваш ключ, все ваши зашифрованные секреты раскроются.


Это такой же вид компромисса, как и при использовании менеджеров паролей, вроде LastPass или 1password. Вместо того, чтобы управлять несколькими секретами (паролями), каждый со своим риском взлома, вы храните их все в одном защищенном хранилище, и используете один мастер пароль для разблокировки.


Когда НЕ стоит использовать git-crypt


Git-crypt это прекрасный способ хранить нужные вашим приложениям секреты прямо в git репозитории, рядом с исходным кодом. Однако, как и другие меры безопасности, это не всегда будет уместно или целесообразно.


Чтобы определить, является ли это решение подходящим для вашего проекта, стоит учесть пару вещей:


  • git-crypt разработан для ситуаций, когда большинство файлов в вашем git репозитории могут оставаться в открытом виде, а зашифровать нужно лишь малую часть из них, в которых есть секреты. Если вам нужно зашифровать большую часть репозитория, возможно вам лучше подойдет другое решение.
  • Нет простого способа отозвать доступ к секретам в репозитории, если вы уже дали кому-то ключ-файл, как и нет простого способа изменить (т.е. заменить) ключ-файл (и даже его изменение не особо помогает, если только не поменять все действующие секреты в репозитории).
  • git-crypt шифрует только содержимое файлов. Таким образов, он не подходит, если так же важны метаданные вашего репозитория (т.е. имена файлов, дата изменения, сообщения коммита и т.д.).
  • Некоторые GUI-приложения git могут работать с git-crypt ненадежно. (Хотя конкретный случай Atlassian SourceTree, указанный в README, уже исправлен).

Больше информации в этом разделе README git-crypt.

Лучший способ использовать git-crypt


Вместо того, чтобы управлять ключ-файлом git-crypt вручную, можно включить в проект git-crypt вместе с gpg, и тогда вы сможете использовать приватный ключ gpg для дешифровки вашего git репозитория. Это так же позволит вам добавлять различных соавторов в репозиторий без обмена секретами между группами. Однако это требует гораздо более сложной настройки, что мы оставим для другой статьи.




Переводчик: DanayDemenir
Редактор: DariaRogoz

Источник: https://habr.com/ru/company/nixys/blog/570306/


Интересные статьи

Интересные статьи

В микросервисных продуктах гораздо сложнее, чем в монолитах, выстраивать последовательные цепочки операций. Распределённые транзакции создают угрозу несогласованности дан...
Однажды, в понедельник, мне пришла в голову мысль — "а покопаюсь ка я в новом ядре" (новым относительно, но об этом позже). Мысль не появилась на ровном месте, а предпосылками для нее стали: ...
Бизнес-смыслы появились в Битриксе в начале 2016 года, но мало кто понимает, как их правильно использовать для удобной настройки интернет-магазинов.
Эта статья для тех, кто собирается открыть интернет-магазин, но еще рассматривает варианты и думает по какому пути пойти, заказать разработку магазина в студии, у фрилансера или выбрать облачный серви...
Одной из «киллер-фич» 12й версии Битрикса была объявлена возможность отдавать статические файлы из CDN, тем самым увеличивая скорость работы сайта. Попробуем оценить практический выигрыш от использова...