Ubuntu 22.04 APT 外部仓库添加指南:解决 apt-key 废弃问题(GPG 密钥管理)

引言

apt-key 是一个用于管理 APT 验证软件包密钥的工具。它与 add-apt-repository 工具密切相关,后者使用密钥服务器将外部存储库添加到 APT 安装的受信任源列表中。然而,通过 apt-keyadd-apt-repository 添加的密钥在 APT 中是全局信任的。这些密钥不仅限于授权它们本来用于的单个存储库。以这种方式添加的任何密钥都可以用于授权添加任何其他外部存储库,这可能会带来重要的安全问题。

从 Ubuntu 20.10 开始,使用 apt-key 会出现一个警告,提示该工具将在不久的将来被弃用;同样,add-apt-repository 也将很快被弃用。尽管在 Ubuntu 22.04 中依然可以使用 apt-keyadd-apt-repository,但忽视这些弃用警告是不可取的。

目前的最佳实践是在 Ubuntu 中使用 gpg 来代替 apt-keyadd-apt-repository。在未来的 Ubuntu 版本中,它将是唯一的选择。apt-keyadd-apt-repository 本身一直作为包装器,调用后台的 gpg。直接使用 gpg 可以省略中介步骤。因此,gpg 的方法与较旧版本的 Ubuntu 向后兼容,并可以作为 apt-key 的替代方案使用。

本教程将概述两种不使用 apt-keyadd-apt-repository 的替代方法。首先,将介绍如何使用 gpg 的公钥添加外部存储库,而不使用 apt-key。其次,作为补充,本教程还将涵盖如何使用 gpg 的密钥服务器添加外部存储库,而不使用 add-apt-repository

先决条件

为了完成本教程,您将需要一个 Ubuntu 22.04 服务器。请确保按照我们的 Ubuntu 22.04 初始服务器设置指南 进行设置,创建一个具有 sudo 权限的非 root 用户以及启用防火墙。

第一步 — 识别组成部分和密钥格式

PGP,即 Pretty Good Privacy,是一种专有加密程序,用于对文件和目录进行签名、加密和解密。PGP 文件是公钥文件,用于在 APT 中验证存储库作为有效来源。GPG,即 GNU Privacy Guard,是 PGP 的开源替代方案。GPG 文件通常是密钥环,用于保存多个密钥。这两种文件类型通常用于签名和加密文件。

gpg 是 GPG 的命令行工具,用于授权外部仓库供 APT 使用。然而,gpg 只接受 GPG 文件。为了使用这个命令行工具处理 PGP 文件,你必须进行转换。

Elasticsearch 是一个常见的密钥转换示例,并将在本节中作为示例使用。您将下载一个按 PGP 格式编排的密钥,并将其转换为具有 .gpg 文件扩展名的 APT 兼容格式。您将通过运行带有 --dearmor 标志的 gpg 命令来完成此操作。接下来,您将将存储库链接添加到软件包源列表中,并附加对转换密钥的直接引用。最后,您将通过安装 Elasticsearch 软件包来验证此过程。

需要添加带有密钥验证的项目总是会提供公钥和表示其精确位置的仓库 URI。以 Elasticsearch 为例,文档在安装页面上给出了这些组件。

这是为 Elasticsearch 提供的组件:

  • 密钥: https://artifacts.elastic.co/GPG-KEY-elasticsearch
  • 存储库: https://artifacts.elastic.co/packages/7.x/apt stable main

接下来,您需要确定您所使用的是 PGP 文件还是 GPG 文件。您可以通过使用 curl 打开 URL 来检查密钥文件。

curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch

这将输出以以下内容开头的密钥文件的内容:

输出
-----BEGIN PGP PUBLIC KEY BLOCK-----
. . .

尽管 URL 中带有 GPG,但第一行表明实际上是一个 PGP 密钥文件。请注意,APT 只接受 GPG 格式。最初,apt-key 会检测 PGP 文件并通过后台调用 gpg 来自动转换为 GPG 格式。第二步将涵盖从 PGP 手动转换为 GPG 的方法,以及在不需要转换时的操作。

步骤2 — 下载密钥并转换为 APT 兼容的文件类型

使用 gpg 方法时,你必须先下载密钥,然后再将其添加到软件包源列表中。之前使用 apt-key 时,并不总是强制遵循这个顺序。现在,你必须在你的源列表中引用已下载密钥文件的路径。如果你还没有下载该密钥,显然就无法引用已存在的路径。

