10.3 采购、开源与许可
概述与动机
几乎每一个现代软件系统,大部分都是由他人编写的组件组装而成的。开源软件构成了操作系统、语言、框架、数据库和云基础设施的根基。它以两种方式进入企业:一种是通过有计划的采购,另一种是通过个别开发者随手写下的 import 语句。本章讲的是如何有计划地进行这种消费(以及在合适的地方进行贡献)。这意味着需要一套战略、许可证合规工作、对义务和著佐权风险的理解,以及一份应对你所依赖组件不可避免地走向生命周期终止的计划。
对于大型团队来说,这里的利害关系同时涉及法律、运维和战略三个层面。在法律层面,开源许可证是具有真实义务、可强制执行的合同。把著佐权(一种可能要求衍生作品以相同条款共享的许可方式)处理错了,在最坏的情况下可能被迫公开专有源代码,或引发诉讼。许可证违规甚至可能在尽职调查期间阻断一次收购或一次公开发行。在运维层面,失于管理的依赖项会腐坏:组件失去维护、积累漏洞,并在仍深埋于生产环境中的情况下走到生命周期终止。在战略层面,开源不仅仅是一项节省成本的投入。它还是避免被锁定、吸引人才、塑造你所依赖的生态系统的一种方式()但这些优势只有在你有意投入的情况下才能获得。
政府领域还多了一层维度。许多司法辖区如今都有明确倾向于开源、开放标准以及跨机构代码共享的政策。这些政策常常被表述为”公共资金,公共代码”:即由纳税人资助的软件,默认情况下应当向公众开放。因此,公共部门的工程师既要应对许可证合规问题,也要应对倾向于优先使用、发布和复用开源软件的积极授权要求。本章旨在让这一切在规模化场景下都变得可管理。
关键原则
- 开源是一条供应链,不是免费的东西。 用对待任何关键供应商同样的严谨态度来对待所消费的组件。
- 许可证是义务,不是可以忽视的许可。 每一个依赖项都带有条款;在发布之前先了解清楚这些条款。
- 著佐权是一项设计约束,而不是一个禁忌。 著佐权许可证是可用的、有价值的;它们只是要求你理解自己是如何组合和分发软件的。
- 有计划地消费,有战略地贡献。 决定引入什么,并在符合自身利益的地方,投入精力向上游贡献,而不是另起分支。
- 对一切进行清点。 你无法合规、保障或更新你看不见的东西;SBOM(软件物料清单,即软件中所有组件的完整清单)是最基本的要求。
- 从一开始就为生命周期终止做计划。 每一个依赖项总有一天会失去维护;在被迫走向退出之前,先了解清楚你的退出方案。
- 在政府领域,默认选择开放。 优先选择开放标准和开源软件,除非有特定理由,否则应发布用公共资金开发的代码。
建议
制定开源战略和消费政策
发布一份清晰的政策,说明开发者如何将开源软件引入组织:哪些许可证是预先批准的,哪些需要评审,哪些在你们的用例中是被禁止的。提供一条快速、低摩擦的审批路径。一项比直接复制代码还慢的政策,只会被人无视。要区分使用场景,因为同一份许可证在组件被用作内部服务、嵌入分发的产品,还是链接进专有应用中时,表现是不一样的。让最省事的路径就是合规的路径:建立一个经过审核的内部组件仓库、在流水线中进行自动化扫描,并为常规情况提供开发者无需咨询律师就能遵循的清晰指引。
管理许可证合规、义务和著佐权风险
要熟悉各类许可证及其义务。宽松型许可证(如 MIT、BSD 和 Apache 2.0)主要要求保留署名和声明;Apache 2.0 还额外附加了明确的专利授权。弱著佐权许可证(如 LGPL 和 MPL)要求你共享对受覆盖文件所做的修改,但通常允许你与专有代码组合使用。强著佐权许可证(如 GPL)可能要求整个分发的作品都以相同条款提供。网络著佐权(AGPL)把这项义务扩展到了通过网络提供的软件上,而不仅仅是以二进制形式分发的软件。最关键的义务取决于两件事:你是否分发该软件,以及你把各个组件结合得有多紧密。让合规工作自动化:扫描依赖项的许可证,生成并附带所需的署名和声明文件,并在构建流程中根据政策设卡,让被禁止的许可证无法悄悄进入生产环境。
建立开源项目办公室(OSPO)
如果你大规模消费开源软件,就要建立一个统筹点()OSPO,负责统管开源战略、政策、合规工具、贡献治理和社区关系。OSPO 能遏制每个团队各自为政所造成的混乱。它提供了单个团队无法自行维护的专业能力。它还能捕获战略价值:决定投资哪些项目、何时向上游贡献,以及如何妥善发布你自己的开源项目。即便是一个小型的 OSPO(有时只是一个人再加一个跨职能工作组),相比放任自流的状态,也能显著改善一致性、降低法律风险。
治理贡献工作,并在适当的地方治理发布工作
要有意识地决定何时回馈上游。把修复和新功能上贡给你所依赖的项目,能减轻你的维护负担,因为你不再需要携带私有补丁。这样做还能积累善意和影响力,并强化对你至关重要的组件。为开发者提供一条清晰、快速的流程来处理经批准的贡献,包括如何处理知识产权和贡献者协议。当你发布自己的开源项目时,要做得规范:选择合适的许可证、记录治理方式,并承诺长期维护。一个被遗弃的项目对你声誉的伤害,比根本没有项目还要大。
满足政府开源和”公共资金,公共代码”的授权要求
公共部门团队应当把开放性当作默认选项。优先选择开放标准,以避免被锁定,并能在各机构和供应商之间协同工作。默认公开发布用公共资金开发的源代码,除非存在特定的、有据可查的豁免情形:例如安全敏感组件、第三方权利,或隐私方面的顾虑。先复用后自建:先检查是否已有其他机构发布过合适的代码。把这些期望融入采购流程中,这样供应商交付的就是开放、可复用、文档完善的代码,政府保留适当的权利,而不是机构自己无法维护或共享的专有黑箱。
管理依赖项和已到生命周期终止的软件
维护一份实时的清单(SBOM),记录每个组件及其版本、许可证和维护状态。让依赖项保持合理的更新频率。小步、频繁的更新,远比罕见的、巨大的跳跃式更新更便宜、更安全。关注上游项目发布的生命周期终止公告和安全支持窗口,并在支持结束之前规划迁移,而不是等到一个漏洞逼得你手忙脚乱之后才行动。对于有被遗弃风险的关键组件,提前决定你将资助维护者、自己参与维护、另起分支,还是替换掉它。对商业软件和开源软件的生命周期终止都要进行跟踪,并把支持到期这件事,与任何其他运维风险一视同仁地对待。
权衡:优缺点
| 选择 | 优点 | 缺点 |
|---|---|---|
| 自由消费开源软件 | 交付速度快;杠杆效应巨大;没有许可费用 | 许可证、安全和维护方面的义务现在归你所有 |
| 严格的许可证白名单 | 法律风险低;可预测 | 拖慢团队节奏;可能排除真正有用的组件 |
| 仅使用宽松型许可证 | 义务最小;易于组合 | 放弃了有价值的著佐权项目;互惠性较弱 |
| 在合适的地方接受著佐权 | 能接触到强大的生态系统;获得互惠收益 | 在组合和分发时需要格外小心 |
| 向上游贡献 | 减轻私有补丁负担;带来影响力和善意 | 需要持续投入;有知识产权和流程开销 |
| 转而自建专有方案 | 完全掌控;没有外部义务 | 成本高昂;重新发明通用轮子;你要永远维护它 |
| 政府默认公开发布 | 透明;可复用;避免被锁定 | 需要发布工作投入;安全评审;持续的维护责任 |
核心张力在于开发者速度与控制力之间的取舍。把一切都锁在繁重的评审之后,开发者就会绕开政策行事。这会制造出失于管理的影子依赖项,比一种宽松但可见的方式更糟糕。而如果完全不加控制,你就会悄悄积累法律和安全债务。解决办法在于自动化和审核策展:通过预先审核过的组件、流水线扫描和清晰的默认设置,让合规路径成为最快的路径,从而在不制造摩擦的情况下实现控制。在著佐权问题上,权衡不在于”有风险还是安全”,而在于”理解还是不理解”。一旦你了解了如何组合和分发软件,著佐权许可证就是完全可用的。
与团队讨论的问题
在内部使用、分发产品和网络提供服务这几种场景下,你对强著佐权和网络著佐权分别有什么明确的规则? 著佐权是一项设计约束,而不是禁忌,其义务取决于两件事:你是否分发该软件,以及你把各个组件结合得有多紧密。一个用在内部工具中的 GPL 组件,和一个链接进你所发布产品中的 GPL 组件,表现截然不同,而 AGPL 把披露义务扩展到了你仅仅通过网络提供的软件上,这改变了你对任何以服务形式运行的软件所做的自建还是采用的判断。针对每种场景把规则写清楚,这样开发者无需咨询律师就能知道(举例来说)宽松型许可证在任何场景下都已预先批准,强著佐权在内部使用没问题但不能进入发布产品,而 AGPL 在接触到联网服务之前需要评审。带来证据:扫描你当前的依赖树,找出著佐权组件目前相对于你的分发边界处于什么位置。然后在构建流程中根据该政策设卡,因为一条没有扫描工具强制执行的规则,开发者迟早会无意中违反它。
你是否需要一个开源项目办公室,今天又是谁负责许可证政策、扫描和贡献决策? 如果诚实的答案是”没有人负责”或”每个团队各自决定”,那你实际上就是在放任自流,悄悄积累法律和安全债务。一个 OSPO,哪怕只是一个人加一个跨职能工作组,也能遏制这种混乱,并捕获战略价值:投资哪些上游项目、何时贡献,以及如何妥善发布自己的项目。把证据带到会议上:有没有人能拿出当前已批准的许可证清单、SBOM,以及在收购尽职调查中会负责回答著佐权问题的人是谁?讨论的结果应当明确职责归属,并通过预先审核的组件和流水线扫描,让合规路径成为最快的路径,从而让开发者在不制造摩擦的情况下获得控制。一项比直接复制代码还慢的政策,只会被人无视。
哪些依赖项一旦明天被遗弃会造成最大伤害,你对每一项都有预先决定好的应对方案吗? 每个依赖项最终都会走到生命周期终止,而这类事件中代价最高昂的版本,是直到一个漏洞逼得人们不得不关注时,才发现某个核心组件在几个月前就已经失去支持。对于那些有被遗弃风险的关键组件,提前决定你将资助维护者、自己参与维护、另起分支,还是替换掉它。带来证据:从你的 SBOM 中列出那些一旦失效就会导致收入型或使命关键型服务中断的组件,并记录每一项的维护状态和安全支持窗口。讨论的结果应当把生命周期终止从一个意外事件,转变为一项受到跟踪、有计划迁移方案的运维风险,与任何其他风险一视同仁。以小步、高频的方式保持依赖项更新,远比那种罕见的、被迫进行的巨大飞跃式更新便宜得多。
你能否生成一份完整、最新、一直深入到传递依赖树底层的 SBOM,需要多快? 当一个头条级漏洞出现在一个被广泛使用的库中时,领导层问的第一个问题就是”我们受影响了吗,受影响的地方在哪里?“一个无法在几小时内给出答案的团队,已经落后了,因为真正的风险往往隐藏在没有人主动选择过的、好几层深的依赖项里。与之相抗衡的考量是成本和噪音:跨众多服务的完整传递清单会生成一份庞大、不断变动的列表,而过度告警会训练人们去无视它,所以你必须决定究竟什么深度、什么严重程度才真正需要触发行动。把证据带进讨论:现在就尝试为一个生产服务生成一份最新的 SBOM,数一数其中有多少组件是直接依赖、多少是传递依赖,并计时看用了多久。对于企业或政府机构来说,要把这一点与一个具体的事件响应目标,以及任何披露受影响组件的监管义务联系起来,因为一项要求你报告你根本无法列举清楚的暴露情况的授权要求,是一项你注定会违反的授权要求。
什么时候一个关键依赖项值得你去资助、贡献或托管维护,而不是把它当作免费的东西? 大多数组织消费开源软件时,把它当作一种公用事业,然后在发现支撑某个营收服务的组件竟然只靠一位无偿的志愿者维护时大吃一惊。有意识地决定资助一位维护者、向上游贡献修复,或者发布并托管维护自己的项目,能把一个脆弱的免费输入,转变为一个持久的、你能施加影响的输入,并让你的工程师不必在每次升级时都携带私有补丁。这里的张力在于:贡献和托管维护需要真实、持续的工程时间投入,并带有知识产权和流程方面的开销,所以你不可能对所有东西都这样做。带来证据:从你的 SBOM 中标出那少数几个一旦失效就会导致使命关键型服务中断的组件,并记录每一项的维护者数量、资金情况,以及你目前已经携带了多少针对它的私有补丁。对于大型或公共组织,要权衡一次大张旗鼓发布、后来却被遗弃的开源项目所造成的声誉损失;而在政府领域,要把对已发布的公共资金代码的持续维护,当作交付工作的一部分,而不是可有可无的附加项。
你的采购流程,实际交付的是带有你所需权利的开放、可复用、文档完善的代码,还是你无法维护或退出的专有黑箱? 在没有开源专业知识的情况下撰写的合同,往往会把你日后会后悔的控制权拱手交给供应商:封闭格式、没有发布或修改的权利,以及在供应商撤出后机构无法打补丁的依赖项。及早把这一点做对,远比在续约时才发现自己无法离开要便宜得多。与之相抗衡的考量是速度和供应商选择:要求开放交付物和可移植性,可能会缩小候选范围、拖慢授标进度,一些确实有用的供应商也会抵触这一点。带来证据:调出两份近期的合同,检查它们是否明确规定了许可证条款、源代码交付、文档标准、SBOM 提供,以及组织所保留的权利。对于企业采购,要把这一点与锁定风险和总成本分析联系起来;对于政府采购,要把它与默认开放和”公共资金,公共代码”的授权要求联系起来,并与那套让你只能豁免安全敏感部分、而不是整个系统的、有据可查的豁免流程联系起来。
行业视角
初创企业。 你几乎所有东西都是用开源软件组装出来的,也没有律师,所以把规则控制在一页纸以内:像 MIT 和 Apache 2.0 这样的宽松型许可证预先批准,强著佐权用于内部工具没问题,但不能进入发布的产品,任何不寻常的情况由创始人快速评审。在流水线中加入许可证和漏洞扫描,从第一天起就维护一份 SBOM,因为把这件事做对的最便宜时机,就是在收购方的尽职调查梳理你的依赖树之前。不要出于恐惧而禁用著佐权,理解它,然后继续前进。
小型企业。 没有开源专家,预算也紧张,所以要靠工具而不是人手:构建流程中的一个扫描器加上一份简短的已批准许可证清单,就能完成大部分本该由人来做的工作。诚实地把消费问题框定为购买还是自建的选择,因为重新发明一个维护良好的开源组件通常是昂贵的选择,但依赖一个你从未清点过的组件同样代价不菲。保留一份简单的记录,说明你在用什么、使用什么许可证,这样当客户的安全问卷调查或漏洞警报出现时,就不会变成一场手忙脚乱。
企业。 在规模化场景下,问题在于跨众多团队的一致性,因此要建立一个 OSPO,负责政策、自动化扫描、署名生成和贡献治理,并通过经过审核、预先审查的组件,让合规路径成为最快的路径。在流水线中按场景强制执行著佐权规则,跨服务维护 SBOM,并把依赖项的更新和生命周期终止作为受跟踪的运维风险来管理。把开源软件当作你代码库中大部分内容的供应链管理工作来对待,并为收购尽职调查准备好可供审计的证据。
政府。 开放性往往是强制性的,而非可选的,所以要默认采用开放标准,并发布用公共资金开发的代码,除非存在出于安全、第三方权利或隐私原因、有据可查的豁免。先检查跨政府目录,复用而不是重新自建,并把开放、可复用、文档完善的交付物和保留权利写入采购流程,这样你得到的就是可维护的代码,而不是专有黑箱。对已发布的代码要求真实的维护责任,并让豁免流程保持狭窄和透明,使它只关闭必须关闭的部分。
示例
初创企业。 一家四人规模、正在开发移动应用的初创公司,几乎所有东西都用开源软件组装而成,也没有在职律师。创始人没有出于恐惧禁用著佐权,而是写了一份单页政策:像 MIT 和 Apache 2.0 这样的宽松型许可证预先批准,像 GPL 这样的强著佐权用于内部工具没问题,但为了避免披露义务,不能进入发布的应用,任何不寻常的情况由创始人快速评审。他们在流水线中加入了许可证和漏洞扫描,这样被禁止的许可证就无法悄悄溜进发布版本,从第一天起就维护一份 SBOM,并向一个关键库上贡了一个小的修复,从而不再需要在每次升级时携带私有补丁。及早把这件事做对,也让他们免于在收购方的尽职调查最终梳理依赖树时遭遇痛苦的意外。
企业。 一家发布分发产品的软件供应商运营着一个 OSPO。该 OSPO 维护一份已批准的许可证清单、一个经过审核的内部组件仓库,以及在每条流水线中的自动化许可证与漏洞扫描。当一名开发者引入一个新依赖项时,流水线会依据政策检查其许可证,生成随产品一同发布的署名声明,并标记出任何需要评审的内容。强著佐权组件被允许用于内部工具,但被阻止进入分发产品,以避免披露义务。公司向少数几个关键依赖项上贡了修复。这消除了此前工程师们在每次升级时都要携带的一大批私有补丁积压。
政府。 某国的数字服务机构在”公共资金,公共代码”的政策下运作。新服务建立在开放标准之上,默认在一个公共代码仓库中公开开发,并在各机构之间复用。其采购模板要求供应商交付开放、文档完善、可复用的代码,政府保留发布和修改的权利。在开始开发一个新组件之前,团队会先搜索一个跨政府目录,查找是否已有可复用的代码。安全敏感模块通过一套有据可查的流程被豁免于公开发布,而不是让整个系统都变成封闭的。
商业理由:动机、投资回报率与总体拥有成本
妥善管理开源软件,是捕获其巨大杠杆效应与为其隐藏成本买单之间的分水岭。开源软件让大型组织能够站在一个它永远无力自行构建的基础之上。但总体拥有成本包括合规、安全补丁和最终迁移,这些成本无论你是否为之规划,都会如期而至。有计划的管理能把不可预测的、代价高昂的危机,转变为小额、稳定、有计划的成本。这些危机包括在收购尽职调查中发现的著佐权违规、被迫紧急迁移出一个已被遗弃的组件,或者一个没人知道存在的依赖项中出现的漏洞。
与暴露的风险相比,采用的成本是不高的:一个 OSPO 或工作组、扫描工具,以及维护清单的纪律。而不采用的成本,会以法律责任、尽职调查失败、可追溯到未打补丁依赖项的安全事件,以及被推迟的升级最终迫使你进行痛苦的大爆炸式迁移所带来的复利成本的形式出现。在向领导层论证时,把开源管理定位为你代码库中大部分内容的供应链管理。也要指出战略上的好处:避免锁定、更快的交付速度、吸引人才,以及对你所依赖生态系统的影响力。在政府领域,还要加上授权要求这个维度。开放性往往是强制性的,而非可选的,做好这件事既能避免不合规,也能避免公共支出的重复浪费。
反模式与陷阱
- 复制粘贴式许可。 开发者引入组件时完全不检查许可证,直到审计或收购时才发现相关义务。
- 没有清单。 当漏洞或许可证问题爆发时,无法回答”我们在用什么、用的是什么许可证?”
- 著佐权恐慌。 出于恐惧而不是理解就禁用所有著佐权许可证,放弃了有价值的生态系统。
- 被遗弃的开源发布项目。 大张旗鼓地发布一个项目,然后再也不维护它,损害了声誉。
- 忽视传递依赖。 只审查直接依赖项,而真正的风险却隐藏在好几层深的地方。
- 生命周期终止的意外。 直到一个漏洞逼得人们关注时,才发现某个核心组件在几个月前就已经失去支持。
- 比复制代码还慢的政策。 一套过于繁重的合规流程,导致开发者绕开它,从而制造出隐形的影子依赖项。
- 政府黑箱。 采购机构无法维护、共享或退出的专有系统,违反了默认开放的原则。
成熟度模型
第 1 级:启动。 开发者自由引入开源软件,没有政策也没有清单。许可证未经审查,著佐权义务未知。生命周期终止是被偶然发现的,通常是在一个漏洞逼得人关注时才发现。没有人负责开源战略。
第 2 级:发展。 已存在一份基础政策和已批准许可证清单,一些团队会遵循它们。会进行扫描,但往往是手动的、滞后的,或只覆盖少数项目。为主要系统维护着一份清单,但传递依赖未被映射。贡献和生命周期终止的处理都是临时性的,各团队之间不一致。
第 3 级:标准化。 一个 OSPO 或类似机构在组织范围内统管战略、政策和工具。许可证和漏洞扫描在每条流水线中自动化进行,署名和声明文件自动生成,构建流程设有关卡,让被禁止的许可证无法进入。SBOM 一直维护到传递依赖树的底层,贡献遵循一套有文档记录的流程,生命周期终止被跟踪并配有计划迁移方案,政府团队默认公开发布。
第 4 级:管理。 该项目按基线进行度量和控制。你会跟踪各服务的政策扫描覆盖率、已披露依赖项漏洞的平均修复时间、处于安全支持窗口内的组件占比、许可证违规的漏检率、依赖项更新滞后度,以及携带的向上游私有补丁数量。著佐权组件相对于分发边界的位置受到监控,指标相对于目标的表现驱动每一次继续或叫停的决策,而不是凭主观判断。
第 5 级:协同。 开源软件是一项在整个组织中持续改进、被整合利用的战略资产。合规完全自动化,不合规的组件无法进入生产环境。你有意识地投资于关键的上游项目,常态化地进行贡献,并托管维护自己那些运作良好的项目。依赖项更新和生命周期终止会随着风险和指标的变化而自适应地管理,开放性也真正成为一种竞争优势和公民层面的优势。
讨论思路
- 在快速的宽松默认策略与避免法律和安全债务所需的控制力之间,正确的分界线在哪里?
- 组织什么时候应该资助或维护一个关键的上游依赖项,而不是把它当作免费的东西?
- 你如何决定自己的哪些组件值得作为开源软件发布并加以维护?
- 对于政府而言,在不侵蚀默认公开发布原则的前提下,豁免组件的流程要怎样设计才站得住脚?
- 许可证和安全评审实际上需要深入传递依赖多深才算合理?
- 对于你以服务形式提供的软件,网络著佐权(AGPL)是否改变了你自建还是采用的判断?
关键要点
- 开源软件占据了大多数代码库的主要部分,必须作为一条供应链来管理,而不是当作免费、无后果的东西对待。
- 许可证带有真实的义务;要理解宽松型、弱著佐权、强著佐权和网络著佐权这几个家族,以及分发和组合方式如何触发相应义务。
- 通过审核策展、自动化扫描和清晰的默认设置,让合规路径成为最快的路径,否则开发者就会绕开政策行事。
- 建立一个 OSPO,在规模化场景下统管战略、合规、贡献和维护工作。
- 维护一份 SBOM,以小步方式保持依赖项更新,并在生命周期终止逼出危机之前提前规划。
- 在政府领域,默认采用开放标准并发布用公共资金开发的代码,先复用后自建。
参考文献与延伸阅读
- Heather Meeker,《Open (Source) for Business》与《Open Source for Business》
- Van Lindberg,《Intellectual Property and Open Source》
- The Linux Foundation 与 TODO Group,《OSPO guides》与《Open Source Program Office resources》
- OpenChain(ISO/IEC 5230),《Open Source License Compliance》
- Software Package Data Exchange(SPDX,ISO/IEC 5962)规范
- CycloneDX SBOM 规范
- Free Software Foundation,《GNU General Public License》与《GPL FAQ》
- Open Source Initiative,《The Open Source Definition》及已批准许可证列表
- Free Software Foundation Europe,《Public Money, Public Code》
- U.S. Federal Source Code Policy 与 Code.gov 指南
- UK Government,《Technology Code of Practice》与开放标准原则