來源證明
來源證明包含有關建置流程的事實,包括以下詳細資訊:
- 建置時間戳記
- 建置參數和環境
- 版本控制中繼資料
- 原始碼詳細資訊
- 建置期間使用的素材(檔案、指令碼)
來源證明遵循 SLSA 來源架構,版本 0.2。
如需有關 BuildKit 如何填入這些來源屬性的詳細資訊,請參閱 SLSA 定義。
建立來源證明
若要建立來源證明,請將 --attest type=provenance
選項傳遞至 docker buildx build
命令
$ docker buildx build --tag <namespace>/<image>:<version> \
--attest type=provenance,mode=[min,max] .
或者,您可以使用速記 --provenance=true
選項代替 --attest type=provenance
。 若要使用速記選項指定 mode
參數,請使用:--provenance=mode=max
。
有關如何使用 GitHub Actions 新增來源證明的範例,請參閱 使用 GitHub Actions 新增證明。
模式
您可以使用 mode
參數定義要包含在來源證明中的詳細資訊層級。 支援的值為 mode=min
和 mode=max
(預設值)。
最小
在 min
模式中,來源證明包含最少的資訊集,例如
- 建置時間戳記
- 使用的前端
- 建置素材
- 來源儲存庫和修訂
- 建置平台
- 可重現性
建置參數的值、密碼的身分識別和豐富的層級中繼資料不包含在 mode=min
中。 min
層級的來源可安全地用於所有建置,因為它不會洩漏建置環境中任何部分的資訊。
以下 JSON 範例顯示使用 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/docker/dockerfile@1",
"digest": {
"sha256": "9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc"
}
},
{
"uri": "pkg:docker/golang@1.19.4-alpine?platform=linux%2Farm64",
"digest": {
"sha256": "a9b24b67dc83b3383d22a14941c2b2b2ca6a103d805cac6820fd1355943beaf1"
}
}
],
"invocation": {
"configSource": { "entryPoint": "Dockerfile" },
"parameters": {
"frontend": "gateway.v0",
"args": {
"cmdline": "docker/dockerfile:1",
"source": "docker/dockerfile:1",
"target": "binaries"
},
"locals": [{ "name": "context" }, { "name": "dockerfile" }]
},
"environment": { "platform": "linux/arm64" }
},
"metadata": {
"buildInvocationID": "c4a87v0sxhliuewig10gnsb6v",
"buildStartedOn": "2022-12-16T08:26:28.651359794Z",
"buildFinishedOn": "2022-12-16T08:26:29.625483253Z",
"reproducible": false,
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"https://mobyproject.org/buildkit@v1#metadata": {
"vcs": {
"revision": "a9ba846486420e07d30db1107411ac3697ecab68",
"source": "git@github.com:<org>/<repo>.git"
}
}
}
}
}
最大
max
模式包含 min
模式中包含的所有資訊,以及
- 建置的 LLB 定義。 這些顯示產生映像檔的確切步驟。
- 有關 Dockerfile 的資訊,包括檔案的完整 base64 編碼版本。
- 描述建置步驟和映像檔層級之間關係的來源地圖。
如果可能,您應該優先使用 mode=max
,因為它包含更詳細的資訊以供分析。
警告
請注意,
mode=max
會公開 建置參數 的值。如果您誤用建置參數來傳遞憑證、驗證權杖或其他密碼,則應重構您的建置,以使用 密碼掛載 來傳遞密碼。 密碼掛載不會洩漏到建置之外,也永遠不會包含在來源證明中。
檢查來源
若要探索透過 image
匯出器匯出的已建立來源,您可以使用 imagetools inspect
。
使用 --format
選項,您可以指定輸出的範本。 所有與來源相關的資料都可在 .Provenance
屬性下取得。 例如,若要以 SLSA 格式取得來源的原始內容
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
--format "{{ json .Provenance.SLSA }}"
{
"buildType": "https://mobyproject.org/buildkit@v1",
...
}
您也可以使用 Go 範本的完整功能來建構更複雜的運算式。 例如,對於使用 mode=max
產生的來源,您可以擷取用於建置映像檔的 Dockerfile 的完整原始碼
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
--format '{{ range (index .Provenance.SLSA.metadata "https://mobyproject.org/buildkit@v1#metadata").source.infos }}{{ if eq .filename "Dockerfile" }}{{ .data }}{{ end }}{{ end }}' | base64 -d
FROM ubuntu:20.04
RUN apt-get update
...
來源證明範例
以下範例顯示 mode=max
的來源證明的 JSON 表示形式
{
"_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/docker/dockerfile@1",
"digest": {
"sha256": "9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc"
}
},
{
"uri": "pkg:docker/golang@1.19.4-alpine?platform=linux%2Farm64",
"digest": {
"sha256": "a9b24b67dc83b3383d22a14941c2b2b2ca6a103d805cac6820fd1355943beaf1"
}
}
],
"buildConfig": {
"llbDefinition": [
{
"id": "step4",
"op": {
"Op": {
"exec": {
"meta": {
"args": ["/bin/sh", "-c", "go mod download -x"],
"env": [
"PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOLANG_VERSION=1.19.4",
"GOPATH=/go",
"CGO_ENABLED=0"
],
"cwd": "/src"
},
"mounts": [
{ "input": 0, "dest": "/", "output": 0 },
{
"input": -1,
"dest": "/go/pkg/mod",
"output": -1,
"mountType": 3,
"cacheOpt": { "ID": "//go/pkg/mod" }
},
{
"input": 1,
"selector": "/go.mod",
"dest": "/src/go.mod",
"output": -1,
"readonly": true
},
{
"input": 1,
"selector": "/go.sum",
"dest": "/src/go.sum",
"output": -1,
"readonly": true
}
]
}
},
"platform": { "Architecture": "arm64", "OS": "linux" },
"constraints": {}
},
"inputs": ["step3:0", "step1:0"]
}
]
},
"metadata": {
"buildInvocationID": "edf52vxjyf9b6o5qd7vgx0gru",
"buildStartedOn": "2022-12-15T15:38:13.391980297Z",
"buildFinishedOn": "2022-12-15T15:38:14.274565297Z",
"reproducible": false,
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"https://mobyproject.org/buildkit@v1#metadata": {
"vcs": {
"revision": "a9ba846486420e07d30db1107411ac3697ecab68-dirty",
"source": "git@github.com:<org>/<repo>.git"
},
"source": {
"locations": {
"step4": {
"locations": [
{
"ranges": [
{ "start": { "line": 5 }, "end": { "line": 5 } },
{ "start": { "line": 6 }, "end": { "line": 6 } },
{ "start": { "line": 7 }, "end": { "line": 7 } },
{ "start": { "line": 8 }, "end": { "line": 8 } }
]
}
]
}
},
"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": "s4j58ngehdal1b5hn7msiqaqe",
"local.sharedkeyhint": "dockerfile"
}
}
},
"constraints": {}
}
},
{ "id": "step1", "op": { "Op": null }, "inputs": ["step0:0"] }
]
}
]
},
"layers": {
"step2:0": [
[
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:261da4162673b93e5c0e7700a3718d40bcc086dbf24b1ec9b54bca0b82300626",
"size": 3259190
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:bc729abf26b5aade3c4426d388b5ea6907fe357dec915ac323bb2fa592d6288f",
"size": 286218
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:7f1d6579712341e8062db43195deb2d84f63b0f2d1ed7c3d2074891085ea1b56",
"size": 116878653
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:652874aefa1343799c619d092ab9280b25f96d97939d5d796437e7288f5599c9",
"size": 156
}
]
]
}
}
}
}
}