Git-LFS中的Apt存档镜像

我继续努力提高公共apt档案的透明度和信心。我在“Apt存档透明度“我在其中提到债务分配项目正在进行中。债务发行人负责镜像一些公共apt存档的索引文件。我已经意识到,拥有一个可公开审计和保存的apt存储库镜像是实现apt透明工作的核心,因此debdistget项目对我的项目来说比我想象的更为重要。当前我跟踪特里斯克尔,PureOS(纯操作系统),侏儒和他们的上游Ubuntu公司,Debian公司德文.

Debdistget下载发布/包/源文件并将其存储在上发布的git存储库中GitLab公司。由于大小限制,它使用两个存储库:一个用于发布/发布中文件(较小)和一个还包括包/源文件(较大)。请参见的存储库示例Trisquel发布文件Trisquel包/源文件。可以在中找到所有分发版的存储库debdistutils的存档GitLab子组.

之所以拆分为两个存储库,是因为合并文件的git存储库变得很大,而且我的一些用户只需要发布文件。目前,带有软件包的存储库(现在包含几个月的数据)为9GBUbuntu公司,2.5GB用于特里斯克尔/Debian公司/PureOS(纯操作系统),970MB用于德文和450MB用于侏儒。存储库大小与存档的大小(用于初始导入)以及更新的频率和大小相关。Ubuntu对Apt分阶段更新(这会引发更大的Packages文件修改波动)似乎是其更大的主要原因。

使用大型Git存储库效率很低,GitLab CI/CD作业会产生大量网络流量,反复下载Git存储库。最重的用户是债务差异下载所有发行版包存储库以对发行版之间的包列表执行差异操作的项目。日常工作需要处理80分钟要运行,大部分时间都花在下载档案上。是的,我知道我可以研究运行端缓存,但我不喜欢缓存带来的复杂性。

幸运的是,并非所有的use-case都需要包文件。这个债务清偿项目只需要发布/发布中文件,以便将签名提交给西格斯托尔Sigsum公司透明度日志。这些工作仍然运行得相当快,但看着存储库大小的增长让我担心Debian公司440MB,PureOS(纯操作系统)130MB,Ubuntu公司/德文90MB,特里斯克尔12MB,侏儒2毫巴。在这里,我认为主要的大小相关性是更新频率,而Debian之所以大,是因为我跟踪的波动性不稳定。

因此,我用第一种方法实现了可扩展性。几个月前,我通过丢弃和重置这些档案库来“解决”这个问题。GitLab CI/CD作业又恢复了速度,一切都很好。然而,这意味着放弃宝贵的历史信息。几天前,我再次达到实用性的极限,并开始探索解决此问题的方法。我喜欢将数据存储在git中(它允许轻松集成软件完整性工具,如保密性卫兵和Sigstore,以及git日志提供了一种数据的时间顺序),因此感觉像是放弃了良好的属性,转而使用传统的基于磁盘的数据库方法。所以我开始了解Git-LFS公司并了解到它能够处理多GB的数据这看起来很有希望。

很快,我编写了一个脚本GitLab CI/CD作业增量更新发布/包/源使用git-LFS存储所有文件的git存储库中的文件。存储库大小现在为Ubuntu 650kb,Debian 300kb,Trisquel 50kb,德文250kb,PureOS 172kb侏儒鸟17kb正如所料,作业可以快速克隆git存档:debdistdiff管道运行时间从80分钟减少到10分钟这与存档大小和CPU运行时间之间的关系更为合理。

这些存储库的LFS存储大小为Ubuntu 15GB,Debian 8GB,Trisquel 1.7GB,德福1.1GB,PureOS(纯操作系统)/侏儒4.2亿。这是几天的数据。看起来原生Git比Git-LFS更擅长压缩/重复数据消除:Ubuntu的两天数据总大小已经是15GB,而纯Git的两个月数据总大小为8GB。这可能是GitLab中Git-LFS的次优实现,但我担心这种新方法也很难扩展。在某种程度上,差异是可以理解的,Git-LFS可能存储两个不同的包装文件(Trisquel的每个文件大约为90MB)作为两个90MB文件存储,但本机Git会将其存储为90MB文件的一个压缩版本和一个相对较小的补丁,以将旧文件转换为下一个文件。因此,Git-LFS方法在总体存储大小方面的扩展性出奇地差。不过,原始存储库要小得多,您通常不必提取所有LFS文件。所以这是净赢。

