SLSA 定义
BuildKit 支持为其运行的构建创建 SLSA 来源。
BuildKit 生成的来源格式由SLSA 来源格式定义。
此页面描述了 BuildKit 如何填充每个字段,以及在生成证明时是否包含该字段 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
证明参数设置。
buildType
对应于SLSA buildType
。
包含在 mode=min
和 mode=max
中。
buildType
字段设置为 https://mobyproject.org/buildkit@v1
可用于确定来源内容的结构。
"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
键定义构建的目标阶段。source
键定义如果使用,则定义 Gateway 前端的源镜像。
以下字段仅包含在mode=max
中
secrets
定义构建期间使用的密钥。请注意,不包含实际的密钥值。ssh
定义构建期间使用的 SSH 转发。
invocation.environment
对应于SLSA invocation.environment
。
包含在 mode=min
和 mode=max
中。
"invocation": {
"environment": {
"platform": "linux/amd64"
},
...
},
BuildKit 目前设置的唯一值是当前构建机器的platform
。请注意,这并不一定是可以通过in-toto
主题字段确定的构建结果的平台。
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
中。
定义溯源信息是否完整。
如果所有构建参数都包含在invocation.parameters
字段中,则completeness.parameters
为真。当以min
模式构建时,构建参数不包含在溯源信息中,参数不完整。对于没有使用前端的直接 LLB 构建,参数也不完整。
对于 BuildKit 构建,completeness.environment
始终为真。
如果materials
字段包含构建的所有依赖项,则completeness.materials
为真。当从本地目录中的未跟踪源构建时,材料不完整,而当从远程 Git 仓库构建时,BuildKit 可以跟踪所有材料,并且completeness.materials
为真。
"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
中。
如果构建是隔离的并且没有访问网络,则此扩展字段设置为 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
中。
定义buildConfig.llbDefinition
字段中定义的 LLB 构建步骤与其原始源代码(例如,Dockerfile 命令)的源映射。source.locations
字段包含在 LLB 步骤中运行的所有 Dockerfile 命令的范围。source.infos
数组包含源代码本身。如果 BuildKit 前端在创建 LLB 定义时提供了此映射,则此映射存在。
layers
仅包含在mode=max
中。
定义buildConfig.llbDefinition
中定义的 LLB 构建步骤挂载到等效层的 OCI 描述符的层映射。如果层数据可用,通常在对镜像进行证明时或构建步骤作为构建的一部分提取了镜像数据时,此映射存在。
vcs
包含在 mode=min
和 mode=max
中。
定义用于构建的版本控制系统的可选元数据。如果构建使用来自 Git 仓库的远程上下文,BuildKit 会自动提取版本控制系统的详细信息并将其显示在invocation.configSource
字段中。但是,如果构建使用来自本地目录的源,即使目录包含 Git 仓库,VCS 信息也会丢失。在这种情况下,构建客户端可以发送额外的vcs:source
和vcs:revision
构建选项,BuildKit 将将其作为额外元数据添加到溯源证明
输出
要检查为容器镜像生成并附加的来源信息,可以使用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
}
]
]
}
}
}
}
}