Skip to content

Commit 91ff73e

Browse files
authored
Merge pull request #6051 from crazy-max/local-fix-platform-attestation
local: fix attestation filename
2 parents 0247e0d + 00f15ab commit 91ff73e

File tree

3 files changed

+261
-13
lines changed

3 files changed

+261
-13
lines changed

exporter/local/fs.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
180180
return nil, nil, err
181181
}
182182
stmtFS := staticfs.NewFS()
183-
split := opt.UsePlatformSplit(isMap)
183+
addPlatformToFilename := isMap && !opt.UsePlatformSplit(isMap)
184184

185185
names := map[string]struct{}{}
186186
for i, stmt := range stmts {
@@ -190,7 +190,7 @@ func CreateFS(ctx context.Context, sessionID string, k string, ref cache.Immutab
190190
}
191191

192192
name := opt.AttestationPrefix + path.Base(attestations[i].Path)
193-
if !split {
193+
if addPlatformToFilename {
194194
nameExt := path.Ext(name)
195195
namBase := strings.TrimSuffix(name, nameExt)
196196
name = fmt.Sprintf("%s.%s%s", namBase, strings.ReplaceAll(k, "/", "_"), nameExt)

frontend/dockerfile/dockerfile_provenance_test.go

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,30 @@ import (
4343
"github.com/tonistiigi/fsutil"
4444
)
4545

46+
var provenanceTests = integration.TestFuncs(
47+
testProvenanceAttestation,
48+
testGitProvenanceAttestation,
49+
testMultiPlatformProvenance,
50+
testClientFrontendProvenance,
51+
testClientLLBProvenance,
52+
testSecretSSHProvenance,
53+
testOCILayoutProvenance,
54+
testNilProvenance,
55+
testDuplicatePlatformProvenance,
56+
testDockerIgnoreMissingProvenance,
57+
testCommandSourceMapping,
58+
testFrontendDeduplicateSources,
59+
testDuplicateLayersProvenance,
60+
testProvenanceExportLocal,
61+
testProvenanceExportLocalForceSplit,
62+
testProvenanceExportLocalMultiPlatform,
63+
testProvenanceExportLocalMultiPlatformNoSplit,
64+
)
65+
66+
func init() {
67+
allTests = append(allTests, provenanceTests...)
68+
}
69+
4670
func testProvenanceAttestation(t *testing.T, sb integration.Sandbox) {
4771
workers.CheckFeatureCompat(t, sb, workers.FeatureDirectPush, workers.FeatureProvenance)
4872
ctx := sb.Context()
@@ -1735,3 +1759,238 @@ RUN date +%s > /b.txt
17351759
require.NotNil(t, layers)
17361760
require.Len(t, layers, 1)
17371761
}
1762+
1763+
func testProvenanceExportLocal(t *testing.T, sb integration.Sandbox) {
1764+
integration.SkipOnPlatform(t, "windows")
1765+
workers.CheckFeatureCompat(t, sb, workers.FeatureProvenance)
1766+
ctx := sb.Context()
1767+
1768+
c, err := client.New(ctx, sb.Address())
1769+
require.NoError(t, err)
1770+
defer c.Close()
1771+
1772+
f := getFrontend(t, sb)
1773+
1774+
dockerfile := []byte(`
1775+
FROM busybox:latest AS base
1776+
COPY <<EOF /out/foo
1777+
ok
1778+
EOF
1779+
1780+
FROM scratch
1781+
COPY --from=base /out /
1782+
`)
1783+
dir := integration.Tmpdir(
1784+
t,
1785+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
1786+
)
1787+
1788+
destDir := t.TempDir()
1789+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
1790+
LocalMounts: map[string]fsutil.FS{
1791+
dockerui.DefaultLocalNameDockerfile: dir,
1792+
dockerui.DefaultLocalNameContext: dir,
1793+
},
1794+
FrontendAttrs: map[string]string{
1795+
"attest:provenance": "mode=max",
1796+
},
1797+
Exports: []client.ExportEntry{
1798+
{
1799+
Type: client.ExporterLocal,
1800+
OutputDir: destDir,
1801+
},
1802+
},
1803+
}, nil)
1804+
require.NoError(t, err)
1805+
1806+
dt, err := os.ReadFile(filepath.Join(destDir, "foo"))
1807+
require.NoError(t, err)
1808+
require.Equal(t, "ok\n", string(dt))
1809+
1810+
dt, err = os.ReadFile(filepath.Join(destDir, "provenance.json"))
1811+
require.NoError(t, err)
1812+
require.NotEqual(t, 0, len(dt))
1813+
1814+
var pred provenancetypes.ProvenancePredicateSLSA02
1815+
require.NoError(t, json.Unmarshal(dt, &pred))
1816+
}
1817+
1818+
func testProvenanceExportLocalForceSplit(t *testing.T, sb integration.Sandbox) {
1819+
integration.SkipOnPlatform(t, "windows")
1820+
workers.CheckFeatureCompat(t, sb, workers.FeatureProvenance)
1821+
ctx := sb.Context()
1822+
1823+
c, err := client.New(ctx, sb.Address())
1824+
require.NoError(t, err)
1825+
defer c.Close()
1826+
1827+
f := getFrontend(t, sb)
1828+
1829+
dockerfile := []byte(`
1830+
FROM busybox:latest AS base
1831+
COPY <<EOF /out/foo
1832+
ok
1833+
EOF
1834+
1835+
FROM scratch
1836+
COPY --from=base /out /
1837+
`)
1838+
dir := integration.Tmpdir(
1839+
t,
1840+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
1841+
)
1842+
1843+
destDir := t.TempDir()
1844+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
1845+
LocalMounts: map[string]fsutil.FS{
1846+
dockerui.DefaultLocalNameDockerfile: dir,
1847+
dockerui.DefaultLocalNameContext: dir,
1848+
},
1849+
FrontendAttrs: map[string]string{
1850+
"attest:provenance": "mode=max",
1851+
},
1852+
Exports: []client.ExportEntry{
1853+
{
1854+
Type: client.ExporterLocal,
1855+
OutputDir: destDir,
1856+
Attrs: map[string]string{
1857+
"platform-split": "true",
1858+
},
1859+
},
1860+
},
1861+
}, nil)
1862+
require.NoError(t, err)
1863+
1864+
expPlatform := strings.ReplaceAll(platforms.FormatAll(platforms.DefaultSpec()), "/", "_")
1865+
1866+
dt, err := os.ReadFile(filepath.Join(destDir, expPlatform, "foo"))
1867+
require.NoError(t, err)
1868+
require.Equal(t, "ok\n", string(dt))
1869+
1870+
dt, err = os.ReadFile(filepath.Join(destDir, expPlatform, "provenance.json"))
1871+
require.NoError(t, err)
1872+
require.NotEqual(t, 0, len(dt))
1873+
1874+
var pred provenancetypes.ProvenancePredicateSLSA02
1875+
require.NoError(t, json.Unmarshal(dt, &pred))
1876+
}
1877+
1878+
func testProvenanceExportLocalMultiPlatform(t *testing.T, sb integration.Sandbox) {
1879+
integration.SkipOnPlatform(t, "windows")
1880+
workers.CheckFeatureCompat(t, sb, workers.FeatureMultiPlatform, workers.FeatureProvenance)
1881+
ctx := sb.Context()
1882+
1883+
c, err := client.New(ctx, sb.Address())
1884+
require.NoError(t, err)
1885+
defer c.Close()
1886+
1887+
f := getFrontend(t, sb)
1888+
1889+
dockerfile := []byte(`
1890+
FROM busybox:latest AS base
1891+
COPY <<EOF /out/foo
1892+
ok
1893+
EOF
1894+
1895+
FROM scratch
1896+
COPY --from=base /out /
1897+
`)
1898+
dir := integration.Tmpdir(
1899+
t,
1900+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
1901+
)
1902+
1903+
destDir := t.TempDir()
1904+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
1905+
LocalMounts: map[string]fsutil.FS{
1906+
dockerui.DefaultLocalNameDockerfile: dir,
1907+
dockerui.DefaultLocalNameContext: dir,
1908+
},
1909+
FrontendAttrs: map[string]string{
1910+
"attest:provenance": "mode=max",
1911+
"platform": "linux/amd64,linux/arm64",
1912+
},
1913+
Exports: []client.ExportEntry{
1914+
{
1915+
Type: client.ExporterLocal,
1916+
OutputDir: destDir,
1917+
},
1918+
},
1919+
}, nil)
1920+
require.NoError(t, err)
1921+
1922+
for _, platform := range []string{"linux_amd64", "linux_arm64"} {
1923+
dt, err := os.ReadFile(filepath.Join(destDir, platform, "foo"))
1924+
require.NoError(t, err)
1925+
require.Equal(t, "ok\n", string(dt))
1926+
1927+
dt, err = os.ReadFile(filepath.Join(destDir, platform, "provenance.json"))
1928+
require.NoError(t, err)
1929+
require.NotEqual(t, 0, len(dt))
1930+
1931+
var pred provenancetypes.ProvenancePredicateSLSA02
1932+
require.NoError(t, json.Unmarshal(dt, &pred))
1933+
}
1934+
}
1935+
1936+
func testProvenanceExportLocalMultiPlatformNoSplit(t *testing.T, sb integration.Sandbox) {
1937+
integration.SkipOnPlatform(t, "windows")
1938+
workers.CheckFeatureCompat(t, sb, workers.FeatureMultiPlatform, workers.FeatureProvenance)
1939+
ctx := sb.Context()
1940+
1941+
c, err := client.New(ctx, sb.Address())
1942+
require.NoError(t, err)
1943+
defer c.Close()
1944+
1945+
f := getFrontend(t, sb)
1946+
1947+
dockerfile := []byte(`
1948+
FROM busybox:latest AS base
1949+
ARG TARGETARCH
1950+
COPY <<EOF /out/foo_${TARGETARCH}
1951+
ok
1952+
EOF
1953+
1954+
FROM scratch
1955+
COPY --from=base /out /
1956+
`)
1957+
dir := integration.Tmpdir(
1958+
t,
1959+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
1960+
)
1961+
1962+
destDir := t.TempDir()
1963+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
1964+
LocalMounts: map[string]fsutil.FS{
1965+
dockerui.DefaultLocalNameDockerfile: dir,
1966+
dockerui.DefaultLocalNameContext: dir,
1967+
},
1968+
FrontendAttrs: map[string]string{
1969+
"attest:provenance": "mode=max",
1970+
"platform": "linux/amd64,linux/arm64",
1971+
},
1972+
Exports: []client.ExportEntry{
1973+
{
1974+
Type: client.ExporterLocal,
1975+
OutputDir: destDir,
1976+
Attrs: map[string]string{
1977+
"platform-split": "false",
1978+
},
1979+
},
1980+
},
1981+
}, nil)
1982+
require.NoError(t, err)
1983+
1984+
for _, arch := range []string{"amd64", "arm64"} {
1985+
dt, err := os.ReadFile(filepath.Join(destDir, "foo_"+arch))
1986+
require.NoError(t, err)
1987+
require.Equal(t, "ok\n", string(dt))
1988+
1989+
dt, err = os.ReadFile(filepath.Join(destDir, "provenance.linux_"+arch+".json"))
1990+
require.NoError(t, err)
1991+
require.NotEqual(t, 0, len(dt))
1992+
1993+
var pred provenancetypes.ProvenancePredicateSLSA02
1994+
require.NoError(t, json.Unmarshal(dt, &pred))
1995+
}
1996+
}

frontend/dockerfile/dockerfile_test.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,6 @@ var allTests = integration.TestFuncs(
189189
testDockerfileAddChownExpand,
190190
testSourceDateEpochWithoutExporter,
191191
testSBOMScannerImage,
192-
testProvenanceAttestation,
193-
testGitProvenanceAttestation,
194-
testMultiPlatformProvenance,
195-
testClientFrontendProvenance,
196-
testClientLLBProvenance,
197-
testSecretSSHProvenance,
198-
testOCILayoutProvenance,
199-
testNilProvenance,
200-
testDuplicatePlatformProvenance,
201-
testDockerIgnoreMissingProvenance,
202-
testCommandSourceMapping,
203192
testSBOMScannerArgs,
204193
testMultiNilRefsOCIExporter,
205194
testNilContextInSolveGateway,

0 commit comments

Comments
 (0)