避免将机密信息提交到 Git

GitBeginner
立即练习

介绍

某个文件在你的机器上可能很有用,却仍不适合放进源代码提交。这个全新的 DeskLite 仓库有一项小型业务变更,以及一份包含虚构凭据的私密配置。私密文件被误加入了暂存区,但从未被提交。

你将学习 Git 工作区、暂存区和提交快照,将私密设置与可交付示例分离,并使用预置的凭据扫描器。无需 Git 账号、远程仓库或任何 Git 基础。

定位工作区和暂存区

在本步骤中,你将识别 Git 正准备保存哪些文件。

Git 在仓库中记录选定的文件版本。工作区包含你编辑的文件。暂存区保存你打算在下一次提交中记录的快照。提交会将该暂存快照保存到本地历史中,不会自动上传任何内容。

cd /home/labex/project/desklite-git

git status 会比较这些区域:

git status

预置终端可能会用颜色区分文件类别;关键是输出的文字。请留意两个不同的类别。private.env 出现在待提交的变更中:它的内容已经暂存。service/app.py 出现在尚未暂存的变更中:业务修改仍只存在于工作区。分支名可能不同,不影响本任务。

git ls-files 列出被跟踪的路径,包括已暂存、等待首次提交的新文件:

git ls-files

私密文件虽然尚未提交,但已经出现在列表中。现在正是阻止泄漏的时候。初始提交历史是干净的。先不要提交:先检查哪些内容会进入提交。

比较两类变更

在本步骤中,你将比较业务修改和已暂存的私密配置。

git --no-pager diff 显示未暂存的变更。全局选项 --no-pager 让输出直接显示在终端中,无需关闭单独的查看器。指定路径可将结果限制为业务文件:

git --no-pager diff service/app.py

以 - 开头的行表示旧内容;以 + 开头的行表示新内容。新程序输出 DeskLite tickets ready。请保留这项预期的业务变更。

git --no-pager diff --cached 则显示已暂存的内容。--cached 选项选择暂存区:

git --no-pager diff --cached

你应能看到 private.env 以及其中的 SERVICE_NAME 和 API_TOKEN 键。令牌是虚构的,在本课程之外没有任何作用。不过,它代表了应当保密的一类值。

暂存快照可能与磁盘上的当前文件不同。因此,仅检查工作区可能漏掉已经准备好提交的内容。提交前,应检查这两类变更。

仓库已配置本地示例作者身份。你无需提供个人信息,也无需将 Git 连接到外部服务。

解读脱敏后的凭据扫描发现

在本步骤中,你将使用预置扫描器检查私密文件,并解读扫描发现。

Gitleaks 检测与凭据相关的文本模式。课程启动器 course-secrets 使用 Gitleaks 8.24.2,以一条固定的本地规则检测本课程合成的 labex_ 令牌格式。它会对匹配值进行脱敏,且不发起网络请求。这条用途有限的课程规则并非完整的生产环境机密检测策略。

向启动器提供文件或目录,即可扫描其当前内容:

course-secrets private.env

预期会看到标识为 desklite-practice-token 的发现、文件名/行号,以及脱敏后的机密值。由于发现了凭据,命令会按预期以状态 1 退出。发现问题与工具无法运行是两种不同情况。

该命令扫描当前文件,不受 Git 是否跟踪它的影响。稍后介绍的历史扫描则检查已提交的变更。即使历史干净,也不代表这个未提交文件可以安全地加入暂存区。

这里的私密值仅存在于暂存区/工作区内容中。如果真实凭据已经泄漏,从新提交中移除它并不会让它失效,也不会抹去旧副本:其所有者需要撤销或更换凭据。本练习不涉及历史重写。

分离私密设置和示例

在本步骤中,你将让 Git 停止跟踪私密设置,添加范围明确的忽略规则,并创建可用的公开示例。

git rm --cached 将路径从暂存/跟踪区域移除,同时保留本地文件。这里用它撤销新私密文件的误暂存操作:

git rm --cached private.env

打开 .gitignore。它告诉 Git 应排除哪些未跟踪路径:

nano .gitignore

输入这一条规则,然后使用 Ctrl+O、Enter、Ctrl+X 保存并退出:

/private.env

