开源项目办公室的重要职责之一,是确保当你的组织把开源代码与商业产品的私有代码或第三方代码结合时,能满足法律规定。
你们应当制定关于开发者如何正确使用开源代码的指引,并建立明确的程序来追踪开源代码的出处、授权方式及其最后的使用地。此指南提供了一个关于使用、发布及分发开源代码的基础合规流程的参考。
Contents
为何要追踪和审查代码?
简单说,如果贵公司未对开发人员如何及何处使用开源代码进行追踪,可能会违反开源许可证的相关规定,这可能导致高额的法律费用,同时也需花费工程师大量时间纠正。忽略开源的法律责任,还会影响贵公司在开源社区中的声誉。
开源项目办公室可以帮助统一关于开源的消费、分发与发布的政策和决策,追踪代码的来源及使用,并保证公司不违背合规责任。
理想地情况下,您的开源方案应该包含一个完整的合规计划,这需要在法律顾问的指导下制定。在此指南里,我们会探讨合规计划的关键部分:关于使用、发布及分发开源代码的政策和程序。
“一个良好设计的开源合规流程,不仅确保满足开源许可的条款,还帮助企业守护自身与第三方供应商的知识产权,避免不必要的泄漏或其他后果。” - Ibrahim Haddad,三星美国研究部门的研发副总裁及开源团队主管
维护开源合规程序对公司有多种益处:
- 技术上的优势:合规的软件集更易于服务、测试、更新及维护。
- 辨识开源代码的核心部分:可以识别哪些代码在公司多个产品和部门中使用,及其对开源策略的策略性价值。
- 显示与开源组件相关的成本与风险:当代码经过多次审查时,这一点更为明显。
- 树立社区信任:在面对合规问题时,此类程序展示了一贯的善意行为。
- 为潜在的收购、出售或新产品/服务的发布做好准备:虽然这不常见,但在交易前的合规确认是必要的。
- 在供应链中塑造良好信誉:可增强软件供应链的合规性,与 OEM 和下游供应商合作。
合规的角色与职责
在贵公司的开源项目里,您可能需要组建一个专门的开源合规团队来确保一切合规。
这个核心团队,常被称作审计团队或开源审查委员会(OSRB),是由工程和产品团队的代表、一名或多名法律顾问,以及合规负责人(通常是开源项目经理)所组成。
还有来自各个部门的人员会持续为开源合规工作提供支持,如:文档编写、供应链、企业拓展、IT、本地化及开源执行委员会(OSEC)等。OSEC 主要负责监督公司的整体开源策略。但不同于核心团队,这个扩展团队的成员在合规工作上只是兼职,这取决于他们从 OSRB 那里收到的任务。
OSRB 的职责是制定开源合规策略和一系列的程序,确定公司如何在日常工作中遵循这些规定。这个策略明确了为了保持合规性必须采取的行动,并为员工与开源软件之间的互动制定了管理准则。其中包括了批准、获取和使用开源的正式程序,以及发布含有开源或基于开源许可的软件的方法。
开源代码使用的基本策略
使用政策是合规计划中的基石。这些规则应该被纳入您的开源策略文档(您应该已经有了这样的文档,是吧?)并让所有人都能方便地查阅。
使用政策确保加入到产品库中的任何软件(无论是专有的、第三方的还是开源的)都经过了审计、检查和批准。同时,它也确保在产品交付给客户之前,您的公司已经计划好满足由于使用各种软件组件而产生的许可证义务。
不必制定一份篇幅冗长或过于复杂的文件。一个有效的开源使用政策应包含以下六个简洁的规则:
- 在将任何开源代码集成到产品中之前,工程师必须得到 OSRB 的同意。
- 从第三方获得的软件必须经过审计,以确定其中是否包含了任何开源代码,确保在产品交付前满足相关许可证的要求。
- 所有软件及其依赖都应经过审计和检查,这包括所有的专有软件组件。
- 在产品交付给客户之前,必须满足开源许可证的要求。
- 在一个项目中得到批准使用某个开源组件,并不代表在另一个项目中也自动获得该组件的使用批准,哪怕这两个组件是完全相同的。
- 任何经过修改的组件都必须再次经过审批流程。
五个阶段的代码审核流程
当你拥有了一套政策,接下来你需要策划并创建一个流程,使得按照这套政策操作变得简便。你的目标是让开发人员轻松使用开源代码并为开源项目做出贡献。
“如果你的代码审核流程太过繁琐,你就可能会妨碍创新,或者让开发人员找到借口去规避这一流程。” - Ibrahim Haddad,三星研究美国的研发副总裁兼开源组负责人
这一流程起始于对所选软件包的源代码进行扫描,接着是识别并处理可能出现的问题,进行法律和架构上的评审,最后决定是否批准其使用。
下面描述的是一个简化的合规审核流程视图。实际上,这是一个持续迭代的过程。值得注意的是,这些步骤只是为了说明,根据公司的具体需求和开源项目的配置,可能需要进行适当调整。
现在,让我们详细了解每一个阶段。
阶段1:源代码检查
在源代码检查阶段,我们使用专业软件工具扫描全部源代码。除了开源工具外,也有许多商业提供商提供这类工具。
当工程师提交一个在线申请表格时,这个阶段通常就开始了。(详细的使用表单和规则,请查看下方链接。)这份表单会列出所有关于开源组件的详细信息,并标明源代码在代码仓库中的位置。
提交表单后,会自动在 JIRA 或 Bugzilla 等系统中生成一个合规性任务,并向指定的审核人发送源代码检查请求。
每隔几周,我们还应进行一次全平台检查,确保没有任何未经申请的开源组件被集成到平台中。如果检查出有问题,系统会自动生成 JIRA 任务并分配给审核员。
源代码检查可能会因以下原因被触发:
- 工程师提交的申请表。
- 定期的全平台检查,这有助于找出未经申请就被引入的开源代码。
- 之前批准的软件组件发生变更。有时,工程师会评估并用一个 OSS 组件的版本进行测试,但在有新版本发布后改用新版本。
- 可能已经包含或尚未包含开源代码的第三方软件提供商的代码。
- 从互联网下载的、其作者或许可不明确的代码,这些代码可能包含或不包含开源代码。
- 新的私有软件组件被引入构建系统,这些组件可能使用了开源代码。
检查完成后,工具会生成报告,内容包括:
- 当前使用中的软件组件,亦称为软件物料清单(BoM)
- 有效的许可证、许可证文本和相关义务概览
- 需要法务确认的许可证问题
- 文件列表
- 已识别的文件
- 代码依赖
- 代码匹配项
- 未识别的文件
- 未识别的代码匹配项
下载开源包的注意事项
保持从网络下载的开源包的原始状态是非常重要的。在后续阶段(分发前),我们会通过比对原始包与修改后的包的差异来确认和追踪对源代码的任何更改。
如果第三方软件提供商使用开源,将该代码集成到产品中的产品团队必须提交描述要使用的开源的开源使用表单。如果第三方软件提供商仅提供二进制文件,而不提供源代码,则产品团队或管理与第三方软件提供商关系的软件供应商经理必须获得确认(例如,扫描报告),确保提供的软件中没有开源成分。
阶段2:识别与处理
在识别和处理阶段,审查团队仔细检视并处理扫描工具标注出的每个文件或代码段。
例如,扫描工具的报告可能指出了如许可证之间的冲突和不兼容性等问题。如果一切正常,那么合规部门会将该审查任务推进到下一阶段,即法律评估阶段。
若存在待处理的问题,合规人员会在审查任务中新建子任务,并分配给合适的工程师去处理。在某些情况下,可能需要对代码进行修改或重写;而在其他情况下,可能只需要对某些部分进行明确或澄清。这些子任务应描述问题、提供给工程师的推荐处理方案以及明确的完成时限。
当所有问题均已处理完毕,合规人员可以关闭相关子任务,并将主任务转交给法律部门继续审查。或者,他们可能会要求再次对源代码进行扫描,根据新的扫描报告确保之前的问题已被彻底解决。一旦确认所有问题都得到妥善处理,合规人员会将审查任务交给法律部门进行最后的评估和确认。
进行法律评估时,应将所有与开源软件有关的许可信息附加到审查任务上,如 COPYING、README、LICENSE 等文件。
第三阶段:法务评估
在法务评估阶段,法务团队(通常为开源评审委员会或OSRB的成员)会检查扫描工具生成的报告、软件组件的授权信息,以及工程师和审核团队在审查工单中提供的所有意见。
当审查工单进入法务评估阶段时,它已经包括了:
- 源代码的扫描报告,以及确保在扫描阶段确定的所有问题都已得到解决的相关信息。
- 附于工单上的许可信息副本:一般情况下,审查人员会把源代码包中的 README、COPYING 和 AUTHORS 文件附加到审查工单上。除了许可证信息,对于开源软件组件,常常需要从 COPYING 或 LICENSE 文件中获取,同时还需要记录版权和所有权声明。这些建议将在产品文档中提供适当的声明。
- 审查人员对审查工单的意见(如需要关注的点、其他疑问等)。
- 审查团队的工程代表或负责该软件包的工程师(软件包的所有者)的意见。
此阶段的目的是形成一个合法的建议,并对涉及的软件组件的许可证做出决策。这里提到的许可证可能有多种,因为在某些情况下,一个软件组件可能包含在多个许可证之下的源代码。在此阶段,存在三种可能的结论:
没有合规问题
如果许可证中没有问题,法务团队将决定软件组件的接受和分发许可证,并将审查工单推进到下一阶段:架构审核阶段。
接受的许可证是您在收到软件包时的许可证。分发的许可证是您在分发软件包时采用的许可证。在某些情况下,当接受的许可证是宽容性的并允许重新授权的许可证(例如,BSD)时,公司可能会选择在其自己的专有许可证下重新授权软件。更为复杂的情况是,一个软件组件包含了专有源代码、在许可证 A 下的源代码、在许可证 B 下的源代码和在许可证 C 下的源代码。在法务评估过程中,法务团队需要确定接受和分发的许可证:
接受的许可证 = 专有许可证 + 许可证 A + 许可证 B + 许可证 C 分发的许可证 = ?
合规冲突
若出现许可证的冲突,例如混合源代码持有不同且不相容的许可证,法律团队会标出这些冲突,并在 JIRA 工单中将任务重新指定给工程团队来进行代码的修改或重构。
举例来说,法务审查可能会发现,公司的保密知识产权与某个开源代码包进行了混合。在这种情况下,法务团队将会指出此问题,并将 JIRA 工单重新指定给工程团队,建议他们从开源组件中分离或移除保密的知识产权部分。如果工程团队决定保留这部分保密知识产权在开源组件中,那么开源执行委员会(OSEC)则需要考虑是否在开源许可证的条款下发布该部分的保密知识产权代码。
合规性方面存在不明确的问题
有时,许可证的信息可能不明确或缺失。在这种情况下,法务团队或工程团队会主动联系项目的维护者或开源代码的开发者,以便澄清这些不明确的地方,并确定这一特定软件组件是基于哪种许可证进行授权的。
第四阶段:架构审核
在架构审核阶段,合规人员与审计团队或开源审核委员会的工程代表对开源、私有和第三方代码的交互进行分析。这主要是通过查看一个架构图来完成的(以下为示例),图中标明了:
- 开源组件(直接使用或经过修改)
- 私有组件
- 来自第三方软件供应商的组件
- 组件间的依赖关系
- 软件组件之间的交互方式(如 TCP/IP、Linux socket、静态或动态链接的函数 API 等)
- 通讯协议
- 特定软件组件与其交互或所依赖的其他开源包,特别是当这些包受不同的开源许可证约束时。
架构审核的结果是分析可能存在的从开源到私有或第三方软件组件的许可义务(以及在开源组件之间的)。
若合规人员发现有问题,比如一个私有软件组件链接到了一个受 GPL 许可的组件,那么合规人员会将合规事项转交给工程部门解决。如无问题,合规人员则将事项推进至审批流程的下一阶段。
第五阶段:终审
终审通常为审计团队或开源审核委员会(OSRB)的线下会议,会议中将决定批准或拒绝软件组件的使用。
团队基于软件组件的详细合规记录来做决策,这些记录包括:
- 由扫描工具输出的源代码扫描结果。
- 已发现的问题列表、解决这些问题的详情,以及确认这些问题得到妥善处理的责任人。
- 架构图以及该软件组件与其他软件组件之间的交互方式。
- 对合规的法律建议以及关于接受和发放许可的决策。
- 若适用于嵌入式环境(如C/C++),还包括动态和静态链接的分析。
在大部分情况下,当软件组件到达终审阶段,除非有特殊原因(如该软件组件不再被采纳),它通常都会得到批准。一旦得到批准,合规人员将为这些批准的软件组件制定许可义务清单,并交给相关部门执行。这可能涉及:
- 更新软件库存,标明特定的 OSS 软件组件版本 x 已得到授权在产品 y 的版本 z 中使用。
- 向文档团队提交任务单,更新产品文档中的终端用户通知,表明产品或服务中已使用开源软件。
- 在产品出货前启动发行流程。
合规人员会追踪所有未完成的任务,并确保它们在产品发货或服务上线前完成。
如需了解更详细的应用流程和可能的场景,请查阅我们的电子书《企业中的开源合规》。
在v1.0之后该怎么做
初始合规,也叫做基线合规,是从开发初期开始的,一直持续到产品的首个版本发布。合规团队会识别出软件基线中的所有开源代码,并确保所有的源代码组件都经过了前述的五个阶段的审查。
“需要明确的是,开源合规并不在1.0版本时就结束了。” - Ibrahim Haddad,三星研究美国的研发副总裁以及开源团队负责人
您还需构建一个增量合规流程,用于产品上线后的源代码审查。这一流程从新的开发分支开始,该分支可能包含新功能或者修复的 bugs。
增量合规即在将新功能加入到基线版本1.0的过程中,持续进行合规检查。与建立初始合规相比,增量合规需要的努力相对较少。但可能会遇到一些挑战。您需要精确地鉴定版本 1.0 和版本 1.1 之间源代码的变化,并确保版本差异中的合规:
- 可能加入了新的软件组件。
- 有些现有软件组件可能被移除了。
- 现有的软件组件或许升级到了新的版本。
- 在各个版本中,软件组件的许可可能发生了改变。
- 现有的软件组件可能有代码的变化,可能是错误修复、功能增加或架构上的调整。
一个显而易见的问题是:我们如何追踪所有的这些变动?答案是:物料清单差异工具(BOM 差异工具)。给定产品 v1.1 的 BOM 和 v1.0 的 BOM,工具会计算其差异,输出如下:
- 在 v1.1 中新加入的软件组件名称。
- 被更新的软件组件名称。
- 被移除的软件组件名称。
有了这些信息后,进行增量合规变得相对简单:
- 将新的软件组件引入到前述的五阶段审查过程中。
- 计算变更的软件组件的源代码差异,并决定是否需要重新进行代码扫描或者依赖之前的扫描结果。
- 更新软件清单,移除不再使用的软件组件。
下文提到的图表描述了增量合规流程的概览。每个产品版本的 BOM 文件都会存储在构建服务器上。BOM 差异工具接收两个 BOM 文件作为输入,每个都代表一个不同的产品版本,然后计算其差异,生成上述的变更列表。
此时,合规人员会为版本中所有新的软件组件建立新的合规工单,更新那些源代码有变更的工单,可能再次引导它们经过审查流程,并最后更新软件清单,移除已批准列表中被移除的软件组件。
开源使用申请表
当开发人员希望将开源软件引入到公司项目中,填写开源使用申请表单是一个关键流程,这需要被高度重视。
开发人员可以在线提交此表单,以申请使用某个特定的开源组件。表单中涉及多个问题,这些问题的目的是为审计小组或开源审查组提供决策所需的信息,以确定是否批准所提议的开源组件的使用。
此链接提供了一个示例表单,其中详细列出了在开源使用申请中需要的信息。一般情况下,这些信息都是通过下拉菜单进行选择的,以便快速和准确地填写。
关于 OSRB 使用的表单,有以下几点规定:
- 该表单仅针对于特定产品在特定场景下的开源使用。它并不是针对所有产品的开源组件进行一般性的批准。
- 该表单是审计流程的基础,它提供了审查小组所需的全部信息,以确保实际的应用方式与在表单中描述的用途、审计结果和架构评审结果相匹配。
- 如果某一开源组件的使用方式发生变更,必须重新填写并提交表单。
- 在将开源代码融合到产品开发流程之前,审计小组或审查组必须先对此表单进行批准。
- 对于任何需要获得专利授权或专利无异议的开源包,必须得到开源执行委员会的批准后才能使用。
结语
开源合规在软件开发中占据了重要的位置。如果你在产品中运用了开源软件,但缺乏健全的合规流程,那么你应该把此指南当作一个行动启示。
从本质上说,开源合规涉及一套控制措施,旨在管理商业产品中开源内容的引入和发布。合规的核心目标是识别产品中所使用的所有开源内容(包括组件和代码片段)并制定满足许可要求的策略。想要更深入地了解开源合规,推荐下载我们提供的免费电子书,《企业开源合规指南》(Open Source Compliance in the Enterprise),作者是 Ibrahim Haddad。
架构图模板
在开源审查流程中的架构审查环节,我们会使用架构图来呈现示例平台上各软件组件间的交互关系。您可以在这里查看一个示例的架构图模板,该图展示了:
- 模块的依赖关系
- 专有组件
- 开源组件(包括已修改和未修改的)
- 动态和静态的链接
- 内核空间与用户空间
- 共享的头文件
- 通讯协议
- 与该软件组件交互或依赖的其他开源组件,特别是当这些组件受到不同开源许可的约束时
鸣谢
以下对本项目的贡献者表示感谢:
Ibrahim Haddad 他是三星研究美洲部门的研发副总裁以及开源团队的主管。