[Dart翻译]托管一个私人Dart包库

594 阅读5分钟

本文由 简悦SimpRead 转码,原文地址 medium.com

Dart 2.15中对安全企业软件包托管的改进

Dart 2.15中为安全的企业软件包托管所做的改进

我们最近发布的Dart 2.15版本增加了对私有软件包库的支持。包库是一个托管Dart包的服务器,供dart pub客户端使用。这篇文章讨论了如何与pub.dev一起使用私有软件包库,利用Dart 2.15中引入的新的token认证机制。

这个功能已经被CloudsmithJFrog Artifactory采用,它们提供了自定义软件包库的服务。

image.png (现在Cloudsmith和JFrog Artifactory都提供私人Dart资源库。)

为什么使用自定义软件包库?

默认的包库,pub.dev,由Dart团队运营。它促进了Dart包的发布,供公众使用,并允许任何Dart开发者使用这些包,只需将包的名称添加到他们的pubspec文件。这使得一个活跃的生态系统能够创建一个丰富的Dart包集合。然而,自定义包库在以下情况下可能会很有用。

  1. 在一个组织内分享私人软件包。这可能是一个组织希望在该组织的成员之间分享内部专有软件包,而不是与一般公众分享。
  2. 严格控制企业环境中的依赖关系。一些企业希望明确地创建允许使用的清单,以批准使用特定的_软件包版本。这样做可能是为了执行代码审查政策或许可证合规性。
  3. 没有公共互联网接入的安全环境。一些组织在监管环境中运作,不允许连接到公共互联网,以及延伸到pub.dev。这通常适用于政府机构/承包商和一些银行服务提供者。

那些只需要分享一些专有软件包的组织(场景1)可能会使用git-dependencies。这是一个强大的机制,因为dart pub客户端命令会调用git客户端来克隆git-dependencies--这样你可能会用你的SSH密钥来认证克隆一个依赖,并使用GitHub/GitLab团队来管理权限。有了GitHub对使用Yubikeys的SSH的支持,这种设置在某些情况下效果很好。

然而,dart pub中的git-dependencies在解决版本问题上有一些局限性。当使用git-dependency时,dart pub只是克隆pubspec.yaml中指定的标签/分支/ref,因为没有机制来尝试依赖的多个版本。因此,使用私有的自定义软件包库是有吸引力的,因为自定义软件包库可以为dart pub客户端提供一个版本列表,允许版本解算器挑选一个兼容的版本,避免冲突。这也使得使用dart pub outdateddart pub upgrade --major-versions来升级私有和公共依赖关系变得容易。

Git 依赖关系不支持寻求 更严格控制依赖关系的组织 (场景2)或使用 没有互联网接入的安全环境 (场景3),因为很多包都必须被镜像。在这些情况下,几乎总是倾向于简单地拥有一个自定义的软件包库,镜像pub.dev中允许列出的子集。

使用自定义软件包库

从Dart 2.15开始,你可以使用_short-form hosted dependency_语法来依赖自定义软件包仓库的软件包。

dependencies:
  foo:
    hosted: https://dart-packages.example.com
    version: ^1.4.0
environment: 
  sdk: >=2.15.0 <3.0.0

简短的语法需要SDK的约束>=2.15.0,因为旧版本的Dart SDK不支持这种语法。如果你不想担心语法问题,你也可以直接使用dart pub add命令来添加来自自定义软件包库的依赖关系。

$ dart pub add foo --hosted https://dart-packages.example.com
Resolving dependencies... 
+ foo 1.4.0
Changed 1 dependency!

使用hosted-dependency语法,可以将来自自定义软件包库的依赖与来自官方软件包库的依赖混合起来。下面的例子依赖于dart-packages.example.com仓库的foo包,以及pub.dev的retry包。

dependencies:
  retry: ^3.0.0
  foo:
    hosted: https://dart-packages.example.com
    version: ^1.4.0
environment: 
  sdk: >=2.15.0 <3.0.0

当使用自定义软件包库共享私有软件包时,这很有用(场景1)。但对于 更严格地控制依赖关系 (情况2)或在 没有互联网访问的安全环境中工作 (情况3),覆盖默认软件包库可能是更好的做法。

覆盖默认软件包库

默认情况下,dart pub getpub.dev获取依赖,除非使用托管-依赖语法来指定一个自定义的包库。然而,我们可以使用环境变量PUB_HOSTED_URL来覆盖_默认的包库。这种方法在镜像pub.dev的子集时特别有用(方案2或3),因为不需要更新pubspec.yaml文件来引用自定义包仓库的URL。例如,只要写下以下内容就足够了。

