当涉及处理机密信息(如密码、令牌、密钥文件等)等,以下问题值得考虑:

  • 安全性十分重要,但高安全性往往伴随着高度的不便。

  • 在团队中,共享某些密钥有时无法避免(因此现在我们需要考虑在多人之间分发和更新密钥的安全方法)。

  • 具体的密钥通常取决于环境。

目前市面上已经存在许多较为成熟的密钥管理产品,比如 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

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

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

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,然后导出、列出和导入私有 gpg Key,可以通过以下方式导出:

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调整等内容,保持关注哦~

git-secret:在 Git 存储库中加密和存储密钥(上)的更多相关文章

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

    在之前的文章中(点击此处查看上一篇文章),我们了解了如何识别包含密钥的文件,将密钥添加到 .gitignore ,通过 git-secret 进行加密,以及将加密文件提交到存储库.在本篇文章中,将带你 ...

  2. git 从存储库中删除敏感数据(删除文件历史)

    1.如果您的历史记录中还没有包含敏感数据的存储库的本地副本,请将存储库克隆到本地计算机. git clone https://github.com/YOUR-USERNAME/YOUR-REPOSIT ...

  3. 无法将分支 master 发布到远程 origin,因为远程存储库中已存在具有同一名称的分支

    无法将分支 master 发布到远程 origin,因为远程存储库中已存在具有同一名称的分支.发布此分支将导致远程存储库中的分支发生非快进更新. 第一次用oschina的git设置完远程仓库后提交出现 ...

  4. 【Cocos2d-X开发学习笔记】第29期:游戏中数据的存储(上)

    本系列学习教程使用的是cocos2d-x-2.1.4(最新版为3.0alpha0-pre) ,PC开发环境Windows7,C++开发环境VS2010 一般游戏中都需要记录玩家数据,便于玩家下次登录时 ...

  5. 本地git部署web连接azure的git存储库

    ​​​本地git部署web 创建本地存储仓库 输入以下命令创建git本地仓库(会在当前目录下生产一个.git的目录) git init 然后提交内容 在git仓库所在的目录下存放好需要的网页文件 将文 ...

  6. g4e基础篇#4 了解Git存储库(Repo)

    章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git 分布式版本控制系统的优势 Git 安装和设置 了解Git存储库(Repo) 起步 1 – 创建分支和保存代码 起步 2 – 了解Git ...

  7. git rebase VS git merge? 更优雅的 git 合并方式值得拥有

    写在前面 如果你不能很好的应用 Git,那么这里为你提供一个非常棒的 Git 在线练习工具 Git Online ,你可以更直观的看到你所使用的命令会产生什么效果 另外,你在使用 Git 合并分支时只 ...

  8. git rebase VS git merge

    git rebase VS git merge 写在前面 如果你不能很好的应用 Git,那么这里为你提供一个非常棒的 Git 在线练习工具 Git Online(回复公众号「工具」,获取更多内容) , ...

  9. Git安装/VScode+Git+Github

    Git安装/VScode+Git+Github 1. 相关简介 git 版本控制工具,支持该工具的网站有Github.BitBucket.Gitorious.国内的OS China仓库.Csdn仓库等 ...

随机推荐

  1. 请问为啥计算器16进制FFFFFFFFFFFF时10进制是-1?

    请问为啥计算器16进制FFFFFFFFFFFF时10进制是-1?

  2. Go语言基础二:常用的Go工具命令

    常用的Go工具命令 Go附带了一下有用的命令,这些命令可以简化开发的过程.命令通常包含的IDE中,从而使工具在整个开发环境中保持一致. go run 命令 go run命令实在开发过程中执行的最常见的 ...

  3. get 和 post 的区别

    1. get 提交的信息显示在地址栏中 post 提交的信息不显示在地址栏中 2. get 对于敏感数据信息不安全,因为信息显示在地址栏中 post 对于敏感数据安全 3. get 不支持大数据量请求 ...

  4. 使用.NET简单实现一个Redis的高性能克隆版(三)

    译者注 该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单.高性能兼容Redis协议的数据库的经历. 首先这个"Redis"是非常简单的实现,但是他 ...

  5. 如何实现 System.out.println("a") 显示 b

    今天看到一篇文章不用反射,能否交换两个字符串的值. 心想字符串常量在常量池里面,是在就算用了反射也交换不了吧.转念一想,不对,字符串常量虽然本身在常量池里面,但是它依然是个对象,那么 private ...

  6. Luogu2574 XOR的艺术 (分块)

    本是要练线段树的,却手贱打了个分块 //#include <iostream> #include <cstdio> #include <cstring> #incl ...

  7. centos/windows服务器,Mysql数据库表结构损坏-已解决

    [问题原因]服务器突然断电 [故障报告]数据库表结构损坏 [解决思路]进入强制恢复模式,备份库表及数据重建 故障发现 周末公司断电,周一启动数据库就直接报错了 查看日志 上面标记的log,明确表示是非 ...

  8. HTML(下)

    (一)表格标签 1.表格的作用 用于显示.展示数据,让数据更加规整,可读性更好,把繁琐的数据表现得很有条理,表格不是用来布局页面的,而是用来展示数据的 2.表格标签基本语法 table--table ...

  9. 一、JDK和JRE

    JDK和JRE JDK=JRE+开发工具包: JRE=JVM+核心类库 如果只是运行Java程序,安装JRE即可:开发Java程序并运行则需要安装JDK.目前最稳定版本是JDK8.0,并且马上部分企业 ...

  10. PerfView专题 (第八篇):洞察 C# 内存泄漏之寻找静态变量名和GC模式

    一:背景 这篇我们来聊一下 PerfView 在协助 WinDbg 分析 Dump 过程中的两个超实用技巧,可能会帮助我们快速定位最后的问题,主要有如下两块: 洞察内存泄漏中的静态大集合变量名. 验证 ...