• 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

    我们在 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 <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 
    ssb rsa2048 2022-03-27 [SEA]
    
    

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

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

    得到以下输出:

    $ path="secret.gpg"
    $ gpg --import "$path"
    gpg: key E1E734E00B611C26: "Pascal Landau " 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 
    sub rsa2048 2022-03-27 [SEA]
    

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

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

    例如:

    $ gpg --import /var/www/app/public.gpg
    gpg: key E1E734E00B611C26: "Pascal Landau " 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调整等内容,保持关注哦~

  • 相关阅读:
    Maven基础概念
    没那么简单!浅析伦敦金与美元的关系
    call函数和apply函数的区别
    第5章:指令级并行--硬件方法
    leetcode - 1293. Shortest Path in a Grid with Obstacles Elimination
    服务器(I/O)之多路转接
    印刷行业的ERP软件的领头羊
    最接近的三数之和 c++
    python文件的读取
    文件夹图片相似图片检测并删除相似图片
  • 原文地址:https://www.cnblogs.com/sealio/p/16741855.html