1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

refactor: context loading and engine methods (#6253)

* refactor: context loading and engine methods

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-02-08 06:55:03 +01:00 committed by GitHub
parent 76e306dbc2
commit 3ff83c7bdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 143 additions and 123 deletions

View file

@ -214,7 +214,8 @@ func main() {
engine := engine.NewEngine( engine := engine.NewEngine(
configuration, configuration,
dClient, dClient,
engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver), rclient,
engine.LegacyContextLoaderFactory(configMapResolver),
// TODO: do we need exceptions here ? // TODO: do we need exceptions here ?
nil, nil,
) )

View file

@ -477,7 +477,8 @@ OuterLoop:
eng := engine.NewEngine( eng := engine.NewEngine(
cfg, cfg,
c.Client, c.Client,
engine.LegacyContextLoaderFactory(c.Client, registryclient.NewOrDie(), nil), registryclient.NewOrDie(),
engine.LegacyContextLoaderFactory(nil),
nil, nil,
) )
policyContext := engine.NewPolicyContextWithJsonContext(ctx). policyContext := engine.NewPolicyContextWithJsonContext(ctx).
@ -525,11 +526,7 @@ OuterLoop:
engineResponses = append(engineResponses, validateResponse) engineResponses = append(engineResponses, validateResponse)
} }
verifyImageResponse, _ := eng.VerifyAndPatchImages( verifyImageResponse, _ := eng.VerifyAndPatchImages(context.TODO(), policyContext)
context.Background(),
registryclient.NewOrDie(),
policyContext,
)
if verifyImageResponse != nil && !verifyImageResponse.IsEmpty() { if verifyImageResponse != nil && !verifyImageResponse.IsEmpty() {
engineResponses = append(engineResponses, verifyImageResponse) engineResponses = append(engineResponses, verifyImageResponse)
info = ProcessValidateEngineResponse(c.Policy, verifyImageResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn) info = ProcessValidateEngineResponse(c.Policy, verifyImageResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
@ -543,9 +540,7 @@ OuterLoop:
} }
if policyHasGenerate { if policyHasGenerate {
generateResponse := eng.ApplyBackgroundChecks( generateResponse := eng.ApplyBackgroundChecks(context.TODO(), policyContext)
policyContext,
)
if generateResponse != nil && !generateResponse.IsEmpty() { if generateResponse != nil && !generateResponse.IsEmpty() {
newRuleResponse, err := handleGeneratePolicy(generateResponse, *policyContext, c.RuleToCloneSourceResource) newRuleResponse, err := handleGeneratePolicy(generateResponse, *policyContext, c.RuleToCloneSourceResource)
if err != nil { if err != nil {
@ -1081,7 +1076,8 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr
c := generate.NewGenerateControllerWithOnlyClient(client, engine.NewEngine( c := generate.NewGenerateControllerWithOnlyClient(client, engine.NewEngine(
config.NewDefaultConfiguration(), config.NewDefaultConfiguration(),
client, client,
engine.LegacyContextLoaderFactory(client, nil, nil), nil,
engine.LegacyContextLoaderFactory(nil),
nil, nil,
)) ))
return c, nil return c, nil

View file

@ -367,7 +367,8 @@ func main() {
eng := engine.NewEngine( eng := engine.NewEngine(
configuration, configuration,
dClient, dClient,
engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver), rclient,
engine.LegacyContextLoaderFactory(configMapResolver),
exceptionsLister, exceptionsLister,
) )
// create non leader controllers // create non leader controllers

View file

@ -129,7 +129,6 @@ func createReportControllers(
backgroundscancontroller.NewController( backgroundscancontroller.NewController(
client, client,
kyvernoClient, kyvernoClient,
rclient,
eng, eng,
metadataFactory, metadataFactory,
kyvernoV1.Policies(), kyvernoV1.Policies(),
@ -315,7 +314,8 @@ func main() {
eng := engine.NewEngine( eng := engine.NewEngine(
configuration, configuration,
dClient, dClient,
engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver), rclient,
engine.LegacyContextLoaderFactory(configMapResolver),
exceptionsLister, exceptionsLister,
) )
// setup leader election // setup leader election

View file

@ -197,7 +197,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
} }
// check if the policy still applies to the resource // 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 { if len(engineResponse.PolicyResponse.Rules) == 0 {
logger.V(4).Info(doesNotApply) logger.V(4).Info(doesNotApply)
return nil, false, errors.New(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 // 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") log.Error(err, "cannot add configmaps to context")
return nil, processExisting, err return nil, processExisting, err
} }

View file

@ -19,7 +19,6 @@ import (
"github.com/kyverno/kyverno/pkg/controllers/report/utils" "github.com/kyverno/kyverno/pkg/controllers/report/utils"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/registryclient"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
reportutils "github.com/kyverno/kyverno/pkg/utils/report" reportutils "github.com/kyverno/kyverno/pkg/utils/report"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
@ -47,7 +46,6 @@ type controller struct {
// clients // clients
client dclient.Interface client dclient.Interface
kyvernoClient versioned.Interface kyvernoClient versioned.Interface
rclient registryclient.Client
engine engineapi.Engine engine engineapi.Engine
// listers // listers
@ -73,7 +71,6 @@ type controller struct {
func NewController( func NewController(
client dclient.Interface, client dclient.Interface,
kyvernoClient versioned.Interface, kyvernoClient versioned.Interface,
rclient registryclient.Client,
engine engineapi.Engine, engine engineapi.Engine,
metadataFactory metadatainformers.SharedInformerFactory, metadataFactory metadatainformers.SharedInformerFactory,
polInformer kyvernov1informers.PolicyInformer, polInformer kyvernov1informers.PolicyInformer,
@ -91,7 +88,6 @@ func NewController(
c := controller{ c := controller{
client: client, client: client,
kyvernoClient: kyvernoClient, kyvernoClient: kyvernoClient,
rclient: rclient,
engine: engine, engine: engine,
polLister: polInformer.Lister(), polLister: polInformer.Lister(),
cpolLister: cpolInformer.Lister(), cpolLister: cpolInformer.Lister(),
@ -308,7 +304,7 @@ func (c *controller) reconcileReport(
// calculate necessary results // calculate necessary results
for _, policy := range backgroundPolicies { for _, policy := range backgroundPolicies {
if full || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() { 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) { for _, result := range scanner.ScanResource(ctx, *target, nsLabels, policy) {
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error

View file

@ -5,12 +5,10 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" 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/config"
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/registryclient"
"go.uber.org/multierr" "go.uber.org/multierr"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
) )
@ -18,8 +16,6 @@ import (
type scanner struct { type scanner struct {
logger logr.Logger logger logr.Logger
engine engineapi.Engine engine engineapi.Engine
client dclient.Interface
rclient registryclient.Client
config config.Configuration config config.Configuration
} }
@ -35,15 +31,11 @@ type Scanner interface {
func NewScanner( func NewScanner(
logger logr.Logger, logger logr.Logger,
engine engineapi.Engine, engine engineapi.Engine,
client dclient.Interface,
rclient registryclient.Client,
config config.Configuration, config config.Configuration,
) Scanner { ) Scanner {
return &scanner{ return &scanner{
logger: logger, logger: logger,
engine: engine, engine: engine,
client: client,
rclient: rclient,
config: config, config: config,
} }
} }
@ -114,7 +106,7 @@ func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unst
WithNewResource(resource). WithNewResource(resource).
WithPolicy(policy). WithPolicy(policy).
WithNamespaceLabels(nsLabels) WithNamespaceLabels(nsLabels)
response, _ := s.engine.VerifyAndPatchImages(ctx, s.rclient, policyCtx) response, _ := s.engine.VerifyAndPatchImages(ctx, policyCtx)
if len(response.PolicyResponse.Rules) > 0 { if len(response.PolicyResponse.Rules) > 0 {
s.logger.Info("validateImages", "policy", policy, "response", response) s.logger.Info("validateImages", "policy", policy, "response", response)
} }

View file

@ -4,13 +4,22 @@ import (
"context" "context"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/clients/dclient"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context" 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 // 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 // ContextLoader abstracts the mechanics to load context entries in the underlying json context
type ContextLoader interface { 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
} }

View file

@ -3,10 +3,13 @@ package api
import ( import (
"context" "context"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" 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 // Engine is the main interface to run policies against resources
type Engine interface { type Engine interface {
// Validate applies validation rules from policy on the resource // Validate applies validation rules from policy on the resource
@ -24,7 +27,6 @@ type Engine interface {
// VerifyAndPatchImages ... // VerifyAndPatchImages ...
VerifyAndPatchImages( VerifyAndPatchImages(
ctx context.Context, ctx context.Context,
rclient registryclient.Client,
policyContext PolicyContext, policyContext PolicyContext,
) (*EngineResponse, *ImageVerificationMetadata) ) (*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 // 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed
ApplyBackgroundChecks( ApplyBackgroundChecks(
ctx context.Context,
policyContext PolicyContext, policyContext PolicyContext,
) *EngineResponse ) *EngineResponse
// GenerateResponse checks for validity of generate rule on the resource // GenerateResponse checks for validity of generate rule on the resource
GenerateResponse( GenerateResponse(
ctx context.Context,
policyContext PolicyContext, policyContext PolicyContext,
gr kyvernov1beta1.UpdateRequest, gr kyvernov1beta1.UpdateRequest,
) *EngineResponse ) *EngineResponse
ContextLoader( ContextLoader(
policyContext PolicyContext, policy kyvernov1.PolicyInterface,
ruleName string, rule kyvernov1.Rule,
) ContextLoader ) EngineContextLoader
} }

View file

@ -19,6 +19,7 @@ import (
// //
// 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed // 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed
func (e *engine) applyBackgroundChecks( func (e *engine) applyBackgroundChecks(
ctx context.Context,
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
) (resp *engineapi.EngineResponse) { ) (resp *engineapi.EngineResponse) {
policyStartTime := time.Now() policyStartTime := time.Now()
@ -132,7 +133,7 @@ func (e *engine) filterRule(
policyContext.JSONContext().Checkpoint() policyContext.JSONContext().Checkpoint()
defer policyContext.JSONContext().Restore() 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()) logger.V(4).Info("cannot add external data to the context", "reason", err.Error())
return nil return nil
} }

View file

@ -3,16 +3,19 @@ package engine
import ( import (
"context" "context"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/registryclient"
) )
type engine struct { type engine struct {
configuration config.Configuration configuration config.Configuration
client dclient.Interface client dclient.Interface
rclient registryclient.Client
contextLoader engineapi.ContextLoaderFactory contextLoader engineapi.ContextLoaderFactory
exceptionSelector engineapi.PolicyExceptionSelector exceptionSelector engineapi.PolicyExceptionSelector
} }
@ -20,12 +23,14 @@ type engine struct {
func NewEngine( func NewEngine(
configuration config.Configuration, configuration config.Configuration,
client dclient.Interface, client dclient.Interface,
rclient registryclient.Client,
contextLoader engineapi.ContextLoaderFactory, contextLoader engineapi.ContextLoaderFactory,
exceptionSelector engineapi.PolicyExceptionSelector, exceptionSelector engineapi.PolicyExceptionSelector,
) engineapi.Engine { ) engineapi.Engine {
return &engine{ return &engine{
configuration: configuration, configuration: configuration,
client: client, client: client,
rclient: rclient,
contextLoader: contextLoader, contextLoader: contextLoader,
exceptionSelector: exceptionSelector, exceptionSelector: exceptionSelector,
} }
@ -47,28 +52,39 @@ func (e *engine) Mutate(
func (e *engine) VerifyAndPatchImages( func (e *engine) VerifyAndPatchImages(
ctx context.Context, ctx context.Context,
rclient registryclient.Client,
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) { ) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) {
return e.verifyAndPatchImages(ctx, rclient, policyContext) return e.verifyAndPatchImages(ctx, policyContext)
} }
func (e *engine) ApplyBackgroundChecks( func (e *engine) ApplyBackgroundChecks(
ctx context.Context,
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
) *engineapi.EngineResponse { ) *engineapi.EngineResponse {
return e.applyBackgroundChecks(policyContext) return e.applyBackgroundChecks(ctx, policyContext)
} }
func (e *engine) GenerateResponse( func (e *engine) GenerateResponse(
ctx context.Context,
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
gr kyvernov1beta1.UpdateRequest, gr kyvernov1beta1.UpdateRequest,
) *engineapi.EngineResponse { ) *engineapi.EngineResponse {
return e.generateResponse(policyContext, gr) return e.generateResponse(ctx, policyContext, gr)
} }
func (e *engine) ContextLoader( func (e *engine) ContextLoader(
policyContext engineapi.PolicyContext, policy kyvernov1.PolicyInterface,
ruleName string, rule kyvernov1.Rule,
) engineapi.ContextLoader { ) engineapi.EngineContextLoader {
return e.contextLoader(policyContext, ruleName) 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,
)
}
} }

View file

@ -1,6 +1,7 @@
package engine package engine
import ( import (
"context"
"time" "time"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
@ -12,6 +13,7 @@ import (
// GenerateResponse checks for validity of generate rule on the resource // GenerateResponse checks for validity of generate rule on the resource
func (e *engine) generateResponse( func (e *engine) generateResponse(
ctx context.Context,
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
gr kyvernov1beta1.UpdateRequest, gr kyvernov1beta1.UpdateRequest,
) (resp *engineapi.EngineResponse) { ) (resp *engineapi.EngineResponse) {

View file

@ -14,7 +14,6 @@ import (
"github.com/kyverno/kyverno/pkg/engine/internal" "github.com/kyverno/kyverno/pkg/engine/internal"
"github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/logging" "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/registryclient"
"github.com/kyverno/kyverno/pkg/tracing" "github.com/kyverno/kyverno/pkg/tracing"
apiutils "github.com/kyverno/kyverno/pkg/utils/api" apiutils "github.com/kyverno/kyverno/pkg/utils/api"
"github.com/kyverno/kyverno/pkg/utils/wildcard" "github.com/kyverno/kyverno/pkg/utils/wildcard"
@ -23,7 +22,6 @@ import (
func (e *engine) verifyAndPatchImages( func (e *engine) verifyAndPatchImages(
ctx context.Context, ctx context.Context,
rclient registryclient.Client,
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) { ) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) {
resp := &engineapi.EngineResponse{} resp := &engineapi.EngineResponse{}
@ -98,7 +96,7 @@ func (e *engine) verifyAndPatchImages(
return return
} }
policyContext.JSONContext().Restore() 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( internal.AddRuleResponse(
&resp.PolicyResponse, &resp.PolicyResponse,
internal.RuleError(rule, engineapi.ImageVerify, "failed to load context", err), internal.RuleError(rule, engineapi.ImageVerify, "failed to load context", err),
@ -117,7 +115,7 @@ func (e *engine) verifyAndPatchImages(
} }
iv := internal.NewImageVerifier( iv := internal.NewImageVerifier(
logger, logger,
rclient, e.rclient,
policyContext, policyContext,
ruleCopy, ruleCopy,
ivm, ivm,

View file

@ -32,7 +32,7 @@ func (e *engine) processImageValidationRule(
if len(matchingImages) == 0 { if len(matchingImages) == 0 {
return internal.RuleSkip(rule, engineapi.Validation, "image verified") 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 { if _, ok := err.(gojmespath.NotFoundError); ok {
log.V(3).Info("failed to load context", "reason", err.Error()) log.V(3).Info("failed to load context", "reason", err.Error())
} else { } else {

View file

@ -171,12 +171,12 @@ func testVerifyAndPatchImages(
e := NewEngine( e := NewEngine(
cfg, cfg,
nil, nil,
LegacyContextLoaderFactory(nil, rclient, cmResolver), rclient,
LegacyContextLoaderFactory(cmResolver),
nil, nil,
) )
return e.VerifyAndPatchImages( return e.VerifyAndPatchImages(
ctx, ctx,
rclient,
pContext, pContext,
) )
} }

View file

@ -7,6 +7,12 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api" 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 { func LoadContext(
return factory(pContext, ruleName).Load(ctx, contextEntries, pContext.JSONContext()) 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())
} }

View file

@ -19,56 +19,52 @@ import (
) )
func LegacyContextLoaderFactory( func LegacyContextLoaderFactory(
client dclient.Interface,
rclient registryclient.Client,
cmResolver engineapi.ConfigmapResolver, cmResolver engineapi.ConfigmapResolver,
) engineapi.ContextLoaderFactory { ) engineapi.ContextLoaderFactory {
return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader {
if store.IsMock() { if store.IsMock() {
return func(pContext engineapi.PolicyContext, ruleName string) engineapi.ContextLoader {
policy := pContext.Policy()
return &mockContextLoader{ return &mockContextLoader{
logger: logging.WithName("MockContextLoaderFactory"), logger: logging.WithName("MockContextLoaderFactory"),
policyName: policy.GetName(), policyName: policy.GetName(),
ruleName: ruleName, ruleName: rule.Name,
client: client,
rclient: rclient,
cmResolver: cmResolver,
} }
} } else {
}
return func(pContext engineapi.PolicyContext, ruleName string) engineapi.ContextLoader {
return &contextLoader{ return &contextLoader{
logger: logging.WithName("LegacyContextLoaderFactory"), logger: logging.WithName("LegacyContextLoaderFactory"),
client: client,
rclient: rclient,
cmResolver: cmResolver, cmResolver: cmResolver,
} }
} }
}
} }
type contextLoader struct { type contextLoader struct {
logger logr.Logger logger logr.Logger
rclient registryclient.Client
client dclient.Interface
cmResolver engineapi.ConfigmapResolver 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 { for _, entry := range contextEntries {
if entry.ConfigMap != nil { 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 return err
} }
} else if entry.APICall != nil { } 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 return err
} }
} else if entry.ImageRegistry != nil { } 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 return err
} }
} else if entry.Variable != nil { } 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 return err
} }
} }
@ -80,17 +76,21 @@ type mockContextLoader struct {
logger logr.Logger logger logr.Logger
policyName string policyName string
ruleName 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) rule := store.GetPolicyRule(l.policyName, l.ruleName)
if rule != nil && len(rule.Values) > 0 { if rule != nil && len(rule.Values) > 0 {
variables := rule.Values variables := rule.Values
for key, value := range variables { for key, value := range variables {
if err := enginectx.AddVariable(key, value); err != nil { if err := jsonContext.AddVariable(key, value); err != nil {
return err return err
} }
} }
@ -100,22 +100,22 @@ func (l *mockContextLoader) Load(ctx context.Context, contextEntries []kyvernov1
for _, entry := range contextEntries { for _, entry := range contextEntries {
if entry.ImageRegistry != nil && hasRegistryAccess { if entry.ImageRegistry != nil && hasRegistryAccess {
rclient := store.GetRegistryClient() 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 return err
} }
} else if entry.Variable != nil { } 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 return err
} }
} else if entry.APICall != nil && store.IsApiCallAllowed() { } 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 return err
} }
} }
} }
if rule != nil && len(rule.ForEachValues) > 0 { if rule != nil && len(rule.ForEachValues) > 0 {
for key, value := range rule.ForEachValues { 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 return err
} }
} }

View file

@ -91,7 +91,7 @@ func (e *engine) mutate(
logger.Error(err, "failed to query resource object") 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 { if _, ok := err.(gojmespath.NotFoundError); ok {
logger.V(3).Info("failed to load context", "reason", err.Error()) logger.V(3).Info("failed to load context", "reason", err.Error())
} else { } else {
@ -144,7 +144,7 @@ func (e *engine) mutate(
policyContext: policyContext, policyContext: policyContext,
resource: patchedResource, resource: patchedResource,
log: logger, log: logger,
contextLoader: e.contextLoader, contextLoader: e.ContextLoader(policyContext.Policy(), *ruleCopy),
nesting: 0, nesting: 0,
} }
@ -198,7 +198,7 @@ type forEachMutator struct {
foreach []kyvernov1.ForEachMutation foreach []kyvernov1.ForEachMutation
resource resourceInfo resource resourceInfo
nesting int nesting int
contextLoader engineapi.ContextLoaderFactory contextLoader engineapi.EngineContextLoader
log logr.Logger log logr.Logger
} }
@ -207,7 +207,7 @@ func (f *forEachMutator) mutateForEach(ctx context.Context) *mutate.Response {
allPatches := make([][]byte, 0) allPatches := make([][]byte, 0)
for _, foreach := range f.foreach { 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") f.log.Error(err, "failed to load context")
return mutate.NewErrorResponse("failed to load context", err) 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) 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) return mutate.NewErrorResponse(fmt.Sprintf("failed to load to mutate.foreach[%d].context", index), err)
} }

View file

@ -30,7 +30,8 @@ func testMutate(
e := NewEngine( e := NewEngine(
cfg, cfg,
client, client,
LegacyContextLoaderFactory(client, rclient, nil), rclient,
LegacyContextLoaderFactory(nil),
nil, nil,
) )
return e.Mutate( return e.Mutate(

View file

@ -127,7 +127,7 @@ func (e *engine) processValidationRule(
policyContext engineapi.PolicyContext, policyContext engineapi.PolicyContext,
rule *kyvernov1.Rule, rule *kyvernov1.Rule,
) *engineapi.RuleResponse { ) *engineapi.RuleResponse {
v := newValidator(log, e.contextLoader, policyContext, rule) v := newValidator(log, e.ContextLoader(policyContext.Policy(), *rule), policyContext, rule)
return v.validate(ctx) return v.validate(ctx)
} }
@ -142,11 +142,11 @@ type validator struct {
deny *kyvernov1.Deny deny *kyvernov1.Deny
podSecurity *kyvernov1.PodSecurity podSecurity *kyvernov1.PodSecurity
forEach []kyvernov1.ForEachValidation forEach []kyvernov1.ForEachValidation
contextLoader engineapi.ContextLoaderFactory contextLoader engineapi.EngineContextLoader
nesting int 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() ruleCopy := rule.DeepCopy()
return &validator{ return &validator{
log: log, log: log,
@ -165,7 +165,7 @@ func newValidator(log logr.Logger, contextLoader engineapi.ContextLoaderFactory,
func newForEachValidator( func newForEachValidator(
foreach kyvernov1.ForEachValidation, foreach kyvernov1.ForEachValidation,
contextLoader engineapi.ContextLoaderFactory, contextLoader engineapi.EngineContextLoader,
nesting int, nesting int,
rule *kyvernov1.Rule, rule *kyvernov1.Rule,
ctx engineapi.PolicyContext, ctx engineapi.PolicyContext,
@ -344,7 +344,7 @@ func addElementToContext(ctx engineapi.PolicyContext, element interface{}, index
} }
func (v *validator) loadContext(ctx context.Context) error { 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 { if _, ok := err.(gojmespath.NotFoundError); ok {
v.log.V(3).Info("failed to load context", "reason", err.Error()) v.log.V(3).Info("failed to load context", "reason", err.Error())
} else { } else {

View file

@ -23,7 +23,8 @@ func testValidate(ctx context.Context, rclient registryclient.Client, pContext *
e := NewEngine( e := NewEngine(
cfg, cfg,
nil, nil,
LegacyContextLoaderFactory(nil, rclient, nil), rclient,
LegacyContextLoaderFactory(nil),
nil, nil,
) )
return e.Validate( return e.Validate(

View file

@ -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) 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 { if len(engineResponse.PolicyResponse.Rules) == 0 {
return true, nil return true, nil
} }

View file

@ -149,7 +149,8 @@ func runTestCase(t *testing.T, tc TestCase) bool {
eng := engine.NewEngine( eng := engine.NewEngine(
config.NewDefaultConfiguration(), config.NewDefaultConfiguration(),
nil, nil,
engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil), registryclient.NewOrDie(),
engine.LegacyContextLoaderFactory(nil),
nil, nil,
) )
er := eng.Mutate( er := eng.Mutate(
@ -184,11 +185,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
if err := createNamespace(client, resource); err != nil { if err := createNamespace(client, resource); err != nil {
t.Error(err) t.Error(err)
} else { } else {
// policyContext := policyContext.WithClient(client) er = eng.ApplyBackgroundChecks(context.TODO(), policyContext)
er = eng.ApplyBackgroundChecks(
policyContext,
)
t.Log(("---Generation---")) t.Log(("---Generation---"))
validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse) validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse)
// Expected generate resource will be in same namespaces as resource // Expected generate resource will be in same namespaces as resource

View file

@ -59,7 +59,8 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
engine: engine.NewEngine( engine: engine.NewEngine(
configuration, configuration,
dclient, dclient,
engine.LegacyContextLoaderFactory(dclient, rclient, configMapResolver), rclient,
engine.LegacyContextLoaderFactory(configMapResolver),
peLister, peLister,
), ),
} }

View file

@ -92,7 +92,7 @@ func (h *generationHandler) Handle(
if request.Kind.Kind != "Namespace" && request.Namespace != "" { if request.Kind.Kind != "Namespace" && request.Namespace != "" {
policyContext = policyContext.WithNamespaceLabels(engineutils.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log)) 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 { for _, rule := range engineResponse.PolicyResponse.Rules {
if rule.Status != engineapi.RuleStatusPass { if rule.Status != engineapi.RuleStatusPass {
h.deleteGR(ctx, engineResponse) h.deleteGR(ctx, engineResponse)

View file

@ -182,7 +182,7 @@ func (h *handlers) Mutate(ctx context.Context, logger logr.Logger, request *admi
logger.Error(err, "failed to build policy context") logger.Error(err, "failed to build policy context")
return admissionutils.Response(request.UID, err) 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) imagePatches, imageVerifyWarnings, err := ivh.Handle(ctx, newRequest, verifyImagesPolicies, policyContext)
if err != nil { if err != nil {
logger.Error(err, "image verification failed") logger.Error(err, "image verification failed")

View file

@ -13,7 +13,6 @@ import (
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
engineapi "github.com/kyverno/kyverno/pkg/engine/api" engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/registryclient"
"github.com/kyverno/kyverno/pkg/tracing" "github.com/kyverno/kyverno/pkg/tracing"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller" controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
jsonutils "github.com/kyverno/kyverno/pkg/utils/json" jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
@ -33,7 +32,6 @@ type ImageVerificationHandler interface {
type imageVerificationHandler struct { type imageVerificationHandler struct {
kyvernoClient versioned.Interface kyvernoClient versioned.Interface
engine engineapi.Engine engine engineapi.Engine
rclient registryclient.Client
log logr.Logger log logr.Logger
eventGen event.Interface eventGen event.Interface
admissionReports bool admissionReports bool
@ -44,7 +42,6 @@ func NewImageVerificationHandler(
log logr.Logger, log logr.Logger,
kyvernoClient versioned.Interface, kyvernoClient versioned.Interface,
engine engineapi.Engine, engine engineapi.Engine,
rclient registryclient.Client,
eventGen event.Interface, eventGen event.Interface,
admissionReports bool, admissionReports bool,
cfg config.Configuration, cfg config.Configuration,
@ -52,7 +49,6 @@ func NewImageVerificationHandler(
return &imageVerificationHandler{ return &imageVerificationHandler{
kyvernoClient: kyvernoClient, kyvernoClient: kyvernoClient,
engine: engine, engine: engine,
rclient: rclient,
log: log, log: log,
eventGen: eventGen, eventGen: eventGen,
admissionReports: admissionReports, admissionReports: admissionReports,
@ -94,7 +90,7 @@ func (h *imageVerificationHandler) handleVerifyImages(
fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()), fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()),
func(ctx context.Context, span trace.Span) { func(ctx context.Context, span trace.Span) {
policyContext := policyContext.WithPolicy(policy) policyContext := policyContext.WithPolicy(policy)
resp, ivm := h.engine.VerifyAndPatchImages(ctx, h.rclient, policyContext) resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext)
engineResponses = append(engineResponses, resp) engineResponses = append(engineResponses, resp)
patches = append(patches, resp.GetPatches()...) patches = append(patches, resp.GetPatches()...)

View file

@ -43,7 +43,7 @@ func (h *handlers) handleMutateExisting(ctx context.Context, logger logr.Logger,
var rules []engineapi.RuleResponse var rules []engineapi.RuleResponse
policyContext := policyContext.WithPolicy(policy) policyContext := policyContext.WithPolicy(policy)
engineResponse := h.engine.ApplyBackgroundChecks(policyContext) engineResponse := h.engine.ApplyBackgroundChecks(ctx, policyContext)
for _, rule := range engineResponse.PolicyResponse.Rules { for _, rule := range engineResponse.PolicyResponse.Rules {
if rule.Status == engineapi.RuleStatusPass { if rule.Status == engineapi.RuleStatusPass {

View file

@ -1052,7 +1052,8 @@ func TestValidate_failure_action_overrides(t *testing.T) {
eng := engine.NewEngine( eng := engine.NewEngine(
config.NewDefaultConfiguration(), config.NewDefaultConfiguration(),
nil, nil,
engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil), registryclient.NewOrDie(),
engine.LegacyContextLoaderFactory(nil),
nil, nil,
) )
for i, tc := range testcases { for i, tc := range testcases {
@ -1130,7 +1131,8 @@ func Test_RuleSelector(t *testing.T) {
eng := engine.NewEngine( eng := engine.NewEngine(
config.NewDefaultConfiguration(), config.NewDefaultConfiguration(),
nil, nil,
engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil), registryclient.NewOrDie(),
engine.LegacyContextLoaderFactory(nil),
nil, nil,
) )
resp := eng.Validate( resp := eng.Validate(