亚马逊AWS官方博客

AWS CodeArtifact 通过 Cargo 增加了对 Rust 包的支持

从今天开始,Rust 开发人员可以在 AWS CodeArtifact 上存储并访问他们的库(在 Rust 的世界中被称为 crate)。

现代软件开发在很大程度上依赖预先编写的代码包来加速开发。这些包对于单个应用程序来说可以有数百个,可以处理常见的编程任务,可以在内部创建或从外部来源获取。尽管这些包有助于显著加快开发,但其使用给组织带来了两个主要挑战:法律和安全问题。

在法律方面,组织需要确保他们拥有这些第三方包的兼容许可证,并且不会侵犯知识产权。安全是另一种风险,因为这些包中的漏洞可能被利用来危害应用程序。一种已知的策略,即供应链攻击,涉及向流行的开源项目注入漏洞。

为了应对这些挑战,组织可以设置私有包存储库。这些存储库存储了经过安全和法律团队审查的预先批准的包,从而限制了法律或安全方面的风险。这就是 CodeArtifact 的用武之地。

AWS CodeArtifact 是一项完全托管的构件存储库服务,旨在安全地存储、发布和共享应用程序开发中使用的软件包。该服务支持常见的包管理器和格式,例如 npmPyPIMavenNuGetSwiftPMRubygem,从而可以轻松集成到现有的开发工作流程中。受控的访问有助于增强安全性,并促进团队间的协作。CodeArtifact 通过与 AWS Identity and Access Management(IAM)以及持续集成和持续部署(CI/CD)工具集成,帮助维持一致、安全且高效的软件开发生命周期。

Stack Overflow 的年度开发人员调查中,Rust 连续第八年位居榜首,成为“最受欢迎的编程语言”,超过 80% 的开发人员表示他们希望明年再次使用该语言。Rust 之所以越来越受欢迎,是因为能够将 C++ 等系统语言的性能和内存安全,与可轻松编写可靠并发代码的功能相结合。再加上丰富的生态系统和对社区协作的高度关注,对于要开发高性能系统和应用程序的开发人员来说,Rust 成为了一个有吸引力的选择。

Rust 开发人员依靠官方包管理器 Cargo 来管理包依赖项。Cargo 简化了查找、下载预先编写的 crate(库)并将其集成到项目中的过程。这不仅通过消除手动依赖项管理节省了时间,而且还确保了兼容性和安全性。Cargo 强大的依赖项解析系统可以解决不同 crate 版本之间的潜在冲突,而且由于许多 crate 都来自精心策划的注册表,因此开发人员可以对代码的质量和安全性更有信心。这种对效率和可靠性的关注使得 Cargo 成为构建 Rust 应用程序的必备工具。

我们为我的 crate 创建一个 CodeArtifact 存储库
在本演示中,我使用 AWS 命令行界面(AWS CLI)AWS 管理控制台创建两个存储库。我将第一个存储库配置为从官方 crates.io 存储库下载公共包。我将第二个存储库配置为仅从第一个存储库下载包。这种双存储库配置是管理存储库和外部连接的推荐方式,请参阅管理外部连接的 CodeArtifact 文档。引用文档:

“建议每个域都有一个存储库,并与给定的公共存储库建立外部连接。要将其他存储库连接到公共存储库,请将带有外部连接的存储库添加为其上游。”

我画了这张图来说明如何设置。

Cargo 的代码构件存储库

可以通过命令行或控制台创建域和存储库。我选择命令行。在 shell 终端中,键入:

CODEARTIFACT_DOMAIN=stormacq-test

# Create an internal-facing repository: crates-io-store
aws codeartifact create-repository \
   --domain $CODEARTIFACT_DOMAIN   \
   --repository crates-io-store

# Associate the internal-facing repository crates-io-store to the public crates-io
aws codeartifact associate-external-connection \
--domain $CODEARTIFACT_DOMAIN \
--repository crates-io-store  \
--external-connection public:crates-io

# Create a second internal-facing repository: cargo-repo 
# and connect it to upstream crates-io-store just created
aws codeartifact create-repository \
   --domain $CODEARTIFACT_DOMAIN   \
   --repository cargo-repo         \
   --upstreams '{"repositoryName":"crates-io-store"}'	 

接下来,作为开发人员,我希望我的本地计算机从我刚刚创建的内部存储库(cargo-repo)中获取 crate。

我将 cargo 配置为从内部存储库,而不是公共的 crates.io 中获取库。为此,我创建了一个 config.toml 文件,指向 CodeArtifact 内部存储库。

# First, I retrieve the URI of the repo
REPO_ENDPOINT=$(aws codeartifact get-repository-endpoint \
                           --domain $CODEARTIFACT_DOMAIN \ 
                           --repository cargo-repo       \
                           --format cargo                \
                           --output text)

# at this stage, REPO_ENDPOINT is https://stormacq-test-012345678912.d.codeartifact.us-west-2.amazonaws.com/cargo/cargo-repo/

