@@ -58,6 +58,7 @@ import (
5858 "github.com/moby/buildkit/session/secrets/secretsprovider"
5959 "github.com/moby/buildkit/session/sshforward/sshprovider"
6060 "github.com/moby/buildkit/solver/errdefs"
61+ provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
6162 "github.com/moby/buildkit/solver/pb"
6263 "github.com/moby/buildkit/solver/result"
6364 "github.com/moby/buildkit/sourcepolicy"
@@ -237,6 +238,7 @@ var allTests = []func(t *testing.T, sb integration.Sandbox){
237238 testRegistryEmptyCacheExport ,
238239 testSnapshotWithMultipleBlobs ,
239240 testImageBlobSource ,
241+ testOCILayoutBlobSource ,
240242 testExportLocalNoPlatformSplit ,
241243 testExportLocalNoPlatformSplitOverwrite ,
242244 testExportLocalForcePlatformSplit ,
@@ -758,6 +760,9 @@ func testExportBusyboxLocal(t *testing.T, sb integration.Sandbox) {
758760 destDir := t .TempDir ()
759761
760762 _ , err = c .Solve (sb .Context (), def , SolveOpt {
763+ FrontendAttrs : map [string ]string {
764+ "attest:provenance" : "" ,
765+ },
761766 Exports : []ExportEntry {
762767 {
763768 Type : ExporterLocal ,
@@ -11597,12 +11602,8 @@ func testImageBlobSource(t *testing.T, sb integration.Sandbox) {
1159711602 require .NoError (t , err )
1159811603
1159911604 var stmt struct {
11600- Predicate struct {
11601- Materials []struct {
11602- URI string `json:"uri"`
11603- Digest map [string ]string `json:"digest"`
11604- } `json:"materials"`
11605- } `json:"predicate"`
11605+ intoto.StatementHeader
11606+ Predicate provenancetypes.ProvenancePredicateSLSA02 `json:"predicate"`
1160611607 }
1160711608 require .NoError (t , json .Unmarshal (provDt , & stmt ))
1160811609
@@ -11624,6 +11625,109 @@ func testImageBlobSource(t *testing.T, sb integration.Sandbox) {
1162411625 require .True (t , found , "expected to find %q in %+v" , expectedName , stmt .Predicate .Materials )
1162511626}
1162611627
11628+ func testOCILayoutBlobSource (t * testing.T , sb integration.Sandbox ) {
11629+ workers .CheckFeatureCompat (t , sb , workers .FeatureOCIExporter , workers .FeatureOCILayout )
11630+ requiresLinux (t )
11631+ c , err := New (sb .Context (), sb .Address ())
11632+ require .NoError (t , err )
11633+ defer c .Close ()
11634+
11635+ st := llb .Image ("alpine" )
11636+ def , err := st .Marshal (sb .Context ())
11637+ require .NoError (t , err )
11638+
11639+ ociDir := t .TempDir ()
11640+ _ , err = c .Solve (sb .Context (), def , SolveOpt {
11641+ Exports : []ExportEntry {
11642+ {
11643+ Type : ExporterOCI ,
11644+ Attrs : map [string ]string {
11645+ "tar" : "false" ,
11646+ },
11647+ OutputDir : ociDir ,
11648+ },
11649+ },
11650+ }, nil )
11651+ require .NoError (t , err )
11652+
11653+ indexDt , err := os .ReadFile (filepath .Join (ociDir , ocispecs .ImageIndexFile ))
11654+ require .NoError (t , err )
11655+
11656+ var index ocispecs.Index
11657+ err = json .Unmarshal (indexDt , & index )
11658+ require .NoError (t , err )
11659+ require .Equal (t , 1 , len (index .Manifests ))
11660+
11661+ var mfst ocispecs.Manifest
11662+ mfstDt , err := os .ReadFile (filepath .Join (ociDir , "blobs/sha256" , index .Manifests [0 ].Digest .Hex ()))
11663+ require .NoError (t , err )
11664+ err = json .Unmarshal (mfstDt , & mfst )
11665+ require .NoError (t , err )
11666+ require .GreaterOrEqual (t , len (mfst .Layers ), 1 )
11667+ layer := mfst .Layers [0 ]
11668+
11669+ store , err := local .NewStore (ociDir )
11670+ require .NoError (t , err )
11671+ csID := "my-blob-content-store"
11672+
11673+ blob := llb .OCILayoutBlob ("not/real@" + layer .Digest .String (), llb .ImageBlobOCIStore ("" , csID ), llb .Filename ("layer.tar.gz" ), llb .Chown (123 , 456 ))
11674+ st = llb .Image ("alpine" ).Run (llb .Shlex (`sh -c 'sha256sum /layers/layer.tar.gz | cut -d" " -f0 > /out/checksum && stat -c "%u-%g-%s" /layers/layer.tar.gz > /out/stat'` ), llb .AddMount ("/layers" , blob , llb .Readonly )).AddMount ("/out" , llb .Scratch ())
11675+
11676+ def , err = st .Marshal (sb .Context ())
11677+ require .NoError (t , err )
11678+
11679+ destDir := t .TempDir ()
11680+ _ , err = c .Solve (sb .Context (), def , SolveOpt {
11681+ FrontendAttrs : map [string ]string {
11682+ "attest:provenance" : "" ,
11683+ },
11684+ Exports : []ExportEntry {
11685+ {
11686+ Type : ExporterLocal ,
11687+ OutputDir : destDir ,
11688+ },
11689+ },
11690+ OCIStores : map [string ]content.Store {
11691+ csID : store ,
11692+ },
11693+ }, nil )
11694+ require .NoError (t , err )
11695+
11696+ dt , err := os .ReadFile (filepath .Join (destDir , "stat" ))
11697+ require .NoError (t , err )
11698+ require .Equal (t , "123-456-" + strconv .FormatInt (layer .Size , 10 ), strings .TrimSpace (string (dt )))
11699+
11700+ dt , err = os .ReadFile (filepath .Join (destDir , "checksum" ))
11701+ require .NoError (t , err )
11702+ require .Equal (t , layer .Digest .Hex (), strings .TrimSpace (string (dt )))
11703+
11704+ provDt , err := os .ReadFile (filepath .Join (destDir , "provenance.json" ))
11705+ require .NoError (t , err )
11706+
11707+ var stmt struct {
11708+ intoto.StatementHeader
11709+ Predicate provenancetypes.ProvenancePredicateSLSA02 `json:"predicate"`
11710+ }
11711+ require .NoError (t , json .Unmarshal (provDt , & stmt ))
11712+
11713+ expectedName , err := purl .RefToPURL (packageurl .TypeOCI , "not/real@" + layer .Digest .String (), nil )
11714+ require .NoError (t , err )
11715+ purlObj , err := packageurl .FromString (expectedName )
11716+ require .NoError (t , err )
11717+ purlObj .Qualifiers = append (purlObj .Qualifiers , packageurl.Qualifier {Key : "ref_type" , Value : "blob" })
11718+ expectedName = purlObj .ToString ()
11719+
11720+ found := false
11721+ for _ , m := range stmt .Predicate .Materials {
11722+ if m .URI == expectedName {
11723+ found = true
11724+ require .Equal (t , layer .Digest .Hex (), m .Digest ["sha256" ])
11725+ break
11726+ }
11727+ }
11728+ require .True (t , found , "expected to find %q in %+v" , expectedName , stmt .Predicate .Materials )
11729+ }
11730+
1162711731func testFrontendVerifyPlatforms (t * testing.T , sb integration.Sandbox ) {
1162811732 c , err := New (sb .Context (), sb .Address ())
1162911733 require .NoError (t , err )
0 commit comments