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
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>"
二、防止敏感信息泄露: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 如果不小心提交了敏感信息怎么办?
我曾经犯过这个错——把数据库密码写在了配置文件里,还提交到了公共仓库。发现后我立刻做了这几步:
- 立即撤销密钥:去云服务商那里吊销泄露的密钥,生成新的。
- 从Git历史中彻底删除:使用
git filter-branch或BFG Repo-Cleaner。 - 强制推送:
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
make install-hooks就能自动安装。省得每个人手动配置。
知识体系总览
下面这张图总结了本章的核心内容,你可以把它当作一个快速参考:
这三个方面——GPG签名、敏感信息防护、权限管理——说白了就是给Git仓库上了三道锁。GPG保证提交者的身份可信,git-secrets防止敏感信息外泄,权限管理控制谁能做什么。
我建议你从今天开始,至少把GPG签名和git-secrets配置上。这两步花不了半小时,但能帮你避免很多麻烦。至于权限管理,找个周末跟团队一起梳理一下,把保护规则定下来。
安全这件事,说白了就是「不怕一万,就怕万一」。等真出了事再补救,代价可就大了。