SLSA 定义
BuildKit 支持 为其运行的构建创建 SLSA Provenance 。
BuildKit 生成的出处格式由SLSA 出处格式定义 。
本页介绍了 BuildKit 如何填充每个字段,以及在生成证明mode=min
和mode=max
.
建造者.id
对应于
SLSAbuilder.id
。
包含在mode=min
和中mode=max
。
该builder.id
字段设置为构建的 URL(如果可用)。
"builder": {
"id": "https://github.com/docker/buildx/actions/runs/3709599520"
},
可以使用证明参数来设置该值builder-id
。
构建类型
对应于
SLSAbuildType
。
包含在mode=min
和中mode=max
。
该buildType
字段设置为https://mobyproject.org/buildkit@v1
可用于确定出处内容的结构。
"buildType": "https://mobyproject.org/buildkit@v1",
调用.configSource
对应于
SLSAinvocation.configSource
。
包含在mode=min
和中mode=max
。
描述初始化构建的配置。
"invocation": {
"configSource": {
"uri": "https://github.com/moby/buildkit.git#refs/tags/v0.11.0",
"digest": {
"sha1": "4b220de5058abfd01ff619c9d2ff6b09a049bea0"
},
"entryPoint": "Dockerfile"
},
...
},
uri
对于从远程上下文(如 Git 或 HTTP URL)初始化的构建,此对象在和字段中定义上下文 URL 及其不可变摘要digest
。对于使用本地前端(例如 Dockerfile)的构建,该entryPoint
字段定义初始化构建的前端文件的路径(filename
frontend 选项)。
调用参数
对应于
SLSAinvocation.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
key 定义构建的目标阶段。该source
键定义网关前端的源图像(如果使用)。
以下字段仅包含在 中mode=max
:
secrets
定义构建期间使用的秘密。请注意,不包括实际的秘密值。ssh
定义构建期间使用的 ssh 转发。
调用.环境
对应于
SLSAinvocation.environment
。
包含在mode=min
和中mode=max
。
"invocation": {
"environment": {
"platform": "linux/amd64"
},
...
},
BuildKit 当前设置的唯一值是platform
当前构建机器的值。请注意,这不一定是可以从主题字段确定的构建结果的平台in-toto
。
材料
对应于
SLSAmaterials
。
包含在mode=min
和中mode=max
。
定义属于构建一部分的所有外部工件。该值取决于工件的类型:
- 包含图像源代码的 Git 存储库的 URL
- HTTP URL(如果您从远程 tarball 构建),或者使用
ADD
Dockerfile 中的命令包含该 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"
}
},
...
],
构建配置
对应于
SLSAbuildConfig
。
仅包含在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",
]
},
...
]
},
元数据.buildInitationId
对应于
SLSAmetadata.buildInvocationId
。
包含在mode=min
和中mode=max
。
构建调用的唯一标识符。当使用单个构建请求构建多平台映像时,该值将由映像的所有平台版本共享。
"metadata": {
"buildInvocationID": "rpv7a389uzil5lqmrgwhijwjz",
...
},
元数据.buildStartedOn
对应于
SLSAmetadata.buildStartedOn
。
包含在mode=min
和中mode=max
。
构建开始时的时间戳。
"metadata": {
"buildStartedOn": "2021-11-17T15:00:00Z",
...
},
元数据.buildFinishedOn
对应于
SLSAmetadata.buildFinishedOn
。
包含在mode=min
和中mode=max
。
构建完成时的时间戳。
"metadata": {
"buildFinishedOn": "2021-11-17T15:01:00Z",
...
},
元数据完整性
对应于
SLSAmetadata.completeness
。
包含在mode=min
和中mode=max
。
定义出处信息是否完整。
completeness.parameters
如果所有构建参数都包含在该
invocation.parameters
字段中,则为 true。使用模式构建时min
,构建参数不包含在出处信息中,并且参数不完整。在不使用前端的直接 LLB 构建上,参数也不完整。
completeness.environment
对于 BuildKit 构建始终如此。
completeness.materials
materials
如果字段包含构建的所有依赖项,则为 true 。当从本地目录中未跟踪的源构建时,材料不完整,而当从远程 Git 存储库构建时,所有材料都可以由 BuildKit 跟踪,并且completeness.materials
是正确的。
"metadata": {
"completeness": {
"parameters": true,
"environment": true,
"materials": true
},
...
},
元数据可再现
对应于
SLSAmetadata.reproducible
。
定义构建结果是否应该是逐字节可重现的。该值可以由用户使用reproducible=true
证明参数来设置。
"metadata": {
"reproducible": false,
...
},
元数据。https://mobyproject.org/buildkit@v1#hermetic
包含在mode=min
和中mode=max
。
如果构建是密封的并且不访问网络,则此扩展字段设置为 true。在 Dockerfiles 中,如果构建不使用RUN
命令或使用标志禁用网络,则构建是密封的--network=none
。
"metadata": {
"https://mobyproject.org/buildkit@v1#hermetic": true,
...
},
元数据。https://mobyproject.org/buildkit@v1#metadata
部分包含在mode=min
.
此扩展字段定义了特定于 BuildKit 的附加元数据,该元数据不属于 SLSA 来源规范的一部分。
"metadata": {
"https://mobyproject.org/buildkit@v1#metadata": {
"source": {...},
"layers": {...},
"vcs": {...},
},
...
},
来源
仅包含在mode=max
.
buildConfig.llbDefinition
定义现场定义的 LLB 构建步骤到其原始源代码(例如 Dockerfile 命令)的源映射
。该source.locations
字段包含 LLB 步骤中运行的所有 Dockerfile 命令的范围。source.infos
数组包含源代码本身。如果 BuildKit 前端在创建 LLB 定义时提供了该映射,则该映射就会存在。
层数
仅包含在mode=max
.
buildConfig.llbDefinition
定义在等效层的 OCI 描述符中定义的 LLB 构建步骤安装的层映射
。如果层数据可用,通常当证明用于图像时或者如果构建步骤将图像数据作为构建的一部分拉入时,则存在此映射。
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
}
]
]
}
}
}
}
}