LWN:"Critical" 项目以及志愿维护者!
共 5395字,需浏览 11分钟
·
2022-07-24 21:25
关注了就能看到更多这么棒的文章哦~
"Critical" projects and volunteer maintainers
By Jake Edge
July 13, 2022
DeepL assisted translation
https://lwn.net/Articles/900953/
过去的五十多年里,自由和开源软件(FOSS)已经从几乎无人使用情况发展成为了我们今天所依赖的大部分基础设施的基础。与软件本身一样,FOSS 正在 "吞噬世界"。但这已经改变了所有这些代码的维护者的角色,或者说正在改变。当 "关键 "基础设施使用自由软件项目的代码时,突然间,没有任何预先警告,这些代码本身就变得至关重要了。但是,这些软件的许多维护者都是志愿者,他们在发布自己的代码时,并不是为了满足大公司和组织的需要,他们只是在解决自己的一些需求,现在很多其他人也在吵着要他来解决需求。
supply-chain security 问题显然是一个需要解决的严重问题。Log4j 的事件就是最近的一个例子,它说明有一些非常小的组件中的安全漏洞是如何通过 dependency chain 在互联网上扩散开来的。一些项目直接依赖于 Log4j,但其他许多项目由于使用了直接或间接依赖于 Log4j 的 package 或 library 而变得易受攻击了。
有些地方的 dependency chain 往往特别复杂,因此更容易被人故意注入恶意软件,这通常是每种特定语言的软件包仓库。像 Python Package Index(PyPI)这样的网站就提供了非常多而复杂的 component 模块,用来被应用程序或其他库所使用。Python 自带的 pip 工具会很高兴地安装 PyPI 软件包以及它们的所有依赖项,而且是递归式的。其他许多语言也有类似的 repository 和工具。
Critical components
目前进行着许多种工作来确定其中最关键的依赖项,并为这些项目来提供帮助,以便它们不会落到 Heartbleed 问题出现前的 OpenSSL 的那个境地,或者代表这个经典的 xkcd (https://xkcd.com/2347/) 中的那个项目。举例来说,开源安全基金会(OpenSSF)有自己创建 Alpha-Omega 项目,正在识别在安全方面需要援助的项目。PyPI 也一直在根据其公共数据集(public data set)来识别在过去 6 个月中被下载最多的软件包;那些在前 1%的软件包被认为是 "critical" 的。大约有 3500 个项目被用这种方式确认出来,这些项目的维护者都被免费提供了一个安全密钥,以帮助他们为其 PyPI 账户设置双重认证(2FA)。
目前,任何软件包都不需要使用 2FA 认证,但 PyPI 计划 "在未来几个月内" 要求关键项目的维护者开始使用 2FA 认证。一旦生效之后,没有启用 2FA(可能会使用安全密钥或基于时间的一次性密码(TOTP)应用软件)的维护者应该就无法进行任何修改了,例如就无法更新软件包。当然,这也有其风险,因为也许某个重要的软件包会因为其维护者没有注册 2FA 而无法获得对某些严重漏洞的更新。
7 月 8 日,Skip Montanaro 在 Python 讨论论坛上发布了一条信息,指出他的一个已停用的项目 lockfile 已被确定为 critical 项目。该项目在其 README 的顶部就标记出已经废弃了(并列出了替代方案),而且自 2015 年以来没有任何 release。他想知道为什么它被认为是 critical 项目,并问道。"我应该怎么做才能摆脱这个称号?"
Donald Stufft 说,该软件包每月的下载量大约为 1000 万次。Dustin Ingram 指出,安全密钥的赠送公告中 FAQ 指出:"一旦项目被指定为关键,它就会无限期地保留这一地位",所以 lockfile 将被视为 critical 的。lockfile module 是 OpenStack 项目的一部分,lockfile 的 README 文件建议与 openstack-dev 邮件列表联系来想办法不再使用自己。
事实上,"自 2015 年 5 月以来,没有 OpenStack 项目声明会直接依赖 lockfile 了",根据 "fungi "的说法(他是 OpenStack 的系统管理员)。但是 lockfile 仍然被 OpenStack 项目的部分内容所使用。在一次完美地展示了 dependency chain 的风险的演示中,fungi 追踪到了这个项目是如何使用它的:
我发现一些 OpenStack 项目依赖于 ansible-runner,而 ansible-runner 又依赖于 python-daemon,而 python-daemon 本身也声明了对 lockfile 的依赖。我需要与其他贡献者来商讨后续如何改变这一点,也许是帮助 python-daemon 的维护者来替换掉 lockfile,或者帮助 ansible-runner 的维护者替换掉 python-daemon。
因此,这个 "关键 "的 PyPI 项目的大部分或者全部下载都可能是由于用在了 OpenStack 的持续集成测试中,而使用 lockfile 的组件很可能在八年前就应该转而用其他实现方案了。Hugo van Kemenade 建议鼓励人们停止使用 lockfile;"如果你仍然有能力发布 release,就在 import 的时候给出一个 DeprecationWarning,来建议替换成什么其他方案。或者像 UserWarning 这样提示更加频繁"。Paul Moore 指出,将其标记为 deprecated 并不会奏效,在 2015 年的时候就停止了新的 release 也没有帮助;"我完全不相信 '告诉人们不要使用它'是一个能摆脱 'critical' 的可行方案。"
Opinions
7 月 9 日,Armin Ronacher 发表了他对 PyPI 的 2FA 要求的看法;那篇文章在 LWN、Hacker News 和其他地方被广泛讨论。Ronacher 明确表示,他不认为 2FA 对 PyPI 项目的维护者是一个不合理的负担,但他确实想知道这一切会导致什么。首先,显然只有 PyPI 的 critical 软件包才需要设置 2FA,所以 "很明显,PyPI 认为做 2FA 的负担很重,因此不能强制对所有人都执行"。
这就产生了一些双重标准。正如 Ronacher 所说,他并没有打算创建一个 critical 包,只是这个事情自然而然就发生了。但是,通过 2FA 可以阻止的那各种问题,比如恶意行为者用偷来的密码来登录 PyPI,也是有可能发生在其他任何软件包上的,而不仅仅是在流行的软件包上发生。"理论上来说这种类型的保护确实应该适用于每一个软件包"。
但是,还有一个问题是,接下来还可能需要什么。如今当 PyPI 创建新项目时,并没有提到 2FA,所以未来也可能会要添加其他东西:
想象中未来的情况下,规则会继续收紧。我们可以想象,index 索引服务可能会希望对新发布的软件包实施加密签名。或者 index 想在作者不回应或对包做坏事的情况下来收回这个 critical package。例如,某个 critical 包被取消发布的话,对生态系统来说就是一个问题。我们可以想象这样一种情况:在这种情况下,index 的维护者会接管该 package 在 index 上的记录,从而挽回损失。同样的,我们也可以想象,未来的 index 会要求软件包对 critical 软件包强制执行一个最低标准,比如要求对关键的 incoming request(安全、商标法等)做出一定的 SLO[服务水平目标,service level objective]。
从安全的角度来看,其中一些要求确实是有意义的;事实上,有些要求也许应该已经到位了。但是现在有一个正在进行的关于不允许项目从 PyPI 中删除的讨论。显然,删除一个其他项目所依赖的项目是一种反社会的行为,但这似乎是作者(可能还有版权持有人)应该有权力做的事情。然而,这可能会导致混乱,就像著名的 left-pad fiasco 事件。
最近 PyPI 推动的 2FA 导致一位维护者意外地删除了 atomicwrites 包的所有旧版本。正如 Stufft 在 PyPI deletion 的讨论中指出的,他应维护者的要求恢复了 atomicwrites 版本,但 "恢复 35 个文件花了大约一个小时"。除了防止维护者删除他们的项目时导致 downstream 下游软件出现混乱外,找到一种方法来避免这类错误也很有用。
正如 Ronacher 所指出的,既然他使用了 PyPI 的资源来发布他的项目,所以他愿意遵守其规则,这些规则的目的是保护索引的用户。但是,PyPI(以及其他语言的类似资源库)在项目发布方面有着近乎垄断的地位,因为 pip 和它是绑定的。他想知道,按照 Rust 的 cargo vet 工具的思路,解决方案是否意味着软件包索引可以摆脱执行安全策略的工作,而将其留给其他人来做:
我喜欢 cargo-vet 的方法,因为它将运行 index 和审查(vetting)两者分隔开了。这也意味着在理论上,可以提供多个相互竞争的 index,并且仍然可以进行审查。最重要的是,它把审查的冲突交给了最关心这个问题的社区,也就是那些商业用户。与其让开源的维护者需要跳过更多的障碍,不如把审查工作外包给其他人。可以等待可信的 "公证人,notaries" 出现,为最常见的库的版本提供审查,并且在新版本经过一些审查之前不会批准它。
Reaction
Django 开发者 James Bennett 在 7 月 11 日对 Ronacher 进行了措辞尖锐的回复(在 Hacker News 和其他地方也有讨论)。在其中的大部分内容中,Bennett 似乎是在对其他人提出的论点做出回复,而不是 Ronacher 提出的论点。但是 Bennett 对 Ronacher 的主要抱怨是,他认为 cargo vet 的方式是有缺陷的,那些发布 FOSS 的人在 "道德和社会意义上" 都应该对用户负责任,尽管在 license 中已经免除了任何法律责任。"是的,如果你发布开源代码,你确实有一些责任,不管你是否愿意。"
Bennett 列举的自由软件维护者的责任似乎总体上来说是合理的,"因为它们本质上都是希望满足 '不要成为一个混蛋' 的最基本的社会期望"。但他在这里建立了一个假象敌,因为 Ronacher 从来没有争论过维护者应该(被允许)是个混蛋。Ronacher 只是想知道随着时间的推移,可能会对维护者提出哪些其他要求,他提到的一些要求(如服务水平目标,即 service level objective)对志愿者性质的维护者来说是相当繁重的。
Bennett 的论点中最薄弱的一点似乎是认为,Ronacher 尽管选择对用户负了一些责任,但是他对用户的亏欠其实更多,因为他在 FOSS 上的工作已经为他打开了各种大门。事实上,这是一个相当奇怪的论点。总的来说,Bennett 似乎在回应 Ronacher 没有提到、甚至没有暗示的很多事情。Ronacher 试图在做的事情的核心是试图弄清楚这里的边界在哪里,而不是声称人们已经越过了边界。
例如,PyPI 似乎不太可能在其 critical 项目上建立两天的安全修复时间要求,但肯定有很多公司和其他组织希望它这样做。所有的人(和所在的单位,比如商业公司)都有一种普遍的倾向,如果他们能找到另一个人的责任,就会推卸责任。发布那些依赖 FOSS 的软件供应链的公司和组织需要更深入地参与来确保代码安全。
做这项工作要花很多钱,也要花很多时间。我们看到了人们努力在做这项工作,PyPI 的 2FA 要求就是其中一个努力。它不可能是万能的方案,但它是一个有用的步骤。
正如 Luis Villa 去年指出的,FOSS 的维护者们被要求做越来越多的事情了;他们往往被要求在没有任何补偿的情况下做这些事情,尽管 "doors opening" 在一定程度上也算是补偿。随着更多 critical 项目被确定出来,我们可能会看到更多这种类型的冲突。如果一个维护者不想遵循 OpenSSF(或其他类似的努力)的建议来进行相应的改动,那么会发生什么?通常来说,fork 动作总被看作是一种敌对行为,但人们担心今后对于那些发现自己与赞助组织(sponsoring organization)不和的项目,最终可能就会直接 fork 了。那是一个与 FOSS 成长起来的世界相当不同的世界。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~