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

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

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

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

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

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

  • 识别包含密钥的文件

  • 确保将密钥添加到.gitignore

  • 通过 git-secret 进行加密

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

在最后我们将能够调用:

  1. make secret-decrypt

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

  1. make secret-encrypt

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

  1. # checkout the branch
  2. git checkout part-6-git-secret-encrypt-repository-docker
  3. # build and start the docker setup
  4. make make-init
  5. make docker-build
  6. make docker-up
  7. # "create" the secret key - the file "secret.gpg.example" would usually NOT live in the repo!
  8. cp secret.gpg.example secret.gpg
  9. # initialize gpg
  10. make gpg-init
  11. # ensure that the decrypted secret file does not exist
  12. ls passwords.txt
  13. # decrypt the secret file
  14. make secret-decrypt
  15. # show the content of the secret file
  16. 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

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

创建 gpg 密钥对

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

  1. name="Pascal Landau"
  2. email="pascal.landau@example.com"
  3. gpg --batch --gen-key <<EOF
  4. Key-Type: 1
  5. Key-Length: 2048
  6. Subkey-Type: 1
  7. Subkey-Length: 2048
  8. Name-Real: $name
  9. Name-Email: $email
  10. Expire-Date: 0
  11. %no-protection
  12. EOF

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

输出:

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

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

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

记住不能共享此密钥。

  1. -----BEGIN PGP PRIVATE KEY BLOCK-----
  2. lQOYBF7VVBwBCADo9un+SySu/InHSkPDpFVKuZXg/s4BbZmqFtYjvUUSoRAeSejv
  3. G21nwttQGut+F+GdpDJL6W4pmLS31Kxpt6LCAxhID+PRYiJQ4k3inJfeUx7Ws339
  4. XDPO3Rys+CmnZchcEgnbOfQlEqo51DMj6mRF2Ra/6svh7lqhrixGx1BaKn6VlHkC
  5. ...
  6. ncIcHxNZt7eK644nWDn7j52HsRi+wcWsZ9mjkUgZLtyMPJNB5qlKQ18QgVdEAhuZ
  7. xT3SieoBPd+tZikhu3BqyIifmLnxOJOjOIhbQrgFiblvzU1iOUOTOcSIB+7A
  8. =YmRm
  9. -----END PGP PRIVATE KEY BLOCK-----

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

  1. gpg --list-secret-keys

输出:

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

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

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

得到以下输出:

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

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

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

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

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

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

导出如下:

  1. -----BEGIN PGP PUBLIC KEY BLOCK-----
  2. mQENBF7VVBwBCADo9un+SySu/InHSkPDpFVKuZXg/s4BbZmqFtYjvUUSoRAeSejv
  3. G21nwttQGut+F+GdpDJL6W4pmLS31Kxpt6LCAxhID+PRYiJQ4k3inJfeUx7Ws339
  4. ...
  5. 3LLbK7Qxz0cV12K7B+n2ei466QAYXo03a7WlsPWn0JTFCsHoCOphjaVsncIcHxNZ
  6. t7eK644nWDn7j52HsRi+wcWsZ9mjkUgZLtyMPJNB5qlKQ18QgVdEAhuZxT3SieoB
  7. Pd+tZikhu3BqyIifmLnxOJOjOIhbQrgFiblvzU1iOUOTOcSIB+7A
  8. =g0hF
  9. -----END PGP PUBLIC KEY BLOCK-----

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

  1. gpg --list-keys

输出:

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

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

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

例如:

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

git-secret

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

  1. $ git secret --version
  2. 0.4.0

git-secret 安装

Alpine 的安装说明如下:

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

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

  1. # File: .docker/images/php/base/Dockerfile
  2. # install git-secret
  3. # @see https://git-secret.io/installation#alpine
  4. ADD https://gitsecret.jfrog.io/artifactory/api/security/keypair/public/repositories/git-secret-apk /etc/apk/keys/git-secret-apk.rsa.pub
  5. RUN echo "https://gitsecret.jfrog.io/artifactory/git-secret-apk/all/main" >> /etc/apk/repositories && \
  6. apk add --update --no-cache \
  7. bash \
  8. git-secret \
  9. gnupg \
  10. make \
  11. #...

git-secret 用法

初始化 git-secret

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

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

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

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

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