开头的 / 将规则限定在本仓库根目录。不要忽略 service/:其中包含应交付的文件。忽略规则不会自动移除已跟踪的文件或旧提交,因此前面的命令不可省略。

使用相同的配置键创建公开示例:

nano service/config.example.env

保存以下内容:

SERVICE_NAME=DeskLite
API_TOKEN=REPLACE_ME

示例告诉未来的运维人员需要哪些设置,同时不提供可用凭据。请将原始私密文件保留在本地。

ls private.env
git status

私密路径应不再被暂存,也不应出现在未跟踪文件列表中。.gitignore 和公开示例应处于未跟踪状态,等待你有选择地加入暂存区。现有业务变更仍未暂存。

只暂存交付文件

在本步骤中,你将准确准备下一次提交所需的文件。

git add 将指定路径的当前内容复制到暂存区。请明确列出每个预期交付的文件:

git add service/app.py service/config.example.env .gitignore

检查文件类别和暂存内容:

git status
git --no-pager diff --cached

结果应恰好包含预期业务修改、范围明确的忽略规则和安全示例,不应含有私密令牌。如果执行 git add 后再次编辑文件,必须在提交前暂存更新后的内容;Git 不会自动替换先前的暂存快照。

再次列出跟踪路径:

git ls-files

三个交付路径都应出现;private.env 不应出现。这项检查与 ls 回答的问题不同:本地私密文件仍存在,但已不受 Git 跟踪。

下一步会扫描可交付目录。扫描有意限定的交付范围,并不能证明机器上其他位置的每个文件都不含机密信息。

扫描交付内容

在本步骤中,你将检查要交付的源文件目录,同时保留本地私密设置。

使用同一个固定规则扫描器检查 service 目录:

course-secrets service

预期输出 no leaks found,且成功退出。扫描器处理实际的源文件和示例内容,不依赖手动编辑的报告。

私密配置位于仓库根目录,在交付目录之外。再次扫描该私密文件仍会报告其令牌;这符合预期。我们分离了不同使用者的访问内容,并没有声称敏感数据已经不复存在。

再检查一次暂存快照:

git --no-pager diff --cached

目录扫描检查当前文件;差异检查 Git 将要保存的内容。二者都必须符合预期交付内容。扫描没有发现问题,只能为配置的规则和范围提供证据,不能证明所有潜在机密信息或安全缺陷都不存在。

现在你已有经过审查的暂存快照。下一步会将它保存为本地提交。

保存本地提交

在本步骤中,你将把审查过的暂存快照保存到本地历史。

git commit 记录暂存区内容。-m 选项提供描述变更的简短消息;引号将消息中的单词保持为一个整体:

git commit -m "Deliver ticket message and safe configuration example"

预期会看到包含三个变更路径的提交摘要。提交 ID 和文件统计可能不同,因此重点关注包含了什么。

git status

预期工作区干净。被忽略的私密文件仍然存在,即使 git status 没有列出它。

提交是本地操作。没有任何内容被推送、上传或共享到远程服务。这已足够练习如何在没有个人账号的情况下准备安全交付。

如果 Git 提示没有可提交的内容,请对照前面步骤检查 git status、git ls-files 和暂存差异。不要通过删除仓库或其现有历史来处理意外状态。

检查历史和业务变更

在本步骤中,你将扫描提交历史,并运行你保留的小程序。

启动器的 --history 选项选择 Gitleaks Git 历史扫描。末尾的 . 表示当前仓库:

course-secrets --history .

预期输出 no leaks found。干净的初始提交和新的交付提交都应通过固定规则检查。前面的文件扫描成功,本身并不能证明历史扫描也会得到这一结果。

python3 运行提供的 Python 程序。本实验不要求你编辑或理解 Python 语法:

python3 service/app.py

预期输出:

DeskLite tickets ready

确认本地私密文件仍存在,且不受 Git 跟踪:

ls private.env
git ls-files

现在你拥有实用的交付文件、安全的配置示例,以及不含练习凭据的本地提交。私密文件没有被删除,业务变更仍然有效。无需复制扫描报告,也无需创建调查文件。

总结

你将本地私密设置与源代码交付分离,在提交前审查暂存区,并使用固定规则、输出脱敏的凭据扫描检查了当前交付文件和本地 Git 历史。业务变更和实用的公开示例得以保留,私密设置则留在提交之外。