dependencies:
  retry: ^3.0.0
  foo: ^1.0.0

如果允许列出的软件包retryfoo的版本被复制到自定义软件包仓库,并且环境变量PUB_HOSTED_URL指向自定义软件包仓库的URL,pub get可以如下工作。

$ export PUB_HOSTED_URL=https://dart-packages.example.com
$ dart pub get
Resolving dependencies... 
+ retry 3.1.0
+ foo 1.4.0
Changed 2 dependencies!

当构建服务器位于企业防火墙后面时,这样做效果最好,因为防火墙禁止外发网络连接,以避免有人忘记设置PUB_HOSTED_URL时发生意外的注入攻击。同样的,也建议设置publish_to: <hosted-url>,以避免意外发布到pub.dev(当PUB_HOSTED_URL没有定义时)。

针对自定义软件包库的认证

大多数自定义软件包库都可能是需要认证的私有软件包库。Dart 2.15引入了dart pub token命令来管理认证令牌。对自定义软件包库的请求使用一个秘密令牌进行认证。你从你的自定义软件包库中获得秘密令牌,并将其传递给dart pub token add <hosted-url>,它提示你使用该令牌,如下所示。

$ dart pub token add https://dart-packages.example.com
Enter secret token: [enter secret token]
Requests to "dart-packages.example.com" will now be authenticated using the secret token.

来自CI环境的认证

在CI中运行时,通常可以将秘密存储在环境变量中,虽然可以使用echo $TOKEN | dart pub token add <hosted-url>来传递秘密,但也可以告诉dart pub在与特定的自定义版本库对话时从环境变量中读取秘密。

$ dart pub token add https://dart-packages.example.com --env-var MY_SECRET_TOKEN
Requests to "https://dart-packages.example.com" will now be authenticated using the secret token stored in the environment variable "MY_SECRET_TOKEN".

这确保了dart pub不会在其配置文件中实际存储秘密,而只是存储它应该从环境变量$MY_SECRET_TOKEN中读取秘密的事实。这允许秘密只在CI环境中操作时被存储在环境变量中,并减少了在CI工作之间共享执行环境时秘密被意外泄露的风险。

发布到自定义软件包库

要发布一个软件包到一个自定义的软件包仓库,你可以指定publish_to: <hosted-url>,然后运行dart pub publish。这使用了与dart pub get相同的认证标志。至少,你的pubspec.yaml文件应该看起来像下面这样。

name: mypkg
version: 1.0.0
publish_to: https://dart-packages.example.com
dependencies:
  meta: ^1.7.0
environment:
  sdk: >=2.15.0 <3.0.0

当运行dart pub publish时,查看给出的信息很重要。在确认发布动作之前,你应该总是做以下工作。

  • 检查软件包将被发布的URL。
  • 查看软件包中包含的文件列表。
  • 考虑软件包的验证建议。比如说。
$ dart pub publish
Publishing mypkg 1.0.0 to https://dart-packages.example.com
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- lib
|   '-- mypkg.dart
'-- pubspec.yaml
Package validation found the following potential issue:
* It's strongly recommended to include a "homepage" or "repository" field in your pubspec.yaml
...

对于发布到自定义仓库来说,这些建议可能并不重要,但为软件包提供元数据往往是有用的。在pub.dev上,有适当的元数据和文档的软件包会得到更多的pub points

通过使用环境变量 "PUB_HOSTED_URL "覆盖_默认的软件包仓库,可以发布到自定义的仓库,但是,如果你这样做,强烈建议你指定 publish_to: <hosted-url>在你的pubspec.yaml文件中;这可以防止你不小心将你的专有软件包发布到公共仓库。如果你不想把你的专有软件包发布到任何软件包仓库,指定publish_to: none来防止意外发布。

获取一个自定义软件包仓库

如前所述,自定义软件包库可作为多个商业供应商的服务,减轻了你托管和维护自己的自定义软件包库的开销。

Cloudsmith中的令牌认证

自2020年以来,Cloudsmith一直在提供私人和公共Dart软件包库。Cloudsmith最近宣布他们的Dart软件包库产品支持令牌认证。欲了解更多信息,请查看Cloudsmith文档

image.png (一个由Cloudsmith托管的私人Dart包库。)

JFrog Artifactory中的Dart支持

JFrog Artifactory最近宣布支持自定义Dart包库,包括支持分层包库和从pub.dev上的公共包库镜像包。欲了解更多信息,请查看JFrog Artifactory文档

image.png (一个由JFrog管理的自定义Dart包库。)


www.deepl.com 翻译