Docker中的内容信任

预计阅读时间:8分钟

在网络系统之间传输数据时,信任是一个主要问题。尤其是,当通过不受信任的媒体(例如Internet)进行通信时,确保系统所运行的所有数据的完整性和发布者至关重要。您使用Docker引擎将图像(数据)推入和拉出到公共或私有注册表。内容信任使您能够验证通过任何渠道从注册表接收的所有数据的完整性和发布者。

关于Docker内容信任(DCT)

Docker Content Trust(DCT)提供了使用数字签名处理发送到远程Docker注册表和从远程Docker注册表接收的数据的功能。这些签名允许客户端或运行时验证特定图像标签的完整性和发布者。

通过DCT,图像发布者可以对他们的图像进行签名,而图像使用者可以确保他们拉出的图像已签名。发布者可以是个人或组织,他们可以手动签署其内容,也可以是自动化软件供应链,其内容作为发布过程的一部分进行签名。

图像标签和DCT

单个图像记录具有以下标识符:

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

特定图像REPOSITORY可以具有多个标签。例如,latest3.1.2都是mongo图像上的标签。图像发布者可以构建图像和标签的组合多次,每次构建时都要更改图像。

DCT与TAG图像的一部分相关联。每个图像存储库都有一组密钥,图像发布者可使用这些密钥对图像标签进行签名。图像发布者可以自行决定要签名哪些标签。

图像存储库可以包含带有一个已签名标签和另一个未签名标签的图像。例如,考虑使用Mongo图像存储库。该latest 标签可以是无符号的,而3.1.6标签可以签署。图片发布者有责任确定图片标签是否已签名。在此表示形式中,一些图像标签已签名,而其他未签名:

签名标签

发布者可以选择签名或不签名。结果,未签名标签的内容和具有相同名称的已签名标签的内容可能不匹配。例如,发布者可以推送已标记的图像someimage:latest并对其进行签名。稍后,同一发布者可以推送未签名的someimage:latest图像。第二次推送将替换最后一个未签名的标签,latest但不会影响已签名的latest版本。选择可以签名的标签的能力允许发布者在正式签署图像之前对图像的未签名版本进行迭代。

图像使用者可以启用DCT以确保他们使用的图像已签名。如果使用者启用DCT,则他们只能使用受信任的映像进行拉取,运行或构建。启用DCT有点像对注册表应用“过滤器”。消费者仅“看到”签名的图像标签,而对他们而言“不可见”的是不那么受欢迎的未签名的图像标签。

信任检视

对于尚未启用DCT的用户,关于它们如何使用Docker映像的操作没有任何变化。每个图像都是可见的,无论是否已签名。

Docker内容信任密钥

通过使用签名密钥来管理对图像标签的信任。首次调用使用DCT的操作时,将创建一个密钥集。密钥集包含以下类别的密钥:

  • 脱机密钥,它是图像标签的DCT的根
  • 签名标签的存储库或标签密钥
  • 服务器管理的密钥,例如时间戳记密钥,它为您的存储库提供新鲜度安全保证

下图描述了各种签名密钥及其关系:

内容信任组件

警告

根密钥的丢失很难恢复。要纠正此丢失,需要Docker支持人员干预以重置存储库状态。这种丢失还需要在丢失之前使用此存储库中已签名标签的每个消费者的手动干预

您应该在安全的地方备份根密钥。鉴于只需要创建新的存储库,将其离线存储在硬件中是一个好主意。有关保护和备份密钥的详细信息,请确保您已阅读如何管理DCT的密钥

使用Docker Content Trust签名映像

在Docker CLI中,我们可以使用$ docker trust命令语法对容器映像进行签名和推送 。它建立在Notary功能集的基础上,可以在此处找到有关Notary的更多信息。

签署映像的前提条件是已连接公证服务器的Docker注册表(例如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服务器。这特定于公证人中称为全局唯一名称(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

或者,一旦导入了按键,就可以$ docker push通过导出DCT环境变量,使用命令来推送图像 。

$ 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 Content Trust实施客户端

默认情况下,在Docker客户端中禁用内容信任。要启用它,请将DOCKER_CONTENT_TRUST环境变量设置为1。除非包含签名,否则这将防止用户使用带标签的图像。

在Docker客户端中启用DCT时docker,对标记的图像进行操作的CLI命令必须具有内容签名或显式的内容哈希。使用DCT的命令是:

  • push
  • build
  • create
  • pull
  • run

例如,启用DCT后,docker pull someimage:latest只有在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
内容信任安全码头工人文档