22、Git安全实践:签名提交(GPG)、防止敏感信息泄露(git-secrets)、权限管理

聊到Git安全,很多人第一反应是「我代码又没被偷,有啥好担心的?」

嗯,我以前也这么想。直到有一次,我在一个开源项目里不小心把AWS的Access Key给提交上去了。那叫一个刺激——几分钟后,我的邮箱就收到了账单警报,有人用我的Key在美西开了几十台高配服务器挖矿。

从那以后,我对Git安全再也不敢马虎了。今天咱们就聊聊三个最实用的安全实践:GPG签名提交、敏感信息防泄露、以及权限管理。

一、GPG签名提交:让每一次提交都有「身份证」

你有没有想过一个问题:Git提交的作者信息是可以随便改的。

git config user.name "Linus Torvalds",然后你就能假装是Linux之父提交代码。这其实挺可怕的。GPG签名就是为了解决这个问题——它给你的每次提交加上一个只有你才能生成的数字签名,别人伪造不了。

1.1 生成GPG密钥

我个人习惯用RSA 4096位的密钥,安全性足够,兼容性也好。

# 安装GPG(macOS)
brew install gpg

# 生成密钥对
gpg --full-generate-key

# 按照提示选择:
# - 密钥类型:RSA and RSA(默认)
# - 密钥长度:4096
# - 有效期:2年(我个人建议设个有效期,到期续签)
# - 填写姓名和邮箱(必须和Git配置的邮箱一致!)

生成完成后,用这个命令查看你的密钥:

gpg --list-secret-keys --keyid-format LONG

# 输出示例:
# /Users/yourname/.gnupg/secring.gpg
# ----------------------------------
# sec   4096R/ABC123DEF456 2024-01-01 [expires: 2026-01-01]
# uid                          Your Name <your.email@example.com>
# ssb   4096R/7890GHI123JKL 2024-01-01

记下那个ABC123DEF456,这就是你的密钥ID。

1.2 配置Git使用GPG签名

# 告诉Git你的GPG密钥
git config --global user.signingkey ABC123DEF456

# 让所有提交都自动签名(强烈推荐)
git config --global commit.gpgsign true

# 如果你用GitHub,还需要把公钥添加到GitHub账号
gpg --armor --export ABC123DEF456
# 复制输出的公钥,去GitHub Settings -> SSH and GPG keys -> New GPG key
小提示:如果你用的是macOS,可能会遇到gpg: signing failed: Inappropriate ioctl for device的错误。解决办法是执行export GPG_TTY=$(tty),然后把这行加到你的.zshrc.bashrc里。

1.3 验证签名提交

配置好之后,每次提交Git都会自动签名。你可以在GitHub上看到提交旁边多了一个绿色的「Verified」标签。

本地验证也很简单:

# 查看最近提交的签名信息
git log --show-signature -1

# 输出示例:
# commit xxxxx...
# gpg: Signature made Mon Jan  1 12:00:00 2024 CST
# gpg:                using RSA key ABC123DEF456
# gpg: Good signature from "Your Name <your.email@example.com>"
注意:如果你换了电脑或者重装了系统,别忘了重新导入密钥。我曾经因为换电脑忘了这茬,导致一堆提交没有签名,CI/CD流水线直接挂了——因为公司规定所有提交必须经过GPG验证。

二、防止敏感信息泄露:git-secrets 实战

说实话,我见过太多人把密码、API Key、Token直接写在代码里了。更可怕的是,很多人提交之后才想起来「哎呀,我好像把密钥写上去了」。

这时候再想从Git历史里彻底删掉?难。因为Git保存了所有历史版本,就算你删了当前文件,历史记录里还躺着呢。

所以,最好的办法是——在提交之前就拦住它。

2.1 安装 git-secrets

git-secrets是AWS开源的一个工具,它能扫描你的代码,发现疑似密钥的字符串就报警,阻止你提交。

# macOS安装
brew install git-secrets

# 或者从源码安装
git clone https://github.com/awslabs/git-secrets.git
cd git-secrets
sudo make install

2.2 配置 git-secrets

# 全局安装钩子(所有仓库都生效)
git secrets --install ~/.git-templates/git-secrets
git config --global init.templateDir ~/.git-templates/git-secrets

# 添加常见的密钥模式
git secrets --register-aws  # 添加AWS密钥模式
git secrets --add 'password\s*=\s*.+'  # 自定义:匹配 password = xxx
git secrets --add 'api[_-]?key\s*=\s*.+'  # 自定义:匹配 api_key = xxx
git secrets --add 'secret\s*=\s*.+'  # 自定义:匹配 secret = xxx