# Next, I create the cargo config file
cat << EOF > ~/.cargo/config.toml
[registries.cargo-repo]
index = "sparse+$REPO_ENDPOINT"
credential-provider = "cargo:token-from-stdout aws codeartifact get-authorization-token --domain $CODEARTIFACT_DOMAIN --query authorizationToken --output text"

[registry]
default = "cargo-repo"

[source.crates-io]
replace-with = "cargo-repo"
EOF

请注意,当我创建配置文件时,这两个环境变量会被替换。cargo 在其配置中不支持环境变量。

从现在起,在这台计算机上,每当我调用 cargo 来添加一个 crate 时,cargo 都会从 CodeArtifact 获得一个授权令牌,用于与内部的 cargo-repo 存储库进行通信。除了根据我使用的命令读取/发布包的权限外,我还必须具有 IAM 权限才能调用 get-authorization-token CodeArtifact API。如果您在构建计算机上为持续集成(CI)管道运行此设置,您的构建计算机必须具有适当的权限才能这样做。

我现在可以测试这个设置并在我的本地项目中添加一个 crate。

$ cargo add regex
    Updating `codeartifact` index
      Adding regex v1.10.4 to dependencies
             Features:
             + perf
             + perf-backtrack
             + perf-cache
             + perf-dfa
             + perf-inline
             + perf-literal
             + perf-onepass
             + std
             + unicode
             + unicode-age
             + unicode-bool
             + unicode-case
             + unicode-gencat
             + unicode-perl
             + unicode-script
             + unicode-segment
             - logging
             - pattern
             - perf-dfa-full
             - unstable
             - use_std
    Updating `cargo-repo` index

# Build the project to trigger the download of the crate
$ cargo build
  Downloaded memchr v2.7.2 (registry `cargo-repo`)
  Downloaded regex-syntax v0.8.3 (registry `cargo-repo`)
  Downloaded regex v1.10.4 (registry `cargo-repo`)
  Downloaded aho-corasick v1.1.3 (registry `cargo-repo`)
  Downloaded regex-automata v0.4.6 (registry `cargo-repo`)
  Downloaded 5 crates (1.5 MB) in 1.99s
   Compiling memchr v2.7.2 (registry `cargo-repo`)
   Compiling regex-syntax v0.8.3 (registry `cargo-repo`)
   Compiling aho-corasick v1.1.3 (registry `cargo-repo`)
   Compiling regex-automata v0.4.6 (registry `cargo-repo`)
   Compiling regex v1.10.4 (registry `cargo-repo`)
   Compiling hello_world v0.1.0 (/home/ec2-user/hello_world)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 16.60s

我可以验证 CodeArtifact 从上游公共存储库下载了 crate 及其依赖项。我连接到 CodeArtifact 控制台并查看我创建的两个存储库中可用包的列表。在此阶段,两个存储库中的包列表应相同。

CodeArtifact cargo 包列表

将私有包发布到存储库
现在我知道上游链接可以按预期运行,我们向我的 cargo-repo 存储库发布一个私有包,以使其可供组织中的其他团队使用。

为此,我像往常一样使用标准的 Rust 工具 cargo。在这样做之前,我将项目文件添加并提交到 git 存储库中。

$  git add . && git commit -m "initial commit"
 5 files changed, 1855 insertions(+)
create mode 100644 .gitignore
create mode 100644 Cargo.lock
create mode 100644 Cargo.toml
create mode 100644 commands.sh
create mode 100644 src/main.rs

$  cargo publish 
    Updating `codeartifact` index
   Packaging hello_world v0.1.0 (/home/ec2-user/hello_world)
    Updating crates.io index
    Updating `codeartifact` index
   Verifying hello_world v0.1.0 (/home/ec2-user/hello_world)
   Compiling libc v0.2.155
... (redacted for brevity) ....
   Compiling hello_world v0.1.0 (/home/ec2-user/hello_world/target/package/hello_world-0.1.0)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 03s
    Packaged 5 files, 44.1KiB (11.5KiB compressed)
   Uploading hello_world v0.1.0 (/home/ec2-user/hello_world)
    Uploaded hello_world v0.1.0 to registry `cargo-repo`
note: waiting for `hello_world v0.1.0` to be available at registry `cargo-repo`.
You may press ctrl-c to skip waiting; the crate should be available shortly.
   Published hello_world v0.1.0 at registry `cargo-repo`

最后,我使用控制台来验证 hello_world crate 现在可以在 cargo-repo 中使用了。

CodeArtifact cargo 包 hello world

定价和可用性
现在,您可以将您的 Rust 库存储在提供 CodeArtifact 的 13 个 AWS 区域中。Rust 包不会产生额外费用。三个账单维度是存储空间(以每月 GB 为单位)、请求数量以及向互联网或其他 AWS 区域传输的数据。向同一区域的 AWS 服务传输数据不收费,这意味着您可以在 Amazon Elastic Compute Cloud(Amazon EC2)AWS CodeBuild 上运行持续集成和交付(CI/CD)作业,而无需为 CodeArtifact 数据传输付费。与往常一样,定价页面包含详细信息。

立即构建您的 Rust 应用程序并将您的私有 crate 上传到 CodeArtifact!

— seb