Skip to content

Commit 9bc425a

Browse files
committed
tests: add test to check url format for image loaded from oci layout
Signed-off-by: Justin Chadwell <[email protected]>
1 parent 667bb72 commit 9bc425a

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

frontend/dockerfile/dockerfile_provenance_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,23 @@ package dockerfile
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67
"net/http"
78
"net/http/httptest"
89
"net/url"
10+
"os"
911
"os/exec"
1012
"path/filepath"
1113
"strings"
1214
"testing"
1315
"time"
1416

17+
"github.com/containerd/containerd/content"
18+
"github.com/containerd/containerd/content/local"
1519
"github.com/containerd/containerd/platforms"
1620
"github.com/containerd/continuity/fs/fstest"
1721
intoto "github.com/in-toto/in-toto-golang/in_toto"
22+
provenanceCommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
1823
"github.com/moby/buildkit/client"
1924
"github.com/moby/buildkit/client/llb"
2025
"github.com/moby/buildkit/exporter/containerimage/exptypes"
@@ -871,6 +876,141 @@ RUN --mount=type=secret,id=mysecret --mount=type=secret,id=othersecret --mount=t
871876
require.True(t, pred.Invocation.Parameters.SSH[0].Optional)
872877
}
873878

879+
func testOCILayoutProvenance(t *testing.T, sb integration.Sandbox) {
880+
integration.CheckFeatureCompat(t, sb, integration.FeatureProvenance)
881+
ctx := sb.Context()
882+
883+
c, err := client.New(ctx, sb.Address())
884+
require.NoError(t, err)
885+
defer c.Close()
886+
887+
registry, err := sb.NewRegistry()
888+
if errors.Is(err, integration.ErrRequirements) {
889+
t.Skip(err.Error())
890+
}
891+
require.NoError(t, err)
892+
target := registry + "/buildkit/clientprovenance:ocilayout"
893+
894+
f := getFrontend(t, sb)
895+
_, isGateway := f.(*gatewayFrontend)
896+
897+
ocidir := t.TempDir()
898+
ociDockerfile := []byte(`
899+
FROM scratch
900+
COPY <<EOF /foo
901+
foo
902+
EOF
903+
`)
904+
dir, err := integration.Tmpdir(
905+
t,
906+
fstest.CreateFile("Dockerfile", ociDockerfile, 0600),
907+
)
908+
require.NoError(t, err)
909+
910+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
911+
LocalDirs: map[string]string{
912+
dockerui.DefaultLocalNameDockerfile: dir,
913+
dockerui.DefaultLocalNameContext: dir,
914+
},
915+
Exports: []client.ExportEntry{
916+
{
917+
Type: client.ExporterOCI,
918+
OutputDir: ocidir,
919+
Attrs: map[string]string{
920+
"tar": "false",
921+
},
922+
},
923+
},
924+
}, nil)
925+
require.NoError(t, err)
926+
927+
var index ocispecs.Index
928+
dt, err := os.ReadFile(filepath.Join(ocidir, "index.json"))
929+
require.NoError(t, err)
930+
err = json.Unmarshal(dt, &index)
931+
require.NoError(t, err)
932+
require.Equal(t, 1, len(index.Manifests))
933+
digest := index.Manifests[0].Digest.Hex()
934+
935+
store, err := local.NewStore(ocidir)
936+
require.NoError(t, err)
937+
ociID := "ocione"
938+
939+
dockerfile := []byte(`
940+
FROM foo
941+
COPY <<EOF /bar
942+
bar
943+
EOF
944+
`)
945+
dir, err = integration.Tmpdir(
946+
t,
947+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
948+
)
949+
require.NoError(t, err)
950+
951+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
952+
LocalDirs: map[string]string{
953+
dockerui.DefaultLocalNameDockerfile: dir,
954+
dockerui.DefaultLocalNameContext: dir,
955+
},
956+
FrontendAttrs: map[string]string{
957+
"context:foo": fmt.Sprintf("oci-layout:%s@sha256:%s", ociID, digest),
958+
"attest:provenance": "mode=max",
959+
},
960+
OCIStores: map[string]content.Store{
961+
ociID: store,
962+
},
963+
Exports: []client.ExportEntry{
964+
{
965+
Type: client.ExporterImage,
966+
Attrs: map[string]string{
967+
"name": target,
968+
"push": "true",
969+
},
970+
},
971+
},
972+
}, nil)
973+
require.NoError(t, err)
974+
975+
desc, provider, err := contentutil.ProviderFromRef(target)
976+
require.NoError(t, err)
977+
imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
978+
require.NoError(t, err)
979+
require.Equal(t, 2, len(imgs.Images))
980+
981+
expPlatform := platforms.Format(platforms.Normalize(platforms.DefaultSpec()))
982+
983+
img := imgs.Find(expPlatform)
984+
require.NotNil(t, img)
985+
require.Equal(t, []byte("foo\n"), img.Layers[0]["foo"].Data)
986+
require.Equal(t, []byte("bar\n"), img.Layers[1]["bar"].Data)
987+
988+
att := imgs.FindAttestation(expPlatform)
989+
type stmtT struct {
990+
Predicate provenance.ProvenancePredicate `json:"predicate"`
991+
}
992+
var stmt stmtT
993+
require.NoError(t, json.Unmarshal(att.LayersRaw[0], &stmt))
994+
pred := stmt.Predicate
995+
996+
if isGateway {
997+
require.Len(t, pred.Materials, 2)
998+
} else {
999+
require.Len(t, pred.Materials, 1)
1000+
}
1001+
var material *provenanceCommon.ProvenanceMaterial
1002+
for _, m := range pred.Materials {
1003+
if strings.Contains(m.URI, "/foo") {
1004+
require.Nil(t, material, pred.Materials)
1005+
material = &m
1006+
}
1007+
}
1008+
require.NotNil(t, material)
1009+
prefix, _, _ := strings.Cut(material.URI, "/")
1010+
require.Equal(t, "pkg:oci", prefix)
1011+
require.Equal(t, digest, material.Digest["sha256"])
1012+
}
1013+
8741014
func testNilProvenance(t *testing.T, sb integration.Sandbox) {
8751015
integration.CheckFeatureCompat(t, sb, integration.FeatureProvenance)
8761016
ctx := sb.Context()

frontend/dockerfile/dockerfile_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ var allTests = integration.TestFuncs(
161161
testClientFrontendProvenance,
162162
testClientLLBProvenance,
163163
testSecretSSHProvenance,
164+
testOCILayoutProvenance,
164165
testNilProvenance,
165166
testSBOMScannerArgs,
166167
testMultiPlatformWarnings,

0 commit comments

Comments
 (0)