diff --git a/cmd/background-controller/main.go b/cmd/background-controller/main.go index 69759dfa99..f7bc6cb41c 100644 --- a/cmd/background-controller/main.go +++ b/cmd/background-controller/main.go @@ -214,7 +214,8 @@ func main() { engine := engine.NewEngine( configuration, dClient, - engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver), + rclient, + engine.LegacyContextLoaderFactory(configMapResolver), // TODO: do we need exceptions here ? nil, ) diff --git a/cmd/cli/kubectl-kyverno/utils/common/common.go b/cmd/cli/kubectl-kyverno/utils/common/common.go index 9480f01d59..e9634d0aa2 100644 --- a/cmd/cli/kubectl-kyverno/utils/common/common.go +++ b/cmd/cli/kubectl-kyverno/utils/common/common.go @@ -477,7 +477,8 @@ OuterLoop: eng := engine.NewEngine( cfg, c.Client, - engine.LegacyContextLoaderFactory(c.Client, registryclient.NewOrDie(), nil), + registryclient.NewOrDie(), + engine.LegacyContextLoaderFactory(nil), nil, ) policyContext := engine.NewPolicyContextWithJsonContext(ctx). @@ -525,11 +526,7 @@ OuterLoop: engineResponses = append(engineResponses, validateResponse) } - verifyImageResponse, _ := eng.VerifyAndPatchImages( - context.Background(), - registryclient.NewOrDie(), - policyContext, - ) + verifyImageResponse, _ := eng.VerifyAndPatchImages(context.TODO(), policyContext) if verifyImageResponse != nil && !verifyImageResponse.IsEmpty() { engineResponses = append(engineResponses, verifyImageResponse) info = ProcessValidateEngineResponse(c.Policy, verifyImageResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn) @@ -543,9 +540,7 @@ OuterLoop: } if policyHasGenerate { - generateResponse := eng.ApplyBackgroundChecks( - policyContext, - ) + generateResponse := eng.ApplyBackgroundChecks(context.TODO(), policyContext) if generateResponse != nil && !generateResponse.IsEmpty() { newRuleResponse, err := handleGeneratePolicy(generateResponse, *policyContext, c.RuleToCloneSourceResource) if err != nil { @@ -1081,7 +1076,8 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr c := generate.NewGenerateControllerWithOnlyClient(client, engine.NewEngine( config.NewDefaultConfiguration(), client, - engine.LegacyContextLoaderFactory(client, nil, nil), + nil, + engine.LegacyContextLoaderFactory(nil), nil, )) return c, nil diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index f5d7c77f25..f4dd44884d 100644 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -367,7 +367,8 @@ func main() { eng := engine.NewEngine( configuration, dClient, - engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver), + rclient, + engine.LegacyContextLoaderFactory(configMapResolver), exceptionsLister, ) // create non leader controllers diff --git a/cmd/reports-controller/main.go b/cmd/reports-controller/main.go index 75493be2ea..a21675adeb 100644 --- a/cmd/reports-controller/main.go +++ b/cmd/reports-controller/main.go @@ -129,7 +129,6 @@ func createReportControllers( backgroundscancontroller.NewController( client, kyvernoClient, - rclient, eng, metadataFactory, kyvernoV1.Policies(), @@ -315,7 +314,8 @@ func main() { eng := engine.NewEngine( configuration, dClient, - engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver), + rclient, + engine.LegacyContextLoaderFactory(configMapResolver), exceptionsLister, ) // setup leader election diff --git a/pkg/background/generate/generate.go b/pkg/background/generate/generate.go index 4507c56580..eb249f1e2a 100644 --- a/pkg/background/generate/generate.go +++ b/pkg/background/generate/generate.go @@ -197,7 +197,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u } // check if the policy still applies to the resource - engineResponse := c.engine.GenerateResponse(policyContext, ur) + engineResponse := c.engine.GenerateResponse(context.Background(), policyContext, ur) if len(engineResponse.PolicyResponse.Rules) == 0 { logger.V(4).Info(doesNotApply) return nil, false, errors.New(doesNotApply) @@ -343,7 +343,7 @@ func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext } // add configmap json data to context - if err := c.engine.ContextLoader(policyContext, rule.Name).Load(context.TODO(), rule.Context, policyContext.JSONContext()); err != nil { + if err := c.engine.ContextLoader(policyContext.Policy(), rule)(context.TODO(), rule.Context, policyContext.JSONContext()); err != nil { log.Error(err, "cannot add configmaps to context") return nil, processExisting, err } diff --git a/pkg/controllers/report/background/controller.go b/pkg/controllers/report/background/controller.go index 382131946f..a3e859a94f 100644 --- a/pkg/controllers/report/background/controller.go +++ b/pkg/controllers/report/background/controller.go @@ -19,7 +19,6 @@ import ( "github.com/kyverno/kyverno/pkg/controllers/report/utils" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/event" - "github.com/kyverno/kyverno/pkg/registryclient" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" reportutils "github.com/kyverno/kyverno/pkg/utils/report" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -47,7 +46,6 @@ type controller struct { // clients client dclient.Interface kyvernoClient versioned.Interface - rclient registryclient.Client engine engineapi.Engine // listers @@ -73,7 +71,6 @@ type controller struct { func NewController( client dclient.Interface, kyvernoClient versioned.Interface, - rclient registryclient.Client, engine engineapi.Engine, metadataFactory metadatainformers.SharedInformerFactory, polInformer kyvernov1informers.PolicyInformer, @@ -91,7 +88,6 @@ func NewController( c := controller{ client: client, kyvernoClient: kyvernoClient, - rclient: rclient, engine: engine, polLister: polInformer.Lister(), cpolLister: cpolInformer.Lister(), @@ -308,7 +304,7 @@ func (c *controller) reconcileReport( // calculate necessary results for _, policy := range backgroundPolicies { if full || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() { - scanner := utils.NewScanner(logger, c.engine, c.client, c.rclient, c.config) + scanner := utils.NewScanner(logger, c.engine, c.config) for _, result := range scanner.ScanResource(ctx, *target, nsLabels, policy) { if result.Error != nil { return result.Error diff --git a/pkg/controllers/report/utils/scanner.go b/pkg/controllers/report/utils/scanner.go index 238acb7807..4fb212618c 100644 --- a/pkg/controllers/report/utils/scanner.go +++ b/pkg/controllers/report/utils/scanner.go @@ -5,22 +5,18 @@ import ( "github.com/go-logr/logr" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" - "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" engineapi "github.com/kyverno/kyverno/pkg/engine/api" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" - "github.com/kyverno/kyverno/pkg/registryclient" "go.uber.org/multierr" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) type scanner struct { - logger logr.Logger - engine engineapi.Engine - client dclient.Interface - rclient registryclient.Client - config config.Configuration + logger logr.Logger + engine engineapi.Engine + config config.Configuration } type ScanResult struct { @@ -35,16 +31,12 @@ type Scanner interface { func NewScanner( logger logr.Logger, engine engineapi.Engine, - client dclient.Interface, - rclient registryclient.Client, config config.Configuration, ) Scanner { return &scanner{ - logger: logger, - engine: engine, - client: client, - rclient: rclient, - config: config, + logger: logger, + engine: engine, + config: config, } } @@ -114,7 +106,7 @@ func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unst WithNewResource(resource). WithPolicy(policy). WithNamespaceLabels(nsLabels) - response, _ := s.engine.VerifyAndPatchImages(ctx, s.rclient, policyCtx) + response, _ := s.engine.VerifyAndPatchImages(ctx, policyCtx) if len(response.PolicyResponse.Rules) > 0 { s.logger.Info("validateImages", "policy", policy, "response", response) } diff --git a/pkg/engine/api/contextloader.go b/pkg/engine/api/contextloader.go index ed99fbe452..92e6b790bd 100644 --- a/pkg/engine/api/contextloader.go +++ b/pkg/engine/api/contextloader.go @@ -4,13 +4,22 @@ import ( "context" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" + "github.com/kyverno/kyverno/pkg/clients/dclient" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" + "github.com/kyverno/kyverno/pkg/registryclient" ) // ContextLoaderFactory provides a ContextLoader given a policy context and rule name -type ContextLoaderFactory = func(pContext PolicyContext, ruleName string) ContextLoader +type ContextLoaderFactory = func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) ContextLoader // ContextLoader abstracts the mechanics to load context entries in the underlying json context type ContextLoader interface { - Load(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error + Load( + ctx context.Context, + client dclient.Interface, + rclient registryclient.Client, + exceptionSelector PolicyExceptionSelector, + contextEntries []kyvernov1.ContextEntry, + jsonContext enginecontext.Interface, + ) error } diff --git a/pkg/engine/api/engine.go b/pkg/engine/api/engine.go index e969f5b1de..e7f85bd9eb 100644 --- a/pkg/engine/api/engine.go +++ b/pkg/engine/api/engine.go @@ -3,10 +3,13 @@ package api import ( "context" + kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" - "github.com/kyverno/kyverno/pkg/registryclient" + enginecontext "github.com/kyverno/kyverno/pkg/engine/context" ) +type EngineContextLoader = func(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error + // Engine is the main interface to run policies against resources type Engine interface { // Validate applies validation rules from policy on the resource @@ -24,7 +27,6 @@ type Engine interface { // VerifyAndPatchImages ... VerifyAndPatchImages( ctx context.Context, - rclient registryclient.Client, policyContext PolicyContext, ) (*EngineResponse, *ImageVerificationMetadata) @@ -34,17 +36,19 @@ type Engine interface { // // 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed ApplyBackgroundChecks( + ctx context.Context, policyContext PolicyContext, ) *EngineResponse // GenerateResponse checks for validity of generate rule on the resource GenerateResponse( + ctx context.Context, policyContext PolicyContext, gr kyvernov1beta1.UpdateRequest, ) *EngineResponse ContextLoader( - policyContext PolicyContext, - ruleName string, - ) ContextLoader + policy kyvernov1.PolicyInterface, + rule kyvernov1.Rule, + ) EngineContextLoader } diff --git a/pkg/engine/background.go b/pkg/engine/background.go index 7b40ba879a..1e5679663c 100644 --- a/pkg/engine/background.go +++ b/pkg/engine/background.go @@ -19,6 +19,7 @@ import ( // // 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed func (e *engine) applyBackgroundChecks( + ctx context.Context, policyContext engineapi.PolicyContext, ) (resp *engineapi.EngineResponse) { policyStartTime := time.Now() @@ -132,7 +133,7 @@ func (e *engine) filterRule( policyContext.JSONContext().Checkpoint() defer policyContext.JSONContext().Restore() - if err := internal.LoadContext(context.TODO(), e.contextLoader, rule.Context, policyContext, rule.Name); err != nil { + if err := internal.LoadContext(context.TODO(), e, policyContext, rule); err != nil { logger.V(4).Info("cannot add external data to the context", "reason", err.Error()) return nil } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 6562c5c478..746ec0e12e 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -3,16 +3,19 @@ package engine import ( "context" + kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" + enginecontext "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/registryclient" ) type engine struct { configuration config.Configuration client dclient.Interface + rclient registryclient.Client contextLoader engineapi.ContextLoaderFactory exceptionSelector engineapi.PolicyExceptionSelector } @@ -20,12 +23,14 @@ type engine struct { func NewEngine( configuration config.Configuration, client dclient.Interface, + rclient registryclient.Client, contextLoader engineapi.ContextLoaderFactory, exceptionSelector engineapi.PolicyExceptionSelector, ) engineapi.Engine { return &engine{ configuration: configuration, client: client, + rclient: rclient, contextLoader: contextLoader, exceptionSelector: exceptionSelector, } @@ -47,28 +52,39 @@ func (e *engine) Mutate( func (e *engine) VerifyAndPatchImages( ctx context.Context, - rclient registryclient.Client, policyContext engineapi.PolicyContext, ) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) { - return e.verifyAndPatchImages(ctx, rclient, policyContext) + return e.verifyAndPatchImages(ctx, policyContext) } func (e *engine) ApplyBackgroundChecks( + ctx context.Context, policyContext engineapi.PolicyContext, ) *engineapi.EngineResponse { - return e.applyBackgroundChecks(policyContext) + return e.applyBackgroundChecks(ctx, policyContext) } func (e *engine) GenerateResponse( + ctx context.Context, policyContext engineapi.PolicyContext, gr kyvernov1beta1.UpdateRequest, ) *engineapi.EngineResponse { - return e.generateResponse(policyContext, gr) + return e.generateResponse(ctx, policyContext, gr) } func (e *engine) ContextLoader( - policyContext engineapi.PolicyContext, - ruleName string, -) engineapi.ContextLoader { - return e.contextLoader(policyContext, ruleName) + policy kyvernov1.PolicyInterface, + rule kyvernov1.Rule, +) engineapi.EngineContextLoader { + loader := e.contextLoader(policy, rule) + return func(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error { + return loader.Load( + ctx, + e.client, + e.rclient, + e.exceptionSelector, + contextEntries, + jsonContext, + ) + } } diff --git a/pkg/engine/generation.go b/pkg/engine/generation.go index 5ef86ad24f..1a8372485e 100644 --- a/pkg/engine/generation.go +++ b/pkg/engine/generation.go @@ -1,6 +1,7 @@ package engine import ( + "context" "time" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" @@ -12,6 +13,7 @@ import ( // GenerateResponse checks for validity of generate rule on the resource func (e *engine) generateResponse( + ctx context.Context, policyContext engineapi.PolicyContext, gr kyvernov1beta1.UpdateRequest, ) (resp *engineapi.EngineResponse) { diff --git a/pkg/engine/imageVerify.go b/pkg/engine/imageVerify.go index 4f776e4819..2ffbb0df7f 100644 --- a/pkg/engine/imageVerify.go +++ b/pkg/engine/imageVerify.go @@ -14,7 +14,6 @@ import ( "github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/logging" - "github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/tracing" apiutils "github.com/kyverno/kyverno/pkg/utils/api" "github.com/kyverno/kyverno/pkg/utils/wildcard" @@ -23,7 +22,6 @@ import ( func (e *engine) verifyAndPatchImages( ctx context.Context, - rclient registryclient.Client, policyContext engineapi.PolicyContext, ) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) { resp := &engineapi.EngineResponse{} @@ -98,7 +96,7 @@ func (e *engine) verifyAndPatchImages( return } policyContext.JSONContext().Restore() - if err := internal.LoadContext(ctx, e.contextLoader, rule.Context, policyContext, rule.Name); err != nil { + if err := internal.LoadContext(ctx, e, policyContext, *rule); err != nil { internal.AddRuleResponse( &resp.PolicyResponse, internal.RuleError(rule, engineapi.ImageVerify, "failed to load context", err), @@ -117,7 +115,7 @@ func (e *engine) verifyAndPatchImages( } iv := internal.NewImageVerifier( logger, - rclient, + e.rclient, policyContext, ruleCopy, ivm, diff --git a/pkg/engine/imageVerifyValidate.go b/pkg/engine/imageVerifyValidate.go index f2037d7a7e..0d85c72878 100644 --- a/pkg/engine/imageVerifyValidate.go +++ b/pkg/engine/imageVerifyValidate.go @@ -32,7 +32,7 @@ func (e *engine) processImageValidationRule( if len(matchingImages) == 0 { return internal.RuleSkip(rule, engineapi.Validation, "image verified") } - if err := internal.LoadContext(ctx, e.contextLoader, rule.Context, enginectx, rule.Name); err != nil { + if err := internal.LoadContext(ctx, e, enginectx, *rule); err != nil { if _, ok := err.(gojmespath.NotFoundError); ok { log.V(3).Info("failed to load context", "reason", err.Error()) } else { diff --git a/pkg/engine/imageVerify_test.go b/pkg/engine/imageVerify_test.go index 3fbf56af05..98aa7d2bfe 100644 --- a/pkg/engine/imageVerify_test.go +++ b/pkg/engine/imageVerify_test.go @@ -171,12 +171,12 @@ func testVerifyAndPatchImages( e := NewEngine( cfg, nil, - LegacyContextLoaderFactory(nil, rclient, cmResolver), + rclient, + LegacyContextLoaderFactory(cmResolver), nil, ) return e.VerifyAndPatchImages( ctx, - rclient, pContext, ) } diff --git a/pkg/engine/internal/context.go b/pkg/engine/internal/context.go index 43b04cb42a..6d9d1f09f6 100644 --- a/pkg/engine/internal/context.go +++ b/pkg/engine/internal/context.go @@ -7,6 +7,12 @@ import ( engineapi "github.com/kyverno/kyverno/pkg/engine/api" ) -func LoadContext(ctx context.Context, factory engineapi.ContextLoaderFactory, contextEntries []kyvernov1.ContextEntry, pContext engineapi.PolicyContext, ruleName string) error { - return factory(pContext, ruleName).Load(ctx, contextEntries, pContext.JSONContext()) +func LoadContext( + ctx context.Context, + engine engineapi.Engine, + pContext engineapi.PolicyContext, + rule kyvernov1.Rule, +) error { + loader := engine.ContextLoader(pContext.Policy(), rule) + return loader(ctx, rule.Context, pContext.JSONContext()) } diff --git a/pkg/engine/jsonContext.go b/pkg/engine/jsonContext.go index 076341243c..cb48e92ae6 100644 --- a/pkg/engine/jsonContext.go +++ b/pkg/engine/jsonContext.go @@ -19,56 +19,52 @@ import ( ) func LegacyContextLoaderFactory( - client dclient.Interface, - rclient registryclient.Client, cmResolver engineapi.ConfigmapResolver, ) engineapi.ContextLoaderFactory { - if store.IsMock() { - return func(pContext engineapi.PolicyContext, ruleName string) engineapi.ContextLoader { - policy := pContext.Policy() + return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader { + if store.IsMock() { return &mockContextLoader{ logger: logging.WithName("MockContextLoaderFactory"), policyName: policy.GetName(), - ruleName: ruleName, - client: client, - rclient: rclient, + ruleName: rule.Name, + } + } else { + return &contextLoader{ + logger: logging.WithName("LegacyContextLoaderFactory"), cmResolver: cmResolver, } } } - return func(pContext engineapi.PolicyContext, ruleName string) engineapi.ContextLoader { - return &contextLoader{ - logger: logging.WithName("LegacyContextLoaderFactory"), - client: client, - rclient: rclient, - cmResolver: cmResolver, - } - } } type contextLoader struct { logger logr.Logger - rclient registryclient.Client - client dclient.Interface cmResolver engineapi.ConfigmapResolver } -func (l *contextLoader) Load(ctx context.Context, contextEntries []kyvernov1.ContextEntry, enginectx enginecontext.Interface) error { +func (l *contextLoader) Load( + ctx context.Context, + client dclient.Interface, + rclient registryclient.Client, + exceptionSelector engineapi.PolicyExceptionSelector, + contextEntries []kyvernov1.ContextEntry, + jsonContext enginecontext.Interface, +) error { for _, entry := range contextEntries { if entry.ConfigMap != nil { - if err := loadConfigMap(ctx, l.logger, entry, enginectx, l.cmResolver); err != nil { + if err := loadConfigMap(ctx, l.logger, entry, jsonContext, l.cmResolver); err != nil { return err } } else if entry.APICall != nil { - if err := loadAPIData(ctx, l.logger, entry, enginectx, l.client); err != nil { + if err := loadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil { return err } } else if entry.ImageRegistry != nil { - if err := loadImageData(ctx, l.rclient, l.logger, entry, enginectx); err != nil { + if err := loadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil { return err } } else if entry.Variable != nil { - if err := loadVariable(l.logger, entry, enginectx); err != nil { + if err := loadVariable(l.logger, entry, jsonContext); err != nil { return err } } @@ -80,17 +76,21 @@ type mockContextLoader struct { logger logr.Logger policyName string ruleName string - rclient registryclient.Client - client dclient.Interface - cmResolver engineapi.ConfigmapResolver } -func (l *mockContextLoader) Load(ctx context.Context, contextEntries []kyvernov1.ContextEntry, enginectx enginecontext.Interface) error { +func (l *mockContextLoader) Load( + ctx context.Context, + client dclient.Interface, + _ registryclient.Client, + _ engineapi.PolicyExceptionSelector, + contextEntries []kyvernov1.ContextEntry, + jsonContext enginecontext.Interface, +) error { rule := store.GetPolicyRule(l.policyName, l.ruleName) if rule != nil && len(rule.Values) > 0 { variables := rule.Values for key, value := range variables { - if err := enginectx.AddVariable(key, value); err != nil { + if err := jsonContext.AddVariable(key, value); err != nil { return err } } @@ -100,22 +100,22 @@ func (l *mockContextLoader) Load(ctx context.Context, contextEntries []kyvernov1 for _, entry := range contextEntries { if entry.ImageRegistry != nil && hasRegistryAccess { rclient := store.GetRegistryClient() - if err := loadImageData(ctx, rclient, l.logger, entry, enginectx); err != nil { + if err := loadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil { return err } } else if entry.Variable != nil { - if err := loadVariable(l.logger, entry, enginectx); err != nil { + if err := loadVariable(l.logger, entry, jsonContext); err != nil { return err } } else if entry.APICall != nil && store.IsApiCallAllowed() { - if err := loadAPIData(ctx, l.logger, entry, enginectx, l.client); err != nil { + if err := loadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil { return err } } } if rule != nil && len(rule.ForEachValues) > 0 { for key, value := range rule.ForEachValues { - if err := enginectx.AddVariable(key, value[store.GetForeachElement()]); err != nil { + if err := jsonContext.AddVariable(key, value[store.GetForeachElement()]); err != nil { return err } } diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index 8ebb3c21f9..b4ff0a5f30 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -91,7 +91,7 @@ func (e *engine) mutate( logger.Error(err, "failed to query resource object") } - if err := internal.LoadContext(ctx, e.contextLoader, rule.Context, policyContext, rule.Name); err != nil { + if err := internal.LoadContext(ctx, e, policyContext, rule); err != nil { if _, ok := err.(gojmespath.NotFoundError); ok { logger.V(3).Info("failed to load context", "reason", err.Error()) } else { @@ -144,7 +144,7 @@ func (e *engine) mutate( policyContext: policyContext, resource: patchedResource, log: logger, - contextLoader: e.contextLoader, + contextLoader: e.ContextLoader(policyContext.Policy(), *ruleCopy), nesting: 0, } @@ -198,7 +198,7 @@ type forEachMutator struct { foreach []kyvernov1.ForEachMutation resource resourceInfo nesting int - contextLoader engineapi.ContextLoaderFactory + contextLoader engineapi.EngineContextLoader log logr.Logger } @@ -207,7 +207,7 @@ func (f *forEachMutator) mutateForEach(ctx context.Context) *mutate.Response { allPatches := make([][]byte, 0) for _, foreach := range f.foreach { - if err := internal.LoadContext(ctx, f.contextLoader, f.rule.Context, f.policyContext, f.rule.Name); err != nil { + if err := f.contextLoader(ctx, f.rule.Context, f.policyContext.JSONContext()); err != nil { f.log.Error(err, "failed to load context") return mutate.NewErrorResponse("failed to load context", err) } @@ -272,7 +272,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F return mutate.NewErrorResponse(fmt.Sprintf("failed to add element to mutate.foreach[%d].context", index), err) } - if err := internal.LoadContext(ctx, f.contextLoader, foreach.Context, policyContext, f.rule.Name); err != nil { + if err := f.contextLoader(ctx, foreach.Context, policyContext.JSONContext()); err != nil { return mutate.NewErrorResponse(fmt.Sprintf("failed to load to mutate.foreach[%d].context", index), err) } diff --git a/pkg/engine/mutation_test.go b/pkg/engine/mutation_test.go index bc95120338..e749d79e7a 100644 --- a/pkg/engine/mutation_test.go +++ b/pkg/engine/mutation_test.go @@ -30,7 +30,8 @@ func testMutate( e := NewEngine( cfg, client, - LegacyContextLoaderFactory(client, rclient, nil), + rclient, + LegacyContextLoaderFactory(nil), nil, ) return e.Mutate( diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index 2451376ba6..52f22a07e4 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -127,7 +127,7 @@ func (e *engine) processValidationRule( policyContext engineapi.PolicyContext, rule *kyvernov1.Rule, ) *engineapi.RuleResponse { - v := newValidator(log, e.contextLoader, policyContext, rule) + v := newValidator(log, e.ContextLoader(policyContext.Policy(), *rule), policyContext, rule) return v.validate(ctx) } @@ -142,11 +142,11 @@ type validator struct { deny *kyvernov1.Deny podSecurity *kyvernov1.PodSecurity forEach []kyvernov1.ForEachValidation - contextLoader engineapi.ContextLoaderFactory + contextLoader engineapi.EngineContextLoader nesting int } -func newValidator(log logr.Logger, contextLoader engineapi.ContextLoaderFactory, ctx engineapi.PolicyContext, rule *kyvernov1.Rule) *validator { +func newValidator(log logr.Logger, contextLoader engineapi.EngineContextLoader, ctx engineapi.PolicyContext, rule *kyvernov1.Rule) *validator { ruleCopy := rule.DeepCopy() return &validator{ log: log, @@ -165,7 +165,7 @@ func newValidator(log logr.Logger, contextLoader engineapi.ContextLoaderFactory, func newForEachValidator( foreach kyvernov1.ForEachValidation, - contextLoader engineapi.ContextLoaderFactory, + contextLoader engineapi.EngineContextLoader, nesting int, rule *kyvernov1.Rule, ctx engineapi.PolicyContext, @@ -344,7 +344,7 @@ func addElementToContext(ctx engineapi.PolicyContext, element interface{}, index } func (v *validator) loadContext(ctx context.Context) error { - if err := internal.LoadContext(ctx, v.contextLoader, v.contextEntries, v.policyContext, v.rule.Name); err != nil { + if err := v.contextLoader(ctx, v.contextEntries, v.policyContext.JSONContext()); err != nil { if _, ok := err.(gojmespath.NotFoundError); ok { v.log.V(3).Info("failed to load context", "reason", err.Error()) } else { diff --git a/pkg/engine/validation_test.go b/pkg/engine/validation_test.go index 76b4f8ed5f..4503fa8aab 100644 --- a/pkg/engine/validation_test.go +++ b/pkg/engine/validation_test.go @@ -23,7 +23,8 @@ func testValidate(ctx context.Context, rclient registryclient.Client, pContext * e := NewEngine( cfg, nil, - LegacyContextLoaderFactory(nil, rclient, nil), + rclient, + LegacyContextLoaderFactory(nil), nil, ) return e.Validate( diff --git a/pkg/policy/policy_controller.go b/pkg/policy/policy_controller.go index b0b976bcb6..527399664a 100644 --- a/pkg/policy/policy_controller.go +++ b/pkg/policy/policy_controller.go @@ -513,7 +513,7 @@ func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest return false, fmt.Errorf("failed to build policy context for rule %s: %w", rule.Name, err) } - engineResponse := pc.engine.ApplyBackgroundChecks(policyContext) + engineResponse := pc.engine.ApplyBackgroundChecks(context.TODO(), policyContext) if len(engineResponse.PolicyResponse.Rules) == 0 { return true, nil } diff --git a/pkg/testrunner/scenario.go b/pkg/testrunner/scenario.go index 57eba27421..5c38f41586 100644 --- a/pkg/testrunner/scenario.go +++ b/pkg/testrunner/scenario.go @@ -149,7 +149,8 @@ func runTestCase(t *testing.T, tc TestCase) bool { eng := engine.NewEngine( config.NewDefaultConfiguration(), nil, - engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil), + registryclient.NewOrDie(), + engine.LegacyContextLoaderFactory(nil), nil, ) er := eng.Mutate( @@ -184,11 +185,7 @@ func runTestCase(t *testing.T, tc TestCase) bool { if err := createNamespace(client, resource); err != nil { t.Error(err) } else { - // policyContext := policyContext.WithClient(client) - - er = eng.ApplyBackgroundChecks( - policyContext, - ) + er = eng.ApplyBackgroundChecks(context.TODO(), policyContext) t.Log(("---Generation---")) validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse) // Expected generate resource will be in same namespaces as resource diff --git a/pkg/webhooks/resource/fake.go b/pkg/webhooks/resource/fake.go index f5335b678c..3996f7aa27 100644 --- a/pkg/webhooks/resource/fake.go +++ b/pkg/webhooks/resource/fake.go @@ -59,7 +59,8 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook engine: engine.NewEngine( configuration, dclient, - engine.LegacyContextLoaderFactory(dclient, rclient, configMapResolver), + rclient, + engine.LegacyContextLoaderFactory(configMapResolver), peLister, ), } diff --git a/pkg/webhooks/resource/generation/generation.go b/pkg/webhooks/resource/generation/generation.go index 8e38733a82..9c86398b1f 100644 --- a/pkg/webhooks/resource/generation/generation.go +++ b/pkg/webhooks/resource/generation/generation.go @@ -92,7 +92,7 @@ func (h *generationHandler) Handle( if request.Kind.Kind != "Namespace" && request.Namespace != "" { policyContext = policyContext.WithNamespaceLabels(engineutils.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log)) } - engineResponse := h.engine.ApplyBackgroundChecks(policyContext) + engineResponse := h.engine.ApplyBackgroundChecks(ctx, policyContext) for _, rule := range engineResponse.PolicyResponse.Rules { if rule.Status != engineapi.RuleStatusPass { h.deleteGR(ctx, engineResponse) diff --git a/pkg/webhooks/resource/handlers.go b/pkg/webhooks/resource/handlers.go index f9a991eb20..f381777126 100644 --- a/pkg/webhooks/resource/handlers.go +++ b/pkg/webhooks/resource/handlers.go @@ -182,7 +182,7 @@ func (h *handlers) Mutate(ctx context.Context, logger logr.Logger, request *admi logger.Error(err, "failed to build policy context") return admissionutils.Response(request.UID, err) } - ivh := imageverification.NewImageVerificationHandler(logger, h.kyvernoClient, h.engine, h.rclient, h.eventGen, h.admissionReports, h.configuration) + ivh := imageverification.NewImageVerificationHandler(logger, h.kyvernoClient, h.engine, h.eventGen, h.admissionReports, h.configuration) imagePatches, imageVerifyWarnings, err := ivh.Handle(ctx, newRequest, verifyImagesPolicies, policyContext) if err != nil { logger.Error(err, "image verification failed") diff --git a/pkg/webhooks/resource/imageverification/handler.go b/pkg/webhooks/resource/imageverification/handler.go index 3469280fe1..915e3460af 100644 --- a/pkg/webhooks/resource/imageverification/handler.go +++ b/pkg/webhooks/resource/imageverification/handler.go @@ -13,7 +13,6 @@ import ( "github.com/kyverno/kyverno/pkg/engine" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/event" - "github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/tracing" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" jsonutils "github.com/kyverno/kyverno/pkg/utils/json" @@ -33,7 +32,6 @@ type ImageVerificationHandler interface { type imageVerificationHandler struct { kyvernoClient versioned.Interface engine engineapi.Engine - rclient registryclient.Client log logr.Logger eventGen event.Interface admissionReports bool @@ -44,7 +42,6 @@ func NewImageVerificationHandler( log logr.Logger, kyvernoClient versioned.Interface, engine engineapi.Engine, - rclient registryclient.Client, eventGen event.Interface, admissionReports bool, cfg config.Configuration, @@ -52,7 +49,6 @@ func NewImageVerificationHandler( return &imageVerificationHandler{ kyvernoClient: kyvernoClient, engine: engine, - rclient: rclient, log: log, eventGen: eventGen, admissionReports: admissionReports, @@ -94,7 +90,7 @@ func (h *imageVerificationHandler) handleVerifyImages( fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()), func(ctx context.Context, span trace.Span) { policyContext := policyContext.WithPolicy(policy) - resp, ivm := h.engine.VerifyAndPatchImages(ctx, h.rclient, policyContext) + resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext) engineResponses = append(engineResponses, resp) patches = append(patches, resp.GetPatches()...) diff --git a/pkg/webhooks/resource/updaterequest.go b/pkg/webhooks/resource/updaterequest.go index 1b6b2a5808..a20e3aa2b8 100644 --- a/pkg/webhooks/resource/updaterequest.go +++ b/pkg/webhooks/resource/updaterequest.go @@ -43,7 +43,7 @@ func (h *handlers) handleMutateExisting(ctx context.Context, logger logr.Logger, var rules []engineapi.RuleResponse policyContext := policyContext.WithPolicy(policy) - engineResponse := h.engine.ApplyBackgroundChecks(policyContext) + engineResponse := h.engine.ApplyBackgroundChecks(ctx, policyContext) for _, rule := range engineResponse.PolicyResponse.Rules { if rule.Status == engineapi.RuleStatusPass { diff --git a/pkg/webhooks/resource/validation_test.go b/pkg/webhooks/resource/validation_test.go index 91e2084f9b..970333ff6b 100644 --- a/pkg/webhooks/resource/validation_test.go +++ b/pkg/webhooks/resource/validation_test.go @@ -1052,7 +1052,8 @@ func TestValidate_failure_action_overrides(t *testing.T) { eng := engine.NewEngine( config.NewDefaultConfiguration(), nil, - engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil), + registryclient.NewOrDie(), + engine.LegacyContextLoaderFactory(nil), nil, ) for i, tc := range testcases { @@ -1130,7 +1131,8 @@ func Test_RuleSelector(t *testing.T) { eng := engine.NewEngine( config.NewDefaultConfiguration(), nil, - engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil), + registryclient.NewOrDie(), + engine.LegacyContextLoaderFactory(nil), nil, ) resp := eng.Validate(