SLSA 定义
BuildKit 支持为其执行的构建创建 SLSA Provenance。
BuildKit 生成的 provenance 格式由SLSA Provenance 格式定义。
本页面描述了 BuildKit 如何填充每个字段,以及在使用 attestations mode=min
和 mode=max
生成证明时是否包含该字段。
builder.id
对应于SLSA builder.id
。
包含于 mode=min
和 mode=max
。
如果可用,builder.id
字段设置为构建的 URL。
"builder": {
"id": "https://github.com/docker/buildx/actions/runs/3709599520"
},
可以使用 builder-id
attestations 参数设置此值。
buildType
对应于SLSA buildType
。
包含于 mode=min
和 mode=max
。
buildType
字段设置为 https://mobyproject.org/buildkit@v1
,可用于确定 provenance 内容的结构。
"buildType": "https://mobyproject.org/buildkit@v1",
invocation.configSource
对应于SLSA invocation.configSource
。
包含于 mode=min
和 mode=max
。
描述初始化构建的配置。
"invocation": {
"configSource": {
"uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
"digest": {
"sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
},
"entryPoint": "Dockerfile"
},
...
},
对于从远程上下文(如 Git 或 HTTP URL)初始化的构建,此对象在 uri
和 digest
字段中定义了上下文 URL 及其不可变摘要。对于使用本地前端(如 Dockerfile)的构建,entryPoint
字段定义了初始化构建的前端文件的路径(filename
前端选项)。
invocation.parameters
对应于SLSA invocation.parameters
。
部分包含于 mode=min
。
描述传递给构建的构建输入。
"invocation": {
"parameters": {
"frontend": "gateway.v0",
"args": {
"build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1",
"label:FOO": "bar",
"source": "docker/dockerfile-upstream:master",
"target": "release"
},
"secrets": [
{
"id": "GIT_AUTH_HEADER",
"optional": true
},
...
],
"ssh": [],
"locals": []
},
...
},
以下字段包含于 mode=min
和 mode=max
locals
列出了构建中使用的所有本地源,包括构建上下文和前端文件。frontend
定义了用于构建的 BuildKit 前端类型。目前可以是dockerfile.v0
或gateway.v0
。args
定义了传递给 BuildKit 前端的构建参数。args
对象内部的键反映了 BuildKit 接收到的选项。例如,build-arg
和label
前缀用于构建参数和标签,target
键定义了构建的目标阶段。如果使用了 Gateway 前端,source
键定义了其源镜像。
以下字段仅包含于 mode=max
secrets
定义了构建期间使用的 secrets。请注意,不包含实际的 secret 值。ssh
定义了构建期间使用的 ssh 转发。
invocation.environment
对应于SLSA invocation.environment
。
包含于 mode=min
和 mode=max
。
"invocation": {
"environment": {
"platform": "linux/amd64"
},
...
},
BuildKit 当前唯一设置的值是当前构建机器的 platform
。请注意,这不一定是构建结果的平台,构建结果的平台可以从 in-toto
subject 字段确定。
materials
对应于SLSA materials
。
包含于 mode=min
和 mode=max
。
定义作为构建一部分的所有外部制品。该值取决于制品的类型
- 包含镜像源代码的 Git 仓库的 URL
- 如果你是从远程 tarball 构建,或在 Dockerfile 中使用
ADD
命令包含的文件,其 HTTP URL - 构建期间使用的任何 Docker 镜像
Docker 镜像的 URL 将采用Package URL格式。
所有构建材料将包含制品的不可变校验和。从可变标签构建时,您可以使用摘要信息来确定制品自构建运行以来是否已更新。
"materials": [
{
"uri": "pkg:docker/alpine@3.17?platform=linux%2Famd64",
"digest": {
"sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
},
{
"uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
"digest": {
"sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
}
},
...
],
buildConfig
对应于SLSA buildConfig
。
仅包含于 mode=max
。
定义构建期间执行的构建步骤。
BuildKit 内部使用 LLB 定义来执行构建步骤。构建步骤的 LLB 定义在 buildConfig.llbDefinition
字段中。
每个 LLB 步骤都是LLB ProtoBuf API的 JSON 定义。LLB 图中一个顶点的依赖可以在每个步骤的 inputs
字段中找到。
"buildConfig": {
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"exec": {
"meta": {
"args": [
"/bin/sh",
"-c",
"go build ."
],
"env": [
"PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOPATH=/go",
"GOFLAGS=-mod=vendor",
],
"cwd": "/src",
},
"mounts": [...]
}
},
"platform": {...},
},
"inputs": [
"step8:0",
"step2:0",
]
},
...
]
},
metadata.buildInvocationId
对应于SLSA metadata.buildInvocationId
。
包含于 mode=min
和 mode=max
。
构建调用的唯一标识符。构建多平台镜像时,如果只发出一个构建请求,此值将在镜像的所有平台版本之间共享。
"metadata": {
"buildInvocationID": "rpv7a389uzil5lqmrgwhijwjz",
...
},
metadata.buildStartedOn
对应于SLSA metadata.buildStartedOn
。
包含于 mode=min
和 mode=max
。
构建开始的时间戳。
"metadata": {
"buildStartedOn": "2021-11-17T15:00:00Z",
...
},
metadata.buildFinishedOn
对应于SLSA metadata.buildFinishedOn
。
包含于 mode=min
和 mode=max
。
构建完成的时间戳。
"metadata": {
"buildFinishedOn": "2021-11-17T15:01:00Z",
...
},
metadata.completeness
对应于SLSA metadata.completeness
。
包含于 mode=min
和 mode=max
。
定义 provenance 信息是否完整。
如果所有构建参数都包含在 invocation.parameters
字段中,则 completeness.parameters
为 true。在使用 min
模式构建时,构建参数不包含在 provenance 信息中,参数不完整。在未使用前端的直接 LLB 构建中,参数也不完整。
对于 BuildKit 构建,completeness.environment
始终为 true。
如果 materials
字段包含构建的所有依赖项,则 completeness.materials
为 true。从本地目录中未跟踪的源构建时,材料不完整;而从远程 Git 仓库构建时,BuildKit 可以跟踪所有材料,completeness.materials
为 true。
"metadata": {
"completeness": {
"parameters": true,
"environment": true,
"materials": true
},
...
},
metadata.reproducible
对应于 SLSA metadata.reproducible
。
定义构建结果是否应该按字节完全重现。用户可以通过 reproducible=true
证明参数来设置此值。
"metadata": {
"reproducible": false,
...
},
metadata.https://mobyproject.org/buildkit@v1#hermetic
包含于 mode=min
和 mode=max
。
如果构建是完全独立的(hermetic)并且没有访问网络,则此扩展字段设置为 true。在 Dockerfile 中,如果构建不使用 RUN
命令或通过 --network=none
标志禁用网络,则该构建被认为是完全独立的。
"metadata": {
"https://mobyproject.org/buildkit@v1#hermetic": true,
...
},
metadata.https://mobyproject.org/buildkit@v1#metadata
部分包含于 mode=min
。
此扩展字段定义了 BuildKit 特有的附加元数据,这些元数据不属于 SLSA 证明规范。
"metadata": {
"https://mobyproject.org/buildkit@v1#metadata": {
"source": {...},
"layers": {...},
"vcs": {...},
},
...
},
source
仅包含于 mode=max
。
定义了 LLB 构建步骤(在 buildConfig.llbDefinition
字段中定义)与其原始源代码(例如,Dockerfile 命令)的源映射。source.locations
字段包含在 LLB 步骤中运行的所有 Dockerfile 命令的范围。source.infos
数组包含源代码本身。如果在创建 LLB 定义时 BuildKit 前端提供了此映射,则该映射存在。
layers
仅包含于 mode=max
。
定义了在 buildConfig.llbDefinition
中定义的 LLB 构建步骤挂载到等效层的 OCI 描述符的层映射。如果层数据可用,则此映射存在,通常发生在证明针对镜像时,或者构建步骤拉取了镜像数据作为构建的一部分时。
vcs
包含于 mode=min
和 mode=max
。
定义用于构建的版本控制系统的可选元数据。如果构建使用了来自 Git 仓库的远程上下文,BuildKit 会自动提取版本控制系统的详细信息并将其显示在 invocation.configSource
字段中。但如果构建使用了来自本地目录的源,即使该目录包含 Git 仓库,VCS 信息也会丢失。在这种情况下,构建客户端可以发送额外的 vcs:source
和 vcs:revision
构建选项,BuildKit 会将它们作为额外元数据添加到证明中。请注意,与 invocation.configSource
字段相反,BuildKit 不会验证 vcs
值,因此它们不可信,只能用作元数据提示。
输出
要检查已生成并附加到容器镜像的证明,可以使用 docker buildx imagetools
命令检查仓库中的镜像。检查证明将显示 证明存储规范 中描述的格式。
例如,对于基于 alpine:latest
的简单 Docker 镜像,在 mode=min
构建模式下检查其证明会产生类似于以下内容的证明:
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
"digest": {
"sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
}
}
],
"predicate": {
"builder": {
"id": ""
},
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
"digest": {
"sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "Dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {},
"locals": [
{
"name": "context"
},
{
"name": "dockerfile"
}
]
},
"environment": {
"platform": "linux/amd64"
}
},
"metadata": {
"buildInvocationID": "yirbp1aosi1vqjmi3z6bc75nb",
"buildStartedOn": "2022-12-08T11:48:59.466513707Z",
"buildFinishedOn": "2022-12-08T11:49:01.256820297Z",
"reproducible": false,
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"https://mobyproject.org/buildkit@v1#metadata": {}
}
}
}
对于类似的构建,但在 mode=max
模式下:
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
"digest": {
"sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
}
}
],
"predicate": {
"builder": {
"id": ""
},
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
"digest": {
"sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "Dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {},
"locals": [
{
"name": "context"
},
{
"name": "dockerfile"
}
]
},
"environment": {
"platform": "linux/amd64"
}
},
"buildConfig": {
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"source": {
"identifier": "docker-image://docker.io/library/alpine:latest@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
},
"platform": {
"Architecture": "amd64",
"OS": "linux"
},
"constraints": {}
}
},
{
"id": "step1",
"op": {
"Op": null
},
"inputs": ["step0:0"]
}
]
},
"metadata": {
"buildInvocationID": "46ue2x93k3xj5l463dektwldw",
"buildStartedOn": "2022-12-08T11:50:54.953375437Z",
"buildFinishedOn": "2022-12-08T11:50:55.447841328Z",
"reproducible": false,
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"https://mobyproject.org/buildkit@v1#metadata": {
"source": {
"locations": {
"step0": {
"locations": [
{
"ranges": [
{
"start": {
"line": 1
},
"end": {
"line": 1
}
}
]
}
]
}
},
"infos": [
{
"filename": "Dockerfile",
"data": "RlJPTSBhbHBpbmU6bGF0ZXN0Cg==",
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"source": {
"identifier": "local://dockerfile",
"attrs": {
"local.differ": "none",
"local.followpaths": "[\"Dockerfile\",\"Dockerfile.dockerignore\",\"dockerfile\"]",
"local.session": "q2jnwdkas0i0iu4knchd92jaz",
"local.sharedkeyhint": "dockerfile"
}
}
},
"constraints": {}
}
},
{
"id": "step1",
"op": {
"Op": null
},
"inputs": ["step0:0"]
}
]
}
]
},
"layers": {
"step0:0": [
[
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:c158987b05517b6f2c5913f3acef1f2182a32345a304fe357e3ace5fadcad715",
"size": 3370706
}
]
]
}
}
}
}
}