From 83f5c4ff1faa07f87db8af898d516908050fd7d3 Mon Sep 17 00:00:00 2001 From: Becky HD Date: Fri, 4 Feb 2022 11:26:07 -0800 Subject: [PATCH] Provide driver AddConstraint and RemoveConstraint (#170) (#182) * provide driver AddConstraint and RemoveConstraint (#170) Signed-off-by: Becky Huang * unit tests for Driver.AddConstraint (#170) Signed-off-by: Becky Huang * No error returns for removing a non-matching constraint (#170) Signed-off-by: Becky Huang * provide driver AddConstraint and RemoveConstraint (#170) Signed-off-by: Becky Huang * provide driver AddConstraint and RemoveConstraint (#170) Signed-off-by: Becky Huang * unit tests for Driver.AddConstraint (#170) Signed-off-by: Becky Huang * No error returns for removing a non-matching constraint (#170) Signed-off-by: Becky Huang * Protect d.templateHandler read/write/delete with mutex, fix test(#170) Signed-off-by: Becky Huang * gvk group check for constraint Signed-off-by: Becky Huang * provide driver AddConstraint and RemoveConstraint (#170) Signed-off-by: Becky Huang * provide driver AddConstraint and RemoveConstraint (#170) Signed-off-by: Becky Huang * unit tests for Driver.AddConstraint (#170) Signed-off-by: Becky Huang * No error returns for removing a non-matching constraint (#170) Signed-off-by: Becky Huang * Protect d.templateHandler read/write/delete with mutex, fix test(#170) Signed-off-by: Becky Huang * gvk group check for constraint Signed-off-by: Becky Huang Co-authored-by: Will Beason --- constraint/pkg/client/client.go | 61 +---- .../client/client_addconstraint_bench_test.go | 4 +- .../pkg/client/client_audit_benchmark_test.go | 12 +- .../client/client_review_benchmark_test.go | 18 +- constraint/pkg/client/client_test.go | 32 +-- .../clienttest/{ => cts}/constraints.go | 2 +- constraint/pkg/client/clienttest/cts/opts.go | 11 +- constraint/pkg/client/drivers/interface.go | 5 + constraint/pkg/client/drivers/local/args.go | 4 +- constraint/pkg/client/drivers/local/local.go | 138 ++++++++++- .../client/drivers/local/local_unit_test.go | 223 ++++++++++++++---- .../pkg/client/drivers/remote/remote.go | 12 +- constraint/pkg/client/e2e_test.go | 74 +++--- constraint/pkg/client/errors/errors.go | 2 + 14 files changed, 422 insertions(+), 176 deletions(-) rename constraint/pkg/client/clienttest/{ => cts}/constraints.go (98%) diff --git a/constraint/pkg/client/client.go b/constraint/pkg/client/client.go index 07cb96c27..dee7a59d8 100644 --- a/constraint/pkg/client/client.go +++ b/constraint/pkg/client/client.go @@ -37,8 +37,9 @@ type Client struct { targets map[string]handler.TargetHandler // mtx guards access to both templates and constraints. - mtx sync.RWMutex - templates map[templateKey]*templateEntry + mtx sync.RWMutex + templates map[templateKey]*templateEntry + // TODO: https://github.com/open-policy-agent/frameworks/issues/187 constraints map[schema.GroupKind]map[string]*unstructured.Unstructured AllowedDataFields []string @@ -414,15 +415,6 @@ func createConstraintGKPath(target string, gk schema.GroupKind) string { return constraintPathMerge(target, createConstraintGKSubPath(gk)) } -// createConstraintPath returns the storage path for a given constraint: constraints..cluster.... -func createConstraintPath(target string, constraint *unstructured.Unstructured) (string, error) { - p, err := createConstraintSubPath(constraint) - if err != nil { - return "", err - } - return constraintPathMerge(target, p), nil -} - // constraintPathMerge is a shared function for creating constraint paths to // ensure uniformity, it is not meant to be called directly. func constraintPathMerge(target, subpath string) string { @@ -470,7 +462,6 @@ func (c *Client) AddConstraint(ctx context.Context, constraint *unstructured.Uns defer c.mtx.Unlock() resp := types.NewResponses() - errMap := make(clienterrors.ErrorMap) entry, err := c.getTemplateEntry(constraint, false) if err != nil { return resp, err @@ -493,27 +484,14 @@ func (c *Client) AddConstraint(ctx context.Context, constraint *unstructured.Uns if err := c.validateConstraint(constraint, false); err != nil { return resp, err } + if err := c.backend.driver.AddConstraint(ctx, constraint); err != nil { + return resp, err + } for _, target := range entry.Targets { - relPath, err := createConstraintPath(target, constraint) - // If we ever create multi-target constraints we will need to handle this more cleverly. - // the short-circuiting question, cleanup, etc. - if err != nil { - errMap[target] = err - continue - } - if err := c.backend.driver.PutData(ctx, relPath, constraint.Object); err != nil { - errMap[target] = err - continue - } resp.Handled[target] = true } - - if len(errMap) == 0 { - c.constraints[constraint.GroupVersionKind().GroupKind()][subPath] = constraint.DeepCopy() - return resp, nil - } - - return resp, &errMap + c.constraints[constraint.GroupVersionKind().GroupKind()][subPath] = constraint.DeepCopy() + return resp, nil } // RemoveConstraint removes a constraint from OPA. On error, the responses @@ -527,7 +505,6 @@ func (c *Client) RemoveConstraint(ctx context.Context, constraint *unstructured. func (c *Client) removeConstraintNoLock(ctx context.Context, constraint *unstructured.Unstructured) (*types.Responses, error) { resp := types.NewResponses() - errMap := make(clienterrors.ErrorMap) entry, err := c.getTemplateEntry(constraint, false) if err != nil { return resp, err @@ -536,26 +513,14 @@ func (c *Client) removeConstraintNoLock(ctx context.Context, constraint *unstruc if err != nil { return resp, err } + if err := c.backend.driver.RemoveConstraint(ctx, constraint); err != nil { + return resp, err + } for _, target := range entry.Targets { - relPath, err := createConstraintPath(target, constraint) - // If we ever create multi-target constraints we will need to handle this more cleverly. - // the short-circuiting question, cleanup, etc. - if err != nil { - errMap[target] = err - continue - } - if _, err := c.backend.driver.DeleteData(ctx, relPath); err != nil { - errMap[target] = err - } resp.Handled[target] = true } - if len(errMap) == 0 { - // If we ever create multi-target constraints we will need to handle this more cleverly. - // the short-circuiting question, cleanup, etc. - delete(c.constraints[constraint.GroupVersionKind().GroupKind()], subPath) - return resp, nil - } - return resp, &errMap + delete(c.constraints[constraint.GroupVersionKind().GroupKind()], subPath) + return resp, nil } // getConstraintNoLock gets the currently recognized constraint without the lock. diff --git a/constraint/pkg/client/client_addconstraint_bench_test.go b/constraint/pkg/client/client_addconstraint_bench_test.go index c65ffe130..c9861c3f6 100644 --- a/constraint/pkg/client/client_addconstraint_bench_test.go +++ b/constraint/pkg/client/client_addconstraint_bench_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest/cts" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest" ) @@ -22,7 +24,7 @@ func BenchmarkClient_AddConstraint(b *testing.B) { for i := 0; i < b.N; i++ { name := fmt.Sprintf("foo-%d", i) - constraint := clienttest.MakeConstraint(b, clienttest.KindCheckData, name, clienttest.WantData("bar")) + constraint := cts.MakeConstraint(b, clienttest.KindCheckData, name, cts.WantData("bar")) _, err = c.AddConstraint(ctx, constraint) if err != nil { diff --git a/constraint/pkg/client/client_audit_benchmark_test.go b/constraint/pkg/client/client_audit_benchmark_test.go index 3ecdd0f04..7aece7973 100644 --- a/constraint/pkg/client/client_audit_benchmark_test.go +++ b/constraint/pkg/client/client_audit_benchmark_test.go @@ -6,6 +6,8 @@ import ( "strings" "testing" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest/cts" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest" "github.com/open-policy-agent/frameworks/constraint/pkg/handler/handlertest" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -19,7 +21,7 @@ func BenchmarkClient_Audit(b *testing.B) { }{{ name: "success", makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, clienttest.WantData("bar")) + return cts.MakeConstraint(b, makeKind(tid), name, cts.WantData("bar")) }, makeObject: func(oid int) *handlertest.Object { name := fmt.Sprintf("has-foo-%d", oid) @@ -31,7 +33,7 @@ func BenchmarkClient_Audit(b *testing.B) { }, { name: "fail", makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, clienttest.WantData("bar")) + return cts.MakeConstraint(b, makeKind(tid), name, cts.WantData("bar")) }, makeObject: func(oid int) *handlertest.Object { name := fmt.Sprintf("has-foo-%d", oid) @@ -43,9 +45,9 @@ func BenchmarkClient_Audit(b *testing.B) { }, { name: "filtered out", makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, - clienttest.WantData("bar"), - clienttest.MatchNamespace("zab")) + return cts.MakeConstraint(b, makeKind(tid), name, + cts.WantData("bar"), + cts.MatchNamespace("zab")) }, makeObject: func(oid int) *handlertest.Object { name := fmt.Sprintf("has-foo-%d", oid) diff --git a/constraint/pkg/client/client_review_benchmark_test.go b/constraint/pkg/client/client_review_benchmark_test.go index d5d2f7928..1d6ff2313 100644 --- a/constraint/pkg/client/client_review_benchmark_test.go +++ b/constraint/pkg/client/client_review_benchmark_test.go @@ -6,6 +6,8 @@ import ( "strings" "testing" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest/cts" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest" "github.com/open-policy-agent/frameworks/constraint/pkg/handler/handlertest" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -25,7 +27,7 @@ func BenchmarkClient_Review(b *testing.B) { }, }, makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, clienttest.WantData("bar")) + return cts.MakeConstraint(b, makeKind(tid), name, cts.WantData("bar")) }, }, { name: "fail", @@ -36,7 +38,7 @@ func BenchmarkClient_Review(b *testing.B) { }, }, makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, clienttest.WantData("bar")) + return cts.MakeConstraint(b, makeKind(tid), name, cts.WantData("bar")) }, }, { name: "filtered out", @@ -48,9 +50,9 @@ func BenchmarkClient_Review(b *testing.B) { }, }, makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, - clienttest.WantData("bar"), - clienttest.MatchNamespace("zab")) + return cts.MakeConstraint(b, makeKind(tid), name, + cts.WantData("bar"), + cts.MatchNamespace("zab")) }, }, { name: "autoreject", @@ -62,9 +64,9 @@ func BenchmarkClient_Review(b *testing.B) { Autoreject: true, }, makeConstraint: func(tid int, name string) *unstructured.Unstructured { - return clienttest.MakeConstraint(b, makeKind(tid), name, - clienttest.WantData("bar"), - clienttest.EnableAutoreject) + return cts.MakeConstraint(b, makeKind(tid), name, + cts.WantData("bar"), + cts.EnableAutoreject) }, }} diff --git a/constraint/pkg/client/client_test.go b/constraint/pkg/client/client_test.go index 6cfedd309..4ea78b376 100644 --- a/constraint/pkg/client/client_test.go +++ b/constraint/pkg/client/client_test.go @@ -695,12 +695,12 @@ func TestClient_RemoveTemplate_CascadingDelete(t *testing.T) { t.Errorf("err = %v; want nil", err) } - cst1 := clienttest.MakeConstraint(t, "CascadingDelete", "cascadingdelete") + cst1 := cts.MakeConstraint(t, "CascadingDelete", "cascadingdelete") if _, err = c.AddConstraint(context.Background(), cst1); err != nil { t.Fatalf("could not add first constraint: %v", err) } - cst2 := clienttest.MakeConstraint(t, "CascadingDelete", "cascadingdelete2") + cst2 := cts.MakeConstraint(t, "CascadingDelete", "cascadingdelete2") if _, err = c.AddConstraint(context.Background(), cst2); err != nil { t.Fatalf("could not add second constraint: %v", err) } @@ -710,12 +710,12 @@ func TestClient_RemoveTemplate_CascadingDelete(t *testing.T) { t.Errorf("err = %v; want nil", err) } - cst3 := clienttest.MakeConstraint(t, "StillPersists", "stillpersists") + cst3 := cts.MakeConstraint(t, "StillPersists", "stillpersists") if _, err = c.AddConstraint(context.Background(), cst3); err != nil { t.Fatalf("could not add third constraint: %v", err) } - cst4 := clienttest.MakeConstraint(t, "StillPersists", "stillpersists2") + cst4 := cts.MakeConstraint(t, "StillPersists", "stillpersists2") if _, err = c.AddConstraint(context.Background(), cst4); err != nil { t.Fatalf("could not add fourth constraint: %v", err) } @@ -796,7 +796,7 @@ func TestClient_AddConstraint(t *testing.T) { { name: "Good Constraint", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - constraint: clienttest.MakeConstraint(t, "Foos", "foo"), + constraint: cts.MakeConstraint(t, "Foos", "foo"), wantHandled: map[string]bool{handlertest.HandlerName: true}, wantAddConstraintError: nil, wantGetConstraintError: nil, @@ -804,7 +804,7 @@ func TestClient_AddConstraint(t *testing.T) { { name: "No Name", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - constraint: clienttest.MakeConstraint(t, "Foos", ""), + constraint: cts.MakeConstraint(t, "Foos", ""), wantHandled: nil, wantAddConstraintError: crds.ErrInvalidConstraint, wantGetConstraintError: crds.ErrInvalidConstraint, @@ -812,7 +812,7 @@ func TestClient_AddConstraint(t *testing.T) { { name: "No Kind", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - constraint: clienttest.MakeConstraint(t, "", "foo"), + constraint: cts.MakeConstraint(t, "", "foo"), wantHandled: nil, wantAddConstraintError: crds.ErrInvalidConstraint, wantGetConstraintError: crds.ErrInvalidConstraint, @@ -820,7 +820,7 @@ func TestClient_AddConstraint(t *testing.T) { { name: "No Template", template: nil, - constraint: clienttest.MakeConstraint(t, "Foo", "foo"), + constraint: cts.MakeConstraint(t, "Foo", "foo"), wantHandled: nil, wantAddConstraintError: client.ErrMissingConstraintTemplate, wantGetConstraintError: client.ErrMissingConstraint, @@ -920,37 +920,37 @@ func TestClient_RemoveConstraint(t *testing.T) { { name: "Good Constraint", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - constraint: clienttest.MakeConstraint(t, "Foos", "foo"), - toRemove: clienttest.MakeConstraint(t, "Foos", "foo"), + constraint: cts.MakeConstraint(t, "Foos", "foo"), + toRemove: cts.MakeConstraint(t, "Foos", "foo"), wantHandled: map[string]bool{handlertest.HandlerName: true}, wantError: nil, }, { name: "No name", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - constraint: clienttest.MakeConstraint(t, "Foos", "foo"), - toRemove: clienttest.MakeConstraint(t, "Foos", ""), + constraint: cts.MakeConstraint(t, "Foos", "foo"), + toRemove: cts.MakeConstraint(t, "Foos", ""), wantHandled: nil, wantError: crds.ErrInvalidConstraint, }, { name: "No Kind", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - constraint: clienttest.MakeConstraint(t, "Foos", "foo"), - toRemove: clienttest.MakeConstraint(t, "", "foo"), + constraint: cts.MakeConstraint(t, "Foos", "foo"), + toRemove: cts.MakeConstraint(t, "", "foo"), wantHandled: nil, wantError: crds.ErrInvalidConstraint, }, { name: "No Template", - toRemove: clienttest.MakeConstraint(t, "Foos", "foo"), + toRemove: cts.MakeConstraint(t, "Foos", "foo"), wantHandled: nil, wantError: client.ErrMissingConstraintTemplate, }, { name: "No Constraint", template: cts.New(cts.OptName("foos"), cts.OptCRDNames("Foos")), - toRemove: clienttest.MakeConstraint(t, "Foos", "bar"), + toRemove: cts.MakeConstraint(t, "Foos", "bar"), wantHandled: map[string]bool{handlertest.HandlerName: true}, wantError: nil, }, diff --git a/constraint/pkg/client/clienttest/constraints.go b/constraint/pkg/client/clienttest/cts/constraints.go similarity index 98% rename from constraint/pkg/client/clienttest/constraints.go rename to constraint/pkg/client/clienttest/cts/constraints.go index 0f90ddf0f..931ab0993 100644 --- a/constraint/pkg/client/clienttest/constraints.go +++ b/constraint/pkg/client/clienttest/cts/constraints.go @@ -1,4 +1,4 @@ -package clienttest +package cts import ( "testing" diff --git a/constraint/pkg/client/clienttest/cts/opts.go b/constraint/pkg/client/clienttest/cts/opts.go index 52006e3e3..e0829c243 100644 --- a/constraint/pkg/client/clienttest/cts/opts.go +++ b/constraint/pkg/client/clienttest/cts/opts.go @@ -5,7 +5,8 @@ import ( "github.com/open-policy-agent/frameworks/constraint/pkg/handler/handlertest" ) -const ModuleDeny = ` +const ( + ModuleDeny = ` package foo violation[{"msg": msg}] { @@ -13,10 +14,14 @@ violation[{"msg": msg}] { msg := "denied" } ` + MockTemplateName string = "fakes" + MockTemplate string = "Fakes" + MockTargetHandler string = "foo" +) var defaults = []Opt{ - OptName("fakes"), - OptCRDNames("Fakes"), + OptName(MockTemplateName), + OptCRDNames(MockTemplate), OptTargets(Target(handlertest.HandlerName, ModuleDeny)), } diff --git a/constraint/pkg/client/drivers/interface.go b/constraint/pkg/client/drivers/interface.go index 55f1185cc..1a8ac2e82 100644 --- a/constraint/pkg/client/drivers/interface.go +++ b/constraint/pkg/client/drivers/interface.go @@ -5,6 +5,7 @@ import ( "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" "github.com/open-policy-agent/frameworks/constraint/pkg/types" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) type QueryCfg struct { @@ -27,6 +28,10 @@ type Driver interface { AddTemplate(ct *templates.ConstraintTemplate) error // RemoveTemplate removes the template source code from OPA RemoveTemplate(ctx context.Context, ct *templates.ConstraintTemplate) error + // AddConstraint inserts validated constraint into OPA + AddConstraint(ctx context.Context, constraint *unstructured.Unstructured) error + // RemoveConstraint removes a constraint from OPA + RemoveConstraint(ctx context.Context, constraint *unstructured.Unstructured) error PutData(ctx context.Context, path string, data interface{}) error DeleteData(ctx context.Context, path string) (bool, error) Query(ctx context.Context, path string, input interface{}, opts ...QueryOpt) (*types.Response, error) diff --git a/constraint/pkg/client/drivers/local/args.go b/constraint/pkg/client/drivers/local/args.go index 3db95ff8a..1ea781413 100644 --- a/constraint/pkg/client/drivers/local/args.go +++ b/constraint/pkg/client/drivers/local/args.go @@ -21,7 +21,9 @@ func Defaults() Arg { if d.modules == nil { d.modules = make(map[string]*ast.Module) } - + if d.templateHandler == nil { + d.templateHandler = make(map[string][]string) + } if d.storage == nil { d.storage = inmem.New() } diff --git a/constraint/pkg/client/drivers/local/local.go b/constraint/pkg/client/drivers/local/local.go index 7971db6fb..4ffda2db0 100644 --- a/constraint/pkg/client/drivers/local/local.go +++ b/constraint/pkg/client/drivers/local/local.go @@ -8,15 +8,20 @@ import ( "fmt" "io/ioutil" "net/http" + "path" "sort" "strings" "sync" "time" + "github.com/open-policy-agent/frameworks/constraint/pkg/apis/constraints" + clienterrors "github.com/open-policy-agent/frameworks/constraint/pkg/client/errors" "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" "github.com/open-policy-agent/frameworks/constraint/pkg/handler" "github.com/open-policy-agent/frameworks/constraint/pkg/regorewriter" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers" "github.com/open-policy-agent/frameworks/constraint/pkg/externaldata" @@ -70,16 +75,20 @@ func New(args ...Arg) drivers.Driver { var _ drivers.Driver = &Driver{} type Driver struct { - modulesMux sync.RWMutex - compiler *ast.Compiler - modules map[string]*ast.Module - storage storage.Store - capabilities *ast.Capabilities - traceEnabled bool - printEnabled bool - printHook print.Hook - providerCache *externaldata.ProviderCache - externs []string + modulesMux sync.RWMutex + compiler *ast.Compiler + modules map[string]*ast.Module + // thMux guards the access to templateHandler + thMux sync.RWMutex + // templateHandler stores the template kind and the mapping target handlers + templateHandler map[string][]string + storage storage.Store + capabilities *ast.Capabilities + traceEnabled bool + printEnabled bool + printHook print.Hook + providerCache *externaldata.ProviderCache + externs []string // handlers is a map from handler name to the respective handler handlers map[string]handler.TargetHandler } @@ -567,10 +576,16 @@ func (d *Driver) AddTemplate(templ *templates.ConstraintTemplate) error { if err = d.putModules(namePrefix, mods); err != nil { return fmt.Errorf("%w: %v", clienterrors.ErrCompile, err) } + d.thMux.Lock() + defer d.thMux.Unlock() + d.templateHandler[templ.Spec.CRD.Spec.Names.Kind] = []string{ + templ.Spec.Targets[0].Target, + } return nil } // RemoveTemplate implements driver.Driver. +// TODO: Cascading deletes. func (d *Driver) RemoveTemplate(ctx context.Context, templ *templates.ConstraintTemplate) error { if err := validateTargets(templ); err != nil { return nil @@ -579,9 +594,54 @@ func (d *Driver) RemoveTemplate(ctx context.Context, templ *templates.Constraint kind := templ.Spec.CRD.Spec.Names.Kind namePrefix := createTemplatePath(targetHandler, kind) _, err := d.deleteModules(namePrefix) + d.thMux.Lock() + defer d.thMux.Unlock() + delete(d.templateHandler, templ.Spec.CRD.Spec.Names.Kind) return err } +func (d *Driver) AddConstraint(ctx context.Context, constraint *unstructured.Unstructured) error { + handlers, err := d.getTargetHandlers(constraint) + if err != nil { + return err + } + + for _, target := range handlers { + relPath, err := createConstraintPath(target, constraint) + // If we ever create multi-target constraints we will need to handle this more cleverly. + // the short-circuiting question, cleanup, etc. + if err != nil { + return err + } + if err := d.PutData(ctx, relPath, constraint.Object); err != nil { + return err + } + } + return nil +} + +func (d *Driver) RemoveConstraint(ctx context.Context, constraint *unstructured.Unstructured) error { + handlers, err := d.getTargetHandlers(constraint) + if err != nil { + if !errors.Is(err, clienterrors.ErrMissingConstraintTemplate) { + return err + } + } + + for _, target := range handlers { + relPath, err := createConstraintPath(target, constraint) + // If we ever create multi-target constraints we will need to handle this more cleverly. + // the short-circuiting question, cleanup, etc. + if err != nil { + return err + } + if _, err := d.DeleteData(ctx, relPath); err != nil { + return err + } + } + return nil +} + // templateLibPrefix returns the new lib prefix for the libs that are specified in the CT. func templateLibPrefix(target, name string) string { return fmt.Sprintf("libs.%s.%s", target, name) @@ -669,6 +729,64 @@ func validateTargets(templ *templates.ConstraintTemplate) error { } } +// createConstraintGKPath returns the subpath for given a constraint GK. +func createConstraintGKSubPath(gk schema.GroupKind) string { + return "/" + path.Join("cluster", gk.Group, gk.Kind) +} + +// createConstraintSubPath returns the key where we will store the constraint +// for each target: cluster.... +func createConstraintSubPath(constraint *unstructured.Unstructured) (string, error) { + if constraint.GetName() == "" { + return "", fmt.Errorf("%w: missing name", clienterrors.ErrInvalidConstraint) + } + + gvk := constraint.GroupVersionKind() + if gvk.Group != constraints.Group { + return "", fmt.Errorf("%w: expect group %q for constrant %q, got %q", + clienterrors.ErrInvalidConstraint, constraints.Group, constraint.GetName(), gvk.Group) + } + + if gvk.Kind == "" { + return "", fmt.Errorf("%w: empty kind for constraint %q", + clienterrors.ErrInvalidConstraint, constraint.GetName()) + } + + return path.Join(createConstraintGKSubPath(gvk.GroupKind()), constraint.GetName()), nil +} + +// constraintPathMerge is a shared function for creating constraint paths to +// ensure uniformity, it is not meant to be called directly. +func constraintPathMerge(target, subpath string) string { + return "/" + path.Join("constraints", target, subpath) +} + +// createConstraintPath returns the storage path for a given constraint: constraints..cluster.... +func createConstraintPath(target string, constraint *unstructured.Unstructured) (string, error) { + p, err := createConstraintSubPath(constraint) + if err != nil { + return "", err + } + return constraintPathMerge(target, p), nil +} + +func (d *Driver) getTargetHandlers(constraint *unstructured.Unstructured) ([]string, error) { + d.thMux.RLock() + defer d.thMux.RUnlock() + + kind := constraint.GetKind() + handlers, ok := d.templateHandler[kind] + if !ok { + var known []string + for k := range d.templateHandler { + known = append(known, k) + } + return nil, fmt.Errorf("%w: Constraint kind %q is not recognized, known kinds %v", + clienterrors.ErrMissingConstraintTemplate, kind, known) + } + return handlers, nil +} + func (d *Driver) SetExterns(fields []string) { d.externs = fields } diff --git a/constraint/pkg/client/drivers/local/local_unit_test.go b/constraint/pkg/client/drivers/local/local_unit_test.go index cf6a3b251..8c246567f 100644 --- a/constraint/pkg/client/drivers/local/local_unit_test.go +++ b/constraint/pkg/client/drivers/local/local_unit_test.go @@ -4,16 +4,17 @@ import ( "context" "errors" "sort" + "strings" "testing" - clienterrors "github.com/open-policy-agent/frameworks/constraint/pkg/client/errors" - "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest/cts" + clienterrors "github.com/open-policy-agent/frameworks/constraint/pkg/client/errors" + "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/storage" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) const ( @@ -43,8 +44,10 @@ fooisbar[msg] { msg := "input.foo is bar" } ` - MockTemplate string = "MockConstraintTemplate" - MockTargetHandler string = "foo" + TemplateModule string = ` +package something + +violation[msg] {msg := "always"}` ) func TestDriver_PutModule(t *testing.T) { @@ -396,23 +399,23 @@ func TestDriver_AddTemplates(t *testing.T) { }, { name: "rego missing violation", - targetHandler: MockTargetHandler, + targetHandler: cts.MockTargetHandler, rego: Module, wantErr: clienterrors.ErrInvalidConstraintTemplate, wantModules: nil, }, { name: "valid template", - targetHandler: MockTargetHandler, + targetHandler: cts.MockTargetHandler, rego: ` package something violation[msg] {msg := "always"}`, - wantModules: []string{toModuleSetName(createTemplatePath(MockTargetHandler, MockTemplate), 0)}, + wantModules: []string{toModuleSetName(createTemplatePath(cts.MockTargetHandler, cts.MockTemplate), 0)}, }, { name: "inventory disallowed template", - targetHandler: MockTargetHandler, + targetHandler: cts.MockTargetHandler, rego: `package something violation[{"msg": "msg"}] { @@ -422,7 +425,7 @@ violation[{"msg": "msg"}] { }, { name: "inventory allowed template", - targetHandler: MockTargetHandler, + targetHandler: cts.MockTargetHandler, rego: `package something violation[{"msg": "msg"}] { @@ -430,7 +433,7 @@ violation[{"msg": "msg"}] { }`, externs: []string{"data.inventory"}, wantErr: nil, - wantModules: []string{toModuleSetName(createTemplatePath(MockTargetHandler, MockTemplate), 0)}, + wantModules: []string{toModuleSetName(createTemplatePath(cts.MockTargetHandler, cts.MockTemplate), 0)}, }, } @@ -442,7 +445,7 @@ violation[{"msg": "msg"}] { t.Fatalf("got New() type = %T, want %T", dr, &Driver{}) } dr.SetExterns(tc.externs) - tmpl := createTemplate(tc.targetHandler, tc.rego) + tmpl := cts.New(cts.OptTargets(cts.Target(tc.targetHandler, tc.rego))) gotErr := dr.AddTemplate(tmpl) if !errors.Is(gotErr, tc.wantErr) { t.Fatalf("got AddTemplate() error = %v, want %v", gotErr, tc.wantErr) @@ -471,7 +474,7 @@ func TestDriver_RemoveTemplates(t *testing.T) { }{ { name: "valid template", - targetHandler: MockTargetHandler, + targetHandler: cts.MockTargetHandler, rego: ` package something @@ -479,7 +482,7 @@ violation[msg] {msg := "always"}`, }, { name: "inventory allowed template", - targetHandler: MockTargetHandler, + targetHandler: cts.MockTargetHandler, rego: `package something violation[{"msg": "msg"}] { @@ -498,7 +501,7 @@ violation[{"msg": "msg"}] { t.Fatalf("got New() type = %T, want %T", dr, &Driver{}) } dr.SetExterns(tc.externs) - tmpl := createTemplate(tc.targetHandler, tc.rego) + tmpl := cts.New(cts.OptTargets(cts.Target(tc.targetHandler, tc.rego))) gotErr := dr.AddTemplate(tmpl) if !errors.Is(gotErr, tc.wantErr) { t.Fatalf("got AddTemplate() error = %v, want %v", gotErr, tc.wantErr) @@ -517,6 +520,165 @@ violation[{"msg": "msg"}] { } } +func TestDriver_AddConstraint(t *testing.T) { + testCases := []struct { + name string + constraint *unstructured.Unstructured + wantAddConstraintError error + }{ + { + name: "Good Constraint", + constraint: cts.MakeConstraint(t, cts.MockTemplate, "tc_good_constraint"), + }, + { + name: "No Name", + constraint: cts.MakeConstraint(t, cts.MockTemplate, ""), + wantAddConstraintError: clienterrors.ErrInvalidConstraint, + }, + { + name: "No Kind", + constraint: cts.MakeConstraint(t, "", "foo-constraint"), + wantAddConstraintError: clienterrors.ErrMissingConstraintTemplate, + }, + { + name: "No Template", + constraint: cts.MakeConstraint(t, "TemplateMissing", "foo-constraint"), + wantAddConstraintError: clienterrors.ErrMissingConstraintTemplate, + }, + { + name: "No Group", + constraint: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "kind": cts.MockTemplate, + "metadata": map[string]interface{}{ + "name": "foo-constraint", + }, + }, + }, + wantAddConstraintError: clienterrors.ErrInvalidConstraint, + }, + { + name: "Incorrect Group", + constraint: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "foo-group/v1", + "kind": cts.MockTemplate, + "metadata": map[string]interface{}{ + "name": "foo-constraint", + }, + }, + }, + wantAddConstraintError: clienterrors.ErrInvalidConstraint, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + d := New() + dr, ok := d.(*Driver) + if !ok { + t.Fatalf("got New() type = %T, want %T", dr, &Driver{}) + } + tmpl := cts.New(cts.OptTargets(cts.Target(cts.MockTargetHandler, TemplateModule))) + err := dr.AddTemplate(tmpl) + if err != nil { + t.Fatalf("got AddTemplate() error = %v", err) + } + err = dr.AddConstraint(context.Background(), tc.constraint) + if !errors.Is(err, tc.wantAddConstraintError) { + t.Fatalf("got AddConstraint() error = %v, want %v", + err, tc.wantAddConstraintError) + } + if err == nil { + storage, err := dr.Dump(context.Background()) + if err != nil { + t.Fatalf("could not dump driver %v", err) + } + if !strings.Contains(storage, tc.constraint.GetName()) { + t.Errorf("expected constraint %s not added to driver", tc.constraint.GetName()) + } + } + }) + } +} + +func TestDriver_RemoveConstraint(t *testing.T) { + tmpl := cts.New(cts.OptTargets(cts.Target(cts.MockTargetHandler, TemplateModule))) + tcs := []struct { + name string + template *templates.ConstraintTemplate + constraint *unstructured.Unstructured + toRemove *unstructured.Unstructured + wantError error + }{ + { + name: "Good Constraint", + template: tmpl, + constraint: cts.MakeConstraint(t, cts.MockTemplate, "foo"), + toRemove: cts.MakeConstraint(t, cts.MockTemplate, "foo"), + wantError: nil, + }, + { + name: "No name", + template: tmpl, + constraint: cts.MakeConstraint(t, cts.MockTemplate, "foo"), + toRemove: cts.MakeConstraint(t, cts.MockTemplate, ""), + wantError: clienterrors.ErrInvalidConstraint, + }, + { + name: "No Kind", + template: tmpl, + constraint: cts.MakeConstraint(t, cts.MockTemplate, "foo"), + toRemove: cts.MakeConstraint(t, "", "foo"), + wantError: nil, + }, + { + name: "No Template", + toRemove: cts.MakeConstraint(t, "Foos", "foo"), + wantError: nil, + }, + { + name: "No Constraint", + template: tmpl, + toRemove: cts.MakeConstraint(t, cts.MockTemplate, "foo"), + wantError: nil, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() + + d := New() + dr, ok := d.(*Driver) + if !ok { + t.Fatalf("got New() type = %T, want %T", dr, &Driver{}) + } + + if tc.template != nil { + err := dr.AddTemplate(tc.template) + if err != nil { + t.Fatal(err) + } + } + + if tc.constraint != nil { + err := dr.AddConstraint(ctx, tc.constraint) + if err != nil { + t.Fatal(err) + } + } + + err := dr.RemoveConstraint(context.Background(), tc.toRemove) + + if !errors.Is(err, tc.wantError) { + t.Errorf("got RemoveConstraint error = %v, want %v", + err, tc.wantError) + } + }) + } +} + func TestDriver_PutData(t *testing.T) { testCases := []struct { name string @@ -897,32 +1059,3 @@ type readErrorStorage struct { func (s *readErrorStorage) Read(_ context.Context, _ storage.Transaction, _ storage.Path) (interface{}, error) { return nil, errors.New("error writing data") } - -func createTemplate(targetHandler, rego string) *templates.ConstraintTemplate { - tmpl := &templates.ConstraintTemplate{ - TypeMeta: v1.TypeMeta{}, - ObjectMeta: v1.ObjectMeta{ - Name: "mockconstrainttemplate", - }, - Spec: templates.ConstraintTemplateSpec{ - CRD: templates.CRD{ - Spec: templates.CRDSpec{ - Names: templates.Names{ - Kind: MockTemplate, - ShortNames: nil, - }, - }, - }, - }, - } - if targetHandler == "" && rego == "" { - return tmpl - } - tmpl.Spec.Targets = []templates.Target{ - { - Target: targetHandler, - Rego: rego, - }, - } - return tmpl -} diff --git a/constraint/pkg/client/drivers/remote/remote.go b/constraint/pkg/client/drivers/remote/remote.go index 05cbfe6fe..52c116aa6 100644 --- a/constraint/pkg/client/drivers/remote/remote.go +++ b/constraint/pkg/client/drivers/remote/remote.go @@ -9,10 +9,10 @@ import ( "net/url" "strings" - "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" - "github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers" + "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" ctypes "github.com/open-policy-agent/frameworks/constraint/pkg/types" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) type Arg func(*inits) @@ -103,6 +103,14 @@ func (d *driver) RemoveTemplate(ctx context.Context, ct *templates.ConstraintTem panic("not implemented") } +func (d *driver) AddConstraint(ctx context.Context, constraint *unstructured.Unstructured) error { + panic("not implemented") +} + +func (d *driver) RemoveConstraint(ctx context.Context, constraint *unstructured.Unstructured) error { + panic("not implemented") +} + func (d *driver) PutData(_ context.Context, path string, data interface{}) error { return d.opa.PutData(path, data) } diff --git a/constraint/pkg/client/e2e_test.go b/constraint/pkg/client/e2e_test.go index 93d533588..60f153630 100644 --- a/constraint/pkg/client/e2e_test.go +++ b/constraint/pkg/client/e2e_test.go @@ -5,6 +5,8 @@ import ( "errors" "testing" + "github.com/open-policy-agent/frameworks/constraint/pkg/client/clienttest/cts" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/open-policy-agent/frameworks/constraint/pkg/client" @@ -63,7 +65,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateDeny(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindDeny, "constraint"), + cts.MakeConstraint(t, clienttest.KindDeny, "constraint"), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -75,7 +77,7 @@ func TestClient_Review(t *testing.T) { wantResults: []*types.Result{{ Msg: "denied", EnforcementAction: "deny", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDeny, "constraint"), + Constraint: cts.MakeConstraint(t, clienttest.KindDeny, "constraint"), }}, }, { @@ -85,7 +87,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateDeny(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindDeny, "constraint", clienttest.EnforcementAction("dryrun")), + cts.MakeConstraint(t, clienttest.KindDeny, "constraint", cts.EnforcementAction("dryrun")), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -97,7 +99,7 @@ func TestClient_Review(t *testing.T) { wantResults: []*types.Result{{ Msg: "denied", EnforcementAction: "dryrun", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDeny, "constraint", clienttest.EnforcementAction("dryrun")), + Constraint: cts.MakeConstraint(t, clienttest.KindDeny, "constraint", cts.EnforcementAction("dryrun")), }}, }, { @@ -107,7 +109,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateDenyImport(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindDenyImport, "constraint"), + cts.MakeConstraint(t, clienttest.KindDenyImport, "constraint"), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -119,7 +121,7 @@ func TestClient_Review(t *testing.T) { wantResults: []*types.Result{{ Msg: "denied with library", EnforcementAction: "deny", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDenyImport, "constraint"), + Constraint: cts.MakeConstraint(t, clienttest.KindDenyImport, "constraint"), }}, }, { @@ -129,7 +131,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateAllow(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindAllow, "constraint"), + cts.MakeConstraint(t, clienttest.KindAllow, "constraint"), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -147,7 +149,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -165,7 +167,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -177,7 +179,7 @@ func TestClient_Review(t *testing.T) { wantResults: []*types.Result{{ Msg: "got qux but want bar for data", EnforcementAction: "deny", - Constraint: clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + Constraint: cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), }}, }, { @@ -187,7 +189,7 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar"), clienttest.EnableAutoreject), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar"), cts.EnableAutoreject), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -199,8 +201,8 @@ func TestClient_Review(t *testing.T) { wantResults: []*types.Result{{ Msg: "autoreject", EnforcementAction: "deny", - Constraint: clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", - clienttest.WantData("bar"), clienttest.EnableAutoreject), + Constraint: cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", + cts.WantData("bar"), cts.EnableAutoreject), }}, }, { @@ -210,8 +212,8 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", - clienttest.WantData("bar"), clienttest.MatchNamespace("billing")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", + cts.WantData("bar"), cts.MatchNamespace("billing")), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -224,8 +226,8 @@ func TestClient_Review(t *testing.T) { wantResults: []*types.Result{{ Msg: "got qux but want bar for data", EnforcementAction: "deny", - Constraint: clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", - clienttest.WantData("bar"), clienttest.MatchNamespace("billing")), + Constraint: cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", + cts.WantData("bar"), cts.MatchNamespace("billing")), }}, }, { @@ -235,8 +237,8 @@ func TestClient_Review(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", - clienttest.WantData("bar"), clienttest.MatchNamespace("billing")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", + cts.WantData("bar"), cts.MatchNamespace("billing")), }, toReview: handlertest.Review{ Object: handlertest.Object{ @@ -296,7 +298,7 @@ func TestClient_Review_Details(t *testing.T) { t.Fatal(err) } - constraint := clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")) + constraint := cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")) _, err = c.AddConstraint(ctx, constraint) if err != nil { t.Fatal(err) @@ -318,8 +320,8 @@ func TestClient_Review_Details(t *testing.T) { want := []*types.Result{{ Msg: "got qux but want bar for data", EnforcementAction: "deny", - Constraint: clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", - clienttest.WantData("bar")), + Constraint: cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", + cts.WantData("bar")), Metadata: map[string]interface{}{"details": map[string]interface{}{"got": "qux"}}, }} @@ -371,7 +373,7 @@ func TestClient_Audit(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), }, objects: nil, want: nil, @@ -382,7 +384,7 @@ func TestClient_Audit(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), }, objects: []*handlertest.Object{ {Name: "foo", Data: "bar"}, @@ -396,7 +398,7 @@ func TestClient_Audit(t *testing.T) { clienttest.TemplateCheckData(), }, constraints: []*unstructured.Unstructured{ - clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), }, objects: []*handlertest.Object{ {Name: "foo", Data: "qux"}, @@ -405,7 +407,7 @@ func TestClient_Audit(t *testing.T) { want: []*types.Result{ { Msg: "got qux but want bar for data", - Constraint: clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + Constraint: cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), Resource: &handlertest.Review{ Object: handlertest.Object{Name: "foo", Data: "qux"}, }, @@ -413,7 +415,7 @@ func TestClient_Audit(t *testing.T) { }, { Msg: "got zab but want bar for data", - Constraint: clienttest.MakeConstraint(t, clienttest.KindCheckData, "constraint", clienttest.WantData("bar")), + Constraint: cts.MakeConstraint(t, clienttest.KindCheckData, "constraint", cts.WantData("bar")), Resource: &handlertest.Review{ Object: handlertest.Object{Name: "foo2", Namespace: "bar", Data: "zab"}, }, @@ -486,7 +488,7 @@ func TestClient_Review_Print(t *testing.T) { wantResults: []*types.Result{ { Msg: "denied", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDenyPrint, "denyprint"), + Constraint: cts.MakeConstraint(t, clienttest.KindDenyPrint, "denyprint"), Resource: &handlertest.Review{Object: handlertest.Object{Name: "hanna"}}, EnforcementAction: "deny", }, @@ -498,7 +500,7 @@ func TestClient_Review_Print(t *testing.T) { wantResults: []*types.Result{ { Msg: "denied", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDenyPrint, "denyprint"), + Constraint: cts.MakeConstraint(t, clienttest.KindDenyPrint, "denyprint"), Resource: &handlertest.Review{Object: handlertest.Object{Name: "hanna"}}, EnforcementAction: "deny", }, @@ -529,7 +531,7 @@ func TestClient_Review_Print(t *testing.T) { t.Fatalf("got AddTemplate: %v", err) } - cstr := clienttest.MakeConstraint(t, clienttest.KindDenyPrint, "denyprint") + cstr := cts.MakeConstraint(t, clienttest.KindDenyPrint, "denyprint") if _, err = c.AddConstraint(ctx, cstr); err != nil { t.Fatalf("got AddConstraint: %v", err) } @@ -561,7 +563,7 @@ func TestE2E_RemoveConstraint(t *testing.T) { t.Fatal(err) } - _, err = c.AddConstraint(ctx, clienttest.MakeConstraint(t, clienttest.KindDeny, "foo")) + _, err = c.AddConstraint(ctx, cts.MakeConstraint(t, clienttest.KindDeny, "foo")) if err != nil { t.Fatal(err) } @@ -574,7 +576,7 @@ func TestE2E_RemoveConstraint(t *testing.T) { got := responses.Results() want := []*types.Result{{ Msg: "denied", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDeny, "foo"), + Constraint: cts.MakeConstraint(t, clienttest.KindDeny, "foo"), EnforcementAction: "deny", }} @@ -582,7 +584,7 @@ func TestE2E_RemoveConstraint(t *testing.T) { t.Fatal(diff) } - _, err = c.RemoveConstraint(ctx, clienttest.MakeConstraint(t, clienttest.KindDeny, "foo")) + _, err = c.RemoveConstraint(ctx, cts.MakeConstraint(t, clienttest.KindDeny, "foo")) if err != nil { t.Fatal(err) } @@ -609,7 +611,7 @@ func TestE2E_RemoveTemplate(t *testing.T) { t.Fatal(err) } - _, err = c.AddConstraint(ctx, clienttest.MakeConstraint(t, clienttest.KindDeny, "foo")) + _, err = c.AddConstraint(ctx, cts.MakeConstraint(t, clienttest.KindDeny, "foo")) if err != nil { t.Fatal(err) } @@ -622,7 +624,7 @@ func TestE2E_RemoveTemplate(t *testing.T) { got := responses.Results() want := []*types.Result{{ Msg: "denied", - Constraint: clienttest.MakeConstraint(t, clienttest.KindDeny, "foo"), + Constraint: cts.MakeConstraint(t, clienttest.KindDeny, "foo"), EnforcementAction: "deny", }} @@ -673,7 +675,7 @@ func TestE2E_Review_Tracing(t *testing.T) { t.Fatal(err) } - _, err = c.AddConstraint(ctx, clienttest.MakeConstraint(t, clienttest.KindDeny, "foo")) + _, err = c.AddConstraint(ctx, cts.MakeConstraint(t, clienttest.KindDeny, "foo")) if err != nil { t.Fatal(err) } diff --git a/constraint/pkg/client/errors/errors.go b/constraint/pkg/client/errors/errors.go index 2bdd42043..14f7c6970 100644 --- a/constraint/pkg/client/errors/errors.go +++ b/constraint/pkg/client/errors/errors.go @@ -14,5 +14,7 @@ var ( ErrTransaction = errors.New("error committing data") ErrInvalidConstraintTemplate = errors.New("invalid ConstraintTemplate") + ErrInvalidConstraint = errors.New("invalid Constraint") + ErrMissingConstraintTemplate = errors.New("missing ConstraintTemplate") ErrInvalidModule = errors.New("invalid module") )