本文为 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_path | Docker 守护进程套接字的位置(Unix) | "unix:///var/run/docker.sock" |
| podman_socket_path | rootful(有 root 权限的)Podman 套接字的位置(Unix) | "unix:///run/podman/podman.sock" |
| podman_socket_path_template | rootless(无 root 权限的)Podman 的套接字模板(Unix)。必须包含一个 %d UID 占位符 | "unix:///run/user/%d/podman/podman.sock" |
| docker_version | Docker 守护进程的 API 版本。若未指定 | |
| container_id_cgroup_matchers | 用于从 cgroup 条目中发现容器 ID 的模式列表(Unix) | |
| docker_host | Docker Engine API 端点的位置(仅 Windows) | "npipe:////./pipe/docker_engine" |
| sigstore | Sigstore 选项。参见 Sigstore 选项。设置后,启用对容器镜像签名与证明(attestation)的验证。 | |
| use_new_container_locator | 若为 true,启用支持 cgroups v2 的新容器定位算法 | true |
| verbose_container_locator_logs | 若为 true,启用用于定位容器的 mountinfo 与 cgroup 信息的详细日志 | false |
配置示例:
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 自定义示例:
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:label | docker:label:com.example.name:foo | 容器每个标签的 key:value 键值对。 |
docker:env | docker:env:VAR=val | 容器每个环境变量的原始字符串值。 |
docker:image_id | docker:image_id:envoyproxy/envoy:contrib-v1.29.1 | 容器的镜像名与版本。 |
docker:image_config_digest | docker: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-id | Rekor 透明日志条目的唯一 LogID(例如 k8s:image-signature-log-id:c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b95918123) |
| docker:image-signature-log-index | Rekor 透明日志条目的日志索引(例如 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。所给的模式不得有歧义;若多个模式可匹配同一输入,将返回错误。
合法示例:
container_id_cgroup_matchers = [
"/docker/<id>",
"/my.slice/*/<id>/*"
]非法示例:
container_id_cgroup_matchers = [
"/a/b/<id>",
"/*/b/<id>"
]注意:所提供的模式不是正则表达式。它是一种简化的匹配语言,强制采用以正斜杠分隔的模式(schema)。
示例
镜像 ID(Image ID)
以下是 Envoy 代理容器的 image_id 选择器示例。首先运行 docker images 查看可用镜像:
$ 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 列。
$ 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)仓库进行工作负载注册时,是一个稳定的匹配目标。
$ 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 [...] 启动,那么工作负载注册可这样进行:
$ spire-server entry create \
-parentID spiffe://example.org/host \
-spiffeID spiffe://example.org/host/foo \
-selector docker:label:com.example.name:foo你可以将多个标签组合为选择器。
$ 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 的情况:
$ spire-server entry create \
-parentID spiffe://example.org/host \
-spiffeID spiffe://example.org/host/foo \
-selector docker:env:ENVIRONMENT=prod