使用 Elasticsearch 时,您将使用 PGP 文件,因此在下载后将其转换为 GPG 文件格式。以下示例使用 curl 下载密钥,并将其传送到 gpg 命令中。通过调用 gpg 时加上 --dearmor 标志将 PGP 密钥转换为 GPG 文件格式,并使用 -o 指示文件输出。

在 Ubuntu 中,/usr/share/keyrings 目录是建议放置您转换后的 GPG 文件的位置,因为它是 Ubuntu 存储其密钥环的默认位置。在此示例中,该文件名为 elastic-7.x.gpg,但任何名称都可行。

curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elastic-7.x.gpg

将这个 PGP 文件转换为正确的 GPG 格式,使其可以被添加到 APT 的源列表中。

注意:如果下载的文件已经是 GPG 格式的,您可以使用类似以下示例的命令直接将文件下载到 /usr/share/keyrings 而无需进行转换:

curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo tee /usr/share/keyrings/elastic-7.x.gpg

在这种情况下,curl 命令的输出将被导入到 tee 中,以将文件保存在正确的位置。

步骤3 — 将存储库添加到您的软件包源列表中

当您下载并将密钥保存为正确的 GPG 文件格式后,您可以将该存储库添加到 APT 软件包源中,并显式地将其与您获取的密钥关联起来。有三种方法可以实现这一点,这些方法都与 APT 如何查找源有关。APT 从一个中央的 sources.list 文件,sources.list.d 目录中的 .list 文件以及 sources.list.d 目录中的 .source 文件中获取源。尽管这三个选项之间没有功能上的区别,但建议您考虑这三个选项,并选择最适合您需求的方法。

选项1 — 直接在 sources.list 中添加

第一种方法涉及将表示源的行直接插入到 /etc/apt/sources.list 中,这是包含 APT 源的主要文件。该文件中包含多个源,包括与 Ubuntu 一起提供的默认源。直接编辑此文件是完全可以接受的,但是选项2和选项3将提供一种更模块化的解决方案,可以更容易地进行编辑和维护。

nano 或您喜欢的文本编辑器打开 /etc/apt/sources.list

sudo nano /etc/apt/sources.list

然后将外部仓库添加到文件底部。

/etc/apt/sources.list 可提供用于软件包管理的软件源清单。

. . .
deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/elastic-7.x.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main

这行内容包含了关于信息来源的以下说明:

  • deb: 这表明源使用了标准的Debian架构。
  • arch=amd64,arm64: 指定了APT数据将下载到的架构。这里是amd64和arm64。
  • signed-by=/usr/share/keyrings/elastic-7.x.gpg: 指定了用于授权此源的密钥,并指向您存储在/usr/share/keyrings目录下的.gpg文件。这部分内容必须包含在内,而在以前的apt-key方法中则不是必需的。这一新增是摆脱apt-key最关键的改变,因为它将密钥与它被允许授权的单一仓库绑定,并修复了apt-key原有的安全缺陷。
  • https://artifacts.elastic.co/packages/7.x/apt stable main: 这是表示仓库中数据确切位置的URI。
  • /etc/apt/sources.list.d/elastic-7.x.list: 这是要创建的新文件的位置和名称。
  • /dev/null: 当命令的输出不必要时使用。将tee指向此位置会省略输出。

按下CTRL+O后按下CTRL+X保存并退出。

第二个选项:在sources.list.d中创建一个新的.list文件

使用这个选项,您将在sources.list.d目录中创建一个新文件。APT会解析这个目录和sources.list文件以添加软件源。这种方法可以让您将软件源的添加单独保存在不同的文件中。如果您需要在以后删除或修改这个添加的软件源,您可以删除这个文件,而不是编辑中央的sources.list文件。将添加的内容保持分离可以更容易地进行维护,而直接编辑sources.list可能会导致在文件中影响到其他软件源的错误发生。

为了做到这一点,将echo命令的输出导入到tee命令中,创建这个新文件并插入适当的行。在下面的示例中,该文件被命名为elastic-7.x.list,但只要它是目录中唯一的文件名,任何名称都可以。

  1. echo “deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/elastic-7.x.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main” | sudo tee /etc/apt/sources.list.d/elastic-7.x.list > /dev/null

 

这个命令与手动创建文件并插入相应文本行的效果完全相同。

选项三:在sources.list.d中创建一个.sources文件

第三种方法不是写入一个.list文件,而是写入一个.sources文件。这种方法相对较新,使用了deb822多行格式,与deb . . .声明相比更少歧义,尽管在功能上是相同的。首先创建一个新文件。

  1. sudo nano /etc/apt/sources.list.d/elastic-7.x.sources

 

