handle attests correctly with provenance and sbom inputs
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									f8bc7f4600
								
							
						
					
					
						commit
						96acf63e4c
					
				| @ -481,7 +481,7 @@ nproc=3`], | |||||||
|       [ |       [ | ||||||
|         'build', |         'build', | ||||||
|         '--iidfile', path.join(tmpDir, 'iidfile'), |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|         "--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, |         '--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
| @ -500,7 +500,7 @@ nproc=3`], | |||||||
|       [ |       [ | ||||||
|         'build', |         'build', | ||||||
|         '--iidfile', path.join(tmpDir, 'iidfile'), |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|         "--provenance", `builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, |         '--attest', `type=provenance,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
| @ -519,7 +519,7 @@ nproc=3`], | |||||||
|       [ |       [ | ||||||
|         'build', |         'build', | ||||||
|         '--iidfile', path.join(tmpDir, 'iidfile'), |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|         "--provenance", `mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, |         '--attest', `type=provenance,mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
| @ -538,7 +538,7 @@ nproc=3`], | |||||||
|       [ |       [ | ||||||
|         'build', |         'build', | ||||||
|         '--iidfile', path.join(tmpDir, 'iidfile'), |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|         "--provenance", 'false', |         '--attest', 'type=provenance,disabled=true', | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
| @ -557,7 +557,7 @@ nproc=3`], | |||||||
|       [ |       [ | ||||||
|         'build', |         'build', | ||||||
|         '--iidfile', path.join(tmpDir, 'iidfile'), |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|         "--provenance", 'builder-id=foo', |         '--attest', 'type=provenance,builder-id=foo', | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
| @ -620,7 +620,7 @@ nproc=3`], | |||||||
|       ] |       ] | ||||||
|     ], |     ], | ||||||
|     [ |     [ | ||||||
|       25, |       26, | ||||||
|       '0.10.0', |       '0.10.0', | ||||||
|       new Map<string, string>([ |       new Map<string, string>([ | ||||||
|         ['context', '.'], |         ['context', '.'], | ||||||
| @ -642,7 +642,7 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`] | |||||||
|       ] |       ] | ||||||
|     ], |     ], | ||||||
|     [ |     [ | ||||||
|       26, |       27, | ||||||
|       '0.10.0', |       '0.10.0', | ||||||
|       new Map<string, string>([ |       new Map<string, string>([ | ||||||
|         ['context', '.'], |         ['context', '.'], | ||||||
| @ -663,7 +663,7 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`] | |||||||
|       ] |       ] | ||||||
|     ], |     ], | ||||||
|     [ |     [ | ||||||
|       27, |       28, | ||||||
|       '0.11.0', |       '0.11.0', | ||||||
|       new Map<string, string>([ |       new Map<string, string>([ | ||||||
|         ['context', '.'], |         ['context', '.'], | ||||||
| @ -677,13 +677,13 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`] | |||||||
|       [ |       [ | ||||||
|         'build', |         'build', | ||||||
|         '--output', 'type=local,dest=./release-out', |         '--output', 'type=local,dest=./release-out', | ||||||
|         "--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, |         '--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
|     ], |     ], | ||||||
|     [ |     [ | ||||||
|       28, |       29, | ||||||
|       '0.12.0', |       '0.12.0', | ||||||
|       new Map<string, string>([ |       new Map<string, string>([ | ||||||
|         ['context', '.'], |         ['context', '.'], | ||||||
| @ -701,13 +701,13 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`] | |||||||
|         '--annotation', 'manifest:example3=yyy', |         '--annotation', 'manifest:example3=yyy', | ||||||
|         '--annotation', 'manifest-descriptor[linux/amd64]:example4=zzz', |         '--annotation', 'manifest-descriptor[linux/amd64]:example4=zzz', | ||||||
|         '--output', 'type=local,dest=./release-out', |         '--output', 'type=local,dest=./release-out', | ||||||
|         "--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, |         '--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
|     ], |     ], | ||||||
|     [ |     [ | ||||||
|       29, |       30, | ||||||
|       '0.12.0', |       '0.12.0', | ||||||
|       new Map<string, string>([ |       new Map<string, string>([ | ||||||
|         ['context', '.'], |         ['context', '.'], | ||||||
| @ -721,11 +721,71 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`] | |||||||
|         'build', |         'build', | ||||||
|         '--iidfile', path.join(tmpDir, 'iidfile'), |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|         "--output", `type=image,"name=localhost:5000/name/app:latest,localhost:5000/name/app:foo",push-by-digest=true,name-canonical=true,push=true`, |         "--output", `type=image,"name=localhost:5000/name/app:latest,localhost:5000/name/app:foo",push-by-digest=true,name-canonical=true,push=true`, | ||||||
|         "--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, |         '--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|         '--metadata-file', path.join(tmpDir, 'metadata-file'), |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|         '.' |         '.' | ||||||
|       ] |       ] | ||||||
|     ] |     ], | ||||||
|  |     [ | ||||||
|  |       31, | ||||||
|  |       '0.13.1', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['provenance', 'mode=max'], | ||||||
|  |         ['sbom', 'true'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|  |         '--attest', `type=provenance,mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|  |         '--attest', `type=sbom,disabled=false`, | ||||||
|  |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       32, | ||||||
|  |       '0.13.1', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['attests', 'type=provenance,mode=min'], | ||||||
|  |         ['provenance', 'mode=max'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|  |         '--attest', `type=provenance,mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|  |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       33, | ||||||
|  |       '0.13.1', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['attests', 'type=provenance,mode=min'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', path.join(tmpDir, 'iidfile'), | ||||||
|  |         '--attest', `type=provenance,mode=min,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|  |         '--metadata-file', path.join(tmpDir, 'metadata-file'), | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|   ])( |   ])( | ||||||
|     '[%d] given %p with %p as inputs, returns %p', |     '[%d] given %p with %p as inputs, returns %p', | ||||||
|     async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => { |     async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => { | ||||||
|  | |||||||
| @ -98,13 +98,6 @@ async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit): | |||||||
|   if (inputs.allow.length > 0) { |   if (inputs.allow.length > 0) { | ||||||
|     args.push('--allow', inputs.allow.join(',')); |     args.push('--allow', inputs.allow.join(',')); | ||||||
|   } |   } | ||||||
|   if (await toolkit.buildx.versionSatisfies('>=0.10.0')) { |  | ||||||
|     await Util.asyncForEach(inputs.attests, async attest => { |  | ||||||
|       args.push('--attest', attest); |  | ||||||
|     }); |  | ||||||
|   } else if (inputs.attests.length > 0) { |  | ||||||
|     core.warning("Attestations are only supported by buildx >= 0.10.0; the input 'attests' is ignored."); |  | ||||||
|   } |  | ||||||
|   if (await toolkit.buildx.versionSatisfies('>=0.12.0')) { |   if (await toolkit.buildx.versionSatisfies('>=0.12.0')) { | ||||||
|     await Util.asyncForEach(inputs.annotations, async annotation => { |     await Util.asyncForEach(inputs.annotations, async annotation => { | ||||||
|       args.push('--annotation', annotation); |       args.push('--annotation', annotation); | ||||||
| @ -157,26 +150,9 @@ async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit): | |||||||
|     args.push('--platform', inputs.platforms.join(',')); |     args.push('--platform', inputs.platforms.join(',')); | ||||||
|   } |   } | ||||||
|   if (await toolkit.buildx.versionSatisfies('>=0.10.0')) { |   if (await toolkit.buildx.versionSatisfies('>=0.10.0')) { | ||||||
|     if (inputs.provenance) { |     args.push(...(await getAttestArgs(inputs, toolkit))); | ||||||
|       args.push('--provenance', inputs.provenance); |   } else { | ||||||
|     } else if ((await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !BuildxInputs.hasDockerExporter(inputs.outputs, inputs.load)) { |     core.warning("Attestations are only supported by buildx >= 0.10.0; the inputs 'attests', 'provenance' and 'sbom' are ignored."); | ||||||
|       // if provenance not specified and BuildKit version compatible for
 |  | ||||||
|       // attestation, set default provenance. Also needs to make sure user
 |  | ||||||
|       // doesn't want to explicitly load the image to docker.
 |  | ||||||
|       if (GitHub.context.payload.repository?.private ?? false) { |  | ||||||
|         // if this is a private repository, we set the default provenance
 |  | ||||||
|         // attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
 |  | ||||||
|         args.push('--provenance', BuildxInputs.resolveProvenanceAttrs(`mode=min,inline-only=true`)); |  | ||||||
|       } else { |  | ||||||
|         // for a public repository, we set max provenance mode.
 |  | ||||||
|         args.push('--provenance', BuildxInputs.resolveProvenanceAttrs(`mode=max`)); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     if (inputs.sbom) { |  | ||||||
|       args.push('--sbom', inputs.sbom); |  | ||||||
|     } |  | ||||||
|   } else if (inputs.provenance || inputs.sbom) { |  | ||||||
|     core.warning("Attestations are only supported by buildx >= 0.10.0; the inputs 'provenance' and 'sbom' are ignored."); |  | ||||||
|   } |   } | ||||||
|   await Util.asyncForEach(inputs.secrets, async secret => { |   await Util.asyncForEach(inputs.secrets, async secret => { | ||||||
|     try { |     try { | ||||||
| @ -238,3 +214,52 @@ async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<st | |||||||
|   } |   } | ||||||
|   return args; |   return args; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | async function getAttestArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> { | ||||||
|  |   const args: Array<string> = []; | ||||||
|  | 
 | ||||||
|  |   // check if provenance attestation is set in attests input
 | ||||||
|  |   let hasAttestProvenance = false; | ||||||
|  |   await Util.asyncForEach(inputs.attests, async (attest: string) => { | ||||||
|  |     if (BuildxInputs.hasAttestationType('provenance', attest)) { | ||||||
|  |       hasAttestProvenance = true; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   let provenanceSet = false; | ||||||
|  |   let sbomSet = false; | ||||||
|  |   if (inputs.provenance) { | ||||||
|  |     args.push('--attest', BuildxInputs.resolveAttestationAttrs(`type=provenance,${inputs.provenance}`)); | ||||||
|  |     provenanceSet = true; | ||||||
|  |   } else if (!hasAttestProvenance && (await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !BuildxInputs.hasDockerExporter(inputs.outputs, inputs.load)) { | ||||||
|  |     // if provenance not specified in provenance or attests inputs and BuildKit
 | ||||||
|  |     // version compatible for attestation, set default provenance. Also needs
 | ||||||
|  |     // to make sure user doesn't want to explicitly load the image to docker.
 | ||||||
|  |     if (GitHub.context.payload.repository?.private ?? false) { | ||||||
|  |       // if this is a private repository, we set the default provenance
 | ||||||
|  |       // attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
 | ||||||
|  |       args.push('--attest', `type=provenance,${BuildxInputs.resolveProvenanceAttrs(`mode=min,inline-only=true`)}`); | ||||||
|  |     } else { | ||||||
|  |       // for a public repository, we set max provenance mode.
 | ||||||
|  |       args.push('--attest', `type=provenance,${BuildxInputs.resolveProvenanceAttrs(`mode=max`)}`); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   if (inputs.sbom) { | ||||||
|  |     args.push('--attest', BuildxInputs.resolveAttestationAttrs(`type=sbom,${inputs.sbom}`)); | ||||||
|  |     sbomSet = true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // set attests but check if provenance or sbom types already set as
 | ||||||
|  |   // provenance and sbom inputs take precedence over attests input.
 | ||||||
|  |   await Util.asyncForEach(inputs.attests, async (attest: string) => { | ||||||
|  |     if (!BuildxInputs.hasAttestationType('provenance', attest) && !BuildxInputs.hasAttestationType('sbom', attest)) { | ||||||
|  |       args.push('--attest', BuildxInputs.resolveAttestationAttrs(attest)); | ||||||
|  |     } else if (!provenanceSet && BuildxInputs.hasAttestationType('provenance', attest)) { | ||||||
|  |       args.push('--attest', BuildxInputs.resolveProvenanceAttrs(attest)); | ||||||
|  |     } else if (!sbomSet && BuildxInputs.hasAttestationType('sbom', attest)) { | ||||||
|  |       args.push('--attest', attest); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return args; | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 CrazyMax
						CrazyMax