4、镜像供应链安全:镜像扫描、签名验证、可信仓库
镜像供应链安全,说白了就是确保你拉下来的每一个容器镜像,从构建到部署,都没有被人动过手脚。我见过太多团队只关注运行时安全,却忽略了镜像本身可能就是个定时炸弹。你想想看,一个带着漏洞的镜像,或者被人篡改过的镜像,一旦跑起来,后果不堪设想。
这一章,我们就来聊聊镜像供应链安全的三个核心环节:镜像扫描、签名验证、可信仓库。这三个环节环环相扣,缺一不可。
4.1 镜像扫描:给镜像做个体检
镜像扫描,就是给镜像做一次全面的体检。它会检查镜像里有没有已知的漏洞、有没有不安全的配置、有没有包含敏感信息。我个人习惯,每次构建完镜像,第一件事就是跑一遍扫描。
扫描工具很多,比如 Trivy、Clair、Anchore、Snyk。我个人用得最多的是 Trivy,因为它轻量、快速、支持多种格式。你可以在 CI/CD 流水线里集成它,也可以在本地跑。
举个例子,用 Trivy 扫描一个镜像:
trivy image nginx:1.21.6
输出结果会告诉你,这个镜像里有哪些 CVE(通用漏洞披露),严重程度如何,有没有修复版本。嗯,这里要注意,扫描结果里的漏洞数量可能会让你吓一跳。我曾经扫描过一个基础镜像,发现了几百个漏洞,其中不少是 HIGH 或 CRITICAL 级别的。
关键点:扫描不是一次性的。镜像会变,漏洞库也会更新。今天没问题的镜像,明天可能就有新漏洞了。所以,定期重新扫描是必须的。
我在项目中遇到过这样的情况:一个镜像在开发环境扫描没问题,到了生产环境再扫,突然冒出来几个高危漏洞。为什么?因为漏洞库更新了。所以,我建议在 CI/CD 流水线里,每次部署前都强制扫描一次,如果发现 CRITICAL 级别的漏洞,直接阻断部署。
小技巧:扫描结果里,有些漏洞是误报,或者影响不大。你可以建一个白名单,把那些确认无害的漏洞排除掉。但白名单要定期审核,别让它变成藏污纳垢的地方。
4.2 签名验证:确保镜像没被篡改
扫描只能发现已知漏洞,但解决不了镜像被篡改的问题。你想想看,如果有人在你构建镜像之后,偷偷往里面塞了个恶意程序,扫描工具是发现不了的,除非那个恶意程序正好是已知的漏洞。
签名验证就是用来解决这个问题的。它通过数字签名,确保镜像的完整性和来源可信。说白了,就是给镜像盖个章,证明它是你构建的,而且没被人动过。
目前最主流的签名工具是 Cosign,它是 Sigstore 项目的一部分。Cosign 支持多种签名方式,比如密钥对、硬件密钥、OIDC(开放身份连接)身份认证。我个人推荐用 OIDC,因为它不需要管理密钥,更安全。
用 Cosign 签名一个镜像:
cosign sign --key cosign.key myregistry.io/myimage:latest
验证签名:
cosign verify --key cosign.pub myregistry.io/myimage:latest
如果验证通过,说明镜像没被篡改。如果验证失败,那就要警惕了,这个镜像可能有问题。
警告:签名密钥一定要保护好。我曾经见过有人把私钥直接放在代码仓库里,那跟没签名有什么区别?私钥应该放在密钥管理服务(KMS)里,或者用硬件安全模块(HSM)保护。
还有一个常见误区:签名只对镜像的 manifest(清单)签名,而不是对每一层签名。所以,如果有人替换了镜像的某一层,但 manifest 没变,签名验证是发现不了的。嗯,这里要注意,签名之前,一定要确保 manifest 的完整性。
4.3 可信仓库:镜像的保险柜
镜像扫描和签名验证都做完了,接下来就是把镜像放到一个安全的地方。这个地方就是可信仓库。说白了,可信仓库就是一个加了安全锁的镜像仓库,只有经过授权的镜像才能被推送和拉取。
常见的可信仓库方案有:
- Harbor:开源的企业级镜像仓库,支持漏洞扫描、签名验证、RBAC(基于角色的访问控制)、复制等功能。
- Docker Registry:Docker 官方的镜像仓库,功能比较简单,需要自己加安全层。
- 云厂商的镜像仓库:比如 AWS ECR、Azure ACR、阿里云 ACR,都自带一些安全功能。
我个人比较推荐 Harbor,因为它功能全面,而且社区活跃。Harbor 支持镜像签名验证,你可以配置策略,只允许经过签名的镜像被部署。这样,即使有人偷偷推送了一个未签名的镜像,也跑不起来。
举个例子,在 Harbor 里配置签名验证策略:
# Harbor 的配置示例
replication:
- name: "only-signed-images"
filters:
- type: "signature"
value: "cosign"
action: "allow"
这个配置的意思是,只允许带有 Cosign 签名的镜像通过复制策略。其他镜像一律拒绝。
关键点:可信仓库不仅仅是存储镜像的地方,它还是安全策略的执行点。你可以在仓库层面做很多事情,比如限制哪些用户能推送镜像、哪些镜像能部署到生产环境、镜像的保留策略等等。
我在项目中遇到过这样一个坑:团队用了 Harbor,但没配置签名验证策略。结果有人不小心推送了一个未签名的镜像到生产仓库,导致线上事故。后来我们加了一条规则:所有推送到生产仓库的镜像,必须经过签名验证,否则自动拒绝。从那以后,再也没出过类似问题。
4.4 三者的协同:构建一条安全的镜像供应链
镜像扫描、签名验证、可信仓库,这三者不是孤立的,它们需要协同工作,才能构建一条安全的镜像供应链。
我建议的流程是这样的:
- 构建镜像:在 CI/CD 流水线里构建镜像。
- 扫描镜像:用 Trivy 等工具扫描镜像,如果发现高危漏洞,阻断构建。
- 签名镜像:扫描通过后,用 Cosign 给镜像签名。
- 推送镜像:将签名后的镜像推送到可信仓库(比如 Harbor)。
- 验证签名:在部署前,仓库或部署工具验证镜像签名是否有效。
- 部署镜像:验证通过后,才允许部署到生产环境。
这个流程看起来简单,但实际落地时,需要 CI/CD 工具、仓库、部署工具的紧密配合。我建议用 Tekton 或 GitLab CI 来编排这个流程,它们都支持自定义任务和策略。
小技巧:如果团队刚开始做镜像供应链安全,不要一下子全上。先从扫描开始,等团队习惯了,再引入签名验证,最后再配置可信仓库的策略。一步一步来,更容易落地。
最后,我想说一句:镜像供应链安全不是一劳永逸的。漏洞会不断出现,签名算法可能会被破解,仓库的配置也可能出错。所以,定期审计、持续改进,才是王道。
好了,这一章的内容就到这里。下一章,我们会聊聊运行时安全,看看镜像跑起来之后,怎么保护它不被攻击。