mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
refactor: move client out of policy context (#6233)
* refactor: move client out of policy context 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 test 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:
parent
6b3be9ada1
commit
7a1d4374c6
29 changed files with 127 additions and 97 deletions
|
@ -213,7 +213,8 @@ func main() {
|
|||
)
|
||||
engine := engine.NewEngine(
|
||||
configuration,
|
||||
engine.LegacyContextLoaderFactory(rclient, configMapResolver),
|
||||
dClient,
|
||||
engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver),
|
||||
// TODO: do we need exceptions here ?
|
||||
nil,
|
||||
)
|
||||
|
|
|
@ -476,7 +476,8 @@ OuterLoop:
|
|||
}
|
||||
eng := engine.NewEngine(
|
||||
cfg,
|
||||
engine.LegacyContextLoaderFactory(registryclient.NewOrDie(), nil),
|
||||
c.Client,
|
||||
engine.LegacyContextLoaderFactory(c.Client, registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
)
|
||||
policyContext := engine.NewPolicyContextWithJsonContext(ctx).
|
||||
|
@ -484,7 +485,6 @@ OuterLoop:
|
|||
WithNewResource(*updatedResource).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithAdmissionInfo(c.UserInfo).
|
||||
WithClient(c.Client).
|
||||
WithSubresourcesInPolicy(subresources)
|
||||
|
||||
mutateResponse := eng.Mutate(
|
||||
|
@ -1080,7 +1080,8 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr
|
|||
client.SetDiscovery(dclient.NewFakeDiscoveryClient(nil))
|
||||
c := generate.NewGenerateControllerWithOnlyClient(client, engine.NewEngine(
|
||||
config.NewDefaultConfiguration(),
|
||||
engine.LegacyContextLoaderFactory(nil, nil),
|
||||
client,
|
||||
engine.LegacyContextLoaderFactory(client, nil, nil),
|
||||
nil,
|
||||
))
|
||||
return c, nil
|
||||
|
|
|
@ -366,7 +366,8 @@ func main() {
|
|||
}
|
||||
eng := engine.NewEngine(
|
||||
configuration,
|
||||
engine.LegacyContextLoaderFactory(rclient, configMapResolver),
|
||||
dClient,
|
||||
engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver),
|
||||
exceptionsLister,
|
||||
)
|
||||
// create non leader controllers
|
||||
|
|
|
@ -314,7 +314,8 @@ func main() {
|
|||
go eventGenerator.Run(ctx, 3)
|
||||
eng := engine.NewEngine(
|
||||
configuration,
|
||||
engine.LegacyContextLoaderFactory(rclient, configMapResolver),
|
||||
dClient,
|
||||
engine.LegacyContextLoaderFactory(dClient, rclient, configMapResolver),
|
||||
exceptionsLister,
|
||||
)
|
||||
// setup leader election
|
||||
|
|
|
@ -81,8 +81,7 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe
|
|||
WithNewResource(*trigger).
|
||||
WithOldResource(old).
|
||||
WithAdmissionInfo(ur.Spec.Context.UserRequestInfo).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithClient(dclient)
|
||||
WithNamespaceLabels(namespaceLabels)
|
||||
|
||||
return policyContext, false, nil
|
||||
}
|
||||
|
|
|
@ -92,7 +92,6 @@ func (s *scanner) validateResource(ctx context.Context, resource unstructured.Un
|
|||
policyCtx := engine.NewPolicyContextWithJsonContext(enginectx).
|
||||
WithNewResource(resource).
|
||||
WithPolicy(policy).
|
||||
WithClient(s.client).
|
||||
WithNamespaceLabels(nsLabels)
|
||||
return s.engine.Validate(ctx, policyCtx), nil
|
||||
}
|
||||
|
@ -114,7 +113,6 @@ func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unst
|
|||
policyCtx := engine.NewPolicyContextWithJsonContext(enginectx).
|
||||
WithNewResource(resource).
|
||||
WithPolicy(policy).
|
||||
WithClient(s.client).
|
||||
WithNamespaceLabels(nsLabels)
|
||||
response, _ := s.engine.VerifyAndPatchImages(ctx, s.rclient, policyCtx)
|
||||
if len(response.PolicyResponse.Rules) > 0 {
|
||||
|
|
|
@ -7,8 +7,10 @@ import (
|
|||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
)
|
||||
|
||||
// ContextLoaderFactory provides a ContextLoader given a policy context and rule name
|
||||
type ContextLoaderFactory = func(pContext PolicyContext, ruleName string) 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
|
||||
}
|
||||
|
|
|
@ -4,19 +4,10 @@ import (
|
|||
"context"
|
||||
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
type NamespacedResourceSelector[T any] interface {
|
||||
// List selects resources based on label selector.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []T, err error)
|
||||
}
|
||||
|
||||
type PolicyExceptionSelector = NamespacedResourceSelector[*kyvernov2alpha1.PolicyException]
|
||||
|
||||
// Engine is the main interface to run policies against resources
|
||||
type Engine interface {
|
||||
// Validate applies validation rules from policy on the resource
|
||||
Validate(
|
||||
|
|
|
@ -3,7 +3,6 @@ package api
|
|||
import (
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -31,6 +30,5 @@ type PolicyContext interface {
|
|||
SetElement(element unstructured.Unstructured)
|
||||
|
||||
JSONContext() enginecontext.Interface
|
||||
Client() dclient.Interface
|
||||
Copy() PolicyContext
|
||||
}
|
||||
|
|
17
pkg/engine/api/selector.go
Normal file
17
pkg/engine/api/selector.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
// NamespacedResourceSelector is an abstract interface used to list namespaced resources given a label selector
|
||||
// Any implementation might exist, cache based, file based, client based etc...
|
||||
type NamespacedResourceSelector[T any] interface {
|
||||
// List selects resources based on label selector.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []T, err error)
|
||||
}
|
||||
|
||||
// PolicyExceptionSelector is an abstract interface used to resolve poliicy exceptions
|
||||
type PolicyExceptionSelector = NamespacedResourceSelector[*kyvernov2alpha1.PolicyException]
|
|
@ -84,7 +84,7 @@ func (e *engine) filterRule(
|
|||
logger := logging.WithName("exception")
|
||||
|
||||
kindsInPolicy := append(rule.MatchResources.GetKinds(), rule.ExcludeResources.GetKinds()...)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(kindsInPolicy, policyContext)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(e.client, kindsInPolicy, policyContext)
|
||||
|
||||
// check if there is a corresponding policy exception
|
||||
ruleResp := hasPolicyExceptions(logger, e.exceptionSelector, policyContext, &rule, subresourceGVKToAPIResource, e.configuration)
|
||||
|
|
|
@ -3,13 +3,14 @@ package engine
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// GetSubresourceGVKToAPIResourceMap returns a map of subresource GVK to APIResource. This is used to determine if a resource is a subresource.
|
||||
func GetSubresourceGVKToAPIResourceMap(kindsInPolicy []string, ctx engineapi.PolicyContext) map[string]*metav1.APIResource {
|
||||
func GetSubresourceGVKToAPIResourceMap(client dclient.Interface, kindsInPolicy []string, ctx engineapi.PolicyContext) map[string]*metav1.APIResource {
|
||||
subresourceGVKToAPIResource := make(map[string]*metav1.APIResource)
|
||||
for _, gvk := range kindsInPolicy {
|
||||
gv, k := kubeutils.GetKindFromGVK(gvk)
|
||||
|
@ -50,9 +51,9 @@ func GetSubresourceGVKToAPIResourceMap(kindsInPolicy []string, ctx engineapi.Pol
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if ctx.Client() != nil {
|
||||
} else if client != nil {
|
||||
// find the resource from API client
|
||||
apiResource, _, _, err := ctx.Client().Discovery().FindResource(gv, k)
|
||||
apiResource, _, _, err := client.Discovery().FindResource(gv, k)
|
||||
if err == nil {
|
||||
if kubeutils.IsSubresource(apiResource.Name) {
|
||||
subresourceGVKToAPIResource[gvk] = apiResource
|
||||
|
|
|
@ -51,7 +51,7 @@ func Test_GetSubresourceGVKToAPIResourceMap(t *testing.T) {
|
|||
|
||||
kindsInPolicy := []string{"Pod", "Eviction", "Pod/status", "Pod/eviction"}
|
||||
|
||||
subresourceGVKToAPIResourceMap := GetSubresourceGVKToAPIResourceMap(kindsInPolicy, policyContext)
|
||||
subresourceGVKToAPIResourceMap := GetSubresourceGVKToAPIResourceMap(nil, kindsInPolicy, policyContext)
|
||||
|
||||
podStatusResourceFromMap := subresourceGVKToAPIResourceMap["Pod/status"]
|
||||
assert.Equal(t, podStatusResourceFromMap.Name, podStatusAPIResource.Name)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
|
||||
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"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
|
@ -11,17 +12,20 @@ import (
|
|||
|
||||
type engine struct {
|
||||
configuration config.Configuration
|
||||
client dclient.Interface
|
||||
contextLoader engineapi.ContextLoaderFactory
|
||||
exceptionSelector engineapi.PolicyExceptionSelector
|
||||
}
|
||||
|
||||
func NewEngine(
|
||||
configuration config.Configuration,
|
||||
client dclient.Interface,
|
||||
contextLoader engineapi.ContextLoaderFactory,
|
||||
exceptionSelector engineapi.PolicyExceptionSelector,
|
||||
) engineapi.Engine {
|
||||
return &engine{
|
||||
configuration: configuration,
|
||||
client: client,
|
||||
contextLoader: contextLoader,
|
||||
exceptionSelector: exceptionSelector,
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ func (e *engine) verifyAndPatchImages(
|
|||
}
|
||||
|
||||
kindsInPolicy := append(rule.MatchResources.GetKinds(), rule.ExcludeResources.GetKinds()...)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(kindsInPolicy, policyContext)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(e.client, kindsInPolicy, policyContext)
|
||||
|
||||
if !matches(logger, rule, policyContext, subresourceGVKToAPIResource, e.configuration) {
|
||||
return
|
||||
|
|
|
@ -169,7 +169,8 @@ func testVerifyAndPatchImages(
|
|||
) (*engineapi.EngineResponse, *engineapi.ImageVerificationMetadata) {
|
||||
e := NewEngine(
|
||||
cfg,
|
||||
LegacyContextLoaderFactory(rclient, cmResolver),
|
||||
nil,
|
||||
LegacyContextLoaderFactory(nil, rclient, cmResolver),
|
||||
nil,
|
||||
)
|
||||
return e.VerifyAndPatchImages(
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
)
|
||||
|
||||
func LegacyContextLoaderFactory(
|
||||
client dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
cmResolver engineapi.ConfigmapResolver,
|
||||
) engineapi.ContextLoaderFactory {
|
||||
|
@ -29,7 +30,7 @@ func LegacyContextLoaderFactory(
|
|||
logger: logging.WithName("MockContextLoaderFactory"),
|
||||
policyName: policy.GetName(),
|
||||
ruleName: ruleName,
|
||||
client: pContext.Client(),
|
||||
client: client,
|
||||
rclient: rclient,
|
||||
cmResolver: cmResolver,
|
||||
}
|
||||
|
@ -38,7 +39,7 @@ func LegacyContextLoaderFactory(
|
|||
return func(pContext engineapi.PolicyContext, ruleName string) engineapi.ContextLoader {
|
||||
return &contextLoader{
|
||||
logger: logging.WithName("LegacyContextLoaderFactory"),
|
||||
client: pContext.Client(),
|
||||
client: client,
|
||||
rclient: rclient,
|
||||
cmResolver: cmResolver,
|
||||
}
|
||||
|
|
|
@ -35,16 +35,26 @@ const (
|
|||
//go:embed resources/default-config.yaml
|
||||
var defaultConfigBytes []byte
|
||||
|
||||
func processYAMLValidationRule(log logr.Logger, ctx engineapi.PolicyContext, rule *kyvernov1.Rule) *engineapi.RuleResponse {
|
||||
func processYAMLValidationRule(
|
||||
client dclient.Interface,
|
||||
log logr.Logger,
|
||||
ctx engineapi.PolicyContext,
|
||||
rule *kyvernov1.Rule,
|
||||
) *engineapi.RuleResponse {
|
||||
if isDeleteRequest(ctx) {
|
||||
return nil
|
||||
}
|
||||
ruleResp := handleVerifyManifest(ctx, rule, log)
|
||||
ruleResp := handleVerifyManifest(client, ctx, rule, log)
|
||||
return ruleResp
|
||||
}
|
||||
|
||||
func handleVerifyManifest(ctx engineapi.PolicyContext, rule *kyvernov1.Rule, logger logr.Logger) *engineapi.RuleResponse {
|
||||
verified, reason, err := verifyManifest(ctx, *rule.Validation.Manifests, logger)
|
||||
func handleVerifyManifest(
|
||||
client dclient.Interface,
|
||||
ctx engineapi.PolicyContext,
|
||||
rule *kyvernov1.Rule,
|
||||
logger logr.Logger,
|
||||
) *engineapi.RuleResponse {
|
||||
verified, reason, err := verifyManifest(client, ctx, *rule.Validation.Manifests, logger)
|
||||
if err != nil {
|
||||
logger.V(3).Info("verifyManifest return err", "error", err.Error())
|
||||
return internal.RuleError(rule, engineapi.Validation, "error occurred during manifest verification", err)
|
||||
|
@ -56,7 +66,12 @@ func handleVerifyManifest(ctx engineapi.PolicyContext, rule *kyvernov1.Rule, log
|
|||
return internal.RuleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func verifyManifest(policyContext engineapi.PolicyContext, verifyRule kyvernov1.Manifests, logger logr.Logger) (bool, string, error) {
|
||||
func verifyManifest(
|
||||
client dclient.Interface,
|
||||
policyContext engineapi.PolicyContext,
|
||||
verifyRule kyvernov1.Manifests,
|
||||
logger logr.Logger,
|
||||
) (bool, string, error) {
|
||||
// load AdmissionRequest
|
||||
request, err := policyContext.JSONContext().Query("request")
|
||||
if err != nil {
|
||||
|
@ -106,7 +121,7 @@ func verifyManifest(policyContext engineapi.PolicyContext, verifyRule kyvernov1.
|
|||
}
|
||||
if !vo.DisableDryRun {
|
||||
// check if kyverno can 'create' dryrun resource
|
||||
ok, err := checkDryRunPermission(policyContext.Client(), adreq.Kind.Kind, vo.DryRunNamespace)
|
||||
ok, err := checkDryRunPermission(client, adreq.Kind.Kind, vo.DryRunNamespace)
|
||||
if err != nil {
|
||||
logger.V(1).Info("failed to check permissions to 'create' resource. disabled DryRun option.", "dryrun namespace", vo.DryRunNamespace, "kind", adreq.Kind.Kind, "error", err.Error())
|
||||
vo.DisableDryRun = true
|
||||
|
|
|
@ -628,7 +628,7 @@ func Test_VerifyManifest_SignedYAML(t *testing.T) {
|
|||
},
|
||||
})
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
verified, _, err := verifyManifest(nil, policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
}
|
||||
|
@ -650,7 +650,7 @@ func Test_VerifyManifest_UnsignedYAML(t *testing.T) {
|
|||
},
|
||||
})
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
verified, _, err := verifyManifest(nil, policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, false)
|
||||
}
|
||||
|
@ -672,7 +672,7 @@ func Test_VerifyManifest_InvalidYAML(t *testing.T) {
|
|||
},
|
||||
})
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
verified, _, err := verifyManifest(nil, policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, false)
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ func Test_VerifyManifest_MustAll_InvalidYAML(t *testing.T) {
|
|||
},
|
||||
})
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
verified, _, err := verifyManifest(nil, policyContext, verifyRule, logger)
|
||||
errMsg := `.attestors[0].entries[1].keys: failed to verify signature: verification failed for 1 signature. all trials: ["[publickey 1/1] [signature 1/1] error: cosign.VerifyBlobCmd() returned an error: invalid signature when validating ASN.1 encoded signature"]`
|
||||
assert.Error(t, err, errMsg)
|
||||
assert.Equal(t, verified, false)
|
||||
|
@ -732,7 +732,7 @@ func Test_VerifyManifest_MustAll_ValidYAML(t *testing.T) {
|
|||
},
|
||||
})
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
verified, _, err := verifyManifest(nil, policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
}
|
||||
|
@ -761,7 +761,7 @@ func Test_VerifyManifest_AtLeastOne(t *testing.T) {
|
|||
},
|
||||
})
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
verified, _, err := verifyManifest(nil, policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
|
@ -24,7 +25,12 @@ type resourceInfo struct {
|
|||
parentResourceGVR metav1.GroupVersionResource
|
||||
}
|
||||
|
||||
func loadTargets(targets []kyvernov1.ResourceSpec, ctx engineapi.PolicyContext, logger logr.Logger) ([]resourceInfo, error) {
|
||||
func loadTargets(
|
||||
client dclient.Interface,
|
||||
targets []kyvernov1.ResourceSpec,
|
||||
ctx engineapi.PolicyContext,
|
||||
logger logr.Logger,
|
||||
) ([]resourceInfo, error) {
|
||||
var targetObjects []resourceInfo
|
||||
var errors []error
|
||||
|
||||
|
@ -35,7 +41,7 @@ func loadTargets(targets []kyvernov1.ResourceSpec, ctx engineapi.PolicyContext,
|
|||
continue
|
||||
}
|
||||
|
||||
objs, err := getTargets(spec, ctx)
|
||||
objs, err := getTargets(client, spec, ctx)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
continue
|
||||
|
@ -76,7 +82,11 @@ func resolveSpec(i int, target kyvernov1.ResourceSpec, ctx engineapi.PolicyConte
|
|||
}, nil
|
||||
}
|
||||
|
||||
func getTargets(target kyvernov1.ResourceSpec, ctx engineapi.PolicyContext) ([]resourceInfo, error) {
|
||||
func getTargets(
|
||||
client dclient.Interface,
|
||||
target kyvernov1.ResourceSpec,
|
||||
ctx engineapi.PolicyContext,
|
||||
) ([]resourceInfo, error) {
|
||||
var targetObjects []resourceInfo
|
||||
namespace := target.Namespace
|
||||
name := target.Name
|
||||
|
@ -86,7 +96,6 @@ func getTargets(target kyvernov1.ResourceSpec, ctx engineapi.PolicyContext) ([]r
|
|||
if policy.IsNamespaced() {
|
||||
namespace = policy.GetNamespace()
|
||||
}
|
||||
client := ctx.Client()
|
||||
apiResource, parentAPIResource, _, err := client.Discovery().FindResource(target.APIVersion, target.Kind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -67,7 +67,7 @@ func (e *engine) mutate(
|
|||
}
|
||||
|
||||
kindsInPolicy := append(rule.MatchResources.GetKinds(), rule.ExcludeResources.GetKinds()...)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(kindsInPolicy, policyContext)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(e.client, kindsInPolicy, policyContext)
|
||||
if err = MatchesResourceDescription(subresourceGVKToAPIResource, matchedResource, rule, policyContext.AdmissionInfo(), excludeResource, policyContext.NamespaceLabels(), policyContext.Policy().GetNamespace(), policyContext.SubResource()); err != nil {
|
||||
logger.V(4).Info("rule not matched", "reason", err.Error())
|
||||
skippedRules = append(skippedRules, rule.Name)
|
||||
|
@ -104,7 +104,7 @@ func (e *engine) mutate(
|
|||
ruleCopy := rule.DeepCopy()
|
||||
var patchedResources []resourceInfo
|
||||
if !policyContext.AdmissionOperation() && rule.IsMutateExisting() {
|
||||
targets, err := loadTargets(ruleCopy.Mutation.Targets, policyContext, logger)
|
||||
targets, err := loadTargets(e.client, ruleCopy.Mutation.Targets, policyContext, logger)
|
||||
if err != nil {
|
||||
rr := internal.RuleResponse(rule, engineapi.Mutation, err.Error(), engineapi.RuleStatusError)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *rr)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
client "github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
|
@ -22,12 +23,14 @@ import (
|
|||
|
||||
func testMutate(
|
||||
ctx context.Context,
|
||||
client dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
pContext *PolicyContext,
|
||||
) *engineapi.EngineResponse {
|
||||
e := NewEngine(
|
||||
cfg,
|
||||
LegacyContextLoaderFactory(rclient, nil),
|
||||
client,
|
||||
LegacyContextLoaderFactory(client, rclient, nil),
|
||||
nil,
|
||||
)
|
||||
return e.Mutate(
|
||||
|
@ -111,7 +114,7 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
|
|||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
|
@ -185,7 +188,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
|||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
}
|
||||
|
@ -278,7 +281,7 @@ func Test_variableSubstitutionCLI(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
t.Log(string(expectedPatch))
|
||||
|
@ -387,7 +390,7 @@ func Test_chained_rules(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, containers[0].(map[string]interface{})["image"], "otherregistry.corp.com/foo/bash:5.0")
|
||||
|
@ -475,7 +478,7 @@ func Test_precondition(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
|
@ -572,7 +575,7 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
|
@ -666,7 +669,7 @@ func Test_foreach(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
|
@ -773,7 +776,7 @@ func Test_foreach_element_mutation(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
|
@ -899,7 +902,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
|
@ -1049,7 +1052,7 @@ func testApplyPolicyToResource(t *testing.T, policyRaw, resourceRaw []byte) *eng
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
return er
|
||||
}
|
||||
|
||||
|
@ -1594,18 +1597,18 @@ func Test_mutate_existing_resources(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext = &PolicyContext{
|
||||
client: dclient,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *trigger,
|
||||
}
|
||||
}
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
|
||||
for _, rr := range er.PolicyResponse.Rules {
|
||||
for i, p := range rr.Patches {
|
||||
assert.Equal(t, test.patches[i], string(p), "test %s failed:\nGot %s\nExpected: %s", test.name, rr.Patches[i], test.patches[i])
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusPass, rr.Status)
|
||||
er := testMutate(context.TODO(), dclient, registryclient.NewOrDie(), policyContext)
|
||||
|
||||
for _, rr := range er.PolicyResponse.Rules {
|
||||
for i, p := range rr.Patches {
|
||||
assert.Equal(t, test.patches[i], string(p), "test %s failed:\nGot %s\nExpected: %s", test.name, rr.Patches[i], test.patches[i])
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusPass, rr.Status)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1708,7 +1711,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 2)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches), 1)
|
||||
|
@ -1723,7 +1726,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
applyOne := kyverno.ApplyOne
|
||||
policyContext.policy.GetSpec().ApplyRules = &applyOne
|
||||
|
||||
er = testMutate(context.TODO(), registryclient.NewOrDie(), policyContext)
|
||||
er = testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
|
||||
|
@ -2090,7 +2093,7 @@ func Test_SpecialCharacters(t *testing.T) {
|
|||
}
|
||||
|
||||
// Mutate and make sure that we got the expected amount of rules.
|
||||
patches := testMutate(context.TODO(), registryclient.NewOrDie(), policyContext).GetPatches()
|
||||
patches := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext).GetPatches()
|
||||
if !reflect.DeepEqual(patches, tt.want) {
|
||||
t.Errorf("Mutate() got patches %s, expected %s", patches, tt.want)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
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"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
|
@ -42,9 +41,6 @@ type PolicyContext struct {
|
|||
// and `requestResource: {group:"apps", version:"v1beta1", resource:"deployments"}` (indicating the resource of the original API request).
|
||||
requestResource metav1.GroupVersionResource
|
||||
|
||||
// Dynamic client - used for api lookups
|
||||
client dclient.Interface
|
||||
|
||||
// jsonContext is the variable context
|
||||
jsonContext enginectx.Interface
|
||||
|
||||
|
@ -113,10 +109,6 @@ func (c *PolicyContext) JSONContext() enginectx.Interface {
|
|||
return c.jsonContext
|
||||
}
|
||||
|
||||
func (c *PolicyContext) Client() dclient.Interface {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c PolicyContext) Copy() engineapi.PolicyContext {
|
||||
return c.copy()
|
||||
}
|
||||
|
@ -163,12 +155,6 @@ func (c *PolicyContext) WithResources(newResource unstructured.Unstructured, old
|
|||
return c.WithNewResource(newResource).WithOldResource(oldResource)
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithClient(client dclient.Interface) *PolicyContext {
|
||||
copy := c.copy()
|
||||
copy.client = client
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) withAdmissionOperation(admissionOperation bool) *PolicyContext {
|
||||
copy := c.copy()
|
||||
copy.admissionOperation = admissionOperation
|
||||
|
@ -207,7 +193,6 @@ func NewPolicyContextFromAdmissionRequest(
|
|||
request *admissionv1.AdmissionRequest,
|
||||
admissionInfo kyvernov1beta1.RequestInfo,
|
||||
configuration config.Configuration,
|
||||
client dclient.Interface,
|
||||
) (*PolicyContext, error) {
|
||||
ctx, err := newVariablesContext(request, &admissionInfo)
|
||||
if err != nil {
|
||||
|
@ -225,7 +210,6 @@ func NewPolicyContextFromAdmissionRequest(
|
|||
WithNewResource(newResource).
|
||||
WithOldResource(oldResource).
|
||||
WithAdmissionInfo(admissionInfo).
|
||||
WithClient(client).
|
||||
withAdmissionOperation(true).
|
||||
WithRequestResource(*requestResource).
|
||||
WithSubresource(request.SubResource)
|
||||
|
|
|
@ -87,7 +87,7 @@ func (e *engine) validateResource(
|
|||
}
|
||||
log = log.WithValues("rule", rule.Name)
|
||||
kindsInPolicy := append(rule.MatchResources.GetKinds(), rule.ExcludeResources.GetKinds()...)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(kindsInPolicy, enginectx)
|
||||
subresourceGVKToAPIResource := GetSubresourceGVKToAPIResourceMap(e.client, kindsInPolicy, enginectx)
|
||||
|
||||
if !matches(log, rule, enginectx, subresourceGVKToAPIResource, e.configuration) {
|
||||
return nil
|
||||
|
@ -104,7 +104,7 @@ func (e *engine) validateResource(
|
|||
} else if hasValidateImage {
|
||||
return e.processImageValidationRule(ctx, log, enginectx, rule)
|
||||
} else if hasYAMLSignatureVerify {
|
||||
return processYAMLValidationRule(log, enginectx, rule)
|
||||
return processYAMLValidationRule(e.client, log, enginectx, rule)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
|
|
@ -22,7 +22,8 @@ import (
|
|||
func testValidate(ctx context.Context, rclient registryclient.Client, pContext *PolicyContext, cfg config.Configuration) *engineapi.EngineResponse {
|
||||
e := NewEngine(
|
||||
cfg,
|
||||
LegacyContextLoaderFactory(rclient, nil),
|
||||
nil,
|
||||
LegacyContextLoaderFactory(nil, rclient, nil),
|
||||
nil,
|
||||
)
|
||||
return e.Validate(
|
||||
|
|
|
@ -148,7 +148,8 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
policyContext := engine.NewPolicyContext().WithPolicy(policy).WithNewResource(*resource)
|
||||
eng := engine.NewEngine(
|
||||
config.NewDefaultConfiguration(),
|
||||
engine.LegacyContextLoaderFactory(registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
)
|
||||
er := eng.Mutate(
|
||||
|
@ -183,7 +184,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
if err := createNamespace(client, resource); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
policyContext := policyContext.WithClient(client)
|
||||
// policyContext := policyContext.WithClient(client)
|
||||
|
||||
er = eng.ApplyBackgroundChecks(
|
||||
policyContext,
|
||||
|
|
|
@ -58,7 +58,8 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
|
|||
urUpdater: webhookutils.NewUpdateRequestUpdater(kyvernoclient, urLister),
|
||||
engine: engine.NewEngine(
|
||||
configuration,
|
||||
engine.LegacyContextLoaderFactory(rclient, configMapResolver),
|
||||
dclient,
|
||||
engine.LegacyContextLoaderFactory(dclient, rclient, configMapResolver),
|
||||
peLister,
|
||||
),
|
||||
}
|
||||
|
|
|
@ -1051,7 +1051,8 @@ func TestValidate_failure_action_overrides(t *testing.T) {
|
|||
|
||||
eng := engine.NewEngine(
|
||||
config.NewDefaultConfiguration(),
|
||||
engine.LegacyContextLoaderFactory(registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
)
|
||||
for i, tc := range testcases {
|
||||
|
@ -1128,7 +1129,8 @@ func Test_RuleSelector(t *testing.T) {
|
|||
|
||||
eng := engine.NewEngine(
|
||||
config.NewDefaultConfiguration(),
|
||||
engine.LegacyContextLoaderFactory(registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
engine.LegacyContextLoaderFactory(nil, registryclient.NewOrDie(), nil),
|
||||
nil,
|
||||
)
|
||||
resp := eng.Validate(
|
||||
|
|
|
@ -18,7 +18,6 @@ type PolicyContextBuilder interface {
|
|||
|
||||
type policyContextBuilder struct {
|
||||
configuration config.Configuration
|
||||
client dclient.Interface
|
||||
rbLister rbacv1listers.RoleBindingLister
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister
|
||||
}
|
||||
|
@ -31,7 +30,6 @@ func NewPolicyContextBuilder(
|
|||
) PolicyContextBuilder {
|
||||
return &policyContextBuilder{
|
||||
configuration: configuration,
|
||||
client: client,
|
||||
rbLister: rbLister,
|
||||
crbLister: crbLister,
|
||||
}
|
||||
|
@ -47,5 +45,5 @@ func (b *policyContextBuilder) Build(request *admissionv1.AdmissionRequest) (*en
|
|||
userRequestInfo.Roles = roles
|
||||
userRequestInfo.ClusterRoles = clusterRoles
|
||||
}
|
||||
return engine.NewPolicyContextFromAdmissionRequest(request, userRequestInfo, b.configuration, b.client)
|
||||
return engine.NewPolicyContextFromAdmissionRequest(request, userRequestInfo, b.configuration)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue