git-secret:在 Git 存储库中加密和存储密钥(上)

目前市面上已经存在许多较为成熟的密钥管理产品,比如 HashiCorp Vault,AWS Secrets Manager 以及 GCP Secret
Manager。由于这些产品需要集成和维护等服务,因此在项目中引入会增加一定成本和开销。阅读本文,将带你了解如何在 Docker 容器中设置git- secretgpg

本文将对以下几点展开讲解:

  • 识别包含密钥的文件

  • 确保将密钥添加到.gitignore

  • 通过git-secret进行加密

  • 将加密文件提交到存储库

在最后我们将能够调用:

make secret-decrypt

这将会披露代码库中的密钥,在必要时对其进行修改,然后运行:

make secret-encrypt

需要再次加密密钥,以便提交(并推送到远程存储库),要查看实际效果请运行以下命令:

# checkout the branch
git checkout part-6-git-secret-encrypt-repository-docker

# build and start the docker setup
make make-init
make docker-build
make docker-up

# "create" the secret key - the file "secret.gpg.example" would usually NOT live in the repo!
cp secret.gpg.example secret.gpg

# initialize gpg
make gpg-init

# ensure that the decrypted secret file does not exist
ls passwords.txt

# decrypt the secret file
make secret-decrypt

# show the content of the secret file
cat passwords.txt

Tooling

我们在 PHPbase镜像中设置gpggit- secret以便这些工具在所有其他容器中都可用。以下所有命令都在application容器中执行。

请注意,git-secret在主机系统和 docker 容器之间共享的文件夹中使用时需要注意。将在下面称为 “git-secret目录和gpg- agentsocket”的部分中更详细地解释这一点。

gpg

gpg 是The GNU Privacy Guard的缩写,是 OpenPGP 标准的开源实践。简而言之,GNU允许我们创建一个个人密钥文件对(类似于
SSH 密钥),其中包含一个私有密钥和一个可以与您想要解密其消息的其他方共享的公共密钥。

gpg 安装

关于安装,我们可以简单地运行apk add gnupg并相应更新.docker/images/php/base/Dockerfile

# File: .docker/images/php/base/DockerfileRUN apk add --update --no-cache \
        bash \
        gnupg \
        make \
#...

创建 gpg 密钥对

我们需要通过以下方式创建gpg密钥对(Key Pair):

name="Pascal Landau"
email="pascal.landau@example.com"
gpg --batch --gen-key <<EOF
Key-Type: 1
Key-Length: 2048
Subkey-Type: 1
Subkey-Length: 2048
Name-Real: $name
Name-Email: $email
Expire-Date: 0
%no-protection
EOF

%no-protection创建一个没有密码的key。

输出:

$ name="Pascal Landau"
$ email="pascal.landau@example.com"
$ gpg --batch --gen-key <<EOF
> Key-Type: 1
> Key-Length: 2048
> Subkey-Type: 1
> Subkey-Length: 2048
> Name-Real: $name
> Name-Email: $email
> Expire-Date: 0
> %no-protection
> EOF
gpg: key E1E734E00B611C26 marked as ultimately trusted
gpg: revocation certificate stored as '/root/.gnupg/opengpg-revocs.d/74082D81525723F5BF5B2099E1E734E00B611C26.rev'

也可以在没有--batch标志的情况下以交互方式引导整个过程运行gpg --gen- key,然后导出、列出和导入私有gpgKey,可以通过以下方式导出:

email="pascal.landau@example.com"
path="secret.gpg"
gpg --output "$path" --armor --export-secret-key "$email"

记住不能共享此密钥。

-----BEGIN PGP PRIVATE KEY BLOCK-----

lQOYBF7VVBwBCADo9un+SySu/InHSkPDpFVKuZXg/s4BbZmqFtYjvUUSoRAeSejv
G21nwttQGut+F+GdpDJL6W4pmLS31Kxpt6LCAxhID+PRYiJQ4k3inJfeUx7Ws339
XDPO3Rys+CmnZchcEgnbOfQlEqo51DMj6mRF2Ra/6svh7lqhrixGx1BaKn6VlHkC
...
ncIcHxNZt7eK644nWDn7j52HsRi+wcWsZ9mjkUgZLtyMPJNB5qlKQ18QgVdEAhuZ
xT3SieoBPd+tZikhu3BqyIifmLnxOJOjOIhbQrgFiblvzU1iOUOTOcSIB+7A
=YmRm
-----END PGP PRIVATE KEY BLOCK-----

所有密钥都可以通过以下方式列出:

gpg --list-secret-keys

输出:

$ gpg --list-secret-keys
/root/.gnupg/pubring.kbx
------------------------
sec rsa2048 2022-03-27 [SCEA]
      74082D81525723F5BF5B2099E1E734E00B611C26
uid [ultimate] Pascal Landau <pascal.landau@example.com>
ssb rsa2048 2022-03-27 [SEA]

可以通过以下方式导入私钥:

path="secret.gpg"
gpg --import "$path"

得到以下输出:

$ path="secret.gpg"
$ gpg --import "$path"
gpg: key E1E734E00B611C26: "Pascal Landau <pascal.landau@example.com>" not changed
gpg: key E1E734E00B611C26: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys unchanged: 1

注意:如果secret key需要密码,这里会提示输入密码。我们可以使用以下方法绕过提示--batch --yes --pinentry-mode loopback

path="secret.gpg"
gpg --import --batch --yes --pinentry-mode loopback "$path"

目前还不需要提供密码,但需要在稍后尝试解密文件时提供。

导出、列出和导入gpg公钥,可以通过以下方式导出public.gpg

email="pascal.landau@example.com"
path="public.gpg"
gpg --armor --export "$email" > "$path"

导出如下:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBF7VVBwBCADo9un+SySu/InHSkPDpFVKuZXg/s4BbZmqFtYjvUUSoRAeSejv
G21nwttQGut+F+GdpDJL6W4pmLS31Kxpt6LCAxhID+PRYiJQ4k3inJfeUx7Ws339
...
3LLbK7Qxz0cV12K7B+n2ei466QAYXo03a7WlsPWn0JTFCsHoCOphjaVsncIcHxNZ
t7eK644nWDn7j52HsRi+wcWsZ9mjkUgZLtyMPJNB5qlKQ18QgVdEAhuZxT3SieoB
Pd+tZikhu3BqyIifmLnxOJOjOIhbQrgFiblvzU1iOUOTOcSIB+7A
=g0hF
-----END PGP PUBLIC KEY BLOCK-----

通过以下方式列出所有公钥:

gpg --list-keys

输出:

$ gpg --list-keys
/root/.gnupg/pubring.kbx
------------------------
pub rsa2048 2022-03-27 [SCEA]
      74082D81525723F5BF5B2099E1E734E00B611C26
uid [ultimate] Pascal Landau <pascal.landau@example.com>
sub rsa2048 2022-03-27 [SEA]

通过以下方式以与私钥相同的方式导入公钥:

path="public.gpg"
gpg --import "$path"

例如:

$ gpg --import /var/www/app/public.gpg
gpg: key E1E734E00B611C26: "Pascal Landau <pascal.landau@example.com>" not changed
gpg: Total number processed: 1
gpg: unchanged: 1

git-secret

git-secret的官方网站可以找到详细介绍该工具的内容。git-
secret允许将某些文件声明为“secret”并通过gpg加密。然后可以将加密的文件直接安全地存储在 Git
存储库中,并在需要时进行解密。本文使用git-secret v0.4.0

$ git secret --version
0.4.0

git-secret 安装

Alpine 的安装说明如下:

sh -c "echo 'https://gitsecret.jfrog.io/artifactory/git-secret-apk/all/main'" >> /etc/apk/repositories
wget -O /etc/apk/keys/git-secret-apk.rsa.pub 'https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk'
apk add --update --no-cache git-secret

.docker/images/php/base/Dockerfile进行更新:

# File: .docker/images/php/base/Dockerfile

# install git-secret
# @see https://git-secret.io/installation#alpine
ADD https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk /etc/apk/keys/git-secret-apk.rsa.pub

RUN echo "https://gitsecret.jfrog.io/artifactory/git-secret-apk/all/main" >> /etc/apk/repositories && \
    apk add --update --no-cache \
        bash \
        git-secret \
        gnupg \
        make \
#...

git-secret 用法

初始化 git-secret

git-secret通过在 Git 存储库的根目录中运行的以下命令进行初始化。

git secret init$ git secret init
git-secret: init created: '/var/www/app/.gitsecret/'

只需这样操作一次,稍后会把文件夹提交到 Git,将包含以下文件:

$ git status | grep ".gitsecret"
        new file: .gitsecret/keys/pubring.kbx
        new file: .gitsecret/keys/pubring.kbx~
        new file: .gitsecret/keys/trustdb.gpg
        new file: .gitsecret/paths/mapping.cfg

pubring.kbx~文件(带有波浪号~)只是一个临时文件,可以安全地被 git 忽略。

git-secret Directory 和 gpg-agent Socket

git-secret在主机系统和 Docker 之间共享的目录中使用,还需要运行以下命令:

tee .gitsecret/keys/S.gpg-agent <<EOF
%Assuan%
socket=/tmp/S.gpg-agent
EOF

tee .gitsecret/keys/S.gpg-agent.ssh <<EOF
%Assuan%
socket=/tmp/S.gpg-agent.ssh
EOF

tee .gitsecret/keys/gpg-agent.conf <<EOF
extra-socket /tmp/S.gpg-agent.extra
browser-socket /tmp/S.gpg-agent.browser
EOF

