软件真是个有趣又深奥的东西,它由看似神奇的代码片段组成,这些代码运行在最终的终端上,本身却并非生命体,但拥有自己的生命周期。
软件最初是源代码的形式,仅仅是存放在某个仓库的文本文件,然后通过独特的构建过程,这些源代码会转变为其他形式。例如交付到 web 服务器的压缩 JavaScript 代码块、包含框架代码和业务逻辑的容器镜像,或者针对特定处理器架构编译的原始二进制文件。
这种最终的形态转变,也就是源代码生成的其他形式,通常被称为“软件制品”。在创建之后,制品通常会处于休眠状态,等待被使用。它们可能会被放置在软件包注册表(例如 npm、RubyGems、PyPI 等)或容器注册表(例如 GitHub Packages、Azure Container Registry、AWS ECR 等)中,也可能作为附加到 GitHub 版本发布的二进制文件,或者仅仅以 ZIP 文件的形式存储在某个 Blob 存储服务中。
最终,有人会决定拾取该制品并使用它。他们可能会解压缩包、执行代码、启动容器、安装驱动程序、更新固件 - 无论采用何种方式,构建完成的软件都将开始运行。
这标志着生产生命周期的顶峰,该周期可能需要大量人力投入、巨额资金,并且鉴于现代世界依赖软件运行,其重要性不言而喻。
然而,在许多情况下,我们并不能完全保证所运行的制品就是我们构建的制品。制品经历的旅程细节要么丢失,要么模糊不清,很难将制品与其来源的源代码和构建指令联系起来。
这种缺乏对制品生命周期的可见性是当今许多最严峻的安全挑战的根源。在整个软件开发生命周期 (SDLC) 中,有机会保护代码转换为制品的流程 - 如此一来,可以消除威胁行为者破坏最终软件并造成严重后果的风险。一些网络安全挑战似乎难以成功应对,但这种情况并非如此。让我们深入了解一些背景知识。