git-secret Directory 和 gpg-agent Socket

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

  1. tee .gitsecret/keys/S.gpg-agent <<EOF
  2. %Assuan%
  3. socket=/tmp/S.gpg-agent
  4. EOF
  5. tee .gitsecret/keys/S.gpg-agent.ssh <<EOF
  6. %Assuan%
  7. socket=/tmp/S.gpg-agent.ssh
  8. EOF
  9. tee .gitsecret/keys/gpg-agent.conf <<EOF
  10. extra-socket /tmp/S.gpg-agent.extra
  11. browser-socket /tmp/S.gpg-agent.browser
  12. EOF

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

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

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

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

对应的错误信息是:

  1. gpg: can't connect to the agent: IPC connect call failed
  2. gpg-agent: error binding socket to '/var/www/app/.gitsecret/keys/S.gpg-agent': I/O error

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

S.gpg-agent

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

s.gpg-agent.ssh

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

gpg-agent.conf

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

添加、列出和删除用户

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

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

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

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

要删除用户,请运行:

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

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

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

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

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

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

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

  1. git secret add .env

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

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

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

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

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

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

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

  1. git secret list$ git secret list
  2. .env

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

  1. git secret list$ git secret list
  2. .env

输出:

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

加密文件

要加密文件,请运行:

  1. git secret hide

输出:

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

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

解密文件

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

  1. git secret reveal

输出:

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

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

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

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

  1. git secret reveal -p 123456

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

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

  1. git secret changes

输出:

  1. $ echo "foo" >> .env
  2. $ git secret changes
  3. git-secret: changes in /var/www/app/.env:
  4. --- /dev/fd/63
  5. +++ /var/www/app/.env
  6. @@ -34,3 +34,4 @@
  7. MAIL_ENCRYPTION=null
  8. MAIL_FROM_ADDRESS=null
  9. MAIL_FROM_NAME="${APP_NAME}"
  10. +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. GitHub中Fork来的仓库如何进行双向更新

    一.做点贡献 想对别人的某个仓库"做点贡献"怎么办? 1. Fork该仓库 首先Fork该仓库,本文以git-learn这个仓库为例 这样自己的账号下就会出现这样一个仓库 2. C ...

  2. Github隐藏使用技巧(超详解)

    目录 github使用说明 查看别人的主页和项目 上传自己的项目 使用git下载github上的文件 使用git实现代码管理 使用git恢复被修改的文件 更多关于git使用小技巧 github使用说明 ...

  3. while循环和dowhile

    while循环语句 根据条件来选择是否执行循环体内的执行语句 while语句会循环判断条件是否成立只要成立就会执行,直到条件不匹配循环结束 int a = 0: while(a<10){ a++ ...

  4. 【Azure Developer】在Azure VM (Windows) 中搭建 kafka服务,并且通过本地以及远程验证 发送+消费 消息

    问题描述 查看了 "How to Install and Run Apache Kafka on Windows? " 一文后,成功安装了Kafka服务,但是如何使用呢?如何在其他 ...

  5. 叫高二上一调?简要题解 (ACD)

    A. 电压机制 题意转换为所有奇环的并排除掉所有偶环留下的边的个数 . 建出 DFS 树,然后只有返祖边可能构成环 . 于是类似树上差分,\(odd_u\) 统计奇环,\(even_u\) 统计偶环 ...

  6. 清北学堂 2020 国庆J2考前综合强化 Day5

    目录 1. 题目 T1 a 题目描述 Sol T2 b 题目描述 Sol T3 c 题目描述 Sol T4 d 题目描述 Sol 2. 算法 - 贪心 & 数学 1. 贪心 2. 数学 2.1 ...

  7. Mybatis的使用(2)

    1 :模糊查询 #{}占位符和¥{}的区别 #{}占位符:传参大部分用#{}传参,它的底层是PreparedStatement对象,是安全的数据库访问,它能够防止sql注入 1.1:如果parmete ...

  8. Vue 监视数据总结 && 表单控件使用总结

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  9. js Fetch返回数据res.json()报错问题

    前言 一直以来在简单的场景中经常使用fetch代替第三方请求库, fetch是JavaScript的原生函数, 简单.高效.快速.稳定.可定制等等诸多优点.一直也是用着很是舒服,直到有一天它竟然报错了 ...

  10. 基于LadybugFlow的微服务编排(1.SpringBoot集成)

    前言 前面的系列文章里,介绍了ladybugflow的业务可视化的设计以及常见场景的使用方法. 感谢大家对项目的关注. 本篇文章介绍一下基于ladybugflow的微服务编排场景及使用方法. 1. 业 ...