这一步很必要,因为git-secret在主机系统和 Docker 容器之间共享代码库的设置中使用时存在问题,具体如下:

  • gpg使用gpg-agent来执行其任务,这两个工具通过在pgp-agent--home-directory中创建的套接字进行通信。

  • 代理通过git-secret使用的gpg命令隐式启动,使用.gitsecret/keys目录作为--home-directory

  • 由于--home-directory的位置与主机系统共享,因此套接字创建将失败。

对应的错误信息是:

gpg: can't connect to the agent: IPC connect call failed

gpg-agent: error binding socket to '/var/www/app/.gitsecret/keys/S.gpg-agent': I/O error

解决此问题,可以通过将其他 gpg 配置文件放在.gitsecret/keys目录中,将gpg配置为对套接字使用不同的位置:

S.gpg-agent

%Assuan%
socket=/tmp/S.gpg-agent

s.gpg-agent.ssh

%Assuan%
socket=/tmp/S.gpg-agent

gpg-agent.conf

extra-socket /tmp/S.gpg-agent.extra
browser-socket /tmp/S.gpg-agent.browser

添加、列出和删除用户

要添加新用户,必须首先导入其公用 gpg 密钥。然后运行:

email="pascal.landau@example.com"
git secret tell "$email"

在这种情况下,用户pascal.landau@example.com现在将能够解密这些密钥。要显示用户请运行:

git secret whoknows$ git secret whoknows
pascal.landau@example.com

要删除用户,请运行:

email="pascal@example.com"
git secret killperson "$email"

这时此命令在git-secret >= 0.5.0中已重命名为removeperson

$ git secret killperson pascal.landau@example.com
git-secret: removed keys.
git-secret: now [pascal.landau@example.com] do not have an access to the repository.
git-secret: make sure to hide the existing secrets again.

用户 pascal@example.com 将无法再解密这些密钥。

注意删除用户后需要重新加密机密,并轮换加密的密钥。

添加、列出和删除文件以进行加密

运行git secret add [filenames...]来为文件加密:

git secret add .env

如果.env没有被添加到.gitignoregit-secret将显示警告并自动添加。

git-secret: these files are not in .gitignore: .env
git-secret: auto adding them to .env
git-secret: 1 item(s) added.

如已添加,则添加文件时不会发出警告。

$ git secret add .env
git-secret: 1 item(s) added.

只需要添加一次文件。然后将它们存在.gitsecret/paths/mapping.cfg:

$ cat .gitsecret/paths/mapping.cfg
.env:505070fc20233cb426eac6a3414399d0f466710c993198b1088e897fdfbbb2d5

还可以通过以下方式显示添加的文件:

git secret list$ git secret list
.env

需要主要的是,这个时候文件尚未加密,如果要从加密中删除文件,请运行:

git secret list$ git secret list
.env

输出:

$ git secret remove .env
git-secret: removed from index.
git-secret: ensure that files: [.env] are now not ignored.

加密文件

要加密文件,请运行:

git secret hide

输出:

$ git secret hide
git-secret: done. 1 of 1 files are hidden.

所有通过git secret tell被添加的用户能够解密这些已经加密的文件,这也意味着每当添加新用户时,您都需要再次运行此命令。

解密文件

可以通过以下方式解密文件:

git secret reveal

输出:

$ git secret reveal
File '/var/www/app/.env' exists. Overwrite? (y/N) y
git-secret: done. 1 of 1 files are revealed.
  • 文件被解密并将覆盖当前未加密的文件。

  • 使用-f选项强制覆盖并以非交互方式运行。

  • 如果只想检查加密文件的内容,可以使用git secret cat $filename例如,git secret cat. env

gpg密钥受密码保护时,需要通过-p选项传递密码。以下是密码示例123456

git secret reveal -p 123456

显示加密和解密文件间的变化

加密文件的一个问题是,无法在远程工具的代码审查期间审查加密文件。为了了解进行了哪些更改,显示加密文件和解密文件之间的更改能够帮助解决这个问题。可以通过以下方式完成:

git secret changes

输出:

$ echo "foo" >> .env
$ git secret changes
git-secret: changes in /var/www/app/.env:
--- /dev/fd/63
+++ /var/www/app/.env
@@ -34,3 +34,4 @@
 MAIL_ENCRYPTION=null
 MAIL_FROM_ADDRESS=null
 MAIL_FROM_NAME="${APP_NAME}"
+foo

注意底部的+foo. 它是通过在第一行echo "foo">>>.env添加的。

本文是git-secret用法的上篇,在下篇中我们将会介绍git-secret的初始设置、Makefile调整等内容,保持关注哦~

网络安全工程师企业级学习路线

这时候你当然需要一份系统性的学习路线

如图片过大被平台压缩导致看不清的话,可以在文末下载(无偿的),大家也可以一起学习交流一下。

一些我收集的网络安全自学入门书籍

一些我白嫖到的不错的视频教程:

上述资料【扫下方二维码】就可以领取了,无偿分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值