5分钟。就这么长时间。
一个安全研究员故意在GitHub的公开仓库中发布了一个AWS访问密钥,作为实验。
5分钟后,就有人在用它挖加密货币了。
5分钟。
有机器人24/7扫描GitHub,专门寻找这种东西:暴露的凭证。而且它们很快。比你意识到自己搞砸了要快得多。
数字很可怕
据GitHub统计,2024年有3900万个密钥在公开仓库中泄露。比前一年增加了67%。
专门扫描这类问题的GitGuardian仅在公开仓库中就发现了2370万个新密钥。最糟糕的是:2022年检测到的70%密钥在2024年仍然有效。
两年后。仍然能用。等着有人使用它们。
不只是无名小卒
丰田在GitHub上暴露了AWS凭证,这些凭证可以访问他们的车辆远程信息处理系统。培生集团因为有人在配置文件中留下GitLab令牌而丢失数据。酒店管理公司Otelier因为Bitbucket上暴露的凭证,看着8TB的S3数据被盗。
这不只发生在实习生身上。财富500强企业也会中招。
经典借口:“这只是我的个人项目”
是啊,当然。
问题是那个个人项目使用了和生产环境相同的OpenAI API密钥。或者你的Telegram机器人令牌。或者你的测试数据库凭证,哦惊喜,里面有真实数据因为"这样测试更容易"。
然后有一天你不假思索地执行git push。或者因为想展示给某人看而把仓库从私有改为公开。或者GitHub出现bug临时暴露了私有仓库(这种事发生过)。
然后你发现AWS账单从20欧元变成了2000欧元。一夜之间。
“但我立刻删除了”
又一个经典。
Git是版本控制系统。它的工作就是记住发生的所有事情。删除提交不会从历史记录中删除密钥。强制推送不会从分支中删除它。绝对不会从已经复制它的机器人那里删除。
一旦密钥接触到公开仓库,就算是被泄露了。句号。必须轮换。
灾难金字塔
这是典型项目中密钥管理的演进过程:
级别1:地狱
| |
直接写在代码里。已提交。在生产环境中。别笑,这真的存在。
级别2:炼狱
| |
好一些,但那个.env最终会出现在备份中,在你通过Slack发送的压缩包中,在你卖掉的硬盘中…
级别3:边缘地带
| |
可以,但你把它们存在哪里?便利贴?桌面上的secrets.txt文件?给自己发的Slack消息?
解决方案:密钥脱离代码,脱离磁盘
在几次差点出事之后,我决定把一切都集中在1Password中,使用其CLI在需要时注入密钥。
概念很简单:
- 密钥存在1Password中,不在我的磁盘上
- 代码包含密钥的引用,而不是密钥本身
- 密钥在运行时注入
.env.template + op inject模式
在每个项目中,我不用包含真实值的.env,而是用一个包含引用的.env.template:
| |
当我需要真实的.env时,执行:
| |
1Password读取op://引用,用真实值解析它们,然后生成文件。.env.local在.gitignore中,永远不会接触git。
这样做有什么好处?
1. 所有密钥的单一存储位置
以前我的凭证分散在15个项目的.env文件中,.bashrc中的环境变量,Slack消息中的令牌,还有一些在便利贴上(别评判我)。
现在一切都在1Password的保险库中。一个地方。加密的。有变更历史。
2. 密钥轮换变得简单
以前:更改API密钥意味着要在所有项目中寻找它,更新文件,祈祷不要忘记任何一个。
现在:在1Password中更新值,在每个项目中执行op inject,完成。
3. 代码记录了需要什么
.env.template是活文档。任何克隆项目的人都知道确切需要哪些密钥。他们只需要在自己的1Password中有这些密钥(或向你要)。
4. 不可能意外提交密钥
提交到git的文件只有op://引用。即使你不假思索地执行git add .,也不会暴露任何东西。
5. 机器间同步免费
新Mac?安装1Password,登录,op inject。所有密钥都可用,无需复制文件或通过Slack发送任何东西。
日常使用:Fish中的延迟加载
对于需要凭证的命令(比如用于AI提交的oco),我在Fish配置中有这个:
| |
第一次执行oco时,它要求Touch ID。之后,变量就在会话中加载了。
唯一的缺点
是的,有一个:你需要时不时用Touch ID或密码授权。
我通过配置1Password记住授权24小时并且只在Mac休眠时锁定来优化了这一点。但是的,偶尔你需要按指纹。
这是不出现在GitGuardian统计数据中的小代价。
这不是可选的
听着,我理解这听起来像偏执。“我不会出事”。“这只是个小项目”。“我没有重要的东西”。
但想想这个:你有任何付费的API密钥吗?OpenAI?AWS?任何按使用量收费的服务?
那么你就有别人可以利用的东西。
机器人不休息。它们不区分初创公司的项目和学生的编程作业。它们扫描一切,测试一切,利用一切。
2024年泄露了3900万个密钥。2022年的70%仍然有效。
正确的密钥管理不是最佳实践。这是基本卫生。
就像洗手。你不是因为有趣才洗手。你洗手是因为不这样做会感染。
你在git中的密钥就是等待发生的感染。
可执行摘要:
- 安装1Password及其CLI(
brew install 1password-cli) - 为开发创建保险库
- 将密钥从
.env文件迁移到保险库 - 使用
op://引用创建.env.template - 将
.env.local添加到.gitignore - 需要时用
op inject重新生成
就这样。30分钟的设置可以让你避免出现在GitGuardian的下一份报告中。
你的AWS凭证会感谢你的。
更新: 在实施所有这些之后,我发现1Password要求Touch ID的频率太高了。高到我开始不看就批准。在安全领域这有个名称,而且不是好事。阅读当安全系统频繁要求权限导致你不再仔细查看时看看我们是如何解决的。