2.3 使用 git-secrets 扫描

# 扫描整个仓库
git secrets --scan

# 扫描暂存区(提交前检查)
git secrets --scan --cached

# 扫描历史记录(亡羊补牢)
git secrets --scan-history
我的建议:git secrets --scan --cached加到pre-commit钩子里。这样每次提交前自动扫描,发现问题直接拒绝提交。我团队里就是这么干的,效果非常好。

2.4 如果不小心提交了敏感信息怎么办?

我曾经犯过这个错——把数据库密码写在了配置文件里,还提交到了公共仓库。发现后我立刻做了这几步:

  1. 立即撤销密钥:去云服务商那里吊销泄露的密钥,生成新的。
  2. 从Git历史中彻底删除:使用git filter-branchBFG Repo-Cleaner
  3. 强制推送git push --force,但要注意这会影响到其他协作者。
# 使用BFG删除包含敏感信息的文件
bfg --delete-files config.yml

# 或者使用git filter-branch
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch config.yml" \
  --prune-empty --tag-name-filter cat -- --all
警告:强制推送会重写历史,如果团队里有人基于旧历史做了分支,会非常痛苦。所以,最好的策略还是预防——在提交前就拦住它。

三、权限管理:谁可以做什么?

权限管理说白了就是回答三个问题:谁能读?谁能写?谁能合并?

我见过不少团队,所有人都是仓库的Admin权限。结果呢?有人不小心把master分支给删了,有人直接往master上推代码,乱成一锅粥。

3.1 分支保护规则

在GitHub/GitLab上,你可以为关键分支(比如master/main、develop)设置保护规则:

规则 说明 我推荐
Require pull request reviews 必须经过Code Review才能合并 至少1人审核
Dismiss stale reviews 新提交后自动撤销旧审核 开启
Require status checks CI/CD必须通过 开启
Restrict push access 限制谁能直接推送 只允许管理员
Require signed commits 要求GPG签名 强烈推荐

3.2 最小权限原则

说白了就是:给每个人刚刚够用的权限,不多给一分。

  • 开发者:只给写权限,不能直接推送到保护分支。
  • 技术负责人:给维护者权限,可以合并PR、管理分支。
  • 管理员:只有1-2个人有,负责仓库设置、权限分配。

我个人习惯用CODEOWNERS文件来自动分配审核人。比如:

# .github/CODEOWNERS
# 所有文件默认由团队负责人审核
* @team-lead

# 配置文件必须由DevOps审核
/config/* @devops-team

# 安全相关代码必须由安全组审核
/security/* @security-team

3.3 使用Git Hooks做自动化权限检查

除了平台层面的权限控制,你还可以用Git Hooks在本地做检查。比如,禁止提交包含TODO/FIXME的代码:

#!/bin/sh
# .git/hooks/pre-commit

# 检查是否包含TODO
if git diff --cached | grep -i "TODO\|FIXME\|HACK"; then
  echo "错误:提交中包含 TODO/FIXME/HACK 标记,请先处理!"
  exit 1
fi
小技巧:把常用的Hook脚本放在一个公共仓库里,团队成员clone项目后执行make install-hooks就能自动安装。省得每个人手动配置。

知识体系总览

下面这张图总结了本章的核心内容,你可以把它当作一个快速参考:

Git安全实践知识体系 GPG签名提交 • 生成RSA 4096密钥 • 配置Git自动签名 • 公钥上传GitHub • 验证签名状态 • CI/CD强制签名检查 效果:提交不可伪造 每个提交都有数字身份证 敏感信息防泄露 • 安装git-secrets • 配置密钥匹配模式 • pre-commit自动扫描 • 扫描历史记录 • 泄露后紧急处理 效果:提交前拦截密钥 避免账单爆炸 权限管理 • 分支保护规则 • 最小权限原则 • CODEOWNERS审核 • Git Hooks自动化 • 角色权限划分 效果:谁做什么清清楚楚 防止误操作 核心原则:预防为主,自动化检查,最小权限

这三个方面——GPG签名、敏感信息防护、权限管理——说白了就是给Git仓库上了三道锁。GPG保证提交者的身份可信,git-secrets防止敏感信息外泄,权限管理控制谁能做什么。

我建议你从今天开始,至少把GPG签名和git-secrets配置上。这两步花不了半小时,但能帮你避免很多麻烦。至于权限管理,找个周末跟团队一起梳理一下,把保护规则定下来。

安全这件事,说白了就是「不怕一万,就怕万一」。等真出了事再补救,代价可就大了。


公众号:蓝海资料掘金营,微信deep3321