Docker 中的內容信任

在網路系統之間傳輸資料時,信任是核心問題。特別是,當透過不安全的媒介(例如網際網路)進行通訊時,確保系統運作的所有資料的完整性和發佈者至關重要。您可以使用 Docker Engine 將映像檔(資料)推送和提取到公開或私有登錄檔。內容信任讓您能夠驗證透過任何通道從登錄檔接收的所有資料的完整性和發佈者。

關於 Docker 內容信任 (DCT)

Docker 內容信任 (DCT) 提供使用數位簽章的功能,適用於傳送到和從遠端 Docker 登錄檔接收的資料。這些簽章允許用戶端或執行階段驗證特定映像檔標籤的完整性和發佈者。

透過 DCT,映像檔發佈者可以簽署其映像檔,而映像檔消費者可以確保其提取的映像檔已簽署。發佈者可以是手動簽署其內容的個人或組織,也可以是將內容簽署作為其發佈流程一部分的自動化軟體供應鏈。

映像檔標籤和 DCT

個別映像檔記錄具有以下識別碼

[REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG]

特定映像檔 `REPOSITORY` 可以有多個標籤。例如,`latest` 和 `3.1.2` 都是 `mongo` 映像檔上的標籤。映像檔發佈者可以多次建置映像檔和標籤組合,每次建置都會變更映像檔。

DCT 與映像檔的 `TAG` 部分相關聯。每個映像檔儲存庫都有一組金鑰,映像檔發佈者使用這些金鑰來簽署映像檔標籤。映像檔發佈者可以自行決定簽署哪些標籤。

映像檔儲存庫可以包含一個標籤已簽署而另一個標籤未簽署的映像檔。例如,請考慮 Mongo 映像檔儲存庫Signed tags

發佈者可以選擇是否簽署特定標籤。因此,未簽署標籤的內容和具有相同名稱的已簽署標籤的內容可能不符。例如,發佈者可以推送標記的映像檔 `someimage:latest` 並簽署它。稍後,同一位發佈者可以推送未簽署的 `someimage:latest` 映像檔。第二次推送會取代最後一個未簽署的標籤 `latest`,但不影響已簽署的 `latest` 版本。選擇可以簽署哪些標籤的功能,允許發佈者在正式簽署映像檔之前迭代其未簽署版本。

映像檔消費者可以啟用 DCT,以確保其使用的映像檔已簽署。如果消費者啟用 DCT,則他們只能使用受信任的映像檔進行提取、執行或建置。啟用 DCT 有點像將「篩選器」套用至您的登錄檔。消費者只「看到」已簽署的映像檔標籤,而較不受歡迎的未簽署映像檔標籤對他們來說是「不可見的」。

Trust view

對於尚未啟用 DCT 的消費者而言,他們使用 Docker 映像檔的方式沒有任何改變。無論映像檔是否已簽署,每個映像檔都可見。

Docker 內容信任金鑰

映像檔標籤的信任是透過使用簽章金鑰來管理的。當第一次叫用使用 DCT 的操作時,會建立一組金鑰。一組金鑰包含以下類別的金鑰

  • 一個離線金鑰,它是映像檔標籤的 DCT 根目錄
  • 簽署標籤的儲存庫或標記金鑰
  • 伺服器管理的金鑰,例如時間戳記金鑰,它為您的儲存庫提供新鮮度安全保證

下圖描述了各種簽署金鑰及其關係

Content Trust components

警告

根金鑰一旦遺失將無法復原。如果您遺失任何其他金鑰,請發送電子郵件至 Docker Hub 支援團隊。金鑰遺失還需要每個在遺失前使用過此儲存庫簽署標籤的使用者進行手動介入。

您應該將根金鑰備份到安全的地方。鑑於它僅用於建立新的儲存庫,因此最好將其離線儲存在硬體中。有關保護和備份金鑰的詳細資訊,請務必閱讀如何 管理 DCT 的金鑰

使用 Docker 內容信任簽署映像檔

在 Docker CLI 中,我們可以使用 $ docker trust 命令語法簽署並推送容器映像。這是建立在 Notary 功能集之上的。如需更多資訊,請參閱 Notary GitHub 儲存庫

簽署映像的先決條件是具有附加 Notary 伺服器的 Docker Registry(例如 Docker Hub)。建立自行託管環境的說明可以在 這裡 找到。

要簽署 Docker 映像,您需要一個委派金鑰對。這些金鑰可以使用 $ docker trust key generate 在本地產生,或由憑證授權單位產生。

首先,我們會將委派私鑰新增到本機 Docker 信任儲存庫。(預設情況下,它儲存在 ~/.docker/trust/ 中)。如果您使用 $ docker trust key generate 產生委派金鑰,則私鑰會自動新增到本機信任存放區。如果您要匯入單獨的金鑰,則需要使用 $ docker trust key load 命令。

