Merge pull request #3738 from tonistiigi/policy-eval-upt
Updated for policy eval
This commit is contained in:
+43
-23
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"maps"
|
||||
"os"
|
||||
@@ -33,6 +34,7 @@ type evalOpts struct {
|
||||
filename string
|
||||
printOutput bool
|
||||
fields []string
|
||||
platform string
|
||||
builder *string
|
||||
}
|
||||
|
||||
@@ -49,9 +51,14 @@ func evalCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
|
||||
return runEval(cmd.Context(), dockerCli, args[0], opts)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&opts.filename, "filename", "Dockerfile", "Policy filename to evaluate")
|
||||
cmd.Flags().BoolVar(&opts.printOutput, "print", false, "Print policy output")
|
||||
cmd.Flags().StringSliceVar(&opts.fields, "fields", nil, "Fields to evaluate")
|
||||
flags := cmd.Flags()
|
||||
flags.StringVarP(&opts.filename, "file", "f", "Dockerfile", "Policy filename to evaluate")
|
||||
flags.BoolVar(&opts.printOutput, "print", false, "Print policy output")
|
||||
flags.StringSliceVar(&opts.fields, "fields", nil, "Fields to evaluate")
|
||||
flags.StringVar(&opts.platform, "platform", "", "Target platform for policy evaluation")
|
||||
// Deprecated: use --file instead
|
||||
flags.StringVar(&opts.filename, "filename", "Dockerfile", "Policy filename to evaluate")
|
||||
flags.MarkHidden("filename")
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -81,29 +88,29 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
|
||||
return err
|
||||
}
|
||||
|
||||
workers, err := c.ListWorkers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var p ocispecs.Platform
|
||||
if opts.platform != "" {
|
||||
parsedPlatform, err := parsePlatform(opts.platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p = *parsedPlatform
|
||||
} else {
|
||||
workers, err := c.ListWorkers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(workers) == 0 {
|
||||
return errors.New("no workers available in the builder")
|
||||
}
|
||||
if len(workers) == 0 {
|
||||
return errors.New("no workers available in the builder")
|
||||
}
|
||||
|
||||
defaultPlatform := workers[0].Platforms[0]
|
||||
p := ocispecs.Platform{
|
||||
Architecture: defaultPlatform.Architecture,
|
||||
OS: defaultPlatform.OS,
|
||||
Variant: defaultPlatform.Variant,
|
||||
p = workers[0].Platforms[0]
|
||||
}
|
||||
metaResolver := sourcemeta.NewResolver(c)
|
||||
defer metaResolver.Close()
|
||||
|
||||
platform := &pb.Platform{
|
||||
Architecture: p.Architecture,
|
||||
OS: p.OS,
|
||||
Variant: p.Variant,
|
||||
}
|
||||
platform := toPBPlatform(p)
|
||||
verifier := policy.SignatureVerifier(confutil.NewConfig(dockerCli))
|
||||
|
||||
if opts.printOutput {
|
||||
@@ -185,9 +192,8 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
|
||||
if opts.filename == "" {
|
||||
return errors.New("filename is required")
|
||||
}
|
||||
policyName := opts.filename
|
||||
policyFile := policyName + ".rego"
|
||||
policyData, err := os.ReadFile(policyFile)
|
||||
policyName, policyFile := policyFileNames(opts.filename)
|
||||
policyData, err := readPolicyData(policyFile, os.Stdin)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read policy file %s", policyFile)
|
||||
}
|
||||
@@ -261,6 +267,20 @@ func runEval(ctx context.Context, dockerCli command.Cli, source string, opts eva
|
||||
}
|
||||
}
|
||||
|
||||
func policyFileNames(filename string) (string, string) {
|
||||
if filename == "-" {
|
||||
return "stdin", filename
|
||||
}
|
||||
return filename, filename + ".rego"
|
||||
}
|
||||
|
||||
func readPolicyData(filename string, stdin io.Reader) ([]byte, error) {
|
||||
if filename == "-" {
|
||||
return io.ReadAll(stdin)
|
||||
}
|
||||
return os.ReadFile(filename)
|
||||
}
|
||||
|
||||
func selectReloadFields(fields []string, unknowns []string) ([]string, []string) {
|
||||
if len(fields) == 0 {
|
||||
return nil, nil
|
||||
|
||||
@@ -6,10 +6,39 @@ import (
|
||||
policytypes "github.com/docker/buildx/policy"
|
||||
"github.com/docker/buildx/util/sourcemeta"
|
||||
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
|
||||
"github.com/moby/buildkit/solver/pb"
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParsePlatform(t *testing.T) {
|
||||
t.Run("normalize", func(t *testing.T) {
|
||||
platform, err := parsePlatform("linux/arm/v7")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &ocispecs.Platform{
|
||||
OS: "linux",
|
||||
Architecture: "arm",
|
||||
Variant: "v7",
|
||||
}, platform)
|
||||
})
|
||||
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
platform, err := parsePlatform("not-a-platform")
|
||||
require.Nil(t, platform)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "invalid platform \"not-a-platform\"")
|
||||
require.ErrorContains(t, err, "unknown operating system or architecture")
|
||||
})
|
||||
}
|
||||
|
||||
func TestToPBPlatform(t *testing.T) {
|
||||
platform := ocispecs.Platform{OS: "linux", Architecture: "amd64"}
|
||||
require.Equal(t, &pb.Platform{
|
||||
OS: "linux",
|
||||
Architecture: "amd64",
|
||||
}, toPBPlatform(platform))
|
||||
}
|
||||
|
||||
func TestSourceResolverOptIncludesResolveAttestations(t *testing.T) {
|
||||
req := &gwpb.ResolveSourceMetaRequest{
|
||||
ResolveMode: "default",
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/moby/buildkit/solver/pb"
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func parsePlatform(platform string) (*ocispecs.Platform, error) {
|
||||
p, err := platforms.Parse(platform)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "invalid platform %q", platform)
|
||||
}
|
||||
p = platforms.Normalize(p)
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func toPBPlatform(platform ocispecs.Platform) *pb.Platform {
|
||||
return &pb.Platform{
|
||||
Architecture: platform.Architecture,
|
||||
OS: platform.OS,
|
||||
Variant: platform.Variant,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user