Git 工作流中的 数据脱敏 最佳实践
前几天想给一个老项目换个 CI,顺手把仓库重新 clone 下来翻了翻,结果 git log -p 看历史的时候发现,两年前调试的时候把一份带真实数据库密码和 OSS AccessKey 的配置文件直接提交上去了,后面虽然把文件删了,但懂 Git 的都知道,删了不代表没了,历史里全都在,仓库是私有的不假,但看着还是膈应,没准儿哪天 token 泄了或者手一抖把仓库开源了,那就乐子大了...
这里把处理过程和后来加的防护记一下,省得下次又忘。
先换密钥,再谈别的
这个顺序很重要。历史里能抹干净,但如果这个仓库推到过远端、或者有别的协作者 clone 过,就应该当密钥已经泄露了。所以第一件事是去控制台把那个 AccessKey 禁用掉换新的,数据库密码也顺手改了。删历史只是让仓库干净,救不回已经泄出去的密钥。
找出历史里到底藏了什么
先全量搜一遍,别凭记忆:
git grep -i 'password\|access_key\|secret' $(git rev-list --all)
这个命令会把所有提交翻一遍,仓库大的话会有点慢,泡杯茶等会儿。更省心的办法是直接上 gitleaks,这玩意儿内置了一堆正则,专门匹配常见密钥的格式:
gitleaks detect --source . --verbose --report-path leaks.json
跑完看一眼 leaks.json,哪里泄露的、哪个 commit、长什么样,全给你列出来了。
从历史里把数据抹掉
抹历史用 git-filter-repo,官方现在也是推荐这个,git filter-branch 就别碰了,慢得要死还一堆坑。
先写一个替换规则文件,格式是 原内容==>替换成什么:
AKIDEXAMPLE123==>[REDACTED]
OldPassw0rd!==>[REDACTED]
然后找个干净的地方重新 clone 一份再操作(filter-repo 官方建议在 fresh clone 上跑,--force 会把 stash 和未提交的改动全干掉,别问我怎么知道的),执行:
git filter-repo --replace-text replacements.txt --force
跑完过后用 git log -S 'AKIDEXAMPLE123' 再查一遍,查不到就说明干净了。另外它会把 remote 给你摘掉,这是保护机制,自己 git remote add origin 加回来,然后 git push --force --all 强推上去,记得喊所有协作者重新 clone,别让他们哪天把旧历史又推回来。
不想折腾的话,BFG Repo-Cleaner 也能干同样的事,就一条命令,代价是得自己装 Java,看个人喜好吧。
以后别再犯:本地和服务端各一道闸
历史洗干净了,更重要的是别再犯。
第一层,该忽略的先忽略。.env、私钥、本地配置这类文件,进项目第一天就该写进 .gitignore:
.env
*.pem
config/local.*
敏感配置走环境变量,仓库里只放一个 .env.example,里面全是占位符。
第二层,本地提交前自动扫一遍。用 pre-commit 挂上 detect-secrets:
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
pre-commit install 装上过后,每次 git commit 都会先扫一遍暂存区,扫出疑似密钥直接拦下来。偶尔有误报,比如测试用的假密钥,git commit --no-verify 跳过就行,但跳之前最好真的确认那是假的。
第三层,服务端兜底。本地 hook 说白了靠自觉,谁电脑上没装都拦不住,所以 CI 里还得再跑一次 gitleaks,拿 GitHub Actions 举例:
name: secrets-scan
on: [push, pull_request]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0 这行别漏,不然只扫得到当前这一次提交。另外如果你用的是 GitHub,仓库设置里的 Push protection 记得打开,扫到已知格式的密钥会直接拒绝推送,等于多了一道不靠自觉的闸。
最后
这套东西说穿了不复杂:密钥泄露先换掉,历史用 filter-repo 洗,本地和服务端各扫一遍。麻烦是麻烦了点,但比起哪天在公网上看到自己的 AccessKey,这点麻烦真不算什么。
评论
还没有评论。
发表评论
提交后评论将经过自动审核,审核通过后公开展示。