使用 Nix 实现可验证安全的软件供应链

Nixcademy Logo

通过 Nix 实现可验证安全的软件供应链 (Demonstrably Secure Software Supply Chains with Nix)

Demonstrably Secure Software Supply Chains with Nix 📆 Mon May 12 2025 作者:Jacek Galowicz (阅读时长:9 分钟)

维护安全的软件开发环境,尤其是那些需要高度完整性保证的环境,通常会带来巨大的开销。组织机构经常求助于物理隔离的环境(air-gapped environments)、广泛的员工审查以及所有软件源的本地分支(local forks)。虽然这些方法旨在提高安全性,但它们会大大降低开发速度,由于过时的软件包而引入漏洞,从而增加成本。 如果您能够在没有这些负担的情况下实现坚如磐石的供应链完整性,会怎么样?

世界各国政府机构都在要求更有力的证据来证明关键系统中使用的软件是安全的。 例如美国的 CISA/DISA,德国的 BSI/DeuMilSAA,法国的 ANSSI/DGSE,意大利的 ACN,西班牙的 CCN 等机构都在制定严格的要求。 对于许多组织机构来说,遵守这些规则并非可选项。

本文探讨了强大的软件包和依赖管理工具 Nix 如何提供一种独特的、强大的解决方案来满足这些安全标准,同时节省成本,解放开发人员以使用几乎不受限制的软件,并消除对限制性的物理隔离环境的需求。 Nix 允许您在交付之前证明软件的确切来源和完整性,而不会妨碍您的开发工作流程。让开发人员使用最新最好的工具链,并在发布后提供供应链完整性证明!

使用 Nix,您可以实现监管机构要求的高度透明度和可验证性。它允许您:

虽然各组织机构才刚刚开始使用 Nix 来满足这些需求,但我们相信,随着监管机构越来越熟悉它的功能,使用 Nix 来展示可验证的供应链完整性将成为一项重要的竞争优势。本文解释了 Nix 如何使之成为可能。

谁会受益?

示例中包含什么

我们的示例 GitHub 项目 applicative-systems/secure-supply-chain 展示了这一愿景的实际应用。它提供了一个相对最小的可启动 NixOS Live CD/USB 镜像,其中包含半真实的演示应用程序:

启动的 ISO 运行这些服务。

我们将此镜像用作半真实的演示器:这可能是您的产品镜像,我们展示了如何从头开始完全重建所有内容,以展示您的供应链完整性。

该项目的 README.md 以简洁的方式解释了完整的步骤。请阅读本文的其余部分,以了解其作用的解释。

Nix 深度探索:从软件包派生到可验证的闭包

存储库中的可启动 ISO/USB 镜像可以通过简单的 nix build .#iso 调用来构建。 这很好,因为它在任何机器/计算机上都以相同的方式工作,但它没有解释来源的真实来源。此外,它不会从源代码重建所有内容,因为它通常可以从 受信任的 cache.nixos.org 下载大多数软件包——但这不会获得政府机构的认可。

当我们在系统镜像 Nix 配方的输出上运行 nix derivation show 时,我们会得到如下输出:

