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

от автора

Большинство программных проектов используют секреты – обычно, как ключи к удаленному 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/articles/570306/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *