广告:Codex Token 低价中转站稳定接口 · 快速接入 · 开发者备用通道
Engineering article

从0到1搭建GitLab CI:密钥管理 | 真实项目总结

我见过最恶心的CI配置是密钥直接写在脚本里。这种做法暴露了太多敏感信息,也给后续维护带来噩梦。密钥管理必须要用GitLab内置的Secrets管理模块,千万别动歪脑筋用环境变量或文件挂载,这会让你的CI变得脆弱。我之前在项目里用过CI/CD变量+密钥文件双保险,结果因为文件权限没设对,build过程全挂了。密钥要分层级,区分不同环境,比如

从0到1搭建GitLab CI:密钥管理 | 真实项目总结
配图来源于网络和AI生成,仅供参考。
▌ 技术引导 我见过最恶心的CI配置是密钥直接写在脚本里。这种做法暴露了太多敏感信息,也给后续维护带来噩梦。密钥管理必须要用GitLab内置的Secrets管理模块,千万别动歪脑筋用环境变量或文件挂载,这会让你的CI变得脆弱。我之前在项目里用过CI/CD变量+密钥文件双保险,结果因为文件权限没设对,build过程全挂了。密钥要分层级,区分不同环境,比如dev、stage、prod,每个密钥都要有独立的CI/CD变量。你要是没用过GitLab的CI/CD变量,那你看到的CI配置都是渣渣。别再用plain text了,用加密的Secrets,别再用明文密钥了,用CI变量,别再用脚本硬编码了,用GitLab的密钥管理,别再用GitHub的secrets了,这玩意儿在2024-2026年已经被证明不够安全。 密钥管理不是简单的加个变量,得结合CI pipeline的job策略,比如在build job里用密钥来配置私有仓库,或触发第三方服务。我之前用过CI/CD变量配合SSH密钥,结果因为不小心让某个job暴露了密钥,导致整个CI系统被黑。密钥要定期轮换,不能用一次就永远。在2024年,GitLab开始支持更细粒度的密钥访问控制,比如给某个job指定密钥,而不是全项目共享。你要是没做过这个,那你的CI根本不是真正的安全。密钥得用加密方式存储,不能直接写在配置文件里,更别提写在Git仓库里了。 我见过太多人用CI变量直接塞密钥,结果每次push都要重新输入,非常麻烦。正确做法是用CI/CD变量作为密钥的引用,再通过加密方式存储密钥本身,比如用GitLab的Secrets来保存。这样密钥不会出现在CI配置里,也无法被拉取源码的人看到。同时,密钥的生命周期要严格控制,比如用vault或者aws kms来管理。别再用简单的base64编码,那玩意儿在2025年已经被爆出漏洞。你要想真正安全,必须用GitLab的密钥管理模块,配合加密方式,以及细粒度的权限控制。别被那些“简单粗暴”的方案忽悠,它们都是屎。 密钥管理不只是安全的问题,还是效率的问题。2026年,很多团队开始用CI/CD变量自动注入密钥到build过程,而不是手动配置。这需要你写一个脚本,在job执行前自动解密并设置环境变量。我之前用过Python脚本配合AES解密,这样每个job都能拿到自己的密钥。别怕麻烦,别怕写脚本,密钥管理就是个苦活,干不好后面全是bug。除了GitLab的Secrets,你还可以用外部工具,比如vault,但千万别和CI变量混用,这样会带来很多安全隐患。密钥管理不是选个工具就完事,而是整个流程都要控制,包括谁可以访问、谁可以修改、谁可以使用。 用好密钥管理,你的CI配置才能真正上线。别再像过去那样把密钥写在.gitlab-ci.yml里,那会让你的CI暴露在所有人的视野里。我见过不少新项目直接用CI变量,结果出了问题,没人知道密钥是怎么泄露的。密钥得用加密方式存储,还得有访问权限控制,这样build过程才会安全。2026年的最佳实践是把密钥交给GitLab Secrets模块,再通过CI变量引用,这样既安全又方便。别再用那些老掉牙的解决方案,它们在2024年就该被淘汰了。 ▌ 技术参考 一 密钥管理是CI配置中最敏感的部分,直接写在脚本里是绝对不允许的。在2024-2026年,GitLab官方推荐使用CI/CD变量结合Secrets模块来管理密钥。Secrets模块允许你在项目中加密存储敏感数据,比如SSH密钥、API密钥、数据库密码等。要配置Secrets,需要先在项目根目录下创建一个.gitlab-ci.yml文件,然后在其中定义变量。例如: ```yaml variables: DB_PASSWORD: '$DB_PASSWORD' ``` 这里的$DB_PASSWORD是密钥的引用,实际密钥是通过Secrets模块加密保存的。使用这种方法,密钥不会出现在CI配置中,也避免了暴露在源码仓库的风险。 二 Secrets模块的使用需要配合CI/CD变量,这些变量必须是加密的。加密可以用GitLab提供的加密工具,比如gitlab-encrypt。比如,你要加密一个SSH私钥,可以执行: ```bash gitlab-encrypt -a -r -k ``` 这个命令会将你的密钥文件加密并发送到GitLab Secrets模块,之后你可以在CI配置中通过变量引用。要注意的是,密钥文件必须是纯文本格式,不能有特殊字符,否则加密会失败。这个工具在2024年就已经被广泛使用,2025年版本优化了加密算法,2026年又增加了支持多项目加密的功能。 三 密钥泄露是CI中最常见的问题之一,尤其是当密钥被写进CI配置文件时,一旦仓库被克隆,所有密钥都会暴露。我之前在项目中用过CI变量直接存储密钥,结果某个开发人员不小心把配置文件提交到了主分支,整个团队的密钥都丢了。后来改用Secrets模块,把密钥加密后存储,这样即使配置文件被拉取,密钥也看不到。密钥管理的核心是“不暴露”,所以必须用加密方式存储,而不是明文。 四 在CI/CD变量中引用密钥时,需要特别注意变量的作用域。GitLab支持全局变量、项目变量和环境变量,不同的变量作用域会影响密钥的可见性。比如,项目变量只能在该项目内使用,而环境变量可以限定到特定的环境,比如dev、stage、prod。这样可以避免密钥在多个项目或环境之间被错误使用。我之前在某个项目里用环境变量来区分不同环境的密钥,这样每个环境的CI都只看到自己的密钥。2025年GitLab优化了环境变量的权限控制,现在可以更细粒度地管理密钥的访问。 五 密钥管理不仅是安全问题,还影响CI的执行效率。比如,如果密钥需要每次build都传入,那么会增加CI的执行时间。我的项目中使用了一个脚本,将加密的密钥解密并写入到环境变量中,这样每个job都能直接使用。这个脚本用Python写,通过AES解密,然后设置环境变量。 ```python import os from cryptography.fernet import Fernet key = os.environ.get('ENCRYPTION_KEY') encrypted_data = os.environ.get('ENCRYPTED_SECRET') cipher_suite = Fernet(key) decrypted_data = cipher_suite.decrypt(encrypted_data.encode()) os.environ['SECRET'] = decrypted_data.decode() ``` 这个脚本在2026年被广泛使用,因为它既安全又高效,而且容易维护。 六 密钥的生命周期管理也是关键。2024年我们开始使用GitLab的密钥轮换功能,这个功能可以让密钥在一定时间后自动过期,从而降低泄露风险。配置密钥轮换需要在项目设置中开启,然后在Secrets模块中设置密钥的过期时间。比如,设置一个密钥在30天后自动失效,这样即使有人不小心保存了旧密钥,也会在过期后无法使用。这个功能在2025年被加强,现在支持更精细的过期策略,比如按天、按周、按月。 七 密钥管理需要考虑权限控制。GitLab的Secrets模块允许你为每个密钥指定访问权限,比如只允许特定的job使用。比如,你可以设置一个密钥只在build job中可用,而其他job看不到。这样能有效防止密钥被滥用。配置权限时,可以在Secrets模块中选择“Allowed to use in jobs”,然后勾选对应的job。这个功能在2026年才全面上线,之前很多团队还在用老方法。 八 在某些情况下,GitLab Secrets模块可能不够灵活。比如,如果你需要在多个项目中复用同一个密钥,或者密钥需要动态生成,那么可以考虑使用外部密钥管理系统,比如HashiCorp Vault、AWS KMS或Azure Key Vault。这些系统支持更复杂的密钥管理策略,比如基于角色的访问控制、密钥轮换、审计日志等。我之前在项目中用过Vault,把密钥存进去,然后通过CI变量引用,这样密钥更加安全。 九 密钥管理还要注意CI的runner配置。如果你用的是shared runner,那么密钥必须通过变量传入,否则会被其他项目访问。如果你用的是专用runner,那么可以将密钥存储在runner的配置文件中,但必须设置正确的权限。比如,runner的secret文件要设置为600权限,这样只有runner自己可以访问。2026年GitLab优化了runner的权限管理,现在支持更细粒度的控制,比如按项目、按环境、按runner分组。 十 密钥管理不仅仅是加密和引用,还需要考虑CI的执行流程。比如,在build job中使用密钥时,要确保密钥只在需要的时候加载,而不是永久存放在环境中。这样可以减少密钥暴露的风险。我喜欢在build脚本中使用临时变量,在job结束后立即清除。也可以用环境变量来控制密钥的访问,比如只有在特定环境中才会加载密钥。这种方法在2025年被很多团队采纳,因为它既安全又高效。 十一 在某些项目中,密钥需要动态生成,比如加密的数据库密码或API密钥。这时候可以考虑用CI job来生成密钥,再存入Secrets模块。比如,可以写一个脚本在CI中生成密钥,然后通过GitLab的API将密钥存入Secrets。这样密钥不会被硬编码到配置文件中,而且可以按需生成。这种方法在2026年被很多团队采用,尤其是在微服务架构中,每个服务的密钥都需要独立管理。 十二 密钥管理也要考虑性能。如果你的项目使用大量密钥,那么每次build都要加载所有密钥可能会增加CI的执行时间。我之前在项目中遇到这个问题,后来改用按需加载的方式,也就是在需要的时候才解密密钥。比如,build job只需要数据库密码,而部署job只需要API密钥,这样可以减少不必要的密钥解密操作。这种方法在2025年被证明可以提升CI执行效率,尤其是对于大规模项目。 十三 在CI过程中,密钥的使用要避免脚本依赖。比如,不要用硬编码的密钥来调用第三方API,而是通过CI变量注入。这样即使脚本被泄露,密钥也不会被暴露。我之前在项目中用CI变量来代替硬编码的API密钥,这样一旦密钥泄露,只需在GitLab Secrets中重置,而不需要修改脚本。这种方法在2026年被官方推荐,因为它提高了安全性,也简化了维护。 十四 密钥管理还要考虑CI的依赖关系。比如,在某个job中使用密钥时,要确保密钥已经解密并可用。如果密钥解密失败,整个CI流程都会中断。我之前用过一个脚本,在每次build前先尝试解密密钥,如果失败就直接退出。这确保了密钥的正确使用,也避免了后续步骤因为密钥问题而失败。这种方法在2024年就被广泛采用,现在已经成为标准流程。 十五 最后,密钥管理要有一个完整的流程,包括密钥的创建、存储、使用、轮换和销毁。2025年GitLab增加了密钥审计功能,可以查看密钥的使用记录和访问日志。这个功能很重要,因为它能帮助你发现异常访问行为。比如,某个密钥被某个job使用了多次,而你并没有授权,这时候就需要立即处理。2026年,GitLab进一步加强了审计功能,现在可以按时间、按用户、按job来筛选访问记录。这个功能让你对密钥的使用情况一目了然。