From 4a8766d6048ae9baf2fdd240535b244d05677193 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Tue, 28 May 2024 13:11:37 +0200 Subject: [PATCH] buildx: history load .dockerbuild Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- __tests__/buildx/history.test.ts | 52 +++++++++++ ...ocker~build-push-action~2778G2.dockerbuild | Bin 0 -> 7649 bytes .../docker~login-action~T0XYYW.dockerbuild | Bin 0 -> 25331 bytes ...cker-action~dfile-error~DEBCS4.dockerbuild | Bin 0 -> 4985 bytes ...-docker-action~go-error~BGI5SX.dockerbuild | Bin 0 -> 9532 bytes src/buildx/history.ts | 88 +++++++++++++++++- src/types/buildkit/buildkit.ts | 6 ++ src/types/buildx/buildx.ts | 24 +++++ src/types/buildx/history.ts | 4 + src/types/intoto/intoto.ts | 20 ++++ .../intoto/slsa_provenance/v0.2/provenance.ts | 69 ++++++++++++++ 11 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 __tests__/buildx/history.test.ts create mode 100644 __tests__/fixtures/oci-archive/docker~build-push-action~2778G2.dockerbuild create mode 100644 __tests__/fixtures/oci-archive/docker~login-action~T0XYYW.dockerbuild create mode 100644 __tests__/fixtures/oci-archive/docker~test-docker-action~dfile-error~DEBCS4.dockerbuild create mode 100644 __tests__/fixtures/oci-archive/docker~test-docker-action~go-error~BGI5SX.dockerbuild create mode 100644 src/types/intoto/intoto.ts create mode 100644 src/types/intoto/slsa_provenance/v0.2/provenance.ts diff --git a/__tests__/buildx/history.test.ts b/__tests__/buildx/history.test.ts new file mode 100644 index 00000000..fe2b4004 --- /dev/null +++ b/__tests__/buildx/history.test.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2024 actions-toolkit authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {afterEach, beforeEach, describe, expect, jest, test} from '@jest/globals'; +import path from 'path'; +import * as rimraf from 'rimraf'; + +import {History} from '../../src/buildx/history'; + +const fixturesDir = path.join(__dirname, '..', 'fixtures'); + +// prettier-ignore +const tmpDir = path.join(process.env.TEMP || '/tmp', 'docker-jest'); + +beforeEach(() => { + jest.clearAllMocks(); +}); + +afterEach(function () { + rimraf.sync(tmpDir); +}); + +describe('load', () => { + // prettier-ignore + test.each([ + ['crazy-max~docker-alpine-s6~II9A63.dockerbuild'], + ['docker~build-push-action~2778G2.dockerbuild'], + ['docker~login-action~T0XYYW.dockerbuild'], + ['docker~test-docker-action~dfile-error~DEBCS4.dockerbuild'], + ['docker~test-docker-action~go-error~BGI5SX.dockerbuild'], + ['moby~buildkit~LWDOW6.dockerbuild'], + ])('loading %p', async (filename) => { + const res = await History.load({ + file: path.join(fixturesDir, 'oci-archive', filename) + }); + console.log(JSON.stringify(res, null, 2)); + expect(res).toBeDefined(); + }); +}); diff --git a/__tests__/fixtures/oci-archive/docker~build-push-action~2778G2.dockerbuild b/__tests__/fixtures/oci-archive/docker~build-push-action~2778G2.dockerbuild new file mode 100644 index 0000000000000000000000000000000000000000..f95e686d25814f1e0c2c73d808e55fcde6c28dfd GIT binary patch literal 7649 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 DRU_^f literal 0 HcmV?d00001 diff --git a/__tests__/fixtures/oci-archive/docker~test-docker-action~go-error~BGI5SX.dockerbuild b/__tests__/fixtures/oci-archive/docker~test-docker-action~go-error~BGI5SX.dockerbuild new file mode 100644 index 0000000000000000000000000000000000000000..4cc0b46672daf2891ed0352b8040ab2c950925f1 GIT binary patch literal 9532 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 adgFTIdgFTCUjIJ;0RR6_<>u7@t^fc)7|${Q literal 0 HcmV?d00001 diff --git a/src/buildx/history.ts b/src/buildx/history.ts index 970e58cf..d558e417 100644 --- a/src/buildx/history.ts +++ b/src/buildx/history.ts @@ -26,8 +26,18 @@ import {Context} from '../context'; import {Docker} from '../docker/docker'; import {Exec} from '../exec'; import {GitHub} from '../github'; - -import {ExportRecordOpts, ExportRecordResponse, Summaries} from '../types/buildx/history'; +import {OCI} from '../oci/oci'; + +import {ExportRecordOpts, ExportRecordResponse, LoadRecordOpts, Summaries} from '../types/buildx/history'; +import {Index} from '../types/oci'; +import {MEDIATYPE_IMAGE_INDEX_V1, MEDIATYPE_IMAGE_MANIFEST_V1} from '../types/oci/mediatype'; +import {Archive} from '../types/oci/oci'; +import {BuildRecord} from '../types/buildx/buildx'; +import {Descriptor} from '../types/oci/descriptor'; +import {MEDIATYPE_PAYLOAD as MEDIATYPE_INTOTO_PAYLOAD, MEDIATYPE_PREDICATE} from '../types/intoto/intoto'; +import {ProvenancePredicate} from '../types/intoto/slsa_provenance/v0.2/provenance'; +import {ANNOTATION_REF_KEY, MEDIATYPE_HISTORY_RECORD_V0, MEDIATYPE_SOLVE_STATUS_V0} from '../types/buildkit/buildkit'; +import {SolveStatus} from '../types/buildkit/client'; export interface HistoryOpts { buildx?: Buildx; @@ -42,6 +52,80 @@ export class History { this.buildx = opts?.buildx || new Buildx(); } + public static async load(opts: LoadRecordOpts): Promise> { + const ociArchive = await OCI.loadArchive({ + file: opts.file + }); + return History.readRecords(ociArchive.root.index, ociArchive); + } + + private static readRecords(index: Index, archive: Archive): Record { + const res: Record = {}; + index.manifests.forEach(desc => { + switch (desc.mediaType) { + case MEDIATYPE_IMAGE_MANIFEST_V1: { + const record = History.readRecord(desc, archive); + res[record.Ref] = record; + break; + } + case MEDIATYPE_IMAGE_INDEX_V1: { + if (!Object.prototype.hasOwnProperty.call(archive.indexes, desc.digest)) { + throw new Error(`Missing index: ${desc.digest}`); + } + const records = History.readRecords(archive.indexes[desc.digest], archive); + for (const ref in records) { + if (!Object.prototype.hasOwnProperty.call(records, ref)) { + continue; + } + res[ref] = records[ref]; + } + break; + } + } + }); + return res; + } + + private static readRecord(desc: Descriptor, archive: Archive): BuildRecord { + if (!Object.prototype.hasOwnProperty.call(archive.manifests, desc.digest)) { + throw new Error(`Missing manifest: ${desc.digest}`); + } + const manifest = archive.manifests[desc.digest]; + if (manifest.config.mediaType !== MEDIATYPE_HISTORY_RECORD_V0) { + throw new Error(`Unexpected config media type: ${manifest.config.mediaType}`); + } + if (!Object.prototype.hasOwnProperty.call(archive.blobs, manifest.config.digest)) { + throw new Error(`Missing config blob: ${manifest.config.digest}`); + } + const record = JSON.parse(archive.blobs[manifest.config.digest]); + if (manifest.annotations && ANNOTATION_REF_KEY in manifest.annotations) { + if (record.Ref !== manifest.annotations[ANNOTATION_REF_KEY]) { + throw new Error(`Mismatched ref ${desc.digest}: ${record.Ref} != ${manifest.annotations[ANNOTATION_REF_KEY]}`); + } + } + manifest.layers.forEach(layer => { + switch (layer.mediaType) { + case MEDIATYPE_SOLVE_STATUS_V0: { + if (!Object.prototype.hasOwnProperty.call(archive.blobs, layer.digest)) { + throw new Error(`Missing blob: ${layer.digest}`); + } + record.solveStatus = JSON.parse(archive.blobs[layer.digest]); + break; + } + case MEDIATYPE_INTOTO_PAYLOAD: { + if (!Object.prototype.hasOwnProperty.call(archive.blobs, layer.digest)) { + throw new Error(`Missing blob: ${layer.digest}`); + } + if (layer.annotations && MEDIATYPE_PREDICATE in layer.annotations && layer.annotations[MEDIATYPE_PREDICATE].startsWith('https://slsa.dev/provenance/')) { + record.provenance = JSON.parse(archive.blobs[layer.digest]); + } + break; + } + } + }); + return record; + } + public async export(opts: ExportRecordOpts): Promise { if (os.platform() === 'win32') { throw new Error('Exporting a build record is currently not supported on Windows'); diff --git a/src/types/buildkit/buildkit.ts b/src/types/buildkit/buildkit.ts index 04d0ff52..c2e52675 100644 --- a/src/types/buildkit/buildkit.ts +++ b/src/types/buildkit/buildkit.ts @@ -14,5 +14,11 @@ * limitations under the License. */ +export const ANNOTATION_REF_KEY = 'vnd.buildkit.history.reference'; + +export const MEDIATYPE_SOLVE_STATUS_V0 = 'application/vnd.buildkit.solvestatus.v0'; + +export const MEDIATYPE_HISTORY_RECORD_V0 = 'application/vnd.buildkit.historyrecord.v0'; + // https://github.com/moby/buildkit/blob/v0.14.0/solver/llbsolver/history.go#L672 export const MEDIATYPE_STATUS_V0 = 'application/vnd.buildkit.status.v0'; diff --git a/src/types/buildx/buildx.ts b/src/types/buildx/buildx.ts index 6dc5e6fb..123d9142 100644 --- a/src/types/buildx/buildx.ts +++ b/src/types/buildx/buildx.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import {SolveStatus} from '../buildkit/client'; +import {BuildHistoryRecord} from '../buildkit/control'; +import {ProvenancePredicate} from '../intoto/slsa_provenance/v0.2/provenance'; + export interface Cert { cacert?: string; cert?: string; @@ -44,3 +48,23 @@ export interface LocalState { DockerfilePath: string; GroupRef?: string; } + +export interface StateGroup { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Definition: any; + Targets: Array; + Inputs: Array; + Refs?: Array; +} + +// https://github.com/docker/desktop-build/blob/b609016485f6d37cb22cdfb616c6222c85c30683/tools/export-build/main.go#L48-L54 +export interface ExportedRecord extends BuildHistoryRecord { + localState: LocalState; + stateGroup: StateGroup; + DefaultPlatform: string; +} + +export interface BuildRecord extends ExportedRecord { + solveStatus?: SolveStatus; + provenance?: ProvenancePredicate; +} diff --git a/src/types/buildx/history.ts b/src/types/buildx/history.ts index 67fbe685..5db393de 100644 --- a/src/types/buildx/history.ts +++ b/src/types/buildx/history.ts @@ -42,3 +42,7 @@ export interface RecordSummary { frontendAttrs: Record; error?: string; } + +export interface LoadRecordOpts { + file: string; +} diff --git a/src/types/intoto/intoto.ts b/src/types/intoto/intoto.ts new file mode 100644 index 00000000..0bad854e --- /dev/null +++ b/src/types/intoto/intoto.ts @@ -0,0 +1,20 @@ +/** + * Copyright 2024 actions-toolkit authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// https://github.com/in-toto/in-toto-golang/blob/dd6278764ab1dae7301609c7510129888e2fd569/in_toto/envelope.go#L17 +export const MEDIATYPE_PAYLOAD = 'application/vnd.in-toto+json'; + +export const MEDIATYPE_PREDICATE = 'in-toto.io/predicate-type'; diff --git a/src/types/intoto/slsa_provenance/v0.2/provenance.ts b/src/types/intoto/slsa_provenance/v0.2/provenance.ts new file mode 100644 index 00000000..832fd38b --- /dev/null +++ b/src/types/intoto/slsa_provenance/v0.2/provenance.ts @@ -0,0 +1,69 @@ +/** + * Copyright 2024 actions-toolkit authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// https://github.com/in-toto/in-toto-golang/blob/master/in_toto/slsa_provenance/v0.2/provenance.go + +export const PREDICATE_SLSA_PROVENANCE = 'https://slsa.dev/provenance/v0.2'; + +export interface ProvenancePredicate { + builder: ProvenanceBuilder; + buildType: string; + invocation?: ProvenanceInvocation; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + buildConfig?: any; + metadata: ProvenanceMetadata; + materials?: Material[]; +} + +export interface ProvenanceBuilder { + id: string; +} + +export interface ProvenanceInvocation { + configSource?: ConfigSource; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + parameters?: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + environment?: any; +} + +export interface DigestSet { + [key: string]: string; +} + +export interface ConfigSource { + uri?: string; + digest?: DigestSet; + entryPoint?: string; +} + +export interface Completeness { + parameters?: boolean; + environment?: boolean; + materials?: boolean; +} + +export interface ProvenanceMetadata { + buildInvocationId?: string; + buildStartedOn?: string; + completeness?: Completeness; + reproducible?: boolean; +} + +export interface Material { + uri: string; + digest: DigestSet; +}