在这项工作中,我一直在思考我的方法与Debian的快照服务。我最终想要的是这两种服务的结合。为了有一个良好的基础来进行透明度工作,我想收集所有发布/包/源文件,以及最终的源代码和二进制文件。虽然从发行版的最新稳定版本开始是有意义的,但这项工作也应该在时间上向后扩展。为了从源代码中重新生成二进制文件,我需要能够安全地找到用于重建的二进制包的早期版本。所以我需要导入所有发布/包/源包从快照到我的存储库。从该服务器检索文件的延迟很慢,因此我无法找到一种高效/并行的方式来下载文件。如果我能完成这项工作,我相信我基于Git-LFS的存储这些文件的新方法将在未来多年内扩展。这还有待观察。也许存储库必须按发行版、体系结构或类似内容进行拆分。

另一个因素是存储成本。虽然基于git-LFS的存储库中包含几年来的文件的git存储库大小可能可以维持,但git-LFS的存储大小肯定不会维持。GitLab似乎对存储库和git-LF中的文件收取相同的费用,而且大约是每100GB 500美元每年。可以设置一个不在GitLab托管的独立Git-LFS后端来服务LFS文件。有人知道适合这种情况的服务器实现吗?我快速看了一下Git-LFS实施列表看起来最合理的方法是设置Gitea-clone福吉乔作为自托管服务器。也许云存储方法a'la S3是未来的发展方向?在GitLab上托管此内容的成本将在以下时间内可控~1TB(5000美元/年)但将其扩展到存储500 TB的数据将意味着每年250万美元这看起来物有所值。

我意识到,最终我想要一个本地的git存储库,其中包含所有apt存档的全部内容,包括它们的二进制和源代码包,并且可以发布。像快照这样的服务(约300TB的数据?)的存储需求目前并不昂贵:20TB的磁盘是500美元一块,因此一个包含36个磁盘的存储机柜大约在500美元左右720TB需要18.000美元使用RAID1意味着360TB,这是一个良好的开端。虽然我听说了~TB大小的Git-LFS存储库,但Git-LFS会扩展到1PB吗?也许拥有数百万个git-LFS指针文件的git存储库的大小将变得无法管理?为了开始使用这种方法,我决定导入Debian的amd64书虫到Git-LFS存储库中。就在附近175GB即使是在GitLab上托管也非常便宜(200GB每年1000美元)。公开此存储库将使编写使用此方法的软件成为可能(例如,移植债务再生产),以确定这是否有用以及是否可以扩展。通过Git-LFS分发apt存储库还可以使用其他有趣的想法来保护数据。考虑配置apt以使用本地文件://指向此git存储库的URL,并使用类似于的方法验证git签出Guix信任git的方法内容或Sigstore的gitsign.

天真地推了一下175GB单个git提交中的存档遇到了包大小限制:

remote:fatal:pack超出了允许的最大大小(4.88 GiB)

然而,将提交分解为针对部分存档的较小提交,使得推送整个存档成为可能。以下是创建此存储库的命令:

