Шифрование файлов в git-репозитории с помощью git-crypt

Nov 20, 2017 10:37 · 694 words · 4 minute read git git-crypt

Иногда возникает необходимость в шифровании определенных файлов в репозитории (например, ключи или пароли), особенно если нет возможности/желания хранить эти файлы отдельно.

Давайте разберемся с использованием утилиты git-crypt, которая обеспечивает прозрачное шифрование и дешифрование файлов в git-репозитории!

С помощью git-crypt выбранные файлы шифруются при их фиксации и дешифруются при извлечении, таким образом можно свободно работать с репозиторием, содержащим публичный и частный контент (даже разработчики без секретного ключа все еще могут клонировать и фиксировать изменения в репозитории с зашифрованными файлами). Это дает возможность хранить «секретные» материалы в том же хранилище, что и код, без необходимости ограничения доступа на весь репозиторий.

Итак, для начала установим утилиту (в примере используется ОС Ubuntu 16.04.3 LTS x86_64):

git clone https://www.agwa.name/git/git-crypt.git
cd git-crypt && make && make install

Ознакомиться с использованием утилиты можно вызвав команду:

git-crypt help

Клонируем реозиторий, над которым будем проводить тесты (в данном примере используется репозиторий из «локального» Gitlab, развернутого в docker-контейнерах):

git clone ssh://git@gitlab.lc:23/develop/test.git test
Cloning into 'test'...
remote: Counting objects: 1832, done.
remote: Compressing objects: 100% (1430/1430), done.
remote: Total 1832 (delta 276), reused 1824 (delta 275)
Receiving objects: 100% (1832/1832), 179.14 MiB | 91.22 MiB/s, done.
Resolving deltas: 100% (276/276), done.
Checking connectivity... done.

Настраиваем git-репозиторий на использование git-crypt:

cd test
git-crypt init
Generating key...

При этом, в репозитории в каталоге .git/git-crypt/keys будет создан симметричный ключ (файл default), который и будет использоваться при шифровании/расшифровке файлов.

Данный симметричный ключ можно просто скопировать (через cp) в отдельное хранилище или «извлечь» с помощью команды (ключ будет сохранен в файл secret в домашнем каталоге пользователя):

git-crypt export-key ~/secret

Содержимое файла выглядит примерно так:

cat secret 
GITCRYPTKEY ��Z���UWwެ[w>W�L_&�v�k���"q�a�@��ԃ�#ȶ�c6ZGfl�-Sk}�D�Ճ�@,\O�S�%������6Ɲ �$����$�w��h��

В корне git-репозитория создаем файл .gitattributes, в котором будут перечислены файлы для шифрования:

touch .gitattributes

Содержимое файла будет примерно таким (как и в файле .gitignore, можно использовать wildcards):

secret filter=git-crypt diff=git-crypt
*.key filter=git-crypt diff=git-crypt
.env.* filter=git-crypt diff=git-crypt

Создаем файл, в котором будут храниться «секреты»:

touch secret

В этот файл я для примера записал свой номер телефона:

cat secret
+380976601216

Фиксируем изменения и пушим их в репозиторий:

git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add ..." to include in what will be committed)

	.gitattributes
	secret

nothing added to commit but untracked files present (use "git add" to track)
git add .
git commit -m "test commit"
[master d6fa879] test commit
 2 files changed, 1 insertion(+)
 create mode 100644 .gitattributes
 create mode 100644 secret
git push
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (4/4), 1.08 KiB | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To ssh://git@gitlab.lc:23/develop/test.git
   4d2bff3..d6fa879  master -> master

Теперь опять клонируем репозиторий но уже в другой каталог (моделируем работу с репозиторием на машине другого разработчика):

git clone ssh://git@gitlab.lc:23/develop/test.git test1
Cloning into 'test1'...
remote: Counting objects: 1853, done.
remote: Compressing objects: 100% (1440/1440), done.
remote: Total 1853 (delta 281), reused 1849 (delta 280)
Receiving objects: 100% (1853/1853), 179.15 MiB | 94.35 MiB/s, done.
Resolving deltas: 100% (281/281), done.
Checking connectivity... done.

Проверяем содержимое нашего «секретного» файла:

cd test1
cat secret 
GITCRYPTb���!��y��M��J[][G��
B⏎

Расшифруем все зашифрованные файлы в репозитории командой (в качестве аргумента команды unlock указываем путь к извлеченному ранее симметричному ключу):

git-crypt unlock ~/secret

Проверяем теперь содержимое нашего «секретного» файла:

cat secret 
+380976601216

Дальше с репозиторием можно работать в обычном режиме.

Можно также собрать docker-образ с утилитой git-crypt по такому набору инструкций (Dockerfile):

FROM alpine:edge
 
ENV VERSION 0.5.0-2
 
RUN apk --update add bash curl git g++ make openssh openssl openssl-dev \
   && curl -L https://github.com/AGWA/git-crypt/archive/debian/$VERSION.tar.gz | tar zxv -C /var/tmp \
   && cd /var/tmp/git-crypt-debian-${VERSION} && make && make install PREFIX=/usr/local \
   && apk del curl \
   && rm -rf /var/cache/apk/*
 
WORKDIR /repo
VOLUME /repo
CMD ["/bin/bash"]

Примечание. Можно даже добавить извлеченный ранее симметричный ключ в этот docker-образ, но не стоит забывать о безопасности.

Собираем образ командой:

docker build --squash -t docker-gc -f Dockerfile .

Расшифровать «секретные» файлы в репозитории теперь можно и с помощью собранного docker-образа, например так:

docker run -it --rm -v $(pwd):/repo -v /home/e.lebed/secret:/repo/.git/.git-crypt/keys/default --user ${id} docker-gc:latest git-crypt unlock /repo/.git/.git-crypt/keys/default

Здесь $(pwd) — текущая директория, ${id} — UID пользователя, под которым был склонирован git-репозиторий (в данном примере e.lebed).

Больше информации об утилите git-crypt можно найти здесь.

tweet Share