然后使用deb822格式添加外部仓库。

以下是“/etc/apt/sources.list.d/elastic-7.x.sources”文件的内容:

Types: deb
Architectures: amd64 arm64
Signed-By: /usr/share/keyrings/elastic-7.x.gpg
URIs: https://artifacts.elastic.co/packages/7.x/apt
Suites: stable
Components: main

在插入文本后保存并退出。

这类似于单行格式,逐行比较后发现两者的信息是相同的,只是组织形式不同而已。需要注意的一点是,这种格式在有多个参数时(例如amd64,arm64),不使用逗号,而是使用空格。

接下来,您将通过进行测试安装来验证此过程。

第四步:从外部仓库安装软件包

为了激活APT浏览主要的sources.list文件以及sources.list.d中的所有.list.sources文件,您必须调用apt update。如果在更新之前直接调用apt install,将导致安装失败,或者安装一个过时的默认软件包。

更新您的软件包列表。

  1. sudo apt update

 

然后安装您的软件包。

  1. sudo apt install elasticsearch

 

apt-key方法相比,这个步骤没有任何变化。一旦这个命令完成,您就完成了安装。

附录:使用密钥服务器添加外部存储库

本节将简要介绍如何使用密钥服务器而不是公钥来添加外部软件源时,如何使用gpg。这个过程与使用公钥的方法几乎相同,唯一的区别在于gpg的调用方式。

`add-apt-repository` 是 `apt-key` 的基于密钥服务器的对应项,两者都有被废弃的可能。在这种情况下,您将使用不同的组件。您会得到一个密钥服务器的URL和密钥ID,而不是一个键和存储库。此时,您可以直接从密钥服务器下载到适当的`.gpg`格式,无需进行任何转换。由于`add-apt-repository`即将在未来版本中废弃,您将使用`gpg`来下载到一个文件,同时覆盖默认的`gpg`行为,不导入到现有的密钥环中。

以下是以开源编程语言R为例的给定组件,这些组件在官方项目网站的安装说明中也可以找到:

  • 密钥服务器: `keyserver.ubuntu.com`
  • 密钥ID: `E298A3A825C0D65DFD57CBB651716619E084DAB9`
  • 存储库: `https://cloud.r-project.org/bin/linux/ubuntu jammy-cran40/`

首先,直接通过`gpg`从密钥服务器下载。请注意,根据下载流量的多少,此下载命令可能需要一段时间来完成。

  1. sudo gpg –homedir /tmp –no-default-keyring –keyring /usr/share/keyrings/R.gpg –keyserver keyserver.ubuntu.com –recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9

 

这个命令包含以下选项,与使用公钥的`gpg`不同:

  • `–no-default-keyring` 结合 `–keyring` 允许将输出写入新文件,而不是导入到现有密钥环中,这是`gpg`在此场景下的默认行为。
  • `–keyserver` 结合 `–recv-keys` 提供您正在下载的特定密钥和位置。
  • `–homedir` 用于覆盖`gpg`创建临时文件的默认位置。`gpg`需要创建这些文件才能完成命令,否则`gpg`会尝试写入`/root`,这会导致权限错误。相反,此命令将临时文件放置在适当的`/tmp`目录中。

接下来,将存储库添加到一个`.list`文件中。这可以通过将`echo`命令传输到`tee`命令中的方式,以与添加外部存储库使用公钥的方法完全相同地完成。

  1. echo “deb [arch=amd64 signed-by=/usr/share/keyrings/R.gpg] https://cloud.r-project.org/bin/linux/ubuntu jammy-cran40/” | sudo tee /etc/apt/sources.list.d/R.list > /dev/null

 

下一步,更新您的仓库列表。

  1. sudo apt update

 

然后您可以安装这个软件包。

  1. sudo apt install r-base

 

使用`gpg`将外部资源库添加到公钥和密钥服务器之间的操作类似,只是调用`gpg`的方式有所不同。

结论

通过使用`gpg`,无论是使用公钥还是密钥服务器,都可以添加外部存储库,而无需使用`apt-key`或`add-apt-repository`作为中间步骤。使用此方法可以确保您的过程在将来的Ubuntu版本中不会过时,因为`apt-key`和`add-apt-repository`已被弃用,并将在将来的版本中移除。使用`gpg`添加外部存储库可以确保密钥仅用于授权您希望的单个存储库。

bannerAds