初始化
git-lfs安装
git lfs track“dists/**”“pool/**”
git添加.gitattributes
git commit-m“添加git-LFS跟踪属性”.gitattributes
time debmirror--method=rsync--host ftp.se.debian.org--root:debian--arch=amd64--source--dist=bookworm,bookworm-updates--section=main--verbose--diff=none--keyring/usr/share/keyrings/debian-archive-keyring.gpg--ignore.git。
git add dists项目
git提交-m“添加”-a
git远程添加源git@gitlab.com:debdistutils/archives/debian/mirror.git
git推送--设置上游源--全部
对于池中的d//;
echo$d;
时间git添加$d;
git commit-m“添加$d”-a
git推送
完成

这个结果存储库大小约为27MB,Git LFS对象存储约为174GB。我认为这种方法可以扩展到为一个版本处理所有架构,但为所有架构的所有版本使用单个git存储库可能会导致git存储库太大(>1GB)。那么,每个版本可能有一个存储库?这些存储库还可以拆分为水池/文件,或者每个体系结构或源的每个版本可能有一个存储库。

最后,我担心如何使用SHA1识别对象。Git和Debian的快照服务目前都在使用SHA1。Git有SHA-256过渡GitLab似乎正在致力于支持基于SHA256的存储库。对于这些概念的长期部署,最好直接使用SHA256标识符。Git-LFS已经使用SHA256,但Git内部使用SHA1,Debian快照服务也是如此。

你怎么认为?快乐黑客!

Apt档案的Sigstore:Apt-cosign

正如我的apt-sigstore的首次公告我的计划是研究西格斯托尔我现在很高兴地宣布apt-sigstore中添加了apt-cosign插件和运营项目债务清偿正在发布关于InRelease(发布中)由以下发行版发布的文件:Trisquel GNU/Linux、PureOS、Gnuinos、Ubuntu、Debian和Devuan。

总结以root身份运行以体验伟大新世界所需的命令:

#以root身份运行所有内容:su/sudo-i/doas-sapt-get安装-y apt-gpg bsdutils wgetwget-nv-O/usr/local/bin/apt-verify-gpgvhttps://gitlab.com/debdistutils/apt-verify/-/raw/main/apt-verify-gpgvchmod+x/usr/local/bin/apt-verify-gpgvmkdir-p/etc/apt/verify.dln-s/usr/bin/gpgv/etc/apt/verify.decho'APT::Key::gpgvc命令“APT-verify-gpgv”;'>/etc/apt/apt.conf.d/75验证wget-O/usr/local/bin/cosignhttps://github.com/sigstore/cosign/releases/download/v2.0.1/cosign-linux-amd64echo 924754b2e62f25683e3e74f90aa5e166944a0f0cf75b4196ee76cb2f487dd980/usr/local/bin/cosign|sha256sum-cchmod+x/usr/local/bin/cosignwget-nv-O/etc/apt/verify.d/apt-cosignhttps://gitlab.com/debdistutils/apt-sigstore/-/raw/main/apt-cosign网站chmod+x/etc/apt/verify.d/apt-签名mkdir-p/etc/apt/trusted.cosign.ddist=$(lsb_release--short--id | tr A-Z A-Z)wget-O/etc/apt/trusted.cosign.d/cosign-public-key-$dist.txt“https://gitlab.com/debdistutils/debdistcanary/-/raw/main/cosign/cosign-public-key-$dist.txt“echo“Cosign::基本URL\”https://gitlab.com/debdistutils/canary网址/$dist/-/raw/main/cosign\“;”>/etc/apt/apt.conf.d/77cosign

然后像往常一样跑步更新源查看syslog进行调试东西。

这是一种在等待构建机器尝试时完成的工作可重复构建PureOS。不幸的是,结果是765个添加/修改的包中仅有16%是我可以复制的。需要做一些基础设施工作来改进:我们应该使用建筑物例如。构建基础结构应该为它构建的每个包生成签名语句:一条语句表示它试图重新生成特定的二进制包(从而生成一些构建日志和diffoscope-output以供审计),另一条语句表明它实际上能够重新生成包。在以下期间验证此类索赔apt-get安装或者可能dpkg-i这是合乎逻辑的下一步。

现在有一些代码清理和发布工作要做。哪个发行版将是第一个包含对Sigstore的本机支持的基于apt的发行版?让我们看看。

Sigstore并不是唯一相关的透明日志,我一直在努力了解Sigsum公司能够支持它。对系统安全的信心越高,就越快乐!

更多关于差异可复制构建的信息:Devuan的可复制性为46%!

在我的工作基础上重建Trisquel GNU/Linux 11.0 aramo,将工具推广到任意两个适配体对感觉很简单,我已经创建了债务再生产作为一个模板项目,通过GitLab CI/CD同时甚至建立我自己的gitlab-runner在备用硬件上。我带来了复制/三色也可以使用debdistreparate,并将旧的再生三奎尔项目。

在解决了一些怪癖之后Devuan GNU+Linux 4.0奇马埃拉因为他们没有修改那么多包,所以速度相当快,现在我可以重新生成Devuan Chimaera在amd64上添加/修改的46%的程序包。我还有更多工作正在进行中(提示:复制/pureos),但是PureOS(纯操作系统)比Trisquel和Devuan的总和还要大。不过,我不确定Devuan或PureOS对可复制构建有多感兴趣。

反思这项工作让我意识到,虽然这里要做的自然是区分两个不同的基于apt的分发,我已经实现了和我对debdistdiff做的一样比较一下也很有趣,Debian书呆子Debian不稳定尤其是现在他们应该相当接近了。我的工具也应该支持这一点。然而,要真正从更完整的现有Debian的可重复测试,这样做会有更多的好处,但我现在还不能清楚地表达出来。

我努力的一个最终目标是提高人们对适配体的信任,并将透明式保护与apt-sigstore公司通过第三方验证的可复制构建可能确实是这样一种用途,这将有利于更广泛的适配体社区。假设您的系统没有安装任何软件包,除非它可以与第三方可复制构建组织进行验证,该组织将结果提交到防篡改透明账本中。但我现在在这里重复,所以将停止。

Trisquel是42%可复制的!

绝对数字可能并不令人印象深刻,但我希望至少有一个有用的贡献,那就是实际上有一个数字可以说明Trisquel有多少是可复制的。希望这将激励其他人帮助改进实际指标。

tl;医生:转到复制-危险.

当我开始了解Trisquel的工作原理,我确定了一些可以提高我对它的信心的事情。对我来说,最困难的事情是手动审核包档案,我写了一个名为债务差异为我实现自动化。这让我思考apt存档透明度更一般化。我在这方面做了一些进一步的工作(提示:apt-验证)它最终应该拥有自己的博客文章。如果我们不信任有意的归档文件中的包。一种可以衡量的增加一揽子计划信任的方法是可复制版本目前,这应该是一个既定的最佳实践。代码审查仍然很重要,但因为它永远不会提供积极的保证,所以我们需要其他能够自动识别次优情况的过程。我认为,可复制构建轻松识别负面结果的方式是推动其成功的主要因素:其结果是有形和可衡量软件工程领域需要更多这样的实践。

我建立Trisquel可复制设置的设计如下。

  • 项目债务分配负责下载Release/Packages文件(其中最相关的文件来自dists(距离)/)来自apt档案,并通过将其提交到GitLab公司-托管的吉特-存储库。我有几个这样的流行apt-archives的存储库,包括特里斯克尔及其上游Ubuntu公司GitLab调用调度管道进行下载一些比赛条件在这里。
  • 项目债务差异用于生成添加和修改的包的列表,这些包是实际能够复制哪些包的输入。它发布几种分布差异的可读性总结,包括Trisquel与Ubuntu。早些时候,我决定重建所有上游的Ubuntu软件包对我来说是不可能的:我个人对Debian/Ubuuntu官方apt档案的信任大于我对Trisquel中添加/修改的软件包的信任。
  • 最终项目复制-危险将各个部分简单地放在一起,如下所示.gitlab-ci.yml公司文件。
    • 有一个(手动触发的)作业生成生成图像要创建生成映像以加快CI/CD的运行,请使用Dockerfile文件.
    • 有一个(手动触发的)作业发电机组-列表它使用debdistdiff生成和存储包列表,并将其输出放入列表/。现在手动触发的原因是比赛条件.
    • 有一个(计划的)作业执行两件事:从包列表中,脚本生成-ci-packages.sh构建GitLab CI/CD指令文件ci-packages.yml公司描述要生成的每个包的作业。第二部分是生成readme.sh基于git存储库中存储的构建日志和diffoscope输出重新生成项目的README.md。
    • 通过ci-packages.yml文件,有大量动态定义的作业,目前手动触发这些作业以避免构建服务器过载。脚本内置软件包.sh调用并尝试重新生成包,并将构建日志和diffoscope输出存储在git项目本身中。

我没想到能够使用GitLab共享的跑步者来构建,但结果证明他们工作得很好,我推迟了自己跑步者的设置。有一个手动管理的列表/禁用-aramo.txt有些软件包需要太多的磁盘空间或花费两个多小时来构建。今天我终于抽出时间使用运行Trisquel aramo的podman设置GitLab跑步者,我希望很快完成其余包的构建-我的一个带有256GB RAM和双2680v4 CPU的Dell R630服务器应提供足够的性能。

当前的局限性和对进一步工作的想法(大多数作为项目问题归档)包括:

  • 我们不支持*.buildinfo(建筑信息)文件夹。据我所知,Trisquel并没有为他们的构建发布它们。改进这一点将是向前迈出的第一步,有谁能帮忙吗?比较buildinfo.debian.net网站例如,许多软件包仅在其NT_GNU_BUILD标识ELF二进制文件中的符号,请参阅libgpg-error的diffoscope输出示例.通过戳入jenkins.trisquel.org网站我设法发现特里斯克建造了initramfs-utils在随机分组中路径/build/initramfs-tools-bzRLUp对这条路进行硬编码允许我复制那个包裹。我希望其他许多包也能这样。不幸的是,这个失败变成了成功,这一包将指针从42%的重复性移动到43%,但我没有让它成为一个好的标题。
  • 从dists/下载Release/Package-files的机制并非万无一失:我们可能无法捕获所有已发布的此类文件。虽然这不太关心再现性,但更关心的是适当的透明度。不过,让Trisquel提供类似于快照.debian.org会有帮助的。
  • 至少有一个其他的CPU体系结构会很好。
  • 由于缺乏时间和精力,处理软件包新版本的增量更新尚不可行。这意味着我们只构建了一个包的一个版本,而从来没有发现过同一包的任何新发布版本。既然Trisquel aramo公司发布后,新版本的预期速度应该很低,但由于安全性或回传,仍然会出现这种情况。
  • 移植这个进行测试FSDG公司-兼容的分发,如PureOS(纯操作系统)侏儒应该比较容易。我也在看德文因为侏儒。
  • 房间里的大象首先是Ubuntu的可复制性。

复活节快乐黑客!

2023-04-17更新:原始项目“复制-危险“此处宣布的内容已存档,并替换为两个项目,一个通用”债务再生产“和一个Trisquel的结果:”复制/三色“.

Apt存档透明度:debdistdiff和Apt-carary

我一直觉得apt软件包存储库的操作是个谜。人们访问重要的apt包存储库的方式、自动非人工更新机制的实现方式以及发布的更改似乎缺乏透明度。我在考虑像这样的大型发行版Ubuntu公司Debian公司,但也包括免费GNU/Linux发行版喜欢特里斯克尔PureOS(纯操作系统)从更著名的分布中派生出来的。

据我所知,任何拥有受基于apt的GNU/Linux发行版信任的OpenPGP私钥的人都可以签署一个修改后的Release/InRelease文件,如果我的机器以某种方式下载了该版本的发布文件,我的机器就可以下载并安装发行版不希望我安装的软件包。此外,似乎任何有权访问主HTTP服务器或其任何镜像的人,或者他们和我的机器之间网络上的任何位置的人(当使用明文HTTP时),都可以在我的机器上暂停安全更新(基于每个IP),或者使用它发送我的机器(同样,基于每个IP以避免检测)修改后的Release/InRelease文件,前提是他们能够获得存档的专用签名密钥。这些都是需要概览的强大力量。

我总是推迟学习保护适当基础设施的过程,在心里将其归类为“如此多的人依赖于此基础设施,以至于有足够多的人可能会花时间审查和改进这些过程”。同时,我一直遵循更自由软件友好的Debian衍生发行版,如gNewSense,并在一些机器上运行它。我从未将它们投入正式的生产使用,因为它们的apt包存储库的信任问题一直是我的一个大问号。我推迟这一点的理由中的“足够的人”部分并不令人信服。在运行的gNewSense系统上,即使是一个简单的问题“是否有人更新apt存储库”也不容易理解。从Debian获取安全更新的gNewSense cron作业一定在某个时候停止了工作,我没有任何好的机制来注意到这一点。很可能是在没有任何公告的情况下发生的。我最近在生产机器上转向了Trisquel,这些问题再次困扰着我。

情况令人不满意,我研究了可以做些什么来改进它。我可以试着了解每个项目涉及的关键人员是谁,甚至可以了解使用了什么硬件组件,或者涉及什么软件来更新和签署apt存储库。服务器是否运行非自由软件?专有BIOS或NIC固件?GnuPG私钥在磁盘上吗?智能卡?TPM?YubiKey?HSM?服务器位于何处,谁有权访问它?我试着做了一点,发现了Trisquel在其默认apt信任存储中具有DSA1024密钥(尽管为了公平起见,apt默认不信任此类签名)。然而,我不确定这是否会扩展到保护我的机器免受此基础设施上的攻击。即使是有着最好意图的人,以及最先进的硬件和软件,也会有问题。

为了增加我对Trisquel的信任,我开始了解它是如何工作的。为了更容易找出Trisquel档案中需要进一步审计的有趣部分,我创建了债务差异将一个apt存档与另一个apt存档进行比较,以生成人类可读的文本输出。有一个GitLab CI/CD cron作业每天都在运行输出比较Trisquel与UbuntuPureOS与Debian。使用这些输出文件让我对流程的工作原理有了更多的了解,甚至我还跌跌撞撞可能是错误的东西其中,Trisquel-aramo是从Ubuntu jammy中导入的,但它包含几个在最终Ubuntu jammy版本中被删除的包(例如,gcc-8、python3.9)。

在以这种方式手动审核Trisquel存档之后,我意识到,无论我从比较Trisque和Ubuntu中可以看出什么,它都只是基于存档的当前快照。明天可能会完全不同。感觉有必要的是持续审计特里斯克档案的差异。我很高兴能发展债务差异为了一个目的(比较两个不同的档案,如Trisquel和Ubuntu),发现该工具可以用于另一个目的。这时,我意识到我需要一个包含所有不同apt归档元数据的日志,以便能够生成归档时间差异的审计日志。我使用发布/发布中包装著名发行版Trisquel、Ubuntu、Debian和PureOS的每个架构/组件的文件。最后,我编写了脚本来自动完成这项工作,这些脚本现在发布在债务分配项目。

此时,关于发行版文件的per-IP替换的一个早期问题一直萦绕在我的脑海中。然而,有了我现在可用的工具,找到解决这个问题的方法很简单!只需计算刚刚下载的InRelease文件的SHA256校验和,看看我的git存储库是否有相同的文件。此时,我开始阅读Apt源代码现在,我对我的系统安全性的怀疑比以往任何时候都多。哦,孩子,名字怎么了恰当的从未有过这样的感觉…Apt?!哦,好吧,我们必须给学生留一些练习。最后,我意识到我想尽可能少地接触apt代码基础,并注意到SigVerify::复制并验证功能打电话执行GPGV它叫apt-key验证称为GnuPG的通用汽车公司.通过设置Apt::Key::gpgv命令我可以得到apt密钥验证调用其他工具通用汽车公司看到我要去哪里了吗?我认为现在完成这项工作很简单,但由于某种原因,我在本地计算的哈希校验和与服务器上的数据不匹配。我放弃了,转而开始做其他事情。

今天我回到了这个想法,并开始调试我从apt中获得的本地文件的外观,以及它们与我在git存储库中直接从apt存档中获得的文件的差异。最终我把这件事追溯到拆分清除签名文件这需要一个InRelease(发布中)文件并将其拆分为两个文件,可能会模仿(旧?)分发这两个文件的方式发布发布.gpg因此,clearsigned InRelease文件被拆分为一个cleartext文件(类似于发布文件)和一个OpenPGP签名文件(类似于发布.gpg文件)。但是为什么InRelease文件的明文变量散列到与Release的散列相同的值?遗憾的是,他们在最后一条新线上有所不同。

解决了这个技术性问题后,很容易就把各个部分打包起来,我想出了一个项目适配子的提供脚本的apt-canary-gpgv根据我称之为“apt canary witness”的文件验证本地apt发布文件,该文件存储在某个URL中。

我现在正在我的Trisquel aramo笔记本电脑Trisquel nabia服务器和Talos II ppc64el Debian机器。这意味着我已经解决了对per-IP替换的担忧(或者至少使其不太可能发生,必须向GitLab和我的系统发送相同的恶意发布文件),并允许我有一个审计日志,记录我实际用于安装和下载包的所有发布文件。

你怎么认为?显然有很多工作和有待改进之处。这是一个理念的验证实现,但我想发布这篇文章,让其他人思考问题和解决问题的各种方法,而不是将其完善并延迟反馈。

顺便说一下,我要去FOSDEM’23年这个周末,帮助管理安全开发室。如果你想聊这个或其他事情,请找我。快乐黑客!