DeveloperWiki:仓库 DB 签名
[RFC] 仓库 DB 签名(以及 ISO/其他制品)
由于在服务器上存放 GPG 私钥的安全隐患,我们的仓库数据库目前未签名,这些服务器会添加软件包到仓库中。然而,我们希望自动签名我们的数据库、ISO 和其他制品,因此必须做出一些妥协。
关于这个主题已经进行过多次讨论
签名仓库数据库非常简单,就像
repo-add -v -s foo.db pacman-3.0.0-1-x86_64.pkg.tar.gz lrwxrwxrwx 1 jelle users 13 Aug 15 20:56 foo.db -> foo.db.tar.gz lrwxrwxrwx 1 jelle users 17 Aug 15 20:56 foo.db.sig -> foo.db.tar.gz.sig -rw-r--r-- 1 jelle users 504 Aug 15 20:56 foo.db.tar.gz -rw-r--r-- 1 jelle users 503 Aug 15 20:56 foo.db.tar.gz.old -rw-r--r-- 1 jelle users 310 Aug 15 20:56 foo.db.tar.gz.sig lrwxrwxrwx 1 jelle users 16 Aug 15 20:56 foo.files -> foo.files.tar.gz lrwxrwxrwx 1 jelle users 20 Aug 15 20:56 foo.files.sig -> foo.files.tar.gz.sig -rw-r--r-- 1 jelle users 782 Aug 15 20:56 foo.files.tar.gz -rw-r--r-- 1 jelle users 782 Aug 15 20:56 foo.files.tar.gz.old -rw-r--r-- 1 jelle users 310 Aug 15 20:56 foo.files.tar.gz.sig
repo-add 如下所示签名仓库
gpg --detach-sign --use-agent --no-armor
无论是否有意,repo-add 都可以只签名数据库而不添加软件包。
repo-add foo.db.tar.gz -s
提议的解决方案
从“安全”隔离区签名(方案 1)
创建一个专用的签名主机,接收文件然后返回签名。
应该为此主机添加一些限制
- 签名频率限制(每月仅签名一次 ISO)
- 安全地记录已签名的制品
- 请求来自特定的 IP (应该只来自 repos.archlinux.org)
- 身份验证 (SSH?)
- 独立的物理主机、虚拟机还是容器?
- 最小访问列表
参见 Bluewind 的提议。Bluewind。
实现:https://git.server-speed.net/users/flo/alass/
从“安全”隔离区签名(方案 2)
隔离区不是接收任意文件,而是拉取待签名的文件,并返回新的已签名文件。
工作流程
- 触发数据库更改操作,仓库被锁定。
- 创建一个新的数据库文件并放置在临时位置。
- 向安全隔离区发送(或更准确地说由其检索)通知,告知有新的数据库文件需要签名。
- 安全隔离区检索待签名的文件。
- 它对其进行签名,并(可选,待定)记录此操作。
- 它将签名上传回数据库服务器。
- 数据库服务器将数据库及其签名移至原位,释放仓库锁并重置通知通道。
全局实现细节
- 此处没有特别/新的内容。
- 这里需要将新生成的数据库放置在特定的位置。
- 此时(主要)有两种可能性,供数据库更改操作通知需要新签名
- 什么都不做:隔离区在临时位置查找数据库,当它看到文件时(而不是例如 404 错误),就知道有事要做。
- 写入特定文件:当没有新的数据库要签名时,该文件可以包含 0,否则包含 1,甚至可以包含实际数据库文件的校验和,以避免传输过程中的损坏问题。
- 如果您执行了上述第二种情况,只需使用相同的安全连接检索数据库。
- 这里可能有很多需要考虑的地方。特别是 *安全* 日志记录非常困难。这将在下面展开讨论。
- 这里有很多可能的上传机制,请参阅后文。
- 这要求数据库更改操作监视签名返回。
具体细节
- 关于从隔离区数据库服务器检索文件:我能想到的最安全的方式是通过非常强化的 HTTPS 连接。
- 这意味着服务器和客户端都需要使用自定义 CA 颁发的证书进行身份验证(CA 可以位于隔离区内),仅使用 TLS 1.3、ECDHE with Ed448 和 Poly1305-Chacha20 或 AES-GCM。
- 我们需要在监视通知文件时保持连接打开,以避免在监视频率下重新建立新的 TLS 会话。
- 上传签名返回:我们可以使用与上述相同的设置进行 HTTP(S) 上传,但不确定这是否非常重要(除非我们签名了一个坏文件,否则签名无论如何都是一个公共文件……)。这里需要仔细考虑攻击场景。
- 对于以上两点,为了更高的安全性,我们可以强制执行双方使用的 IP 地址。仓库服务器上的实际入口点也可以是 TOR 隐藏服务,但不确定我们是否想要这样做(我猜可能存在缺点)。
- 现在,让我们深入研究日志记录和威胁模型。这可能是最困难的部分。
- 如果我们不考虑隔离区可能被攻破,那么我们只需要签名脚本也将签名记录到远程上传点和一个本地文件(以防发生网络故障)。
如果我们认为隔离区可能被攻破,但没有 root 权限,我们可以将密钥仅root 可访问或放在 HSM 中,但让(仅 root 可写的)签名+日志记录脚本可供普通用户使用。这样,攻击者将无法在未记录的情况下签名文件。
如果我们认为隔离区已被 root 攻破,那么拥有 HSM 是唯一可以稍微保护我们免受彻底失败的方法(这将要求攻击者保持他们在隔离区内的存在,这将防止长期攻击),但这基本上仍然是游戏结束。请注意,这些细节中的大多数也适用于方案 1。
- 与方案 1 相比的优势
- 至少在隔离区上少打开一个端口(“提交”端口),这意味着如果我们仅允许物理访问该机器而不允许 SSH,则可以减少到零(我们也可以将 SSH 隐藏在 TOR 中)。
根据实现细节,针对任意文件签名的保护可能会更强大。
- 与方案 1 相比的缺点
- 需要在两侧都有监视器(等待文件签名,等待签名上传),而方案 1 实际上不需要(好吧,您仍然需要等待签名返回,但这只是您“握手”的一部分)。为了没有多大程度的安全性提升而增加了复杂性(好吧,在某种程度上,提高一点安全性需要付出很多努力)。
https://www.mail-archive.com/arch-dev-public@archlinux.org/msg25637.html
比较优势/缺点
- 两种方案都存在一个问题,即仓库数据库在一段时间内未签名。一个解决方案是使用临时数据库,然后再移动该数据库
其他发行版中的解决方案
Debian
OpenSuSe 构建服务
OBS (OpenSUSE 构建服务) 有一个签名守护程序,它接受数据并返回签名。
Fedora
未解决的问题
- 应该使用哪个密钥来签名仓库数据库?
- 通过 SSH 进行远程仓库数据库签名?
- 分发公钥。在密钥环中?
- 使用硬件令牌?