如何處理 apt-key 和 add-apt-repository 的棄用,使用 gpg 在 Ubuntu 22.04 上添加外部存儲庫

介紹

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,而且在未來版本中,它將是唯一的選項。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用戶並啟用防火牆。

步驟 1 — 辨識組件和關鍵格式

PGP,或者稱為Pretty Good Privacy,是一個專有的加密程序,用於對文件和目錄進行簽名、加密和解密。PGP文件是公鑰文件,在這個過程中用於驗證存儲庫是否為有效來源,在apt內使用。GPG,或者稱為GNU Privacy Guard,是PGP的開源替代方案。GPG文件通常是鑰匙環,這是保存多個密鑰的文件。這兩種文件類型通常用於對文件進行簽名和加密。

gpg是GPG的命令行工具,可用於授權外部存儲庫供apt使用。但是,gpg只接受GPG文件。為了使用這個命令行工具與PGP文件,您必須將它們轉換為GPG文件。

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 來檢查:

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

這將輸出鍵文件的內容,它以以下內容開頭:

Output
-----BEGIN PGP PUBLIC KEY BLOCK----- . . .

儘管 URL 中有 GPG,但第一行指示實際上這是一個 PGP 金鑰文件。請注意這一點,因為 apt 只接受 GPG 格式。最初,apt-key 檢測到 PGP 文件並通過在後台調用 gpg 自動將其轉換為 GPG。步驟 2 將涵蓋從 PGP 到 GPG 的手動轉換,以及在不需要轉換時應該做什麼。

步驟 2 — 下載金鑰並轉換為 apt 兼容的文件類型

使用 gpg 方法時,必須先下載金鑰,然後再將其添加到套件來源清單中。以前使用 apt-key 時,並不總是執行這個順序。現在,您需要在您的源清單中引用下載的金鑰文件的路徑。如果您尚未下載金鑰,顯然就無法引用現有的路徑。

使用 Elasticsearch 時,您將使用 PGP 文件,因此您需要在下載後將其轉換為 GPG 文件格式。以下示例使用 curl 下載金鑰,並將下載的內容傳輸到 gpg 命令中。調用 gpg 時使用 --dearmor 標誌將 PGP 金鑰轉換為 GPG 文件格式,使用 -o 來指定文件輸出。

在 Ubuntu 中,建議將轉換後的 GPG 文件存儲在 /usr/share/keyrings 目錄中,因為這是 Ubuntu 存儲其金鑰圈的默認位置。在此示例中,文件名為 elastic-7.x.gpg,但任何名稱都可以使用:

  1. 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 而無需使用類似以下示例的命令進行轉換:

  1. 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:

  1. 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數據的架構。這里是amd64arm64
  • 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以儲存並退出。

選項2 — 在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

這個指令與手動創建文件並插入適當的文字行相同。

選項 3 — 在 sources.list.d 中創建一個 .sources 檔案

第三種方法是將內容寫入一個 .sources 檔案而不是 .list 檔案。這種方法相對較新,使用的是 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)不使用逗號,而是使用空格。

接下來,您將通過進行測試安裝來驗證此過程。

步驟 4 — 從外部存儲庫安裝套件

您必須執行apt update命令,以便提示apt查看主要的sources.list檔案,以及sources.list.d目錄中的所有.list.sources檔案。在執行apt install之前沒有更新會導致安裝失敗,或者從apt安裝過時的預設套件。

更新您的存儲庫:

  1. sudo apt update

然後安裝您的套件:

  1. sudo apt install elasticsearch

這個步驟與使用apt-key方法相比沒有變化。一旦此命令完成,您將完成安裝。

補充 – 使用金鑰伺服器添加外部存儲庫

本部分將簡要介紹使用金鑰伺服器而不是公鑰來添加外部存儲庫的過程。該過程與公鑰方法幾乎相同,不同之處在於如何調用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-keyadd-apt-repository作為中介。使用此方法可確保您的流程不會在未來的Ubuntu版本中變得過時,因為apt-keyadd-apt-repository已被棄用,並將在將來的版本中刪除。使用gpg添加外部存儲庫可確保金鑰僅用於授權您打算的單個存儲庫。

Source:
https://www.digitalocean.com/community/tutorials/how-to-handle-apt-key-and-add-apt-repository-deprecation-using-gpg-to-add-external-repositories-on-ubuntu-22-04