PEP 752 – 包存储库的隐式命名空间
- 作者:
- Ofek Lev <ofekmeister at gmail.com>
- 赞助人:
- Barry Warsaw <barry at python.org>
- PEP 代表:
- Dustin Ingram <di at python.org>
- 讨论列表:
- Discourse 帖子
- 状态:
- 草稿
- 类型:
- 标准跟踪
- 主题:
- 打包
- 创建日期:
- 2024年8月13日
- 更新历史:
- 2024年8月18日, 2024年9月7日
摘要
本 PEP 指定了一种方法,允许组织为将来的上传保留包名称前缀。
“命名空间是一个非常棒的想法——让我们多用一些!” - PEP 20
动机
当前的生态系统缺乏一种方法,让拥有大量包的项目能够表明经过验证的所有权模式。一些例子
- Typeshed 是一项社区努力,旨在维护各种包的类型存根。他们维护的存根包镜像了它们的目标包名称,并以
types-
为前缀。例如,包requests
有一个用户依赖的存根,称为types-requests
。 - 主要的云提供商,如亚马逊、谷歌和微软,为每个功能对应的包都使用一个共同的前缀 [1]。例如,谷歌的大多数包都以
google-cloud-
为前缀,例如google-cloud-compute
用于 使用虚拟机。 - 许多项目 [2] 支持一种模型,其中一些包由官方维护,并鼓励第三方开发者通过创建自己的包来参与。例如,Datadog 为任何规模的组织提供可观察性服务。 Datadog Agent 附带了 官方集成,用于许多产品,如各种数据库和 Web 服务器,这些集成作为以
datadog-
为前缀的 Python 包分发。还支持创建 第三方集成,客户可以使用这些集成。
此类项目特别容易受到名称占用攻击,最终可能导致 依赖关系混淆。
例如,假设发布了一个新产品,监控该产品将很有价值。可以合理地假设 Datadog 最终会将其作为官方集成来支持。由于路线图优先级和实现所需的时间,交付此类集成需要相当长的时间。无法预留每个潜在包的名称,因此在此期间,攻击者可能会创建一个看起来合法的包,该包会在运行时执行恶意代码。用户更有可能安装此类包,这样做会损害整个项目的声誉。
虽然 PEP 708 试图解决此攻击媒介,但它专门针对在依赖关系解析期间考虑多个存储库的情况,并且没有为上述用例提供任何保护。
命名空间还可以大幅减少 错别字占用 的发生率,因为错别字必须出现在前缀本身中,而前缀是 规范化 的,并且可能是一个简短、众所周知的标识符,例如 aws-
。
基本原理
其他包生态系统通常通过采用两种方法之一来解决此问题:最小化或最大化向后兼容性。
- NPM 有 作用域包 的概念,它主要为了解决可用优质包名称稀缺(无论这种现象是真实还是感知到的)的问题而 引入 的。当用户或组织注册时,他们会获得与其名称匹配的作用域。例如,用于使用 Google Cloud Storage 的 包 是
@google-cloud/storage
,其中@google-cloud/
是作用域。普通用户帐户(非组织)可以发布 非作用域 包供公众使用。这种方法的向后兼容性最低,因为每个安装程序和工具都必须进行修改以考虑作用域。 - NuGet 有 包 ID 前缀保留 的概念,它主要为了满足希望了解包来源的用户而 引入 的。一个包名称前缀可以被一个或多个所有者保留使用。每个保留的包在 其页面上 都有一个特殊的指示,用于传达这一点。保留后,如果用户不是前缀的所有者,则任何具有保留前缀的上传都将失败。具有已拥有前缀的现有包可以照常继续发布。这种方法的向后兼容性最高,因为只需要修改 PyPI 等索引,而无需更改安装程序。
本 PEP 指定了 NuGet 在扁平命名空间中授权保留的方法。任何需要新包语法的解决方案都必须构建在现有的扁平命名空间之上,因此通过保留机制获得的隐式命名空间将是此类显式命名空间的先决条件。
术语
本文档中的关键词“必须”、“不得”、“需要”、“应”、“不应”、“建议”、“可能”和“可选”的解释方式如 RFC 2119 中所述。
- 组织
- 组织 是拥有项目并与之关联各种用户的实体。
- 授权
- 授权是在包存储库中预留命名空间。
- 开放命名空间
- 一个 开放 命名空间允许任何项目所有者上传。
- 受限命名空间
- 受限命名空间仅允许命名空间的所有者上传。
- 父命名空间
- 命名空间的父级是指没有尾部连字符分量的命名空间,例如
foo-bar
的父级是foo
。 - 子命名空间
- 命名空间的子级是指具有附加尾部连字符分量的命名空间,例如
foo-bar
是foo
的有效子级,foo-bar-baz
也是。
规范
组织
任何允许创建项目的包存储库(例如,非镜像)组织。组织是拥有项目并与之关联各种用户的实体。
组织组织。组织是拥有项目并与之关联各种用户的实体。
命名
语义
命名空间授权授予以下所有权
- 与命名空间本身匹配的项目,例如占位符包 microsoft。
- 以命名空间后跟连字符开头的项目。例如,命名空间
foo
将匹配规范化的项目名称foo-bar
,但不匹配项目名称foobar
。
包名称匹配作用于 规范化 的命名空间。
命名空间是每个包存储库的,组织。组织是拥有项目并与之关联各种用户的实体。
授权不得重叠。例如,如果存在 foo-bar
的现有授权,则禁止新的 foo
授权。通过将提议的命名空间与每个现有根授权的规范化命名空间进行比较来确定重叠。每个比较都必须在提议的和现有的命名空间末尾附加连字符。当任何现有命名空间以提议的命名空间开头时,就会检测到重叠。
上传
如果以下条件对于给定的上传都为真
- 项目尚不存在。
- 名称与保留的命名空间匹配。
- 项目不是由拥有该命名空间的活动授权的组织拥有的。
则上传必须失败并返回 403 HTTP 状态代码。
开放命名空间
授权的所有者可以选择允许其他人使用关联的命名空间发布新项目。这样做必须允许 上传 任何用户匹配命名空间的新项目。
命名空间的所有者可以将其设为开放状态,并允许其他组织使用该授权。在这种情况下,授权的组织没有特殊权限,等同于没有所有权的开放授权。
存储库元数据
JSON API 版本将从 1.0
递增到 1.1
。支持此 PEP 的存储库必须实施以下 API 更改。不支持此 PEP 的存储库不得实施这些更改,以便 API 的使用者能够确定存储库是否支持此 PEP。
项目详情
项目详细信息响应将按如下方式修改。
如果项目与活动命名空间授权不匹配,则 namespace
键必须为 null
。如果项目与命名空间授权匹配,则该值必须是包含以下键的映射
prefix
:这是关联的规范化命名空间,例如foo-bar
。如果项目的拥有者拥有多个匹配的授权,则此命名空间必须是字符数最多的命名空间。例如,如果项目名称同时匹配foo-bar
和foo-bar-baz
,则此键将为后者。authorized
:这是一个布尔值,如果项目的拥有者是组织并且是授权的当前拥有者之一,则为 true。这对于希望区分官方包和社区包的工具很有用。open
:这是一个布尔值,指示命名空间是否开放。
命名空间详情
此 URL 的格式为 /namespace/<namespace>
,其中 <namespace>
是规范化命名空间。例如,命名空间 foo.bar
的 URL 将为 /namespace/foo-bar
。
响应将是包含以下键的映射
prefix
:这是命名空间的规范化版本,例如foo-bar
。owner
:这是负责命名空间的组织。open
:这是一个布尔值,指示命名空间是否开放。parent
:如果存在,则为父命名空间。例如,如果命名空间是foo-bar
并且存在foo
的活动授权,则此值为"foo"
。如果没有父级,则此键将为null
。children
:这是任何子命名空间的数组。例如,如果命名空间是foo
并且foo-bar
和foo-bar-baz
存在活动授权,则此值为["foo-bar", "foo-bar-baz"]
。
撤销授权
当保留的命名空间变得无人认领时,存储库必须在 API 中将 namespace
键设置为 null
。
以前已被认领但现在未被认领的命名空间应该可以被任何组织再次认领。
向后兼容性
没有内在的担忧,因为仍然存在扁平的命名空间,并且安装程序不需要修改。此外,许多项目已经选择使用前缀来表示共享的目的,例如 typeshed 所做的那样。
安全影响
- 有机会在 PEP 740 和 PEP 480 之上构建,以便能够以密码学方式证明特定版本来自关联命名空间的拥有者。此 PEP 并未尝试描述这将如何发生,只是计划在未来进行相关工作。
如何教授
对于软件包的使用者,我们将记录元数据如何在 API 中公开,并可能在未来的说明中提供支持利用命名空间在安装期间提供额外安全保证的工具。
参考实现
目前没有。
被拒绝的想法
组织范围
此 PEP 的主要动机是减少依赖关系混淆攻击,并且允许使用旧的扁平命名空间会增加 NPM 风格的作用域风险。如果文档指示用户在命名空间 foo
中安装 bar
,则用户必须小心安装 @foo/bar
而不是 foo-bar
,反之亦然。Python 包生态系统具有用于名称的规范化规则,以最大程度地提高通信的便捷性,这将是一个倒退。
Python 的运行时环境也不利于作用域。虽然同一 JavaScript 包的多个版本可以共存,但 Python 只允许一个全局命名空间。除非对语言本身进行重大更改,否则这几乎不可能改变。此外,用户已经习惯于期望包名称通常与他们要导入的名称相同,并且消除扁平命名空间将取消该约定。
作用域将特别受到组织更改的影响,而组织更改必然会随着时间的推移而发生。组织可能会由于内部调整、收购或任何其他原因而更改其名称。每当发生这种情况时,他们拥有的每个项目实际上都会被重命名,这会导致用户不必要的混淆,而且经常发生。
最后,对社区的破坏将是巨大的,因为它将需要每个包管理器、安全扫描仪、IDE 等的更新。使用作用域发布的新包将与旧工具不兼容,并且会造成用户的困惑,以及维护人员不得不处理此类投诉的挫败感。
未解决的问题
目前没有。
脚注
版权
本文档置于公共领域或根据 CC0-1.0-Universal 许可证发布,以较宽松者为准。
来源:https://github.com/python/peps/blob/main/peps/pep-0752.rst
上次修改时间:2024-09-07 18:25:12 GMT