$ docker trust key generate jeff
Generating key for jeff...
Enter passphrase for new jeff key with ID 9deed25:
Repeat passphrase for new jeff key with ID 9deed25:
Successfully generated and loaded private key. Corresponding public key available: /home/ubuntu/Documents/mytrustdir/jeff.pub

或者,如果您已有現有的金鑰

$ docker trust key load key.pem --name jeff
Loading key from "key.pem"...
Enter passphrase for new jeff key with ID 8ae710e:
Repeat passphrase for new jeff key with ID 8ae710e:
Successfully imported key from key.pem

接下來,我們需要將委派公鑰新增到 Notary 伺服器;這特定於 Notary 中稱為全域唯一名稱 (GUN) 的特定映像儲存庫。如果這是您第一次將委派新增到該儲存庫,則此命令還將使用本機 Notary 標準根金鑰初始化儲存庫。要進一步了解如何初始化儲存庫以及委派的角色,請前往 內容信任的委派

$ docker trust signer add --key cert.pem jeff registry.example.com/admin/demo
Adding signer "jeff" to registry.example.com/admin/demo...
Enter passphrase for new repository key with ID 10b5e94:

最後,我們將使用委派私鑰簽署特定標籤並將其推送至登錄檔。

$ docker trust sign registry.example.com/admin/demo:1
Signing and pushing trust data for local image registry.example.com/admin/demo:1, may overwrite remote trust data
The push refers to repository [registry.example.com/admin/demo]
7bff100f35cb: Pushed
1: digest: sha256:3d2e482b82608d153a374df3357c0291589a61cc194ec4a9ca2381073a17f58e size: 528
Signing and pushing trust metadata
Enter passphrase for signer key with ID 8ae710e:
Successfully signed registry.example.com/admin/demo:1

或者,匯入金鑰後,可以透過匯出 DCT 環境變數,使用 $ docker push 命令推送映像。

$ export DOCKER_CONTENT_TRUST=1

$ docker push registry.example.com/admin/demo:1
The push refers to repository [registry.example.com/admin/demo:1]
7bff100f35cb: Pushed
1: digest: sha256:3d2e482b82608d153a374df3357c0291589a61cc194ec4a9ca2381073a17f58e size: 528
Signing and pushing trust metadata
Enter passphrase for signer key with ID 8ae710e:
Successfully signed registry.example.com/admin/demo:1

可以使用 $ docker trust inspect 命令檢視標籤或儲存庫的遠端信任資料。

$ docker trust inspect --pretty registry.example.com/admin/demo:1

Signatures for registry.example.com/admin/demo:1

SIGNED TAG          DIGEST                                                             SIGNERS
1                   3d2e482b82608d153a374df3357c0291589a61cc194ec4a9ca2381073a17f58e   jeff

List of signers and their keys for registry.example.com/admin/demo:1

SIGNER              KEYS
jeff                8ae710e3ba82

Administrative keys for registry.example.com/admin/demo:1

  Repository Key:	10b5e94c916a0977471cc08fa56c1a5679819b2005ba6a257aa78ce76d3a1e27
  Root Key:	84ca6e4416416d78c4597e754f38517bea95ab427e5f95871f90d460573071fc

可以使用 $ docker trust revoke 命令移除標籤的遠端信任資料。

$ docker trust revoke registry.example.com/admin/demo:1
Enter passphrase for signer key with ID 8ae710e:
Successfully deleted signature for registry.example.com/admin/demo:1

使用 Docker 內容信任進行用戶端強制執行

Docker 用戶端中預設停用內容信任。要啟用它,請將 DOCKER_CONTENT_TRUST 環境變數設定為 1。這可以防止使用者使用未簽名的標籤映像。

在 Docker 用戶端中啟用 DCT 後,對標籤映像進行操作的 docker CLI 命令必須具有內容簽名或明確的內容雜湊。使用 DCT 運作的命令有:

  • push(推送)
  • build(建置)
  • create(建立)
  • pull(拉取)
  • run(執行)

例如,啟用 DCT 後,只有在 someimage:latest 已簽署的情況下,docker pull someimage:latest 才會成功。但是,只要雜湊存在,使用明確內容雜湊的操作就會始終成功。

$ docker pull registry.example.com/user/image:1
Error: remote trust data does not exist for registry.example.com/user/image: registry.example.com does not have trust data for registry.example.com/user/image

$ docker pull registry.example.com/user/image@sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a
sha256:ee7491c9c31db1ffb7673d91e9fac5d6354a89d0e97408567e09df069a1687c1: Pulling from user/image
ff3a5c916c92: Pull complete
a59a168caba3: Pull complete
Digest: sha256:ee7491c9c31db1ffb7673d91e9fac5d6354a89d0e97408567e09df069a1687c1
Status: Downloaded newer image for registry.example.com/user/image@sha256:ee7491c9c31db1ffb7673d91e9fac5d6354a89d0e97408567e09df069a1687c1