$ nix derivation show $(nix build --print-out-paths .#iso)
{
 "/nix/store/sd3cmxsjpjpl298v88csr96ywph1s39g-nixos-supply-chain-25.05pre-git-x86_64-linux.iso.drv": {
  # ...
  "inputDrvs": {
    # list of derivations that this derivation depends on
    "/nix/store/abc123-bla.drv": {
      # ...
    },
  },
  "inputSrcs": [
    # list of source folders, scripts, and other directly
    # referenced files
  ],
  "name": "nixos-supply-chain-25.05pre-git-x86_64-linux.iso",
  "outputs": {
    "path": "/nix/store/xvrwkzlz8a1jbvn910kvc0k27j6qhmjx-nixos-supply-chain-25.05pre-git-x86_64-linux.iso"
   }
  },
}

这是 Nix 派生 的 JSON 结构化内容。(描述软件包的 Nix 表达式会评估为派生。派生是更易于机器读取的数据结构,用于描述完整的构建环境)这个描述了系统镜像的输入

(顺便说一句:在我们的 Nix & NixOS 101 培训 中,我们在第二天彻底介绍了这个主题!)

对于我们的系统镜像,此数据结构实际上描述了 第一级 依赖项列表。在下图中,这些是浅蓝色框:

(依赖关系已大大简化,因为如果我们包含所有内容,图的复杂性将会大大增加)

构建依赖关系树

由于我们的派生依赖于其他派生,我们可以嵌套到每个派生中并获得下一个依赖项列表。 上一个命令的 --recursive 标志会执行此操作:

$ nix derivation show --recursive $(nix build --print-out-paths .#iso)

此命令的输出是派生数据结构的列表。下图显示了此输出描述的图结构(同样,有点简化)。在这里,我们可以看到,如果我们的构建系统尚未可用,也需要从某些源代码进行编译。编译器需要从某些其他编译器进行引导,依此类推:

在跟踪所有依赖项的依赖项之后,我们到达了源代码包和引导编译器。 Nixpkgs 定义了所谓的 引导 tarball,其中包含引导编译器、最小的引导 shell 和最小化的 coreutils。 它大约 30MB 小(这使得它本身可以很好地进行审计),并且是我们从源代码开始构建 所有 其他内容所需的唯一二进制片段(如果我们愿意,我们也可以从源代码构建它)。

为了证明这组源代码导致了我们的产品二进制文件,我们可以这样做:

  1. 剥离所有中间派生,仅保留可下载且内容可验证的源代码包。
  2. 将这些导出到脱机系统。 必须事先以某种方式设置此系统(一次),以使验证机构接受其完整性。
  3. 在脱机系统上从头开始重建所有内容,以生成二进制文件。

从某种意义上说,我们是从 中提取 叶子 。但是我们如何做到这一点?

从依赖关系树中剥离源代码

这在使用 Nix 时很简单:所有源代码包和引导 tarball 都是所谓的 固定输出派生 (FOD) 并且可以轻松过滤掉。

与常规派生相比,固定输出派生的构建器进程可以访问互联网,但前提是它提供 输出哈希 的承诺:

# example fixed-output derivation
builtins.fetchurl {
 url = "http://some/download/source.tar.gz";
 sha256 = "1md7jsf123a45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
}

如果 promished 哈希对于输出不正确,则固定输出派生将失败。如果它没有失败,我们甚至不在乎下载镜像是否由某些不受信任的第三方拥有 - 因为哈希证明内容是我们期望的。对于所有源代码下载,都需要这种派生 - 如果我们无法访问源代码,我们将无法生成它或神奇地让它出现。

我们瞄准的部分是此图中的“固定输出派生”框中的所有软件包:

我们已经掌握了该信息,只是未经过滤。此命令提取所有 FOD 叶子

$ nix derivation show -r "$(nix build .#iso --print-out-paths)" |
 jq -r 'to_entries[] | select(.value.outputs.out.hash != null) | .key'

jq 是一个有用的 JSON 处理器应用程序,可帮助我们过滤所有具有 输出哈希 的派生。 每个知道其自身输出哈希的派生都是 固定输出派生 (FOD)

一旦我们在列表中有了所有固定输出派生,我们就可以将它们从 Nix 存储导出到单个文件中:

$ nix-store --export "${fixedOutputDerivations[@]}" > source-export.closure

这个新文件 source-export.closure 在我们的示例项目中重达 5.5 GB。 这不小,但第三方可以实际对其进行审计。(我们甚至可以轻松地附加更多元信息,例如原始 URL 等,以使该过程更容易)

最后的重建

现在,具有安全许可的某人可以获取 source-export.closure 文件,将其复制到 USB 记忆棒或类似设备上,将其携带到经过验证的物理隔离系统,并在那里从头开始完全重建所有内容。 这证明了在此过程中创建的二进制文件的完整性(假设运行脱机构建的系统已在单独的过程中得到验证)。

在该脱机系统上,我们只需运行:

$ nix-store --import < source-export.closure
$ nix-build path/to/nix/expression.nix

该系统无法下载任何内容,因为它无法访问互联网,因此它会从头开始重建 所有内容 。 对于示例存储库,这在普通的笔记本电脑上又花费了大约 12 个小时。 结果 必须 由 tarball 中的源代码创建,而不是其他任何东西!

因为我们不仅演示了有效负载二进制文件的完整性,还演示了编译器编译器的完整性,所以此演示可以说比从二进制发行版(例如 Debian、Ubuntu、Fedora 等)开始的各方做得更深入。

结论

从本质上讲,我们已经展示了 Nix 如何能够明确证明您的系统镜像仅源自一组特定的、受信任的源代码 - 包括所有依赖项和构建工具。 通过将所有必要的源材料收集到单个“源闭包”中,可以实现完整的脱机重建,从而提供可验证的供应链完整性。

这种能力将合规性从开发障碍转变为最终验证步骤。 通过将开发与严格的、前期的安全协议分离,团队可以利用最新的工具,更有效地协作,并无缝地为开源项目做出贡献。 监管机构的供应链证明的复杂任务简化为可管理且廉价的操作,个人使用单台机器即可实际实现。

Nix 的力量源于其核心功能:可重现的构建、固定输出派生以及创建脱机源闭包的能力。 虽然首次使用 Nix 涉及应对独特的挑战和调整现有的工作流程,但它提供了无与伦比的完整性和可重现性(顺便说一句,guix 也存在)。 Nix 使具有强大的供应链保证的软件开发成为一种现实且廉价的开发后流程,而不是从一开始就成为一种昂贵且具有限制性的约束。

请注意,使用著名的 Nix 模式 IFD动态派生 可能会降低此过程的简单性。 当然,也有解决方案。

我们 Nixcademy 在指导公司完成此采用流程方面拥有丰富的经验。 我们帮助组织在管理层面上了解机遇和风险,并与工程团队合作以有效地实施这些解决方案。 如果您希望利用 Nix 来加强您的供应链安全性、简化合规性并增强您的开发团队的能力,我们将竭诚为您服务。 请联系我们,以探讨如何定制这些强大的基于 Nix 的解决方案以适应您的特定需求和流程。

Jacek Galowicz

关于 Jacek Galowicz

Jacek 是 Nixcademy 的 CEO,对函数式编程、控制复杂性以及在全世界传播 Nix 和 NixOS 感兴趣。 他还写了一本关于 C++ 的书,并就软件质量进行了大学讲座。

分享此页面

分享 Nixcademy 在 Twitter/X 上 关注我们在 X 上 Nixcademy 在 LinkedIn 上 关注我们在 LinkedIn 上

获取在线 Nix(OS) 课程

Nixcademy online classes

您是否正在寻找...

试试我们的在线课程!

Nixcademy Certificate

Nixcademy 新闻通讯:每月接收 Nix(OS) 博客摘要

Nixcademy Newsletter

接收包含有用摘要的博客文章和播客的每月摘要,以与 Nix 和 NixOS 的世界保持联系!

及时了解我们的最新课程、服务以及新闻通讯订阅者的独家折扣!

立即订阅

Nixcademy

如果您正在评估或已经将资源投入 Nix & NixOS,那么 Nixcademy 是您的合作伙伴,可以最大限度地减少项目中的摩擦、时间投入和初始错误!

服务

Nix & NixOS 101 高级培训 指导 咨询 博客

有用的链接

速查表 法律声明 数据保护

联系方式

hello@nixcademy.com 安排会议 +49 1523 7191800 © 2025 Applicative Systems GmbH。 保留所有权利。

Cookie - 为什么呢?

当然,即使没有 Cookie,我们仍然可以看到经常访问此网站。 但是为了向您提供最相关的内容,我们衡量哪些访问者喜欢哪些内容。 Cookie 帮助我们使此站点对您来说更好。

接受所有拒绝所有

管理设置 隐私政策 法律声明