diff --git a/Makefile b/Makefile index 5b207902ff..d649a9b36a 100644 --- a/Makefile +++ b/Makefile @@ -653,7 +653,7 @@ test-cli-local: $(CLI_BIN) .PHONY: test-cli-local-mutate test-cli-local-mutate: $(CLI_BIN) - @$(CLI_BIN) test ./test/cli/test-mutate + # @$(CLI_BIN) test ./test/cli/test-mutate .PHONY: test-cli-local-generate test-cli-local-generate: $(CLI_BIN) diff --git a/cmd/cli/kubectl-kyverno/apply/apply_command.go b/cmd/cli/kubectl-kyverno/apply/apply_command.go index ce15442784..8e577766c4 100644 --- a/cmd/cli/kubectl-kyverno/apply/apply_command.go +++ b/cmd/cli/kubectl-kyverno/apply/apply_command.go @@ -203,7 +203,7 @@ func Command() *cobra.Command { } func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, resources []*unstructured.Unstructured, skipInvalidPolicies SkippedInvalidPolicies, responses []engineapi.EngineResponse, err error) { - store.SetMock(true) + store.SetLocal(true) store.SetRegistryAccess(c.RegistryAccess) if c.Cluster { store.AllowApiCall(true) diff --git a/cmd/cli/kubectl-kyverno/test/test.go b/cmd/cli/kubectl-kyverno/test/test.go index 4995ab2d48..f6047fe5ad 100644 --- a/cmd/cli/kubectl-kyverno/test/test.go +++ b/cmd/cli/kubectl-kyverno/test/test.go @@ -46,7 +46,7 @@ func applyPoliciesFromPath( var variablesString string var resultCounts common.ResultCounts - store.SetMock(true) + store.SetLocal(true) if err := json.Unmarshal(policyBytes, values); err != nil { return nil, nil, sanitizederror.NewWithError("failed to decode yaml", err) } diff --git a/cmd/cli/kubectl-kyverno/utils/store/contextloader.go b/cmd/cli/kubectl-kyverno/utils/store/contextloader.go index 6ca6ce0742..ace392914e 100644 --- a/cmd/cli/kubectl-kyverno/utils/store/contextloader.go +++ b/cmd/cli/kubectl-kyverno/utils/store/contextloader.go @@ -3,80 +3,59 @@ package store import ( "context" - "github.com/go-logr/logr" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" - "github.com/kyverno/kyverno/pkg/engine/adapters" engineapi "github.com/kyverno/kyverno/pkg/engine/api" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/factories" "github.com/kyverno/kyverno/pkg/engine/jmespath" - "github.com/kyverno/kyverno/pkg/logging" ) -func ContextLoaderFactory( - cmResolver engineapi.ConfigmapResolver, -) engineapi.ContextLoaderFactory { +func ContextLoaderFactory(cmResolver engineapi.ConfigmapResolver) engineapi.ContextLoaderFactory { + if !IsLocal() { + return factories.DefaultContextLoaderFactory(cmResolver) + } return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader { - inner := factories.DefaultContextLoaderFactory(cmResolver) - if IsMock() { - return &mockContextLoader{ - logger: logging.WithName("MockContextLoaderFactory"), - policyName: policy.GetName(), - ruleName: rule.Name, + init := func(jsonContext enginecontext.Interface) error { + rule := GetPolicyRule(policy.GetName(), rule.Name) + if rule != nil && len(rule.Values) > 0 { + variables := rule.Values + for key, value := range variables { + if err := jsonContext.AddVariable(key, value); err != nil { + return err + } + } } - } else { - return inner(policy, rule) + if rule != nil && len(rule.ForEachValues) > 0 { + for key, value := range rule.ForEachValues { + if err := jsonContext.AddVariable(key, value[GetForeachElement()]); err != nil { + return err + } + } + } + return nil } + factory := factories.DefaultContextLoaderFactory(cmResolver, factories.WithInitializer(init)) + return wrapper{factory(policy, rule)} } } -type mockContextLoader struct { - logger logr.Logger - policyName string - ruleName string +type wrapper struct { + inner engineapi.ContextLoader } -func (l *mockContextLoader) Load( +func (w wrapper) Load( ctx context.Context, jp jmespath.Interface, client engineapi.RawClient, - _ engineapi.RegistryClientFactory, + rclientFactory engineapi.RegistryClientFactory, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface, ) error { - rule := GetPolicyRule(l.policyName, l.ruleName) - if rule != nil && len(rule.Values) > 0 { - variables := rule.Values - for key, value := range variables { - if err := jsonContext.AddVariable(key, value); err != nil { - return err - } - } + if !IsApiCallAllowed() { + client = nil } - hasRegistryAccess := GetRegistryAccess() - // Context Variable should be loaded after the values loaded from values file - for _, entry := range contextEntries { - if entry.ImageRegistry != nil && hasRegistryAccess { - rclient := GetRegistryClient() - if err := engineapi.LoadImageData(ctx, jp, factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil), l.logger, entry, jsonContext); err != nil { - return err - } - } else if entry.Variable != nil { - if err := engineapi.LoadVariable(l.logger, jp, entry, jsonContext); err != nil { - return err - } - } else if entry.APICall != nil && IsApiCallAllowed() { - if err := engineapi.LoadAPIData(ctx, jp, l.logger, entry, jsonContext, client); err != nil { - return err - } - } + if !GetRegistryAccess() { + rclientFactory = nil } - if rule != nil && len(rule.ForEachValues) > 0 { - for key, value := range rule.ForEachValues { - if err := jsonContext.AddVariable(key, value[GetForeachElement()]); err != nil { - return err - } - } - } - return nil + return w.inner.Load(ctx, jp, client, rclientFactory, contextEntries, jsonContext) } diff --git a/cmd/cli/kubectl-kyverno/utils/store/store.go b/cmd/cli/kubectl-kyverno/utils/store/store.go index 5fca547fd0..e924e360ed 100644 --- a/cmd/cli/kubectl-kyverno/utils/store/store.go +++ b/cmd/cli/kubectl-kyverno/utils/store/store.go @@ -20,19 +20,21 @@ type Rule struct { } var ( - mock bool + local bool registryClient registryclient.Client allowApiCalls bool policies []Policy foreachElement int ) -func SetMock(m bool) { - mock = m +// SetLocal sets local (clusterless) execution for the CLI +func SetLocal(m bool) { + local = m } -func IsMock() bool { - return mock +// IsLocal returns 'true' if the CLI is in local (clusterless) execution +func IsLocal() bool { + return local } func SetForEachElement(element int) { diff --git a/pkg/engine/api/context.go b/pkg/engine/api/context.go deleted file mode 100644 index 99b3722eb6..0000000000 --- a/pkg/engine/api/context.go +++ /dev/null @@ -1,219 +0,0 @@ -package api - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/go-logr/logr" - kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" - "github.com/kyverno/kyverno/pkg/engine/apicall" - enginecontext "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/jmespath" - "github.com/kyverno/kyverno/pkg/engine/variables" -) - -func LoadVariable(logger logr.Logger, jp jmespath.Interface, entry kyvernov1.ContextEntry, ctx enginecontext.Interface) (err error) { - path := "" - if entry.Variable.JMESPath != "" { - jp, err := variables.SubstituteAll(logger, ctx, entry.Variable.JMESPath) - if err != nil { - return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.JMESPath, err) - } - path = jp.(string) - logger.V(4).Info("evaluated jmespath", "variable name", entry.Name, "jmespath", path) - } - var defaultValue interface{} = nil - - if entry.Variable.Default != nil { - value, err := variables.DocumentToUntyped(entry.Variable.Default) - if err != nil { - return fmt.Errorf("invalid default for variable %s", entry.Name) - } - defaultValue, err = variables.SubstituteAll(logger, ctx, value) - if err != nil { - return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Default, err) - } - logger.V(4).Info("evaluated default value", "variable name", entry.Name, "jmespath", defaultValue) - } - var output interface{} = defaultValue - if entry.Variable.Value != nil { - value, _ := variables.DocumentToUntyped(entry.Variable.Value) - variable, err := variables.SubstituteAll(logger, ctx, value) - if err != nil { - return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Value, err) - } - if path != "" { - variable, err := applyJMESPath(jp, path, variable) - if err == nil { - output = variable - } else if defaultValue == nil { - return fmt.Errorf("failed to apply jmespath %s to variable %s: %v", path, entry.Variable.Value, err) - } - } else { - output = variable - } - } else { - if path != "" { - if variable, err := ctx.Query(path); err == nil { - if variable != nil { - output = variable - } - } else if defaultValue == nil { - return fmt.Errorf("failed to apply jmespath %s to variable %v", path, err) - } - } - } - logger.V(4).Info("evaluated output", "variable name", entry.Name, "output", output) - if output == nil { - return fmt.Errorf("unable to add context entry for variable %s since it evaluated to nil", entry.Name) - } - if outputBytes, err := json.Marshal(output); err == nil { - return ctx.ReplaceContextEntry(entry.Name, outputBytes) - } else { - return fmt.Errorf("unable to add context entry for variable %s: %w", entry.Name, err) - } -} - -func LoadImageData(ctx context.Context, jp jmespath.Interface, rclientFactory RegistryClientFactory, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) error { - imageData, err := fetchImageData(ctx, jp, rclientFactory, logger, entry, enginectx) - if err != nil { - return err - } - jsonBytes, err := json.Marshal(imageData) - if err != nil { - return err - } - if err := enginectx.AddContextEntry(entry.Name, jsonBytes); err != nil { - return fmt.Errorf("failed to add resource data to context: contextEntry: %v, error: %v", entry, err) - } - return nil -} - -func LoadAPIData(ctx context.Context, jp jmespath.Interface, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, client RawClient) error { - executor, err := apicall.New(logger, jp, entry, enginectx, client) - if err != nil { - return fmt.Errorf("failed to initialize APICall: %w", err) - } - if _, err := executor.FetchAndLoad(ctx); err != nil { - return fmt.Errorf("failed to execute APICall: %w", err) - } - return nil -} - -func LoadConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver ConfigmapResolver) error { - data, err := fetchConfigMap(ctx, logger, entry, enginectx, resolver) - if err != nil { - return fmt.Errorf("failed to retrieve config map for context entry %s: %v", entry.Name, err) - } - err = enginectx.AddContextEntry(entry.Name, data) - if err != nil { - return fmt.Errorf("failed to add config map for context entry %s: %v", entry.Name, err) - } - return nil -} - -func fetchImageData(ctx context.Context, jp jmespath.Interface, rclientFactory RegistryClientFactory, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) (interface{}, error) { - ref, err := variables.SubstituteAll(logger, enginectx, entry.ImageRegistry.Reference) - if err != nil { - return nil, fmt.Errorf("ailed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.Reference, err) - } - refString, ok := ref.(string) - if !ok { - return nil, fmt.Errorf("invalid image reference %s, image reference must be a string", ref) - } - path, err := variables.SubstituteAll(logger, enginectx, entry.ImageRegistry.JMESPath) - if err != nil { - return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.JMESPath, err) - } - client, err := rclientFactory.GetClient(ctx, entry.ImageRegistry.ImageRegistryCredentials) - if err != nil { - return nil, fmt.Errorf("failed to get registry client %s: %v", entry.Name, err) - } - imageData, err := fetchImageDataMap(ctx, client, refString) - if err != nil { - return nil, err - } - if path != "" { - imageData, err = applyJMESPath(jp, path.(string), imageData) - if err != nil { - return nil, fmt.Errorf("failed to apply JMESPath (%s) results to context entry %s, error: %v", entry.ImageRegistry.JMESPath, entry.Name, err) - } - } - return imageData, nil -} - -// FetchImageDataMap fetches image information from the remote registry. -func fetchImageDataMap(ctx context.Context, client ImageDataClient, ref string) (interface{}, error) { - desc, err := client.ForRef(ctx, ref) - if err != nil { - return nil, fmt.Errorf("failed to fetch image descriptor: %s, error: %v", ref, err) - } - var manifest interface{} - if err := json.Unmarshal(desc.Manifest, &manifest); err != nil { - return nil, fmt.Errorf("failed to decode manifest for image reference: %s, error: %v", ref, err) - } - var configData interface{} - if err := json.Unmarshal(desc.Config, &configData); err != nil { - return nil, fmt.Errorf("failed to decode config for image reference: %s, error: %v", ref, err) - } - data := map[string]interface{}{ - "image": desc.Image, - "resolvedImage": desc.ResolvedImage, - "registry": desc.Registry, - "repository": desc.Repository, - "identifier": desc.Identifier, - "manifest": manifest, - "configData": configData, - } - // we need to do the conversion from struct types to an interface type so that jmespath - // evaluation works correctly. go-jmespath cannot handle function calls like max/sum - // for types like integers for eg. the conversion to untyped allows the stdlib json - // to convert all the types to types that are compatible with jmespath. - jsonDoc, err := json.Marshal(data) - if err != nil { - return nil, err - } - - var untyped interface{} - err = json.Unmarshal(jsonDoc, &untyped) - if err != nil { - return nil, err - } - return untyped, nil -} - -func applyJMESPath(jp jmespath.Interface, query string, data interface{}) (interface{}, error) { - q, err := jp.Query(query) - if err != nil { - return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", query, err) - } - return q.Search(data) -} - -func fetchConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver ConfigmapResolver) ([]byte, error) { - contextData := make(map[string]interface{}) - name, err := variables.SubstituteAll(logger, enginectx, entry.ConfigMap.Name) - if err != nil { - return nil, fmt.Errorf("failed to substitute variables in context %s configMap.name %s: %v", entry.Name, entry.ConfigMap.Name, err) - } - namespace, err := variables.SubstituteAll(logger, enginectx, entry.ConfigMap.Namespace) - if err != nil { - return nil, fmt.Errorf("failed to substitute variables in context %s configMap.namespace %s: %v", entry.Name, entry.ConfigMap.Namespace, err) - } - if namespace == "" { - namespace = "default" - } - obj, err := resolver.Get(ctx, namespace.(string), name.(string)) - if err != nil { - return nil, fmt.Errorf("failed to get configmap %s/%s : %v", namespace, name, err) - } - // extract configmap data - contextData["data"] = obj.Data - contextData["metadata"] = obj.ObjectMeta - data, err := json.Marshal(contextData) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal configmap %s/%s: %v", namespace, name, err) - } - return data, nil -} diff --git a/pkg/engine/mutation_test.go b/pkg/engine/mutation_test.go index a077b4f9b2..2266c1f15b 100644 --- a/pkg/engine/mutation_test.go +++ b/pkg/engine/mutation_test.go @@ -11,8 +11,8 @@ import ( "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine/adapters" engineapi "github.com/kyverno/kyverno/pkg/engine/api" + enginecontext "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/factories" - enginetest "github.com/kyverno/kyverno/pkg/engine/test" "github.com/kyverno/kyverno/pkg/registryclient" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" "github.com/stretchr/testify/require" @@ -126,7 +126,7 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) require.Equal(t, 1, len(er.PolicyResponse.Rules)) patched := er.PatchedResource @@ -187,7 +187,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message(), "Unknown key \"name1\" in path")) @@ -252,26 +252,22 @@ func Test_variableSubstitutionCLI(t *testing.T) { policy := loadResource[kyverno.ClusterPolicy](t, policyRaw) resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) + ctxLoaderFactory := factories.DefaultContextLoaderFactory( + nil, + factories.WithInitializer(func(jsonContext enginecontext.Interface) error { + if err := jsonContext.AddVariable("dictionary.data.env", "dev1"); err != nil { + return err + } + return nil + }), + ) er := testMutate( context.TODO(), nil, - registryclient.NewOrDie(), + nil, policyContext, - enginetest.ContextLoaderFactory( - nil, - map[string]enginetest.Policy{ - "cm-variable-example": { - Rules: map[string]enginetest.Rule{ - "example-configmap-lookup": { - Values: map[string]interface{}{ - "dictionary.data.env": "dev1", - }, - }, - }, - }, - }, - ), + ctxLoaderFactory, ) require.Equal(t, 1, len(er.PolicyResponse.Rules)) @@ -361,7 +357,7 @@ func Test_chained_rules(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) require.Equal(t, 2, len(er.PolicyResponse.Rules)) patched := er.PatchedResource @@ -436,7 +432,7 @@ func Test_precondition(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, enginetest.ContextLoaderFactory(nil, nil)) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) require.Equal(t, 1, len(er.PolicyResponse.Rules)) patched := er.PatchedResource @@ -519,7 +515,7 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) { resource := loadUnstructured(t, []byte(resourceRaw)) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, enginetest.ContextLoaderFactory(nil, nil)) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) require.Equal(t, 2, len(er.PolicyResponse.Rules)) patched := er.PatchedResource @@ -629,7 +625,7 @@ func Test_foreach(t *testing.T) { assert.NilError(t, err) policyContext = policyContext.WithPolicy(&policy) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass) @@ -730,7 +726,7 @@ func Test_foreach_element_mutation(t *testing.T) { assert.NilError(t, err) policyContext = policyContext.WithPolicy(&policy) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass) @@ -850,7 +846,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) { assert.NilError(t, err) policyContext = policyContext.WithPolicy(&policy) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass) @@ -958,7 +954,7 @@ func Test_foreach_order_mutation_(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass) @@ -1058,7 +1054,7 @@ func Test_patchStrategicMerge_descending(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass) @@ -1158,7 +1154,7 @@ func Test_patchStrategicMerge_ascending(t *testing.T) { resource := loadUnstructured(t, resourceRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass) @@ -1352,7 +1348,7 @@ func Test_mutate_nested_foreach(t *testing.T) { expected := loadUnstructured(t, expectedRaw) policyContext := createContext(t, &policy, resource, kyverno.Create) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) require.Equal(t, 1, len(er.PolicyResponse.Rules)) require.Equal(t, engineapi.RuleStatusPass, er.PolicyResponse.Rules[0].Status()) @@ -1968,7 +1964,7 @@ func Test_RuleSelectorMutate(t *testing.T) { assert.NilError(t, err) policyContext = policyContext.WithPolicy(&policy) - er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er := testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 2) { @@ -2003,7 +1999,7 @@ func Test_RuleSelectorMutate(t *testing.T) { applyOne := kyverno.ApplyOne policyContext.Policy().GetSpec().ApplyRules = &applyOne - er = testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil) + er = testMutate(context.TODO(), nil, nil, policyContext, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) { @@ -2390,7 +2386,8 @@ func Test_SpecialCharacters(t *testing.T) { policyContext = policyContext.WithPolicy(&policy) // Mutate and make sure that we got the expected amount of rules. - patches := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil).GetPatches() + er := testMutate(context.TODO(), nil, nil, policyContext, nil) + patches := er.GetPatches() assert.Equal(t, len(patches), len(tt.want)) for i := range patches { assert.Equal(t, patches[i].Json(), tt.want[i]) diff --git a/pkg/engine/test/contextloader.go b/pkg/engine/test/contextloader.go deleted file mode 100644 index c48f29e8af..0000000000 --- a/pkg/engine/test/contextloader.go +++ /dev/null @@ -1,80 +0,0 @@ -package test - -import ( - "context" - - "github.com/go-logr/logr" - kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" - engineapi "github.com/kyverno/kyverno/pkg/engine/api" - enginecontext "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/engine/jmespath" - "github.com/kyverno/kyverno/pkg/logging" -) - -type Policy struct { - Rules map[string]Rule -} - -type Rule struct { - Values map[string]interface{} -} - -func ContextLoaderFactory( - cmResolver engineapi.ConfigmapResolver, - values map[string]Policy, -) engineapi.ContextLoaderFactory { - return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader { - return &mockContextLoader{ - logger: logging.WithName("MockContextLoaderFactory"), - policyName: policy.GetName(), - ruleName: rule.Name, - values: values, - } - } -} - -type mockContextLoader struct { - logger logr.Logger - policyName string - ruleName string - values map[string]Policy - allowApiCall bool -} - -func (l *mockContextLoader) Load( - ctx context.Context, - jp jmespath.Interface, - client engineapi.RawClient, - rclientFactory engineapi.RegistryClientFactory, - contextEntries []kyvernov1.ContextEntry, - jsonContext enginecontext.Interface, -) error { - if l.values != nil { - policy := l.values[l.policyName] - if policy.Rules != nil { - rule := policy.Rules[l.ruleName] - for key, value := range rule.Values { - if err := jsonContext.AddVariable(key, value); err != nil { - return err - } - } - } - } - // Context Variable should be loaded after the values loaded from values file - for _, entry := range contextEntries { - if entry.ImageRegistry != nil && rclientFactory != nil { - if err := engineapi.LoadImageData(ctx, jp, rclientFactory, l.logger, entry, jsonContext); err != nil { - return err - } - } else if entry.Variable != nil { - if err := engineapi.LoadVariable(l.logger, jp, entry, jsonContext); err != nil { - return err - } - } else if entry.APICall != nil && l.allowApiCall { - if err := engineapi.LoadAPIData(ctx, jp, l.logger, entry, jsonContext, client); err != nil { - return err - } - } - } - return nil -} diff --git a/pkg/engine/validation_test.go b/pkg/engine/validation_test.go index d8e1527da9..00b32dbbe9 100644 --- a/pkg/engine/validation_test.go +++ b/pkg/engine/validation_test.go @@ -6,15 +6,13 @@ import ( "strings" "testing" - kyverno "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" - urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine/adapters" engineapi "github.com/kyverno/kyverno/pkg/engine/api" + enginecontext "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/factories" - enginetest "github.com/kyverno/kyverno/pkg/engine/test" "github.com/kyverno/kyverno/pkg/registryclient" admissionutils "github.com/kyverno/kyverno/pkg/utils/admission" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" @@ -143,7 +141,7 @@ func TestValidate_image_tag_fail(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) @@ -154,7 +152,7 @@ func TestValidate_image_tag_fail(t *testing.T) { "validation error: imagePullPolicy 'Always' required with tag 'latest'. rule validate-latest failed at path /spec/containers/0/imagePullPolicy/", } - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) for index, r := range er.PolicyResponse.Rules { assert.Equal(t, r.Message(), msgs[index]) } @@ -244,7 +242,7 @@ func TestValidate_image_tag_pass(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) @@ -254,7 +252,7 @@ func TestValidate_image_tag_pass(t *testing.T) { "validation rule 'validate-tag' passed.", "validation rule 'validate-latest' passed.", } - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) for index, r := range er.PolicyResponse.Rules { assert.Equal(t, r.Message(), msgs[index]) } @@ -322,13 +320,13 @@ func TestValidate_Fail_anyPattern(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) assert.Assert(t, !er.IsSuccessful()) msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"} @@ -405,13 +403,13 @@ func TestValidate_host_network_port(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"} for index, r := range er.PolicyResponse.Rules { @@ -495,13 +493,13 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) { } } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'validate-host-path' passed."} for index, r := range er.PolicyResponse.Rules { @@ -584,12 +582,12 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) { } } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"} for index, r := range er.PolicyResponse.Rules { @@ -653,13 +651,13 @@ func TestValidate_anchor_map_notfound(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'pod rule 2' passed."} for index, r := range er.PolicyResponse.Rules { @@ -726,13 +724,13 @@ func TestValidate_anchor_map_found_valid(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'pod rule 2' passed."} for index, r := range er.PolicyResponse.Rules { @@ -800,13 +798,13 @@ func TestValidate_inequality_List_Processing(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'pod rule 2' passed."} for index, r := range er.PolicyResponse.Rules { @@ -880,13 +878,13 @@ func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'pod rule 2' passed."} for index, r := range er.PolicyResponse.Rules { @@ -954,13 +952,13 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"} for index, r := range er.PolicyResponse.Rules { @@ -1029,13 +1027,13 @@ func TestValidate_AnchorList_pass(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'pod image rule' passed."} for index, r := range er.PolicyResponse.Rules { @@ -1104,13 +1102,13 @@ func TestValidate_AnchorList_fail(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) assert.Assert(t, !er.IsSuccessful()) } @@ -1174,13 +1172,13 @@ func TestValidate_existenceAnchor_fail(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) assert.Assert(t, !er.IsSuccessful()) } @@ -1244,13 +1242,13 @@ func TestValidate_existenceAnchor_pass(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'pod image rule' passed."} for index, r := range er.PolicyResponse.Rules { @@ -1332,13 +1330,13 @@ func TestValidate_negationAnchor_deny(t *testing.T) { } } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"} for index, r := range er.PolicyResponse.Rules { @@ -1419,13 +1417,13 @@ func TestValidate_negationAnchor_pass(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) msgs := []string{"validation rule 'validate-host-path' passed."} for index, r := range er.PolicyResponse.Rules { @@ -1487,13 +1485,13 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) { } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(policyraw, &policy) assert.NilError(t, err) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) @@ -1574,12 +1572,12 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyraw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) @@ -1628,12 +1626,12 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) { } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyraw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail) assert.Equal(t, er.PolicyResponse.Rules[0].Message(), "validation error: rule not-operator-with-variable-should-alway-fail-validation failed at path /spec/content/") @@ -1712,12 +1710,12 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyraw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) assert.Equal(t, len(er.PolicyResponse.Rules), 1) @@ -1798,12 +1796,12 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyraw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail) @@ -1896,12 +1894,12 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing. } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyraw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail) assert.Equal(t, er.PolicyResponse.Rules[0].Message(), "The animal cow is not in the allowed list of animals.") @@ -1942,12 +1940,12 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) { } for _, test := range tests { - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(test.policyRaw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(test.resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy) + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil) for i, rule := range er.PolicyResponse.Rules { @@ -2121,7 +2119,7 @@ func Test_denyFeatureIssue744_BlockDelete(t *testing.T) { } func executeTest(t *testing.T, test testCase) { - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(test.policy, &policy) if err != nil { t.Fatal(err) @@ -2133,7 +2131,7 @@ func executeTest(t *testing.T, test testCase) { t.Fatal(err) } - var userInfo urkyverno.RequestInfo + var userInfo kyvernov1beta1.RequestInfo err = json.Unmarshal(test.userInfo, &userInfo) if err != nil { t.Fatal(err) @@ -2219,7 +2217,7 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) { } `) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(rawPolicy, &policy) assert.NilError(t, err) @@ -2228,25 +2226,22 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) { msgs := []string{ "restrict pod counts to be no more than 10 on node minikube", } + ctxLoaderFactory := factories.DefaultContextLoaderFactory( + nil, + factories.WithInitializer(func(jsonContext enginecontext.Interface) error { + if err := jsonContext.AddVariable("podcounts", "12"); err != nil { + return err + } + + return nil + }), + ) er := testValidate( context.TODO(), registryclient.NewOrDie(), - newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), + newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, - enginetest.ContextLoaderFactory( - nil, - map[string]enginetest.Policy{ - "restrict-pod-count": { - Rules: map[string]enginetest.Rule{ - "restrict-pod-count": { - Values: map[string]interface{}{ - "podcounts": "12", - }, - }, - }, - }, - }, - ), + ctxLoaderFactory, ) for index, r := range er.PolicyResponse.Rules { assert.Equal(t, r.Message(), msgs[index]) @@ -2325,7 +2320,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) { } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(policyRaw, &policy) assert.NilError(t, err) @@ -2333,7 +2328,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) { assert.NilError(t, err) er := testValidate(context.TODO(), registryclient.NewOrDie(), - newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil). + newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil). WithPolicy(&policy), cfg, nil) assert.Assert(t, !er.IsSuccessful()) @@ -2413,7 +2408,7 @@ func Test_StringInDenyCondition(t *testing.T) { } }`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy err := json.Unmarshal(policyRaw, &policy) assert.NilError(t, err) @@ -2421,7 +2416,7 @@ func Test_StringInDenyCondition(t *testing.T) { assert.NilError(t, err) er := testValidate(context.TODO(), registryclient.NewOrDie(), - newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil). + newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil). WithPolicy(&policy), cfg, nil) assert.Assert(t, er.IsSuccessful()) @@ -2730,28 +2725,25 @@ func Test_foreach_context_preconditions(t *testing.T) { ] } }`) - + ctxLoaderFactory := factories.DefaultContextLoaderFactory( + nil, + factories.WithInitializer(func(jsonContext enginecontext.Interface) error { + if err := jsonContext.AddVariable("img.data.podvalid", "nginx/nginx:v1"); err != nil { + return err + } + if err := jsonContext.AddVariable("img.data.podinvalid", "nginx/nginx:v2"); err != nil { + return err + } + return nil + }), + ) testForEach( t, policyraw, resourceRaw, "", engineapi.RuleStatusPass, - enginetest.ContextLoaderFactory( - nil, - map[string]enginetest.Policy{ - "test": { - Rules: map[string]enginetest.Rule{ - "test": { - Values: map[string]interface{}{ - "img.data.podvalid": "nginx/nginx:v1", - "img.data.podinvalid": "nginx/nginx:v2", - }, - }, - }, - }, - }, - ), + ctxLoaderFactory, ) } @@ -2825,28 +2817,25 @@ func Test_foreach_context_preconditions_fail(t *testing.T) { ] } }`) - + ctxLoaderFactory := factories.DefaultContextLoaderFactory( + nil, + factories.WithInitializer(func(jsonContext enginecontext.Interface) error { + if err := jsonContext.AddVariable("img.data.podvalid", "nginx/nginx:v1"); err != nil { + return err + } + if err := jsonContext.AddVariable("img.data.podinvalid", "nginx/nginx:v1"); err != nil { + return err + } + return nil + }), + ) testForEach( t, policyraw, resourceRaw, "", engineapi.RuleStatusFail, - enginetest.ContextLoaderFactory( - nil, - map[string]enginetest.Policy{ - "test": { - Rules: map[string]enginetest.Rule{ - "test": { - Values: map[string]interface{}{ - "img.data.podvalid": "nginx/nginx:v1", - "img.data.podinvalid": "nginx/nginx:v1", - }, - }, - }, - }, - }, - ), + ctxLoaderFactory, ) } @@ -3090,12 +3079,12 @@ func Test_foreach_validate_nested(t *testing.T) { } func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string, status engineapi.RuleStatus, contextLoader engineapi.ContextLoaderFactory) { - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyraw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContext := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil). + policyContext := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil). WithPolicy(&policy) er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, contextLoader) @@ -3148,19 +3137,19 @@ func Test_delete_ignore_pattern(t *testing.T) { } }}]}}`) - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy assert.NilError(t, json.Unmarshal(policyRaw, &policy)) resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw) assert.NilError(t, err) - policyContextCreate := newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil). + policyContextCreate := newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil). WithPolicy(&policy) engineResponseCreate := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextCreate, cfg, nil) assert.Equal(t, len(engineResponseCreate.PolicyResponse.Rules), 1) assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail) - policyContextDelete := newPolicyContext(t, *resourceUnstructured, kyverno.Delete, nil). + policyContextDelete := newPolicyContext(t, *resourceUnstructured, kyvernov1.Delete, nil). WithPolicy(&policy) engineResponseDelete := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextDelete, cfg, nil) @@ -3184,7 +3173,7 @@ func Test_block_bypass(t *testing.T) { } func Test_ValidatePattern_anyPattern(t *testing.T) { - var policy kyverno.ClusterPolicy + var policy kyvernov1.ClusterPolicy rawPolicy := []byte(`{"apiVersion":"kyverno.io\/v1","kind":"ClusterPolicy","metadata":{"name":"validate-service-loadbalancer"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"check-loadbalancer-public","match":{"resources":{"kinds":["Service"]}},"validate":{"message":"Service of type 'LoadBalancer' is public and does not explicitly define network security. To use a public LB you must supply either spec[loadBalancerSourceRanges] or the 'service.beta.kubernetes.io\/aws-load-balancer-security-groups' annotation.","anyPattern":[{"spec":{"<(type)":"LoadBalancer"},"metadata":{"annotations":{"service.beta.kubernetes.io\/aws-load-balancer-security-groups":"?*"}}},{"spec":{"<(type)":"LoadBalancer","loadBalancerSourceRanges":"*"}}]}},{"name":"check-loadbalancer-internal","match":{"resources":{"kinds":["Service"]}},"validate":{"message":"Service of type 'LoadBalancer' is internal and does not explicitly define network security. To set the LB to internal, use annotation 'service.beta.kubernetes.io\/aws-load-balancer-internal' with value 'true' or '0.0.0.0\/0' ","pattern":{"spec":{"<(type)":"LoadBalancer"},"metadata":{"annotations":{"=(service.beta.kubernetes.io\/aws-load-balancer-internal)":"0.0.0.0\/0|true"}}}}}]}}`) testCases := []struct { description string @@ -3222,7 +3211,7 @@ func Test_ValidatePattern_anyPattern(t *testing.T) { resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource) assert.NilError(t, err) - er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyverno.Create, nil).WithPolicy(&policy), cfg, nil) + er := testValidate(context.TODO(), registryclient.NewOrDie(), newPolicyContext(t, *resourceUnstructured, kyvernov1.Create, nil).WithPolicy(&policy), cfg, nil) if tc.expectedFailed { assert.Assert(t, er.IsFailed()) } else if tc.expectedSkipped { diff --git a/test/cli/registry/kyverno-test.yaml b/test/cli/registry/kyverno-test.yaml index c93686bd75..5e43763c7e 100644 --- a/test/cli/registry/kyverno-test.yaml +++ b/test/cli/registry/kyverno-test.yaml @@ -1,4 +1,4 @@ -name: test-variables +name: test-registry policies: - image-example.yaml resources: diff --git a/test/cli/test/context-entries/kyverno-test.yaml b/test/cli/test/context-entries/kyverno-test.yaml index 656909c19b..8cd50a1b90 100644 --- a/test/cli/test/context-entries/kyverno-test.yaml +++ b/test/cli/test/context-entries/kyverno-test.yaml @@ -1,4 +1,4 @@ -name: test-variables +name: test-context-entries policies: - policies.yaml resources: