Skip to content

本文为 SPIRE 官方文档 plugin_agent_workloadattestor_docker 的中文译本,以英文原文为准。 🔗 穿越源码分析:Agent 详解 · WorkloadAttestor

Agent 插件:WorkloadAttestor "docker"

docker 插件基于容器标签为调用 agent 的工作负载(workload)生成选择器(selector)。其做法是:在 Unix 系统上从工作负载的 cgroup 归属中取得容器 ID(在 Windows 上则从 Job Object 名称中取得),再查询容器运行时 API(默认为 Docker,检测到时为 Podman)以获取该容器的标签。

配置项说明默认值
docker_socket_pathDocker 守护进程套接字的位置(Unix)"unix:///var/run/docker.sock"
podman_socket_pathrootful(有 root 权限的)Podman 套接字的位置(Unix)"unix:///run/podman/podman.sock"
podman_socket_path_templaterootless(无 root 权限的)Podman 的套接字模板(Unix)。必须包含一个 %d UID 占位符"unix:///run/user/%d/podman/podman.sock"
docker_versionDocker 守护进程的 API 版本。若未指定
container_id_cgroup_matchers用于从 cgroup 条目中发现容器 ID 的模式列表(Unix)
docker_hostDocker Engine API 端点的位置(仅 Windows)"npipe:////./pipe/docker_engine"
sigstoreSigstore 选项。参见 Sigstore 选项。设置后,启用对容器镜像签名与证明(attestation)的验证。
use_new_container_locator若为 true,启用支持 cgroups v2 的新容器定位算法true
verbose_container_locator_logs若为 true,启用用于定位容器的 mountinfo 与 cgroup 信息的详细日志false

配置示例:

hcl
    WorkloadAttestor "docker" {
        plugin_data {
        }
    }

Podman 支持(Unix)

该插件支持 Podman 工作负载,包括多用户主机上的 rootless Podman。

在认证时,插件会检查工作负载的 cgroup 路径:

  • 如果检测到 Podman 的 cgroup 路径且其中包含用户切片(user slice,/user-<uid>.slice/),SPIRE 会将该工作负载视为 rootless Podman,并使用把 <uid> 代入 %d 后的 podman_socket_path_template 调用 Podman API。
  • 如果检测到 Podman 的 cgroup 路径但不含用户切片 UID,SPIRE 使用 podman_socket_path(rootful Podman)。
  • 如果未检测到 Podman 的 cgroup 路径,SPIRE 使用 docker_socket_path(Docker)。

这种按工作负载选择套接字的方式,避免了将 rootless Podman 工作负载全部经由单个全局守护进程套接字路由。

rootless 自定义示例:

hcl
WorkloadAttestor "docker" {
    plugin_data {
        podman_socket_path_template = "unix:///custom/user/%d/podman.sock"
    }
}

Sigstore 功能

该功能为 docker 工作负载认证器扩展了使用 Sigstore 生态验证容器镜像签名与证明(attestation)的能力。它是可选的,仅在配置了 sigstore 块时启用。

Sigstore 选项

选项说明
allowed_identities将 OIDC Provider URI 映射到允许的主体(subject)列表。支持正则表达式模式。默认为空。若未指定,则接受来自任意签发者的签名。(例如 "https://accounts.google.com" = ["subject1@example.com","subject2@example.com"])。
skipped_images列出要从 Sigstore 签名验证中排除的镜像 ID。对这些镜像,不会生成任何 Sigstore 选择器。默认为空列表。
rekor_url指定用于透明日志(transparency log)验证的 Rekor URL。默认是公共 Rekor 实例 https://rekor.sigstore.dev
ignore_tlog若设为 true,则跳过透明日志验证,且不生成基于 Rekor bundle 的选择器。
ignore_attestations若设为 true,则跳过镜像证明验证,且不生成 image-attestations:verified 选择器。
ignore_sct若设为 true,则跳过签名证书时间戳(Signed Certificate Timestamp, SCT)验证。
registry_credentials将每个镜像仓库 URL 映射到对应的认证凭据。示例:{"docker.io": {"username": "user", "password": "pass"}}

自定义 CA 根

可通过 cosign initialize 命令提供经 TUF 签名的自定义 CA 根。此方法会安全地固定(pin)CA 根,确保验证过程中只使用受信任的证书。此外,还可通过 SIGSTORE_ROOT_FILE 环境变量指定用于证书验证的受信任根。有关 Cosign 配置的更多细节,请参阅文档

工作负载选择器

由于选择器是基于容器的 docker 标签动态创建的,因此没有一份已知选择器的固定清单。相反,容器的每个标签都会用于构建选择器列表。

选择器示例说明
docker:labeldocker:label:com.example.name:foo容器每个标签的 key:value 键值对。
docker:envdocker:env:VAR=val容器每个环境变量的原始字符串值。
docker:image_iddocker:image_id:envoyproxy/envoy:contrib-v1.29.1容器的镜像名与版本。
docker:image_config_digestdocker:image_config_digest:sha256:9f86d1..5f00a08镜像配置摘要(内容寻址、与仓库无关)。

启用 Sigstore 后可用的选择器(当配置使用 sigstore 时可用)

选择器取值
docker:image-signature:verified镜像签名已验证且有效时。
docker:image-attestations:verified镜像证明已验证且有效时。
docker:image-signature-value签名的 base64 编码值(例如 k8s:image-signature-content:MEUCIQCyem8Gcr0sPFMP7fTXazCN57NcN5+MjxJw9Oo0x2eM+AIgdgBP96BO1Te/NdbjHbUeb0BUye6deRgVtQEv5No5smA=)
docker:image-signature-subject签名镜像的 OIDC 主体(principal)(例如 k8s:image-signature-subject:spirex@example.com)
docker:image-signature-issuer签名的 OIDC 签发者(例如 k8s:image-signature-issuer:https://accounts.google.com)
docker:image-signature-log-idRekor 透明日志条目的唯一 LogID(例如 k8s:image-signature-log-id:c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b95918123)
docker:image-signature-log-indexRekor 透明日志条目的日志索引(例如 k8s:image-signature-log-index:105695637)
docker:image-signature-integrated-time镜像签名被并入签名透明日志的时间(Unix 时间戳格式)(例如 k8s:image-signature-integrated-time:1719237832)
docker:image-signature-signed-entry-timestamp已签名条目的 base64 编码值(对 logID、logIndex、body 和 integratedTime 的签名)(例如 k8s:image-signature-integrated-time:MEQCIDP77vB0/MEbR1QKZ7Ol8PgFwGEEvnQJiv5cO7ATDYRwAiB9eBLYZjclxRNaaNJVBdQfP9Y8vGVJjwdbisme2cKabc)

ignore_tlog 设为 true,则不会生成基于 Rekor bundle 的选择器(-log-id-log-index-integrated-time-signed-entry-timestamp)。

容器 ID CGroup 匹配器

所提供的模式应使用通配符匹配符 * 和捕获符 <id>,来描述应如何从 cgroup 条目中提取容器 ID。所给的模式不得有歧义;若多个模式可匹配同一输入,将返回错误。

合法示例:

hcl
    container_id_cgroup_matchers = [
        "/docker/<id>",
        "/my.slice/*/<id>/*"
    ]

非法示例:

hcl
    container_id_cgroup_matchers = [
        "/a/b/<id>",
        "/*/b/<id>"
    ]

注意:所提供的模式不是正则表达式。它是一种简化的匹配语言,强制采用以正斜杠分隔的模式(schema)。

示例

镜像 ID(Image ID)

以下是 Envoy 代理容器的 image_id 选择器示例。首先运行 docker images 查看可用镜像:

shell
$ docker images
REPOSITORY                    TAG               IMAGE ID       CREATED        SIZE
prom/prometheus               latest            1d3b7f56885b   2 weeks ago    262MB
spiffe.io                     latest            02acdde06edc   2 weeks ago    1.17GB
ghcr.io/spiffe/spire-agent    1.9.1             622ce7acc7e8   4 weeks ago    57.9MB
ghcr.io/spiffe/spire-server   1.9.1             e3b24c3cd9e1   4 weeks ago    103MB
envoyproxy/envoy              contrib-v1.29.1   644f45f6626c   7 weeks ago    181MB

然后使用 REPOSITORY:TAG 作为选择器,而不是 IMAGE ID 列。

shell
$ spire-server entry create \
    -parentID spiffe://example.org/host \
    -spiffeID spiffe://example.org/host/foo \
    -selector docker:image_id:envoyproxy/envoy:contrib-v1.29.1

镜像配置摘要(Image config digest)

在可用时,插件会为镜像配置摘要生成一个选择器。该值是内容寻址的,不依赖仓库主机名,因此在跨镜像(mirror)仓库进行工作负载注册时,是一个稳定的匹配目标。

shell
$ spire-server entry create \
    -parentID spiffe://example.org/host \
    -spiffeID spiffe://example.org/host/foo \
    -selector docker:image_config_digest:sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

标签(Labels)

如果一个工作负载容器以 docker run --label com.example.name=foo [...] 启动,那么工作负载注册可这样进行:

shell
$ spire-server entry create \
    -parentID spiffe://example.org/host \
    -spiffeID spiffe://example.org/host/foo \
    -selector docker:label:com.example.name:foo

你可以将多个标签组合为选择器。

shell
$ spire-server entry create \
    -parentID spiffe://example.org/host \
    -spiffeID spiffe://example.org/host/foo \
    -selector docker:label:com.example.name:foo
    -selector docker:label:com.example.cluster:prod

环境变量(Environment variables)

以下是环境变量选择器的示例,匹配变量 ENVIRONMENT 值为 prod 的情况:

shell
$ spire-server entry create \
    -parentID spiffe://example.org/host \
    -spiffeID spiffe://example.org/host/foo \
    -selector docker:env:ENVIRONMENT=prod