Skip to content

Commit

Permalink
exporter: add validation for platforms key value
Browse files Browse the repository at this point in the history
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 432ece72ae124ce8a29ced6854a08206f09f3a73)
(cherry picked from commit e4bd60baf77b4ec92aba60f568831fb3076fc158)
  • Loading branch information
tonistiigi committed Jan 31, 2024
1 parent 481d9c4 commit 96663dd
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
2 changes: 2 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ func TestIntegration(t *testing.T) {
testExportLocalNoPlatformSplitOverwrite,
testValidateNullConfig,
testValidateInvalidConfig,
testValidatePlatformsEmpty,
testValidatePlatformsInvalid,
)
}

Expand Down
108 changes: 108 additions & 0 deletions client/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/frontend/gateway/client"
"github.com/moby/buildkit/util/testutil/integration"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -96,3 +97,110 @@ func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) {
require.Error(t, err)
require.Contains(t, err.Error(), "invalid image config for export: missing os")
}

func testValidatePlatformsEmpty(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)

ctx := sb.Context()

c, err := New(ctx, sb.Address())
require.NoError(t, err)
defer c.Close()

b := func(ctx context.Context, c client.Client) (*client.Result, error) {
def, err := llb.Scratch().Marshal(ctx)
if err != nil {
return nil, err
}

res, err := c.Solve(ctx, client.SolveRequest{
Evaluate: true,
Definition: def.ToPB(),
})
if err != nil {
return nil, err
}
res.AddMeta("refs.platforms", []byte("null"))
return res, nil
}

_, err = c.Build(ctx, SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterOCI,
Output: fixedWriteCloser(nopWriteCloser{io.Discard}),
},
},
}, "", b, nil)
require.Error(t, err)
require.Contains(t, err.Error(), "invalid empty platforms index for exporter")
}

func testValidatePlatformsInvalid(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)

ctx := sb.Context()

c, err := New(ctx, sb.Address())
require.NoError(t, err)
defer c.Close()

tcases := []struct {
name string
value []exptypes.Platform
exp string
}{
{
name: "emptyID",
value: []exptypes.Platform{{}},
exp: "invalid empty platform key for exporter",
},
{
name: "missingOS",
value: []exptypes.Platform{
{
ID: "foo",
},
},
exp: "invalid platform value",
},
}

for _, tc := range tcases {
t.Run(tc.name, func(t *testing.T) {
b := func(ctx context.Context, c client.Client) (*client.Result, error) {
def, err := llb.Scratch().Marshal(ctx)
if err != nil {
return nil, err
}

res, err := c.Solve(ctx, client.SolveRequest{
Evaluate: true,
Definition: def.ToPB(),
})
if err != nil {
return nil, err
}

dt, err := json.Marshal(exptypes.Platforms{Platforms: tc.value})
if err != nil {
return nil, err
}

res.AddMeta("refs.platforms", dt)
return res, nil
}

_, err = c.Build(ctx, SolveOpt{
Exports: []ExportEntry{
{
Type: ExporterOCI,
Output: fixedWriteCloser(nopWriteCloser{io.Discard}),
},
},
}, "", b, nil)
require.Error(t, err)
require.Contains(t, err.Error(), tc.exp)
})
}
}
14 changes: 14 additions & 0 deletions exporter/containerimage/exptypes/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
return Platforms{}, errors.Wrapf(err, "failed to parse platforms passed to provenance processor")
}
}
if len(ps.Platforms) == 0 {
return Platforms{}, errors.Errorf("invalid empty platforms index for exporter")
}
for i, p := range ps.Platforms {
if p.ID == "" {
return Platforms{}, errors.Errorf("invalid empty platform key for exporter")
}
if p.Platform.OS == "" || p.Platform.Architecture == "" {
return Platforms{}, errors.Errorf("invalid platform value %v for exporter", p.Platform)
}
ps.Platforms[i].Platform = platforms.Normalize(p.Platform)
}
return ps, nil
}

Expand All @@ -36,6 +48,8 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
OSFeatures: img.OSFeatures,
Variant: img.Variant,
}
} else if img.OS != "" || img.Architecture != "" {
return Platforms{}, errors.Errorf("invalid image config: os and architecture must be specified together")
}
}
p = platforms.Normalize(p)
Expand Down

0 comments on commit 96663dd

Please sign in to comment.