17. 把密码提交进 Git?安全实践:密钥管理与审计日志
「Git」系列已发布: 00. 改崩代码不敢回退?Git 版本控制 3 分钟救你狗命 | 01. Git 装完不会配?Windows/macOS/Linux 三端配置一次到位 | 02. Git 配置总踩坑?全局/仓库/SSH 密钥一次搞懂 | 03. add/commit/push 别再死记:Git 工作流核心概念实操 | 04. Git 分支管理:5 步彻底搞懂 branch 与 merge | 05. clone/fetch/pull/push 分不清?Git 远程协作实战 | 06. 给版本打上永久印记:Git 标签管理与发布实战 | 07. 切分支怕丢改动?Git stash 暂存恢复保护现场 | 08. rebase 不是 merge 的替代品:Git 故事线重构进阶 | 09. Git 日志与调试:log/blame/diff 让历史无所遁形 | 10. 提交代码自动检查:Git Hooks 实战,质量不再靠人工 | 11. 多仓库依赖怎么管?Git 子模块统一版本一键更新 | 12. GitFlow vs GitHub Flow vs 主干:团队工作流 3 选 1 | 13. 仓库越来越大?Git LFS 让图片视频不再撑爆仓库 | 14. 合并冲突不是噩梦:Git 合并策略与冲突解决 | 15. 常用命令记不住?Git 别名让操作变成快捷键 | 16. 仓库太大会卡顿?git gc + bfg 清理历史垃圾实战 | 17. 把密码提交进 Git?安全实践:密钥管理与审计日志(本文)
密钥进仓库等于把家门钥匙挂门口。.gitignore、secret 扫描、pre-commit 钩子、审计日志——一套 Git 安全实践堵死泄露口。
配置详解(第 02 篇)和远程仓库操作(第 05 篇)要熟。需要装 GPG(GnuPG)做提交签名验证。
一、提交签名
1.1 GPG 签名的意义
Git 的提交者信息(name + email)随便填——没有任何机制阻止伪造:
git config user.name "Linus Torvalds"
git config user.email "torvalds@linux-foundation.org"
git commit -m "fake commit"
签名通过非对称加密验证提交真实性——只有持有私钥的人才能生成有效签名。
1.1.1 生成 GPG 密钥
# 装 GPG
# macOS: brew install gnupg
# Ubuntu: sudo apt install gnupg2
# 生成密钥对
gpg --full-generate-key
# 交互选择:
# 密钥类型:RSA and RSA(默认)
# 密钥长度:4096
# 有效期:2y
# 姓名:和 Git 的 user.name 一致
# 邮箱:和 Git 的 user.email 一致
# 示例输出:
# pub rsa4096 2024-01-01 [SC] [expires: 2026-01-01]
# ABCDEF1234567890ABCDEF1234567890ABCDEF12
# uid Zhang San <zhangsan@example.com>
# sub rsa4096 2024-01-01 [E] [expires: 2026-01-01]
1.1.2 配置 Git 签名
# 列出密钥
gpg --list-secret-keys --keyid-format=long
# 拿到密钥 ID(sec 行后的 16 位十六进制)
# sec rsa4096/ABCDEF1234567890 2024-01-01
# 配置 Git 用这个密钥
git config --global user.signingkey ABCDEF1234567890
# 所有提交自动签名
git config --global commit.gpgsign true
# 所有标签自动签名
git config --global tag.gpgsign true
1.1.3 日常操作
# 带签名提交
git commit -S -m "feat: 实现用户认证模块"
# 带签名标签
git tag -s v1.0.0 -m "v1.0.0 正式发布"
# 验证提交签名
git verify-commit HEAD
# 验证标签签名
git verify-tag v1.0.0
# 看签名状态
git log --show-signature -5
1.1.4 上传公钥到 GitLab
# 导出公钥
gpg --armor --export ABCDEF1234567890
# 粘贴到 GitLab → 用户设置 → GPG Keys → 添加密钥
验证后会显示 “Verified” 徽章。
1.2 敏感信息保护
本节围绕 敏感信息保护 进行介绍,说明它的核心概念、常见使用场景以及在实际操作中需要注意的要点,帮助读者快速掌握该功能的作用并安全地落地。
1.2.1 检测已提交的敏感信息
# git-secrets(AWS 开源)
brew install git-secrets
git secrets --install
git secrets --register-aws
# 扫当前仓库
git secrets --scan-history
# 自定义规则
git secrets --add 'API[_-]?KEY\s*[:=]\s*[A-Za-z0-9+/]{20,}'
git secrets --add '-----BEGIN RSA PRIVATE KEY-----'
# Gitleaks(更全面)
brew install gitleaks
gitleaks detect --source . --verbose
gitleaks detect --source . --report-path gitleaks-report.json
1.2.2 从历史中移除敏感信息
# 用 BFG(见第 16 篇)
# 建要替换的文本文件
echo "AKIAIOSFODNN7EXAMPLE" >> sensitive.txt
echo "password: production123" >> sensitive.txt
# 执行替换
java -jar bfg.jar --replace-text sensitive.txt my-repo.git
# 或用 filter-repo
git filter-repo --path passwords.txt --invert-paths
# 替换后强制推送(团队协调好)
git push origin --force --all
git push origin --force --tags
1.2.3 预防措施
# .git/hooks/pre-commit
#!/bin/bash
# 拦截疑似密钥的提交
PATTERNS=(
"AKIA[0-9A-Z]{16}" # AWS Access Key
"sk-[a-zA-Z0-9]{32}" # Stripe Secret Key
"ghp_[a-zA-Z0-9]{36}" # GitHub Personal Access Token
"glpat-[a-zA-Z0-9\-]{20,}" # GitLab Personal Access Token
"-----BEGIN RSA PRIVATE KEY"
"-----BEGIN OPENSSH PRIVATE KEY"
)
for pattern in "${PATTERNS[@]}"; do
if git diff --cached --name-only | xargs grep -lE "$pattern" 2>/dev/null; then
echo "============================================"
echo "警告:检测到疑似敏感信息"
echo "请确认是否确实需要提交这些凭据"
echo "============================================"
exit 1
fi
done
exit 0
1.3 访问控制
本节围绕 访问控制 进行介绍,说明它的核心概念、常见使用场景以及在实际操作中需要注意的要点,帮助读者快速掌握该功能的作用并安全地落地。
1.3.1 分支保护
在 GitLab 配置:
项目 → Settings → Repository → Protected Branches
main 分支:
- Allowed to merge: Maintainers only
- Allowed to push: No one
- Require approval: 2 approvers
- Code owner approval: Required
develop 分支:
- Allowed to merge: Maintainers + Developers
- Allowed to push: No one
1.3.2 推送规则(GitLab Premium/Ultimate)
Push Rules 可以在项目级阻止不合规推送——限制提交者邮箱格式、提交信息必须含 JIRA 编号、分支命名规范、文件大小上限、禁止特定扩展名。
1.3.3 签名策略强制执行
# .gitlab-ci.yml
verify-commits:
stage: .pre
script:
- |
for commit in $(git rev-list origin/main..HEAD); do
if ! git verify-commit $commit 2>/dev/null; then
echo "错误:$commit 未签名或签名无效"
exit 1
fi
done
rules:
- if: $CI_MERGE_REQUEST_ID
1.4 仓库安全审计
本节围绕 仓库安全审计 进行介绍,说明它的核心概念、常见使用场景以及在实际操作中需要注意的要点,帮助读者快速掌握该功能的作用并安全地落地。
1.4.1 审计日志
GitLab 提供完整审计日志(Admin Area → Monitoring → Audit Events),可追踪:
- 用户登录/登出
- 项目创建/删除/可见性变更
- 成员权限变更
- Merge Request 合并/关闭
- 分支保护规则变更
- CI/CD 变量修改
1.4.2 定期安全扫描
# 自动化审计脚本
#!/bin/bash
# audit-gitlab.sh
GITLAB_URL="(gitlab.example.com)"
TOKEN="$GITLAB_API_TOKEN"
# 列出所有公开项目(潜在泄露)
curl -s --header "PRIVATE-TOKEN: $TOKEN" \
"$GITLAB_URL/api/v4/projects?visibility=public&per_page=100" | \
jq '.[] | {name: .name, visibility: .visibility, last_activity: .last_activity_at}'
# 检查无保护分支的项目
curl -s --header "PRIVATE-TOKEN: $TOKEN" \
"$GITLAB_URL/api/v4/projects?per_page=100" | \
jq -r '.[] | select(.archived == false) | .id' | \
while read project_id; do
protected=$(curl -s --header "PRIVATE-TOKEN: $TOKEN" \
"$GITLAB_URL/api/v4/projects/$project_id/protected_branches" | jq 'length')
if [ "$protected" -eq 0 ]; then
echo "项目 $project_id 没有保护分支"
fi
done
1.5 SSH 签名(Git 2.34+)
除了 GPG,Git 2.34+ 也能用 SSH 密钥签名:
# 配置 SSH 签名
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
# 允许的签名者
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
# ~/.ssh/allowed_signers 格式:
# zhangsan@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
# 验证 SSH 签名
git verify-commit HEAD
1.6 文章引用
📌 本文首发于微信公众号 【运维知识点滴】——专注运维实战干货,微信搜索“运维知识点滴”或扫下方二维码关注,更新不迷路。
| 微信公众号【运维知识点滴】 | 微信小程序【A5单据合并&大试卷拆分转A4打印】 |
|---|---|
![]() |
![]() |
| 运维实战干货 · 关注追更 | Word 转 PDF · 试卷/发票打印神器 · 免费 |
💡 小程序【A5单据合并&大试卷拆分转A4打印】是干嘛的? 一个 Word 转 PDF 的打印神器,专治“文档版式和打印机对不上”:
- A3 试卷打不出来? 学校发的电子版试卷多是 A3,家用打印机只吃 A4——上传 Word 一键转换:可缩到一页 A4(页数不变),也可对半拆成两张 A4(1:1 原大、字更清晰),两种模式自选;
- 版式不乱:真实渲染引擎原样转换、绝不重排内容,转出的 PDF 和原 Word 排版一致,公式/表格/图片不跑版;
- 两张 A5 单据拼一张 A4:出租车票、火车票等报销凭证拼版后,一次打印、整齐粘贴;
- 隐私省心:无需注册,转换结果留存 5 天、最多下载 5 次即自动删除,不留任何历史记录;
- 微信扫码即用,免费、免安装,支持 doc / docx(≤50MB)。

