Шифрование файлов в git-репозитории с помощью git-crypt
Nov 20, 2017 10:37 · 694 words · 4 minute read
Иногда возникает необходимость в шифровании определенных файлов в репозитории (например, ключи или пароли), особенно если нет возможности/желания хранить эти файлы отдельно.
Давайте разберемся с использованием утилиты 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
можно найти здесь.