mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
refactor: make policy context immutable and fields private (#5523)
* refactor: make policy context immutable and fields private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * refactor: make policy context immutable and fields private 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> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
d7c7bbc843
commit
5b89e2e5f8
30 changed files with 538 additions and 470 deletions
|
@ -450,14 +450,12 @@ OuterLoop:
|
|||
log.Log.Error(err, "failed to add image variables to context")
|
||||
}
|
||||
|
||||
policyContext := &engine.PolicyContext{
|
||||
Policy: c.Policy,
|
||||
NewResource: *updatedResource,
|
||||
JSONContext: ctx,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
AdmissionInfo: c.UserInfo,
|
||||
Client: c.Client,
|
||||
}
|
||||
policyContext := engine.NewPolicyContextWithJsonContext(ctx).
|
||||
WithPolicy(c.Policy).
|
||||
WithNewResource(*updatedResource).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithAdmissionInfo(c.UserInfo).
|
||||
WithClient(c.Client)
|
||||
|
||||
mutateResponse := engine.Mutate(policyContext)
|
||||
if mutateResponse != nil {
|
||||
|
@ -478,7 +476,7 @@ OuterLoop:
|
|||
}
|
||||
}
|
||||
|
||||
policyContext.NewResource = mutateResponse.PatchedResource
|
||||
policyContext = policyContext.WithNewResource(mutateResponse.PatchedResource)
|
||||
|
||||
var info Info
|
||||
var validateResponse *response.EngineResponse
|
||||
|
@ -505,16 +503,6 @@ OuterLoop:
|
|||
}
|
||||
|
||||
if policyHasGenerate {
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: *c.Resource,
|
||||
Policy: c.Policy,
|
||||
ExcludeGroupRole: []string{},
|
||||
ExcludeResourceFunc: func(s1, s2, s3 string) bool {
|
||||
return false
|
||||
},
|
||||
JSONContext: ctx,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
}
|
||||
generateResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
if generateResponse != nil && !generateResponse.IsEmpty() {
|
||||
newRuleResponse, err := handleGeneratePolicy(generateResponse, *policyContext, c.RuleToCloneSourceResource)
|
||||
|
@ -1011,7 +999,8 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr
|
|||
|
||||
// handleGeneratePolicy returns a new RuleResponse with the Kyverno generated resource configuration by applying the generate rule.
|
||||
func handleGeneratePolicy(generateResponse *response.EngineResponse, policyContext engine.PolicyContext, ruleToCloneSourceResource map[string]string) ([]response.RuleResponse, error) {
|
||||
objects := []runtime.Object{&policyContext.NewResource}
|
||||
resource := policyContext.NewResource()
|
||||
objects := []runtime.Object{&resource}
|
||||
resources := []*unstructured.Unstructured{}
|
||||
for _, rule := range generateResponse.PolicyResponse.Rules {
|
||||
if path, ok := ruleToCloneSourceResource[rule.Name]; ok {
|
||||
|
|
|
@ -77,18 +77,14 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe
|
|||
logger.Error(err, "unable to add image info to variables context")
|
||||
}
|
||||
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: *trigger,
|
||||
OldResource: old,
|
||||
Policy: policy,
|
||||
AdmissionInfo: ur.Spec.Context.UserRequestInfo,
|
||||
ExcludeGroupRole: cfg.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: cfg.ToFilter,
|
||||
JSONContext: ctx,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
Client: dclient,
|
||||
AdmissionOperation: false,
|
||||
}
|
||||
policyContext := engine.NewPolicyContextWithJsonContext(ctx).
|
||||
WithPolicy(policy).
|
||||
WithNewResource(*trigger).
|
||||
WithOldResource(old).
|
||||
WithAdmissionInfo(ur.Spec.Context.UserRequestInfo).
|
||||
WithConfiguration(cfg).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithClient(dclient)
|
||||
|
||||
return policyContext, false, nil
|
||||
}
|
||||
|
|
|
@ -306,13 +306,12 @@ func updateStatus(statusControl common.StatusControlInterface, ur kyvernov1beta1
|
|||
func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, ur kyvernov1beta1.UpdateRequest, applicableRules []string) (genResources []kyvernov1.ResourceSpec, processExisting bool, err error) {
|
||||
// Get the response as the actions to be performed on the resource
|
||||
// - - substitute values
|
||||
policy := policyContext.Policy
|
||||
resource := policyContext.NewResource
|
||||
|
||||
jsonContext := policyContext.JSONContext
|
||||
policy := policyContext.Policy()
|
||||
resource := policyContext.NewResource()
|
||||
jsonContext := policyContext.JSONContext()
|
||||
// To manage existing resources, we compare the creation time for the default resource to be generated and policy creation time
|
||||
ruleNameToProcessingTime := make(map[string]time.Duration)
|
||||
applyRules := policyContext.Policy.GetSpec().GetApplyRules()
|
||||
applyRules := policy.GetSpec().GetApplyRules()
|
||||
applyCount := 0
|
||||
|
||||
for _, rule := range autogen.ComputeRules(policy) {
|
||||
|
@ -347,7 +346,7 @@ func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext
|
|||
return nil, processExisting, err
|
||||
}
|
||||
|
||||
if rule, err = variables.SubstituteAllInRule(log, policyContext.JSONContext, rule); err != nil {
|
||||
if rule, err = variables.SubstituteAllInRule(log, policyContext.JSONContext(), rule); err != nil {
|
||||
log.Error(err, "variable substitution failed for rule %s", rule.Name)
|
||||
return nil, processExisting, err
|
||||
}
|
||||
|
|
|
@ -75,14 +75,12 @@ func (s *scanner) validateResource(resource unstructured.Unstructured, nsLabels
|
|||
if err := ctx.AddOperation("CREATE"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policyCtx := &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: resource,
|
||||
JSONContext: ctx,
|
||||
Client: s.client,
|
||||
NamespaceLabels: nsLabels,
|
||||
ExcludeGroupRole: s.excludeGroupRole,
|
||||
}
|
||||
policyCtx := engine.NewPolicyContextWithJsonContext(ctx).
|
||||
WithNewResource(resource).
|
||||
WithPolicy(policy).
|
||||
WithClient(s.client).
|
||||
WithNamespaceLabels(nsLabels).
|
||||
WithExcludeGroupRole(s.excludeGroupRole...)
|
||||
return engine.Validate(policyCtx), nil
|
||||
}
|
||||
|
||||
|
@ -100,14 +98,12 @@ func (s *scanner) validateImages(resource unstructured.Unstructured, nsLabels ma
|
|||
if err := ctx.AddOperation("CREATE"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policyCtx := &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: resource,
|
||||
JSONContext: ctx,
|
||||
Client: s.client,
|
||||
NamespaceLabels: nsLabels,
|
||||
ExcludeGroupRole: s.excludeGroupRole,
|
||||
}
|
||||
policyCtx := engine.NewPolicyContextWithJsonContext(ctx).
|
||||
WithNewResource(resource).
|
||||
WithPolicy(policy).
|
||||
WithClient(s.client).
|
||||
WithNamespaceLabels(nsLabels).
|
||||
WithExcludeGroupRole(s.excludeGroupRole...)
|
||||
response, _ := engine.VerifyAndPatchImages(policyCtx)
|
||||
if len(response.PolicyResponse.Rules) > 0 {
|
||||
s.logger.Info("validateImages", "policy", policy, "response", response)
|
||||
|
|
|
@ -12,7 +12,6 @@ var client Cosign = &driver{}
|
|||
|
||||
type Cosign interface {
|
||||
VerifyImageSignatures(ctx context.Context, signedImgRef name.Reference, co *cosign.CheckOpts) ([]oci.Signature, bool, error)
|
||||
|
||||
VerifyImageAttestations(ctx context.Context, signedImgRef name.Reference, co *cosign.CheckOpts) (checkedAttestations []oci.Signature, bundleVerified bool, err error)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,15 @@ func ApplyBackgroundChecks(policyContext *PolicyContext) (resp *response.EngineR
|
|||
}
|
||||
|
||||
func filterRules(policyContext *PolicyContext, startTime time.Time) *response.EngineResponse {
|
||||
kind := policyContext.NewResource.GetKind()
|
||||
name := policyContext.NewResource.GetName()
|
||||
namespace := policyContext.NewResource.GetNamespace()
|
||||
apiVersion := policyContext.NewResource.GetAPIVersion()
|
||||
kind := policyContext.newResource.GetKind()
|
||||
name := policyContext.newResource.GetName()
|
||||
namespace := policyContext.newResource.GetNamespace()
|
||||
apiVersion := policyContext.newResource.GetAPIVersion()
|
||||
resp := &response.EngineResponse{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: response.PolicySpec{
|
||||
Name: policyContext.Policy.GetName(),
|
||||
Namespace: policyContext.Policy.GetNamespace(),
|
||||
Name: policyContext.policy.GetName(),
|
||||
Namespace: policyContext.policy.GetNamespace(),
|
||||
},
|
||||
PolicyStats: response.PolicyStats{
|
||||
PolicyExecutionTimestamp: startTime.Unix(),
|
||||
|
@ -44,13 +44,13 @@ func filterRules(policyContext *PolicyContext, startTime time.Time) *response.En
|
|||
},
|
||||
}
|
||||
|
||||
if policyContext.ExcludeResourceFunc(kind, namespace, name) {
|
||||
if policyContext.excludeResourceFunc(kind, namespace, name) {
|
||||
logging.WithName("ApplyBackgroundChecks").Info("resource excluded", "kind", kind, "namespace", namespace, "name", name)
|
||||
return resp
|
||||
}
|
||||
|
||||
applyRules := policyContext.Policy.GetSpec().GetApplyRules()
|
||||
for _, rule := range autogen.ComputeRules(policyContext.Policy) {
|
||||
applyRules := policyContext.policy.GetSpec().GetApplyRules()
|
||||
for _, rule := range autogen.ComputeRules(policyContext.policy) {
|
||||
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
if applyRules == kyvernov1.ApplyOne && ruleResp.Status != response.RuleStatusSkip {
|
||||
|
@ -75,13 +75,13 @@ func filterRule(rule kyvernov1.Rule, policyContext *PolicyContext) *response.Rul
|
|||
var err error
|
||||
startTime := time.Now()
|
||||
|
||||
policy := policyContext.Policy
|
||||
newResource := policyContext.NewResource
|
||||
oldResource := policyContext.OldResource
|
||||
admissionInfo := policyContext.AdmissionInfo
|
||||
ctx := policyContext.JSONContext
|
||||
excludeGroupRole := policyContext.ExcludeGroupRole
|
||||
namespaceLabels := policyContext.NamespaceLabels
|
||||
policy := policyContext.policy
|
||||
newResource := policyContext.newResource
|
||||
oldResource := policyContext.oldResource
|
||||
admissionInfo := policyContext.admissionInfo
|
||||
ctx := policyContext.jsonContext
|
||||
excludeGroupRole := policyContext.excludeGroupRole
|
||||
namespaceLabels := policyContext.namespaceLabels
|
||||
|
||||
logger := logging.WithName(string(ruleType)).WithValues("policy", policy.GetName(),
|
||||
"kind", newResource.GetKind(), "namespace", newResource.GetNamespace(), "name", newResource.GetName())
|
||||
|
@ -105,8 +105,8 @@ func filterRule(rule kyvernov1.Rule, policyContext *PolicyContext) *response.Rul
|
|||
return nil
|
||||
}
|
||||
|
||||
policyContext.JSONContext.Checkpoint()
|
||||
defer policyContext.JSONContext.Restore()
|
||||
policyContext.jsonContext.Checkpoint()
|
||||
defer policyContext.jsonContext.Restore()
|
||||
|
||||
if err = LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
logger.V(4).Info("cannot add external data to the context", "reason", err.Error())
|
||||
|
|
|
@ -17,10 +17,10 @@ func GenerateResponse(policyContext *PolicyContext, gr kyvernov1beta1.UpdateRequ
|
|||
}
|
||||
|
||||
func filterGenerateRules(policyContext *PolicyContext, policyNameKey string, startTime time.Time) *response.EngineResponse {
|
||||
kind := policyContext.NewResource.GetKind()
|
||||
name := policyContext.NewResource.GetName()
|
||||
namespace := policyContext.NewResource.GetNamespace()
|
||||
apiVersion := policyContext.NewResource.GetAPIVersion()
|
||||
kind := policyContext.newResource.GetKind()
|
||||
name := policyContext.newResource.GetName()
|
||||
namespace := policyContext.newResource.GetNamespace()
|
||||
apiVersion := policyContext.newResource.GetAPIVersion()
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(policyNameKey)
|
||||
if err != nil {
|
||||
logging.Error(err, "failed to spilt name and namespace", policyNameKey)
|
||||
|
@ -44,12 +44,12 @@ func filterGenerateRules(policyContext *PolicyContext, policyNameKey string, sta
|
|||
},
|
||||
}
|
||||
|
||||
if policyContext.ExcludeResourceFunc(kind, namespace, name) {
|
||||
if policyContext.excludeResourceFunc(kind, namespace, name) {
|
||||
logging.WithName("Generate").Info("resource excluded", "kind", kind, "namespace", namespace, "name", name)
|
||||
return resp
|
||||
}
|
||||
|
||||
for _, rule := range autogen.ComputeRules(policyContext.Policy) {
|
||||
for _, rule := range autogen.ComputeRules(policyContext.policy) {
|
||||
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
}
|
||||
|
|
|
@ -48,10 +48,10 @@ func extractMatchingImages(policyContext *PolicyContext, rule *kyvernov1.Rule) (
|
|||
images map[string]map[string]apiutils.ImageInfo
|
||||
err error
|
||||
)
|
||||
images = policyContext.JSONContext.ImageInfo()
|
||||
images = policyContext.jsonContext.ImageInfo()
|
||||
if rule.ImageExtractors != nil {
|
||||
images, err = policyContext.JSONContext.GenerateCustomImageInfo(
|
||||
&policyContext.NewResource, rule.ImageExtractors)
|
||||
images, err = policyContext.jsonContext.GenerateCustomImageInfo(
|
||||
&policyContext.newResource, rule.ImageExtractors)
|
||||
if err != nil {
|
||||
// if we get an error while generating custom images from image extractors,
|
||||
// don't check for matching images in imageExtractors
|
||||
|
@ -65,8 +65,8 @@ func extractMatchingImages(policyContext *PolicyContext, rule *kyvernov1.Rule) (
|
|||
func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineResponse, *ImageVerificationMetadata) {
|
||||
resp := &response.EngineResponse{}
|
||||
|
||||
policy := policyContext.Policy
|
||||
patchedResource := policyContext.NewResource
|
||||
policy := policyContext.policy
|
||||
patchedResource := policyContext.newResource
|
||||
logger := logging.WithName("EngineVerifyImages").WithValues("policy", policy.GetName(),
|
||||
"kind", patchedResource.GetKind(), "namespace", patchedResource.GetNamespace(), "name", patchedResource.GetName())
|
||||
|
||||
|
@ -78,8 +78,8 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineRespons
|
|||
"applied", resp.PolicyResponse.RulesAppliedCount, "successful", resp.IsSuccessful())
|
||||
}()
|
||||
|
||||
policyContext.JSONContext.Checkpoint()
|
||||
defer policyContext.JSONContext.Restore()
|
||||
policyContext.jsonContext.Checkpoint()
|
||||
defer policyContext.jsonContext.Restore()
|
||||
|
||||
// update image registry secrets
|
||||
if err := registryclient.DefaultClient.RefreshKeychainPullSecrets(); err != nil {
|
||||
|
@ -87,7 +87,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineRespons
|
|||
}
|
||||
|
||||
ivm := &ImageVerificationMetadata{}
|
||||
rules := autogen.ComputeRules(policyContext.Policy)
|
||||
rules := autogen.ComputeRules(policyContext.policy)
|
||||
applyRules := policy.GetSpec().GetApplyRules()
|
||||
|
||||
for i := range rules {
|
||||
|
@ -115,13 +115,13 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineRespons
|
|||
continue
|
||||
}
|
||||
|
||||
policyContext.JSONContext.Restore()
|
||||
policyContext.jsonContext.Restore()
|
||||
if err := LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
appendResponse(resp, rule, fmt.Sprintf("failed to load context: %s", err.Error()), response.RuleStatusError)
|
||||
continue
|
||||
}
|
||||
|
||||
ruleCopy, err := substituteVariables(rule, policyContext.JSONContext, logger)
|
||||
ruleCopy, err := substituteVariables(rule, policyContext.jsonContext, logger)
|
||||
if err != nil {
|
||||
appendResponse(resp, rule, fmt.Sprintf("failed to substitute variables: %s", err.Error()), response.RuleStatusError)
|
||||
continue
|
||||
|
@ -201,13 +201,13 @@ func (iv *imageVerifier) verify(imageVerify kyvernov1.ImageVerification, matched
|
|||
}
|
||||
|
||||
pointer := jsonpointer.ParsePath(imageInfo.Pointer).JMESPath()
|
||||
changed, err := iv.policyContext.JSONContext.HasChanged(pointer)
|
||||
changed, err := iv.policyContext.jsonContext.HasChanged(pointer)
|
||||
if err == nil && !changed {
|
||||
iv.logger.V(4).Info("no change in image, skipping check", "image", image)
|
||||
continue
|
||||
}
|
||||
|
||||
verified, err := isImageVerified(iv.policyContext.NewResource, image, iv.logger)
|
||||
verified, err := isImageVerified(iv.policyContext.newResource, image, iv.logger)
|
||||
if err == nil && verified {
|
||||
iv.logger.Info("image was previously verified, skipping check", "image", image)
|
||||
continue
|
||||
|
@ -266,14 +266,14 @@ func (iv *imageVerifier) handleMutateDigest(digest string, imageInfo apiutils.Im
|
|||
}
|
||||
|
||||
func hasImageVerifiedAnnotationChanged(ctx *PolicyContext, log logr.Logger) bool {
|
||||
if reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) ||
|
||||
reflect.DeepEqual(ctx.OldResource, unstructured.Unstructured{}) {
|
||||
if reflect.DeepEqual(ctx.newResource, unstructured.Unstructured{}) ||
|
||||
reflect.DeepEqual(ctx.oldResource, unstructured.Unstructured{}) {
|
||||
return false
|
||||
}
|
||||
|
||||
key := imageVerifyAnnotationKey
|
||||
newValue := ctx.NewResource.GetAnnotations()[key]
|
||||
oldValue := ctx.OldResource.GetAnnotations()[key]
|
||||
newValue := ctx.newResource.GetAnnotations()[key]
|
||||
oldValue := ctx.oldResource.GetAnnotations()[key]
|
||||
result := newValue != oldValue
|
||||
if result {
|
||||
log.V(2).Info("annotation mismatch", "oldValue", oldValue, "newValue", newValue, "key", key)
|
||||
|
@ -301,7 +301,7 @@ func (iv *imageVerifier) verifyImage(imageVerify kyvernov1.ImageVerification, im
|
|||
iv.logger.V(2).Info("verifying image signatures", "image", image,
|
||||
"attestors", len(imageVerify.Attestors), "attestations", len(imageVerify.Attestations))
|
||||
|
||||
if err := iv.policyContext.JSONContext.AddImageInfo(imageInfo); err != nil {
|
||||
if err := iv.policyContext.jsonContext.AddImageInfo(imageInfo); err != nil {
|
||||
iv.logger.Error(err, "failed to add image to context")
|
||||
msg := fmt.Sprintf("failed to add image to context %s: %s", image, err.Error())
|
||||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusError, nil), ""
|
||||
|
@ -628,10 +628,10 @@ func (iv *imageVerifier) checkAttestations(a kyvernov1.Attestation, s map[string
|
|||
return true, nil
|
||||
}
|
||||
|
||||
iv.policyContext.JSONContext.Checkpoint()
|
||||
defer iv.policyContext.JSONContext.Restore()
|
||||
iv.policyContext.jsonContext.Checkpoint()
|
||||
defer iv.policyContext.jsonContext.Restore()
|
||||
|
||||
return evaluateConditions(a.Conditions, iv.policyContext.JSONContext, s, iv.logger)
|
||||
return evaluateConditions(a.Conditions, iv.policyContext.jsonContext, s, iv.logger)
|
||||
}
|
||||
|
||||
func evaluateConditions(
|
||||
|
|
|
@ -42,7 +42,7 @@ func processImageValidationRule(log logr.Logger, ctx *PolicyContext, rule *kyver
|
|||
}
|
||||
|
||||
if !preconditionsPassed {
|
||||
if ctx.Policy.GetSpec().ValidationFailureAction.Audit() {
|
||||
if ctx.policy.GetSpec().ValidationFailureAction.Audit() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func processImageValidationRule(log logr.Logger, ctx *PolicyContext, rule *kyver
|
|||
|
||||
for _, v := range rule.VerifyImages {
|
||||
imageVerify := v.Convert()
|
||||
for _, infoMap := range ctx.JSONContext.ImageInfo() {
|
||||
for _, infoMap := range ctx.jsonContext.ImageInfo() {
|
||||
for name, imageInfo := range infoMap {
|
||||
image := imageInfo.String()
|
||||
log = log.WithValues("rule", rule.Name)
|
||||
|
@ -80,8 +80,8 @@ func validateImage(ctx *PolicyContext, imageVerify *kyvernov1.ImageVerification,
|
|||
return fmt.Errorf("missing digest for %s", image)
|
||||
}
|
||||
|
||||
if imageVerify.Required && !reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) {
|
||||
verified, err := isImageVerified(ctx.NewResource, image, log)
|
||||
if imageVerify.Required && !reflect.DeepEqual(ctx.newResource, unstructured.Unstructured{}) {
|
||||
verified, err := isImageVerified(ctx.newResource, image, log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -181,9 +181,9 @@ func buildContext(t *testing.T, policy, resource string, oldResource string) *Po
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &cpol,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured,
|
||||
policy: &cpol,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
if oldResource != "" {
|
||||
|
@ -193,7 +193,7 @@ func buildContext(t *testing.T, policy, resource string, oldResource string) *Po
|
|||
err = context.AddOldResource(ctx, []byte(oldResource))
|
||||
assert.NilError(t, err)
|
||||
|
||||
policyContext.OldResource = *oldResourceUnstructured
|
||||
policyContext.oldResource = *oldResourceUnstructured
|
||||
}
|
||||
|
||||
if err := ctx.AddImageInfos(resourceUnstructured); err != nil {
|
||||
|
@ -418,7 +418,7 @@ func Test_ConfigMapMissingSuccess(t *testing.T) {
|
|||
func Test_ConfigMapMissingFailure(t *testing.T) {
|
||||
ghcrImage := strings.Replace(testConfigMapMissingResource, "nginx:latest", "ghcr.io/kyverno/test-verify-image:signed", -1)
|
||||
policyContext := buildContext(t, testConfigMapMissing, ghcrImage, "")
|
||||
policyContext.Client = client.NewEmptyFakeClient()
|
||||
policyContext.client = client.NewEmptyFakeClient()
|
||||
cosign.ClearMock()
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
|
@ -499,7 +499,7 @@ func Test_RuleSelectorImageVerify(t *testing.T) {
|
|||
|
||||
policyContext := buildContext(t, testSampleSingleKeyPolicy, testSampleResource, "")
|
||||
rule := newStaticKeyRule("match-all", "*", testOtherKey)
|
||||
spec := policyContext.Policy.GetSpec()
|
||||
spec := policyContext.policy.GetSpec()
|
||||
spec.Rules = append(spec.Rules, *rule)
|
||||
|
||||
applyAll := kyverno.ApplyAll
|
||||
|
|
|
@ -19,13 +19,13 @@ func LoadContext(logger logr.Logger, contextEntries []kyvernov1.ContextEntry, ct
|
|||
return nil
|
||||
}
|
||||
|
||||
policyName := ctx.Policy.GetName()
|
||||
policyName := ctx.policy.GetName()
|
||||
if store.GetMock() {
|
||||
rule := store.GetPolicyRuleFromContext(policyName, ruleName)
|
||||
if rule != nil && len(rule.Values) > 0 {
|
||||
variables := rule.Values
|
||||
for key, value := range variables {
|
||||
if err := ctx.JSONContext.AddVariable(key, value); err != nil {
|
||||
if err := ctx.jsonContext.AddVariable(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func LoadContext(logger logr.Logger, contextEntries []kyvernov1.ContextEntry, ct
|
|||
|
||||
if rule != nil && len(rule.ForeachValues) > 0 {
|
||||
for key, value := range rule.ForeachValues {
|
||||
if err := ctx.JSONContext.AddVariable(key, value[store.ForeachElement]); err != nil {
|
||||
if err := ctx.jsonContext.AddVariable(key, value[store.ForeachElement]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ func LoadContext(logger logr.Logger, contextEntries []kyvernov1.ContextEntry, ct
|
|||
func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) (err error) {
|
||||
path := ""
|
||||
if entry.Variable.JMESPath != "" {
|
||||
jp, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.Variable.JMESPath)
|
||||
jp, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.Variable.JMESPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.JMESPath, err)
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyC
|
|||
if err != nil {
|
||||
return fmt.Errorf("invalid default for variable %s", entry.Name)
|
||||
}
|
||||
defaultValue, err = variables.SubstituteAll(logger, ctx.JSONContext, value)
|
||||
defaultValue, err = variables.SubstituteAll(logger, ctx.jsonContext, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Default, err)
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyC
|
|||
var output interface{} = defaultValue
|
||||
if entry.Variable.Value != nil {
|
||||
value, _ := variables.DocumentToUntyped(entry.Variable.Value)
|
||||
variable, err := variables.SubstituteAll(logger, ctx.JSONContext, value)
|
||||
variable, err := variables.SubstituteAll(logger, ctx.jsonContext, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Value, err)
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyC
|
|||
}
|
||||
} else {
|
||||
if path != "" {
|
||||
if variable, err := ctx.JSONContext.Query(path); err == nil {
|
||||
if variable, err := ctx.jsonContext.Query(path); err == nil {
|
||||
output = variable
|
||||
} else if defaultValue == nil {
|
||||
return fmt.Errorf("failed to apply jmespath %s to variable %v", path, err)
|
||||
|
@ -134,7 +134,7 @@ func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyC
|
|||
return fmt.Errorf("unable to add context entry for variable %s since it evaluated to nil", entry.Name)
|
||||
}
|
||||
if outputBytes, err := json.Marshal(output); err == nil {
|
||||
return ctx.JSONContext.ReplaceContextEntry(entry.Name, outputBytes)
|
||||
return ctx.jsonContext.ReplaceContextEntry(entry.Name, outputBytes)
|
||||
} else {
|
||||
return fmt.Errorf("unable to add context entry for variable %s: %w", entry.Name, err)
|
||||
}
|
||||
|
@ -152,14 +152,14 @@ func loadImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Policy
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.JSONContext.AddContextEntry(entry.Name, jsonBytes); err != nil {
|
||||
if err := ctx.jsonContext.AddContextEntry(entry.Name, jsonBytes); err != nil {
|
||||
return fmt.Errorf("failed to add resource data to context: contextEntry: %v, error: %v", entry, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) (interface{}, error) {
|
||||
ref, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.ImageRegistry.Reference)
|
||||
ref, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.ImageRegistry.Reference)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ailed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.Reference, err)
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ func fetchImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Polic
|
|||
if !ok {
|
||||
return nil, fmt.Errorf("invalid image reference %s, image reference must be a string", ref)
|
||||
}
|
||||
path, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.ImageRegistry.JMESPath)
|
||||
path, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.ImageRegistry.JMESPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.JMESPath, err)
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ func loadAPIData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyCo
|
|||
}
|
||||
|
||||
if entry.APICall.JMESPath == "" {
|
||||
err = ctx.JSONContext.AddContextEntry(entry.Name, jsonData)
|
||||
err = ctx.jsonContext.AddContextEntry(entry.Name, jsonData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add resource data to context: contextEntry: %v, error: %v", entry, err)
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ func loadAPIData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyCo
|
|||
return nil
|
||||
}
|
||||
|
||||
path, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.APICall.JMESPath)
|
||||
path, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.APICall.JMESPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.APICall.JMESPath, err)
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ func loadAPIData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyCo
|
|||
return fmt.Errorf("failed to marshall data %v for context entry %v: %v", contextData, entry, err)
|
||||
}
|
||||
|
||||
err = ctx.JSONContext.AddContextEntry(entry.Name, contextData)
|
||||
err = ctx.jsonContext.AddContextEntry(entry.Name, contextData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add JMESPath (%s) results to context, error: %v", entry.APICall.JMESPath, err)
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ func fetchAPIData(log logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyCont
|
|||
return nil, fmt.Errorf("missing APICall in context entry %s %v", entry.Name, entry.APICall)
|
||||
}
|
||||
|
||||
path, err := variables.SubstituteAll(log, ctx.JSONContext, entry.APICall.URLPath)
|
||||
path, err := variables.SubstituteAll(log, ctx.jsonContext, entry.APICall.URLPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.APICall.URLPath, err)
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ func fetchAPIData(log logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyCont
|
|||
}
|
||||
|
||||
func getResource(ctx *PolicyContext, p string) ([]byte, error) {
|
||||
return ctx.Client.RawAbsPath(context.TODO(), p)
|
||||
return ctx.client.RawAbsPath(context.TODO(), p)
|
||||
}
|
||||
|
||||
func loadConfigMap(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) error {
|
||||
|
@ -326,7 +326,7 @@ func loadConfigMap(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Policy
|
|||
return fmt.Errorf("failed to retrieve config map for context entry %s: %v", entry.Name, err)
|
||||
}
|
||||
|
||||
err = ctx.JSONContext.AddContextEntry(entry.Name, data)
|
||||
err = ctx.jsonContext.AddContextEntry(entry.Name, data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add config map for context entry %s: %v", entry.Name, err)
|
||||
}
|
||||
|
@ -337,12 +337,12 @@ func loadConfigMap(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Policy
|
|||
func fetchConfigMap(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) ([]byte, error) {
|
||||
contextData := make(map[string]interface{})
|
||||
|
||||
name, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.ConfigMap.Name)
|
||||
name, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.ConfigMap.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context %s configMap.name %s: %v", entry.Name, entry.ConfigMap.Name, err)
|
||||
}
|
||||
|
||||
namespace, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.ConfigMap.Namespace)
|
||||
namespace, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.ConfigMap.Namespace)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context %s configMap.namespace %s: %v", entry.Name, entry.ConfigMap.Namespace, err)
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ func fetchConfigMap(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Polic
|
|||
namespace = "default"
|
||||
}
|
||||
|
||||
obj, err := ctx.Client.GetResource(context.TODO(), "v1", "ConfigMap", namespace.(string), name.(string))
|
||||
obj, err := ctx.client.GetResource(context.TODO(), "v1", "ConfigMap", namespace.(string), name.(string))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get configmap %s/%s : %v", namespace, name, err)
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ func handleVerifyManifest(ctx *PolicyContext, rule *kyvernov1.Rule, logger logr.
|
|||
|
||||
func verifyManifest(policyContext *PolicyContext, verifyRule kyvernov1.Manifests, logger logr.Logger) (bool, string, error) {
|
||||
// load AdmissionRequest
|
||||
request, err := policyContext.JSONContext.Query("request")
|
||||
request, err := policyContext.jsonContext.Query("request")
|
||||
if err != nil {
|
||||
return false, "", errors.Wrapf(err, "failed to get a request from policyContext")
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func verifyManifest(policyContext *PolicyContext, verifyRule kyvernov1.Manifests
|
|||
}
|
||||
if !vo.DisableDryRun {
|
||||
// check if kyverno can 'create' dryrun resource
|
||||
ok, err := checkDryRunPermission(policyContext.Client, adreq.Kind.Kind, vo.DryRunNamespace)
|
||||
ok, err := checkDryRunPermission(policyContext.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
|
||||
|
|
|
@ -614,8 +614,8 @@ func Test_VerifyManifest_SignedYAML(t *testing.T) {
|
|||
policyContext := buildContext(t, test_policy, signed_resource, "")
|
||||
var request *v1.AdmissionRequest
|
||||
_ = json.Unmarshal([]byte(signed_adreq), &request)
|
||||
policyContext.JSONContext.AddRequest(request)
|
||||
policyContext.Policy.SetName("test-policy")
|
||||
policyContext.jsonContext.AddRequest(request)
|
||||
policyContext.policy.SetName("test-policy")
|
||||
verifyRule := kyvernov1.Manifests{}
|
||||
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
|
||||
Entries: []kyvernov1.Attestor{
|
||||
|
@ -636,8 +636,8 @@ func Test_VerifyManifest_UnsignedYAML(t *testing.T) {
|
|||
policyContext := buildContext(t, test_policy, unsigned_resource, "")
|
||||
var request *v1.AdmissionRequest
|
||||
_ = json.Unmarshal([]byte(unsigned_adreq), &request)
|
||||
policyContext.JSONContext.AddRequest(request)
|
||||
policyContext.Policy.SetName("test-policy")
|
||||
policyContext.jsonContext.AddRequest(request)
|
||||
policyContext.policy.SetName("test-policy")
|
||||
verifyRule := kyvernov1.Manifests{}
|
||||
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
|
||||
Entries: []kyvernov1.Attestor{
|
||||
|
@ -658,8 +658,8 @@ func Test_VerifyManifest_InvalidYAML(t *testing.T) {
|
|||
policyContext := buildContext(t, test_policy, invalid_resource, "")
|
||||
var request *v1.AdmissionRequest
|
||||
_ = json.Unmarshal([]byte(invalid_adreq), &request)
|
||||
policyContext.JSONContext.AddRequest(request)
|
||||
policyContext.Policy.SetName("test-policy")
|
||||
policyContext.jsonContext.AddRequest(request)
|
||||
policyContext.policy.SetName("test-policy")
|
||||
verifyRule := kyvernov1.Manifests{}
|
||||
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
|
||||
Entries: []kyvernov1.Attestor{
|
||||
|
@ -680,8 +680,8 @@ func Test_VerifyManifest_MustAll_InvalidYAML(t *testing.T) {
|
|||
policyContext := buildContext(t, test_policy, multi_sig_resource, "")
|
||||
var request *v1.AdmissionRequest
|
||||
_ = json.Unmarshal([]byte(multi_sig_adreq), &request)
|
||||
policyContext.JSONContext.AddRequest(request)
|
||||
policyContext.Policy.SetName("test-policy")
|
||||
policyContext.jsonContext.AddRequest(request)
|
||||
policyContext.policy.SetName("test-policy")
|
||||
verifyRule := kyvernov1.Manifests{}
|
||||
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
|
||||
Entries: []kyvernov1.Attestor{
|
||||
|
@ -708,8 +708,8 @@ func Test_VerifyManifest_MustAll_ValidYAML(t *testing.T) {
|
|||
policyContext := buildContext(t, test_policy, multi_sig2_resource, "")
|
||||
var request *v1.AdmissionRequest
|
||||
_ = json.Unmarshal([]byte(multi_sig2_adreq), &request)
|
||||
policyContext.JSONContext.AddRequest(request)
|
||||
policyContext.Policy.SetName("test-policy")
|
||||
policyContext.jsonContext.AddRequest(request)
|
||||
policyContext.policy.SetName("test-policy")
|
||||
verifyRule := kyvernov1.Manifests{}
|
||||
count := 3
|
||||
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
|
||||
|
@ -740,8 +740,8 @@ func Test_VerifyManifest_AtLeastOne(t *testing.T) {
|
|||
policyContext := buildContext(t, test_policy, multi_sig_resource, "")
|
||||
var request *v1.AdmissionRequest
|
||||
_ = json.Unmarshal([]byte(multi_sig_adreq), &request)
|
||||
policyContext.JSONContext.AddRequest(request)
|
||||
policyContext.Policy.SetName("test-policy")
|
||||
policyContext.jsonContext.AddRequest(request)
|
||||
policyContext.policy.SetName("test-policy")
|
||||
verifyRule := kyvernov1.Manifests{}
|
||||
count := 1
|
||||
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
|
||||
|
|
|
@ -36,22 +36,22 @@ func loadTargets(targets []kyvernov1.ResourceSpec, ctx *PolicyContext, logger lo
|
|||
}
|
||||
|
||||
func resolveSpec(i int, target kyvernov1.ResourceSpec, ctx *PolicyContext, logger logr.Logger) (kyvernov1.ResourceSpec, error) {
|
||||
kind, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Kind)
|
||||
kind, err := variables.SubstituteAll(logger, ctx.jsonContext, target.Kind)
|
||||
if err != nil {
|
||||
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Kind %s: %v", i, target.Kind, err)
|
||||
}
|
||||
|
||||
apiversion, err := variables.SubstituteAll(logger, ctx.JSONContext, target.APIVersion)
|
||||
apiversion, err := variables.SubstituteAll(logger, ctx.jsonContext, target.APIVersion)
|
||||
if err != nil {
|
||||
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].APIVersion %s: %v", i, target.APIVersion, err)
|
||||
}
|
||||
|
||||
namespace, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Namespace)
|
||||
namespace, err := variables.SubstituteAll(logger, ctx.jsonContext, target.Namespace)
|
||||
if err != nil {
|
||||
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Namespace %s: %v", i, target.Namespace, err)
|
||||
}
|
||||
|
||||
name, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Name)
|
||||
name, err := variables.SubstituteAll(logger, ctx.jsonContext, target.Name)
|
||||
if err != nil {
|
||||
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Name %s: %v", i, target.Name, err)
|
||||
}
|
||||
|
@ -70,13 +70,13 @@ func getTargets(target kyvernov1.ResourceSpec, ctx *PolicyContext, logger logr.L
|
|||
name := target.Name
|
||||
|
||||
// if it's namespaced policy, targets has to be loaded only from the policy's namespace
|
||||
if ctx.Policy.IsNamespaced() {
|
||||
namespace = ctx.Policy.GetNamespace()
|
||||
if ctx.policy.IsNamespaced() {
|
||||
namespace = ctx.policy.GetNamespace()
|
||||
}
|
||||
|
||||
if namespace != "" && name != "" &&
|
||||
!wildcard.ContainsWildcard(namespace) && !wildcard.ContainsWildcard(name) {
|
||||
obj, err := ctx.Client.GetResource(context.TODO(), target.APIVersion, target.Kind, namespace, name)
|
||||
obj, err := ctx.client.GetResource(context.TODO(), target.APIVersion, target.Kind, namespace, name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get target %s/%s %s/%s : %v", target.APIVersion, target.Kind, namespace, name, err)
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ func getTargets(target kyvernov1.ResourceSpec, ctx *PolicyContext, logger logr.L
|
|||
}
|
||||
|
||||
// list all targets if wildcard is specified
|
||||
objList, err := ctx.Client.ListResource(context.TODO(), target.APIVersion, target.Kind, "", nil)
|
||||
objList, err := ctx.client.ListResource(context.TODO(), target.APIVersion, target.Kind, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ import (
|
|||
// Mutate performs mutation. Overlay first and then mutation patches
|
||||
func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
startTime := time.Now()
|
||||
policy := policyContext.Policy
|
||||
policy := policyContext.policy
|
||||
resp = &response.EngineResponse{
|
||||
Policy: policy,
|
||||
}
|
||||
matchedResource := policyContext.NewResource
|
||||
ctx := policyContext.JSONContext
|
||||
matchedResource := policyContext.newResource
|
||||
ctx := policyContext.jsonContext
|
||||
var skippedRules []string
|
||||
|
||||
logger := logging.WithName("EngineMutate").WithValues("policy", policy.GetName(), "kind", matchedResource.GetKind(),
|
||||
|
@ -35,8 +35,8 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
startMutateResultResponse(resp, policy, matchedResource)
|
||||
defer endMutateResultResponse(logger, resp, startTime)
|
||||
|
||||
policyContext.JSONContext.Checkpoint()
|
||||
defer policyContext.JSONContext.Restore()
|
||||
policyContext.jsonContext.Checkpoint()
|
||||
defer policyContext.jsonContext.Restore()
|
||||
|
||||
var err error
|
||||
applyRules := policy.GetSpec().GetApplyRules()
|
||||
|
@ -48,19 +48,19 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
|
||||
logger := logger.WithValues("rule", rule.Name)
|
||||
var excludeResource []string
|
||||
if len(policyContext.ExcludeGroupRole) > 0 {
|
||||
excludeResource = policyContext.ExcludeGroupRole
|
||||
if len(policyContext.excludeGroupRole) > 0 {
|
||||
excludeResource = policyContext.excludeGroupRole
|
||||
}
|
||||
|
||||
if err = MatchesResourceDescription(matchedResource, rule, policyContext.AdmissionInfo, excludeResource, policyContext.NamespaceLabels, policyContext.Policy.GetNamespace()); err != nil {
|
||||
if err = MatchesResourceDescription(matchedResource, rule, policyContext.admissionInfo, excludeResource, policyContext.namespaceLabels, policyContext.policy.GetNamespace()); err != nil {
|
||||
logger.V(4).Info("rule not matched", "reason", err.Error())
|
||||
skippedRules = append(skippedRules, rule.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
logger.V(3).Info("processing mutate rule", "applyRules", applyRules)
|
||||
resource, err := policyContext.JSONContext.Query("request.object")
|
||||
policyContext.JSONContext.Reset()
|
||||
resource, err := policyContext.jsonContext.Query("request.object")
|
||||
policyContext.jsonContext.Reset()
|
||||
if err == nil && resource != nil {
|
||||
if err := ctx.AddResource(resource.(map[string]interface{})); err != nil {
|
||||
logger.Error(err, "unable to update resource object")
|
||||
|
@ -80,7 +80,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
|
||||
ruleCopy := rule.DeepCopy()
|
||||
var patchedResources []unstructured.Unstructured
|
||||
if !policyContext.AdmissionOperation && rule.IsMutateExisting() {
|
||||
if !policyContext.admissionOperation && rule.IsMutateExisting() {
|
||||
targets, err := loadTargets(ruleCopy.Mutation.Targets, policyContext, logger)
|
||||
if err != nil {
|
||||
rr := ruleResponse(rule, response.Mutation, err.Error(), response.RuleStatusError, nil)
|
||||
|
@ -97,9 +97,9 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
continue
|
||||
}
|
||||
|
||||
if !policyContext.AdmissionOperation && rule.IsMutateExisting() {
|
||||
if !policyContext.admissionOperation && rule.IsMutateExisting() {
|
||||
policyContext := policyContext.Copy()
|
||||
if err := policyContext.JSONContext.AddTargetResource(patchedResource.Object); err != nil {
|
||||
if err := policyContext.jsonContext.AddTargetResource(patchedResource.Object); err != nil {
|
||||
logging.Error(err, "failed to add target resource to the context")
|
||||
continue
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ func mutateResource(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructu
|
|||
return ruleResponse(*rule, response.Mutation, "preconditions not met", response.RuleStatusSkip, &resource), resource
|
||||
}
|
||||
|
||||
mutateResp := mutate.Mutate(rule, ctx.JSONContext, resource, logger)
|
||||
mutateResp := mutate.Mutate(rule, ctx.jsonContext, resource, logger)
|
||||
ruleResp := buildRuleResponse(rule, mutateResp, &mutateResp.PatchedResource)
|
||||
return ruleResp, mutateResp.PatchedResource
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ func mutateForEach(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructur
|
|||
return ruleResponse(*rule, response.Mutation, "preconditions not met", response.RuleStatusSkip, &patchedResource), resource
|
||||
}
|
||||
|
||||
elements, err := evaluateList(foreach.List, ctx.JSONContext)
|
||||
elements, err := evaluateList(foreach.List, ctx.jsonContext)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to evaluate list %s", foreach.List)
|
||||
return ruleError(rule, response.Mutation, msg, err), resource
|
||||
|
@ -214,8 +214,8 @@ func mutateForEach(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructur
|
|||
}
|
||||
|
||||
func mutateElements(name string, foreach kyvernov1.ForEachMutation, ctx *PolicyContext, elements []interface{}, resource unstructured.Unstructured, logger logr.Logger) *mutate.Response {
|
||||
ctx.JSONContext.Checkpoint()
|
||||
defer ctx.JSONContext.Restore()
|
||||
ctx.jsonContext.Checkpoint()
|
||||
defer ctx.jsonContext.Restore()
|
||||
|
||||
patchedResource := resource
|
||||
var allPatches [][]byte
|
||||
|
@ -227,7 +227,7 @@ func mutateElements(name string, foreach kyvernov1.ForEachMutation, ctx *PolicyC
|
|||
if e == nil {
|
||||
continue
|
||||
}
|
||||
ctx.JSONContext.Reset()
|
||||
ctx.jsonContext.Reset()
|
||||
ctx := ctx.Copy()
|
||||
store.SetForeachElement(i)
|
||||
falseVar := false
|
||||
|
@ -249,7 +249,7 @@ func mutateElements(name string, foreach kyvernov1.ForEachMutation, ctx *PolicyC
|
|||
continue
|
||||
}
|
||||
|
||||
mutateResp := mutate.ForEach(name, foreach, ctx.JSONContext, patchedResource, logger)
|
||||
mutateResp := mutate.ForEach(name, foreach, ctx.jsonContext, patchedResource, logger)
|
||||
if mutateResp.Status == response.RuleStatusFail || mutateResp.Status == response.RuleStatusError {
|
||||
return mutateResp
|
||||
}
|
||||
|
|
|
@ -90,9 +90,9 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Mutate(policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
|
||||
|
@ -163,9 +163,9 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Mutate(policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
|
@ -258,9 +258,9 @@ func Test_variableSubstitutionCLI(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
|
@ -361,9 +361,9 @@ func Test_chained_rules(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resource,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resource,
|
||||
}
|
||||
|
||||
err = ctx.AddImageInfos(resource)
|
||||
|
@ -455,9 +455,9 @@ func Test_precondition(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
|
@ -552,9 +552,9 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
|
@ -640,9 +640,9 @@ func Test_foreach(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resource,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resource,
|
||||
}
|
||||
|
||||
err = ctx.AddImageInfos(resource)
|
||||
|
@ -747,9 +747,9 @@ func Test_foreach_element_mutation(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resource,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resource,
|
||||
}
|
||||
|
||||
err = ctx.AddImageInfos(resource)
|
||||
|
@ -873,9 +873,9 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resource,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resource,
|
||||
}
|
||||
|
||||
err = ctx.AddImageInfos(resource)
|
||||
|
@ -1000,9 +1000,9 @@ func Test_foreach_order_mutation_(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resource,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resource,
|
||||
}
|
||||
|
||||
err = ctx.AddImageInfos(resource)
|
||||
|
@ -1451,10 +1451,10 @@ func Test_mutate_existing_resources(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext = &PolicyContext{
|
||||
Client: dclient,
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *trigger,
|
||||
client: dclient,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *trigger,
|
||||
}
|
||||
}
|
||||
er := Mutate(policyContext)
|
||||
|
@ -1560,9 +1560,9 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
|
@ -1578,7 +1578,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
}
|
||||
|
||||
applyOne := kyverno.ApplyOne
|
||||
policyContext.Policy.GetSpec().ApplyRules = &applyOne
|
||||
policyContext.policy.GetSpec().ApplyRules = &applyOne
|
||||
|
||||
er = Mutate(policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
|
@ -1941,9 +1941,9 @@ func Test_SpecialCharacters(t *testing.T) {
|
|||
|
||||
// Create policy context.
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resource,
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resource,
|
||||
}
|
||||
|
||||
// Mutate and make sure that we got the expected amount of rules.
|
||||
|
|
|
@ -4,55 +4,196 @@ 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"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// ExcludeFunc is a function used to determine if a resource is excluded
|
||||
type ExcludeFunc = func(kind, namespace, name string) bool
|
||||
|
||||
// PolicyContext contains the contexts for engine to process
|
||||
type PolicyContext struct {
|
||||
// Policy is the policy to be processed
|
||||
Policy kyvernov1.PolicyInterface
|
||||
// policy is the policy to be processed
|
||||
policy kyvernov1.PolicyInterface
|
||||
|
||||
// NewResource is the resource to be processed
|
||||
NewResource unstructured.Unstructured
|
||||
// newResource is the resource to be processed
|
||||
newResource unstructured.Unstructured
|
||||
|
||||
// OldResource is the prior resource for an update, or nil
|
||||
OldResource unstructured.Unstructured
|
||||
// oldResource is the prior resource for an update, or nil
|
||||
oldResource unstructured.Unstructured
|
||||
|
||||
// Element is set when the context is used for processing a foreach loop
|
||||
Element unstructured.Unstructured
|
||||
// element is set when the context is used for processing a foreach loop
|
||||
element unstructured.Unstructured
|
||||
|
||||
// AdmissionInfo contains the admission request information
|
||||
AdmissionInfo kyvernov1beta1.RequestInfo
|
||||
// admissionInfo contains the admission request information
|
||||
admissionInfo kyvernov1beta1.RequestInfo
|
||||
|
||||
// Dynamic client - used for api lookups
|
||||
Client dclient.Interface
|
||||
client dclient.Interface
|
||||
|
||||
// Config handler
|
||||
ExcludeGroupRole []string
|
||||
excludeGroupRole []string
|
||||
|
||||
ExcludeResourceFunc func(kind, namespace, name string) bool
|
||||
excludeResourceFunc ExcludeFunc
|
||||
|
||||
// JSONContext is the variable context
|
||||
JSONContext context.Interface
|
||||
// jsonContext is the variable context
|
||||
jsonContext context.Interface
|
||||
|
||||
// NamespaceLabels stores the label of namespace to be processed by namespace selector
|
||||
NamespaceLabels map[string]string
|
||||
// namespaceLabels stores the label of namespace to be processed by namespace selector
|
||||
namespaceLabels map[string]string
|
||||
|
||||
// AdmissionOperation represents if the caller is from the webhook server
|
||||
AdmissionOperation bool
|
||||
// admissionOperation represents if the caller is from the webhook server
|
||||
admissionOperation bool
|
||||
}
|
||||
|
||||
func (pc *PolicyContext) Copy() *PolicyContext {
|
||||
// Getters
|
||||
|
||||
func (c *PolicyContext) Policy() kyvernov1.PolicyInterface {
|
||||
return c.policy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) NewResource() unstructured.Unstructured {
|
||||
return c.newResource
|
||||
}
|
||||
|
||||
func (c *PolicyContext) OldResource() unstructured.Unstructured {
|
||||
return c.oldResource
|
||||
}
|
||||
|
||||
func (c *PolicyContext) AdmissionInfo() kyvernov1beta1.RequestInfo {
|
||||
return c.admissionInfo
|
||||
}
|
||||
|
||||
func (c *PolicyContext) JSONContext() context.Interface {
|
||||
return c.jsonContext
|
||||
}
|
||||
|
||||
// Mutators
|
||||
|
||||
func (c *PolicyContext) WithPolicy(policy kyvernov1.PolicyInterface) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.policy = policy
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithNamespaceLabels(namespaceLabels map[string]string) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.namespaceLabels = namespaceLabels
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithAdmissionInfo(admissionInfo kyvernov1beta1.RequestInfo) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.admissionInfo = admissionInfo
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithNewResource(resource unstructured.Unstructured) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.newResource = resource
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithOldResource(resource unstructured.Unstructured) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.oldResource = resource
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithResources(newResource unstructured.Unstructured, oldResource unstructured.Unstructured) *PolicyContext {
|
||||
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) WithExcludeGroupRole(excludeGroupRole ...string) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.excludeGroupRole = excludeGroupRole
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithExcludeResourceFunc(excludeResourceFunc ExcludeFunc) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.excludeResourceFunc = excludeResourceFunc
|
||||
return copy
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithConfiguration(configuration config.Configuration) *PolicyContext {
|
||||
return c.WithExcludeResourceFunc(configuration.ToFilter).WithExcludeGroupRole(configuration.GetExcludeGroupRole()...)
|
||||
}
|
||||
|
||||
func (c *PolicyContext) WithAdmissionOperation(admissionOperation bool) *PolicyContext {
|
||||
copy := c.Copy()
|
||||
copy.admissionOperation = admissionOperation
|
||||
return copy
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
func NewPolicyContextWithJsonContext(jsonContext context.Interface) *PolicyContext {
|
||||
return &PolicyContext{
|
||||
Policy: pc.Policy,
|
||||
NewResource: pc.NewResource,
|
||||
OldResource: pc.OldResource,
|
||||
AdmissionInfo: pc.AdmissionInfo,
|
||||
Client: pc.Client,
|
||||
ExcludeGroupRole: pc.ExcludeGroupRole,
|
||||
ExcludeResourceFunc: pc.ExcludeResourceFunc,
|
||||
JSONContext: pc.JSONContext,
|
||||
NamespaceLabels: pc.NamespaceLabels,
|
||||
jsonContext: jsonContext,
|
||||
excludeGroupRole: []string{},
|
||||
excludeResourceFunc: func(string, string, string) bool {
|
||||
return false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewPolicyContext() *PolicyContext {
|
||||
return NewPolicyContextWithJsonContext(context.NewContext())
|
||||
}
|
||||
|
||||
func NewPolicyContextFromAdmissionRequest(
|
||||
request *admissionv1.AdmissionRequest,
|
||||
admissionInfo kyvernov1beta1.RequestInfo,
|
||||
configuration config.Configuration,
|
||||
client dclient.Interface,
|
||||
) (*PolicyContext, error) {
|
||||
ctx, err := newVariablesContext(request, &admissionInfo)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create policy rule context")
|
||||
}
|
||||
newResource, oldResource, err := utils.ExtractResources(nil, request)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse resource")
|
||||
}
|
||||
if err := ctx.AddImageInfos(&newResource); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to add image information to the policy rule context")
|
||||
}
|
||||
policyContext := NewPolicyContextWithJsonContext(ctx).
|
||||
WithNewResource(newResource).
|
||||
WithOldResource(oldResource).
|
||||
WithAdmissionInfo(admissionInfo).
|
||||
WithConfiguration(configuration).
|
||||
WithClient(client).
|
||||
WithAdmissionOperation(true)
|
||||
return policyContext, nil
|
||||
}
|
||||
|
||||
func (c PolicyContext) Copy() *PolicyContext {
|
||||
return &c
|
||||
}
|
||||
|
||||
func newVariablesContext(request *admissionv1.AdmissionRequest, userRequestInfo *kyvernov1beta1.RequestInfo) (enginectx.Interface, error) {
|
||||
ctx := enginectx.NewContext()
|
||||
if err := ctx.AddRequest(request); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load incoming request in context")
|
||||
}
|
||||
if err := ctx.AddUserInfo(*userRequestInfo); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load userInfo in context")
|
||||
}
|
||||
if err := ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load service account in context")
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
|
|
@ -426,7 +426,7 @@ func ManagedPodResource(policy kyvernov1.PolicyInterface, resource unstructured.
|
|||
}
|
||||
|
||||
func checkPreconditions(logger logr.Logger, ctx *PolicyContext, anyAllConditions apiextensions.JSON) (bool, error) {
|
||||
preconditions, err := variables.SubstituteAllInPreconditions(logger, ctx.JSONContext, anyAllConditions)
|
||||
preconditions, err := variables.SubstituteAllInPreconditions(logger, ctx.jsonContext, anyAllConditions)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "failed to substitute variables in preconditions")
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ func checkPreconditions(logger logr.Logger, ctx *PolicyContext, anyAllConditions
|
|||
return false, errors.Wrapf(err, "failed to parse preconditions")
|
||||
}
|
||||
|
||||
pass := variables.EvaluateConditions(logger, ctx.JSONContext, typeConditions)
|
||||
pass := variables.EvaluateConditions(logger, ctx.jsonContext, typeConditions)
|
||||
return pass, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,11 @@ func Validate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
}
|
||||
|
||||
func buildLogger(ctx *PolicyContext) logr.Logger {
|
||||
logger := logging.WithName("EngineValidate").WithValues("policy", ctx.Policy.GetName())
|
||||
if reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) {
|
||||
logger = logger.WithValues("kind", ctx.OldResource.GetKind(), "namespace", ctx.OldResource.GetNamespace(), "name", ctx.OldResource.GetName())
|
||||
logger := logging.WithName("EngineValidate").WithValues("policy", ctx.policy.GetName())
|
||||
if reflect.DeepEqual(ctx.newResource, unstructured.Unstructured{}) {
|
||||
logger = logger.WithValues("kind", ctx.oldResource.GetKind(), "namespace", ctx.oldResource.GetNamespace(), "name", ctx.oldResource.GetName())
|
||||
} else {
|
||||
logger = logger.WithValues("kind", ctx.NewResource.GetKind(), "namespace", ctx.NewResource.GetNamespace(), "name", ctx.NewResource.GetName())
|
||||
logger = logger.WithValues("kind", ctx.newResource.GetKind(), "namespace", ctx.newResource.GetNamespace(), "name", ctx.newResource.GetName())
|
||||
}
|
||||
|
||||
return logger
|
||||
|
@ -63,24 +63,24 @@ func buildResponse(ctx *PolicyContext, resp *response.EngineResponse, startTime
|
|||
|
||||
if reflect.DeepEqual(resp.PatchedResource, unstructured.Unstructured{}) {
|
||||
// for delete requests patched resource will be oldResource since newResource is empty
|
||||
resource := ctx.NewResource
|
||||
if reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) {
|
||||
resource = ctx.OldResource
|
||||
resource := ctx.newResource
|
||||
if reflect.DeepEqual(ctx.newResource, unstructured.Unstructured{}) {
|
||||
resource = ctx.oldResource
|
||||
}
|
||||
|
||||
resp.PatchedResource = resource
|
||||
}
|
||||
|
||||
resp.Policy = ctx.Policy
|
||||
resp.PolicyResponse.Policy.Name = ctx.Policy.GetName()
|
||||
resp.PolicyResponse.Policy.Namespace = ctx.Policy.GetNamespace()
|
||||
resp.Policy = ctx.policy
|
||||
resp.PolicyResponse.Policy.Name = ctx.policy.GetName()
|
||||
resp.PolicyResponse.Policy.Namespace = ctx.policy.GetNamespace()
|
||||
resp.PolicyResponse.Resource.Name = resp.PatchedResource.GetName()
|
||||
resp.PolicyResponse.Resource.Namespace = resp.PatchedResource.GetNamespace()
|
||||
resp.PolicyResponse.Resource.Kind = resp.PatchedResource.GetKind()
|
||||
resp.PolicyResponse.Resource.APIVersion = resp.PatchedResource.GetAPIVersion()
|
||||
resp.PolicyResponse.ValidationFailureAction = ctx.Policy.GetSpec().ValidationFailureAction
|
||||
resp.PolicyResponse.ValidationFailureAction = ctx.policy.GetSpec().ValidationFailureAction
|
||||
|
||||
for _, v := range ctx.Policy.GetSpec().ValidationFailureActionOverrides {
|
||||
for _, v := range ctx.policy.GetSpec().ValidationFailureActionOverrides {
|
||||
resp.PolicyResponse.ValidationFailureActionOverrides = append(resp.PolicyResponse.ValidationFailureActionOverrides, response.ValidationFailureActionOverride{Action: v.Action, Namespaces: v.Namespaces})
|
||||
}
|
||||
|
||||
|
@ -91,19 +91,19 @@ func buildResponse(ctx *PolicyContext, resp *response.EngineResponse, startTime
|
|||
func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineResponse {
|
||||
resp := &response.EngineResponse{}
|
||||
|
||||
ctx.JSONContext.Checkpoint()
|
||||
defer ctx.JSONContext.Restore()
|
||||
ctx.jsonContext.Checkpoint()
|
||||
defer ctx.jsonContext.Restore()
|
||||
|
||||
rules := autogen.ComputeRules(ctx.Policy)
|
||||
rules := autogen.ComputeRules(ctx.policy)
|
||||
matchCount := 0
|
||||
applyRules := ctx.Policy.GetSpec().GetApplyRules()
|
||||
applyRules := ctx.policy.GetSpec().GetApplyRules()
|
||||
|
||||
if ctx.Policy.IsNamespaced() {
|
||||
polNs := ctx.Policy.GetNamespace()
|
||||
if ctx.NewResource.Object != nil && (ctx.NewResource.GetNamespace() != polNs || ctx.NewResource.GetNamespace() == "") {
|
||||
if ctx.policy.IsNamespaced() {
|
||||
polNs := ctx.policy.GetNamespace()
|
||||
if ctx.newResource.Object != nil && (ctx.newResource.GetNamespace() != polNs || ctx.newResource.GetNamespace() == "") {
|
||||
return resp
|
||||
}
|
||||
if ctx.OldResource.Object != nil && (ctx.OldResource.GetNamespace() != polNs || ctx.OldResource.GetNamespace() == "") {
|
||||
if ctx.oldResource.Object != nil && (ctx.oldResource.GetNamespace() != polNs || ctx.oldResource.GetNamespace() == "") {
|
||||
return resp
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
|
|||
}
|
||||
|
||||
log.V(3).Info("processing validation rule", "matchCount", matchCount, "applyRules", applyRules)
|
||||
ctx.JSONContext.Reset()
|
||||
ctx.jsonContext.Reset()
|
||||
startTime := time.Now()
|
||||
|
||||
var ruleResp *response.RuleResponse
|
||||
|
@ -148,14 +148,14 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
|
|||
|
||||
func validateOldObject(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) (*response.RuleResponse, error) {
|
||||
ctxCopy := ctx.Copy()
|
||||
ctxCopy.NewResource = *ctxCopy.OldResource.DeepCopy()
|
||||
ctxCopy.OldResource = unstructured.Unstructured{}
|
||||
ctxCopy.newResource = *ctxCopy.oldResource.DeepCopy()
|
||||
ctxCopy.oldResource = unstructured.Unstructured{}
|
||||
|
||||
if err := context.ReplaceResource(ctxCopy.JSONContext, ctxCopy.NewResource.Object); err != nil {
|
||||
if err := context.ReplaceResource(ctxCopy.jsonContext, ctxCopy.newResource.Object); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to replace object in the JSON context")
|
||||
}
|
||||
|
||||
if err := context.ReplaceOldResource(ctxCopy.JSONContext, ctxCopy.OldResource.Object); err != nil {
|
||||
if err := context.ReplaceOldResource(ctxCopy.jsonContext, ctxCopy.oldResource.Object); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to replace old object in the JSON context")
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
|||
}
|
||||
|
||||
for _, foreach := range foreachList {
|
||||
elements, err := evaluateList(foreach.List, v.ctx.JSONContext)
|
||||
elements, err := evaluateList(foreach.List, v.ctx.jsonContext)
|
||||
if err != nil {
|
||||
v.log.V(2).Info("failed to evaluate list", "list", foreach.List, "error", err.Error())
|
||||
continue
|
||||
|
@ -321,8 +321,8 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
|||
}
|
||||
|
||||
func (v *validator) validateElements(foreach kyvernov1.ForEachValidation, elements []interface{}, elementScope *bool) (*response.RuleResponse, int) {
|
||||
v.ctx.JSONContext.Checkpoint()
|
||||
defer v.ctx.JSONContext.Restore()
|
||||
v.ctx.jsonContext.Checkpoint()
|
||||
defer v.ctx.jsonContext.Restore()
|
||||
applyCount := 0
|
||||
|
||||
for i, e := range elements {
|
||||
|
@ -330,7 +330,7 @@ func (v *validator) validateElements(foreach kyvernov1.ForEachValidation, elemen
|
|||
continue
|
||||
}
|
||||
store.SetForeachElement(i)
|
||||
v.ctx.JSONContext.Reset()
|
||||
v.ctx.jsonContext.Reset()
|
||||
|
||||
ctx := v.ctx.Copy()
|
||||
if err := addElementToContext(ctx, e, i, elementScope); err != nil {
|
||||
|
@ -369,7 +369,7 @@ func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, el
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ctx.JSONContext.AddElement(data, elementIndex); err != nil {
|
||||
if err := ctx.jsonContext.AddElement(data, elementIndex); err != nil {
|
||||
return errors.Wrapf(err, "failed to add element (%v) to JSON context", e)
|
||||
}
|
||||
dataMap, ok := data.(map[string]interface{})
|
||||
|
@ -392,7 +392,7 @@ func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, el
|
|||
if scoped {
|
||||
u := unstructured.Unstructured{}
|
||||
u.SetUnstructuredContent(dataMap)
|
||||
ctx.Element = u
|
||||
ctx.element = u
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ func (v *validator) loadContext() error {
|
|||
|
||||
func (v *validator) validateDeny() *response.RuleResponse {
|
||||
anyAllCond := v.deny.GetAnyAllConditions()
|
||||
anyAllCond, err := variables.SubstituteAll(v.log, v.ctx.JSONContext, anyAllCond)
|
||||
anyAllCond, err := variables.SubstituteAll(v.log, v.ctx.jsonContext, anyAllCond)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, response.Validation, "failed to substitute variables in deny conditions", err)
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ func (v *validator) validateDeny() *response.RuleResponse {
|
|||
return ruleError(v.rule, response.Validation, "invalid deny conditions", err)
|
||||
}
|
||||
|
||||
deny := variables.EvaluateConditions(v.log, v.ctx.JSONContext, denyConditions)
|
||||
deny := variables.EvaluateConditions(v.log, v.ctx.jsonContext, denyConditions)
|
||||
if deny {
|
||||
return ruleResponse(*v.rule, response.Validation, v.getDenyMessage(deny), response.RuleStatusFail, nil)
|
||||
}
|
||||
|
@ -445,7 +445,7 @@ func (v *validator) getDenyMessage(deny bool) string {
|
|||
return fmt.Sprintf("validation error: rule %s failed", v.rule.Name)
|
||||
}
|
||||
|
||||
raw, err := variables.SubstituteAll(v.log, v.ctx.JSONContext, msg)
|
||||
raw, err := variables.SubstituteAll(v.log, v.ctx.jsonContext, msg)
|
||||
if err != nil {
|
||||
return msg
|
||||
}
|
||||
|
@ -454,12 +454,12 @@ func (v *validator) getDenyMessage(deny bool) string {
|
|||
}
|
||||
|
||||
func getSpec(v *validator) (podSpec *corev1.PodSpec, metadata *metav1.ObjectMeta, err error) {
|
||||
kind := v.ctx.NewResource.GetKind()
|
||||
kind := v.ctx.newResource.GetKind()
|
||||
|
||||
if kind == "DaemonSet" || kind == "Deployment" || kind == "Job" || kind == "StatefulSet" || kind == "ReplicaSet" || kind == "ReplicationController" {
|
||||
var deployment appsv1.Deployment
|
||||
|
||||
resourceBytes, err := v.ctx.NewResource.MarshalJSON()
|
||||
resourceBytes, err := v.ctx.newResource.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -473,7 +473,7 @@ func getSpec(v *validator) (podSpec *corev1.PodSpec, metadata *metav1.ObjectMeta
|
|||
} else if kind == "CronJob" {
|
||||
var cronJob batchv1.CronJob
|
||||
|
||||
resourceBytes, err := v.ctx.NewResource.MarshalJSON()
|
||||
resourceBytes, err := v.ctx.newResource.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ func getSpec(v *validator) (podSpec *corev1.PodSpec, metadata *metav1.ObjectMeta
|
|||
} else if kind == "Pod" {
|
||||
var pod corev1.Pod
|
||||
|
||||
resourceBytes, err := v.ctx.NewResource.MarshalJSON()
|
||||
resourceBytes, err := v.ctx.newResource.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -531,8 +531,8 @@ func (v *validator) validatePodSecurity() *response.RuleResponse {
|
|||
}
|
||||
|
||||
func (v *validator) validateResourceWithRule() *response.RuleResponse {
|
||||
if !isEmptyUnstructured(&v.ctx.Element) {
|
||||
return v.validatePatterns(v.ctx.Element)
|
||||
if !isEmptyUnstructured(&v.ctx.element) {
|
||||
return v.validatePatterns(v.ctx.element)
|
||||
}
|
||||
|
||||
if isDeleteRequest(v.ctx) {
|
||||
|
@ -540,18 +540,18 @@ func (v *validator) validateResourceWithRule() *response.RuleResponse {
|
|||
return nil
|
||||
}
|
||||
|
||||
resp := v.validatePatterns(v.ctx.NewResource)
|
||||
resp := v.validatePatterns(v.ctx.newResource)
|
||||
return resp
|
||||
}
|
||||
|
||||
func isDeleteRequest(ctx *PolicyContext) bool {
|
||||
// if the OldResource is not empty, and the NewResource is empty, the request is a DELETE
|
||||
return isEmptyUnstructured(&ctx.NewResource)
|
||||
return isEmptyUnstructured(&ctx.newResource)
|
||||
}
|
||||
|
||||
func isUpdateRequest(ctx *PolicyContext) bool {
|
||||
// is the OldObject and NewObject are available, the request is an UPDATE
|
||||
return !isEmptyUnstructured(&ctx.OldResource) && !isEmptyUnstructured(&ctx.NewResource)
|
||||
return !isEmptyUnstructured(&ctx.oldResource) && !isEmptyUnstructured(&ctx.newResource)
|
||||
}
|
||||
|
||||
func isEmptyUnstructured(u *unstructured.Unstructured) bool {
|
||||
|
@ -568,13 +568,13 @@ func isEmptyUnstructured(u *unstructured.Unstructured) bool {
|
|||
|
||||
// matches checks if either the new or old resource satisfies the filter conditions defined in the rule
|
||||
func matches(logger logr.Logger, rule *kyvernov1.Rule, ctx *PolicyContext) bool {
|
||||
err := MatchesResourceDescription(ctx.NewResource, *rule, ctx.AdmissionInfo, ctx.ExcludeGroupRole, ctx.NamespaceLabels, "")
|
||||
err := MatchesResourceDescription(ctx.newResource, *rule, ctx.admissionInfo, ctx.excludeGroupRole, ctx.namespaceLabels, "")
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(ctx.OldResource, unstructured.Unstructured{}) {
|
||||
err := MatchesResourceDescription(ctx.OldResource, *rule, ctx.AdmissionInfo, ctx.ExcludeGroupRole, ctx.NamespaceLabels, "")
|
||||
if !reflect.DeepEqual(ctx.oldResource, unstructured.Unstructured{}) {
|
||||
err := MatchesResourceDescription(ctx.oldResource, *rule, ctx.admissionInfo, ctx.excludeGroupRole, ctx.namespaceLabels, "")
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ func (v *validator) buildErrorMessage(err error, path string) string {
|
|||
return fmt.Sprintf("validation error: rule %s execution error: %s", v.rule.Name, err.Error())
|
||||
}
|
||||
|
||||
msgRaw, sErr := variables.SubstituteAll(v.log, v.ctx.JSONContext, v.rule.Validation.Message)
|
||||
msgRaw, sErr := variables.SubstituteAll(v.log, v.ctx.jsonContext, v.rule.Validation.Message)
|
||||
if sErr != nil {
|
||||
v.log.V(2).Info("failed to substitute variables in message", "error", sErr)
|
||||
return fmt.Sprintf("validation error: variables substitution error in rule %s execution error: %s", v.rule.Name, err.Error())
|
||||
|
@ -749,7 +749,7 @@ func buildAnyPatternErrorMessage(rule *kyvernov1.Rule, errors []string) string {
|
|||
|
||||
func (v *validator) substitutePatterns() error {
|
||||
if v.pattern != nil {
|
||||
i, err := variables.SubstituteAll(v.log, v.ctx.JSONContext, v.pattern)
|
||||
i, err := variables.SubstituteAll(v.log, v.ctx.jsonContext, v.pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -759,7 +759,7 @@ func (v *validator) substitutePatterns() error {
|
|||
}
|
||||
|
||||
if v.anyPattern != nil {
|
||||
i, err := variables.SubstituteAll(v.log, v.ctx.JSONContext, v.anyPattern)
|
||||
i, err := variables.SubstituteAll(v.log, v.ctx.jsonContext, v.anyPattern)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -776,7 +776,7 @@ func (v *validator) substituteDeny() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
i, err := variables.SubstituteAll(v.log, v.ctx.JSONContext, v.deny)
|
||||
i, err := variables.SubstituteAll(v.log, v.ctx.jsonContext, v.deny)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
|
|||
"validation error: imagePullPolicy 'Always' required with tag 'latest'. rule validate-latest failed at path /spec/containers/0/imagePullPolicy/",
|
||||
}
|
||||
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
|
|||
"validation rule 'validate-tag' passed.",
|
||||
"validation rule 'validate-latest' passed.",
|
||||
}
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
|
||||
msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"}
|
||||
|
@ -388,7 +388,7 @@ func TestValidate_host_network_port(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -478,7 +478,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -566,7 +566,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -636,7 +636,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -709,7 +709,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -783,7 +783,7 @@ func TestValidate_inequality_List_Processing(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -863,7 +863,7 @@ func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -937,7 +937,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1012,7 +1012,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1087,7 +1087,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -1157,7 +1157,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1227,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1315,7 +1315,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1402,7 +1402,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1475,9 +1475,9 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
|
@ -1568,9 +1568,9 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
|
@ -1629,9 +1629,9 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "validation error: rule not-operator-with-variable-should-alway-fail-validation failed at path /spec/content/")
|
||||
|
@ -1720,9 +1720,9 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
|
@ -1813,9 +1813,9 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
|
@ -1918,9 +1918,9 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "The animal cow is not in the allowed list of animals.")
|
||||
|
@ -1971,9 +1971,9 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
|
||||
for i, rule := range er.PolicyResponse.Rules {
|
||||
|
@ -2133,11 +2133,11 @@ func executeTest(t *testing.T, test testCase) {
|
|||
}
|
||||
|
||||
pc := &PolicyContext{
|
||||
Policy: &policy,
|
||||
NewResource: newR,
|
||||
OldResource: oldR,
|
||||
AdmissionInfo: userInfo,
|
||||
JSONContext: ctx,
|
||||
policy: &policy,
|
||||
newResource: newR,
|
||||
oldResource: oldR,
|
||||
admissionInfo: userInfo,
|
||||
jsonContext: ctx,
|
||||
}
|
||||
|
||||
resp := Validate(pc)
|
||||
|
@ -2239,7 +2239,7 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
|
|||
msgs := []string{
|
||||
"restrict pod counts to be no more than 10 on node minikube",
|
||||
}
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -2328,7 +2328,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: ctx})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -2417,7 +2417,7 @@ func Test_StringInDenyCondition(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: ctx})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx})
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -3001,9 +3001,9 @@ func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string,
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, status)
|
||||
|
@ -3065,17 +3065,17 @@ func Test_delete_ignore_pattern(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
policyContextCreate := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
engineResponseCreate := Validate(policyContextCreate)
|
||||
assert.Equal(t, len(engineResponseCreate.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
|
||||
policyContextDelete := &PolicyContext{
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
OldResource: *resourceUnstructured}
|
||||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
oldResource: *resourceUnstructured}
|
||||
engineResponseDelete := Validate(policyContextDelete)
|
||||
assert.Equal(t, len(engineResponseDelete.PolicyResponse.Rules), 0)
|
||||
}
|
||||
|
@ -3135,7 +3135,7 @@ func Test_ValidatePattern_anyPattern(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(tc.rawResource)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(&PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
if tc.expectedFailed {
|
||||
assert.Assert(t, er.IsFailed())
|
||||
} else if tc.expectedSkipped {
|
||||
|
|
|
@ -61,14 +61,12 @@ func applyPolicy(policy kyvernov1.PolicyInterface, resource unstructured.Unstruc
|
|||
logger.Error(err, "failed to process mutation rule")
|
||||
}
|
||||
|
||||
policyCtx := &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: resource,
|
||||
ExcludeGroupRole: excludeGroupRole,
|
||||
JSONContext: ctx,
|
||||
Client: client,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
}
|
||||
policyCtx := engine.NewPolicyContextWithJsonContext(ctx).
|
||||
WithPolicy(policy).
|
||||
WithNewResource(resource).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithClient(client).
|
||||
WithExcludeGroupRole(excludeGroupRole...)
|
||||
|
||||
engineResponseValidation = engine.Validate(policyCtx)
|
||||
engineResponses = append(engineResponses, mergeRuleRespose(engineResponseMutation, engineResponseValidation))
|
||||
|
@ -77,12 +75,10 @@ func applyPolicy(policy kyvernov1.PolicyInterface, resource unstructured.Unstruc
|
|||
}
|
||||
|
||||
func mutation(policy kyvernov1.PolicyInterface, resource unstructured.Unstructured, log logr.Logger, jsonContext context.Interface, namespaceLabels map[string]string) (*response.EngineResponse, error) {
|
||||
policyContext := &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: resource,
|
||||
JSONContext: jsonContext,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
}
|
||||
policyContext := engine.NewPolicyContextWithJsonContext(jsonContext).
|
||||
WithPolicy(policy).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithNewResource(resource)
|
||||
|
||||
engineResponse := engine.Mutate(policyContext)
|
||||
if !engineResponse.IsSuccessful() {
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
@ -144,14 +143,9 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
ctx := &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: *resource,
|
||||
ExcludeGroupRole: []string{},
|
||||
JSONContext: enginecontext.NewContext(),
|
||||
}
|
||||
policyContext := engine.NewPolicyContext().WithPolicy(policy).WithNewResource(*resource)
|
||||
|
||||
er := engine.Mutate(ctx)
|
||||
er := engine.Mutate(policyContext)
|
||||
t.Log("---Mutation---")
|
||||
validateResource(t, er.PatchedResource, tc.Expected.Mutation.PatchedResource)
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Mutation.PolicyResponse)
|
||||
|
@ -161,14 +155,9 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
resource = &er.PatchedResource
|
||||
}
|
||||
|
||||
ctx = &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: *resource,
|
||||
ExcludeGroupRole: []string{},
|
||||
JSONContext: enginecontext.NewContext(),
|
||||
}
|
||||
policyContext = policyContext.WithNewResource(*resource)
|
||||
|
||||
er = engine.Validate(ctx)
|
||||
er = engine.Validate(policyContext)
|
||||
t.Log("---Validation---")
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Validation.PolicyResponse)
|
||||
|
||||
|
@ -182,16 +171,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
if err := createNamespace(client, resource); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: *resource,
|
||||
Policy: policy,
|
||||
Client: client,
|
||||
ExcludeGroupRole: []string{},
|
||||
ExcludeResourceFunc: func(s1, s2, s3 string) bool {
|
||||
return false
|
||||
},
|
||||
JSONContext: enginecontext.NewContext(),
|
||||
}
|
||||
policyContext := policyContext.WithClient(client)
|
||||
|
||||
er = engine.ApplyBackgroundChecks(policyContext)
|
||||
t.Log(("---Generation---"))
|
||||
|
|
|
@ -88,9 +88,9 @@ func (h *generationHandler) Handle(
|
|||
if (request.Operation == admissionv1.Create || request.Operation == admissionv1.Update) && len(policies) != 0 {
|
||||
for _, policy := range policies {
|
||||
var rules []response.RuleResponse
|
||||
policyContext.Policy = policy
|
||||
policyContext := policyContext.WithPolicy(policy)
|
||||
if request.Kind.Kind != "Namespace" && request.Namespace != "" {
|
||||
policyContext.NamespaceLabels = common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log)
|
||||
policyContext = policyContext.WithNamespaceLabels(common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log))
|
||||
}
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
|
@ -113,11 +113,12 @@ func (h *generationHandler) Handle(
|
|||
go webhookutils.RegisterPolicyExecutionDurationMetricGenerate(context.TODO(), h.log, metricsConfig, string(request.Operation), policy, *engineResponse)
|
||||
}
|
||||
|
||||
if failedResponse := applyUpdateRequest(request, kyvernov1beta1.Generate, h.urGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
if failedResponse := applyUpdateRequest(request, kyvernov1beta1.Generate, h.urGenerator, policyContext.AdmissionInfo(), request.Operation, engineResponses...); failedResponse != nil {
|
||||
// report failure event
|
||||
for _, failedUR := range failedResponse {
|
||||
err := fmt.Errorf("failed to create Update Request: %v", failedUR.err)
|
||||
e := event.NewBackgroundFailedEvent(err, failedUR.ur.Policy, "", event.GeneratePolicyController, &policyContext.NewResource)
|
||||
newResource := policyContext.NewResource()
|
||||
e := event.NewBackgroundFailedEvent(err, failedUR.ur.Policy, "", event.GeneratePolicyController, &newResource)
|
||||
h.eventGen.Add(e...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ func (h *handlers) Validate(ctx context.Context, logger logr.Logger, request *ad
|
|||
|
||||
logger.V(4).Info("processing policies for validate admission request", "validate", len(policies), "mutate", len(mutatePolicies), "generate", len(generatePolicies))
|
||||
|
||||
policyContext, err := h.pcBuilder.Build(request, generatePolicies...)
|
||||
policyContext, err := h.pcBuilder.Build(request)
|
||||
if err != nil {
|
||||
return errorResponse(logger, request.UID, err, "failed create policy context")
|
||||
}
|
||||
|
@ -152,13 +152,13 @@ func (h *handlers) Mutate(ctx context.Context, logger logr.Logger, request *admi
|
|||
return admissionutils.ResponseSuccess(request.UID)
|
||||
}
|
||||
logger.V(4).Info("processing policies for mutate admission request", "mutatePolicies", len(mutatePolicies), "verifyImagesPolicies", len(verifyImagesPolicies))
|
||||
policyContext, err := h.pcBuilder.Build(request, mutatePolicies...)
|
||||
policyContext, err := h.pcBuilder.Build(request)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to build policy context")
|
||||
return admissionutils.Response(request.UID, err)
|
||||
}
|
||||
// update container images to a canonical form
|
||||
if err := enginectx.MutateResourceWithImageInfo(request.Object.Raw, policyContext.JSONContext); err != nil {
|
||||
if err := enginectx.MutateResourceWithImageInfo(request.Object.Raw, policyContext.JSONContext()); err != nil {
|
||||
logger.Error(err, "failed to patch images info to resource, policies that mutate images may be impacted")
|
||||
}
|
||||
mh := mutation.NewMutationHandler(logger, h.eventGen, h.openApiManager, h.nsLister)
|
||||
|
@ -169,7 +169,7 @@ func (h *handlers) Mutate(ctx context.Context, logger logr.Logger, request *admi
|
|||
}
|
||||
newRequest := patchRequest(mutatePatches, request, logger)
|
||||
// rebuild context to process images updated via mutate policies
|
||||
policyContext, err = h.pcBuilder.Build(newRequest, mutatePolicies...)
|
||||
policyContext, err = h.pcBuilder.Build(newRequest)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to build policy context")
|
||||
return admissionutils.Response(request.UID, err)
|
||||
|
|
|
@ -75,7 +75,7 @@ func (h *imageVerificationHandler) handleVerifyImages(logger logr.Logger, reques
|
|||
var patches [][]byte
|
||||
verifiedImageData := &engine.ImageVerificationMetadata{}
|
||||
for _, p := range policies {
|
||||
policyContext.Policy = p
|
||||
policyContext := policyContext.WithPolicy(p)
|
||||
resp, ivm := engine.VerifyAndPatchImages(policyContext)
|
||||
|
||||
engineResponses = append(engineResponses, resp)
|
||||
|
@ -83,7 +83,7 @@ func (h *imageVerificationHandler) handleVerifyImages(logger logr.Logger, reques
|
|||
verifiedImageData.Merge(ivm)
|
||||
}
|
||||
|
||||
failurePolicy := policyContext.Policy.GetSpec().GetFailurePolicy()
|
||||
failurePolicy := policies[0].GetSpec().GetFailurePolicy()
|
||||
blocked := webhookutils.BlockRequest(engineResponses, failurePolicy, logger)
|
||||
if !isResourceDeleted(policyContext) {
|
||||
events := webhookutils.GenerateEvents(engineResponses, blocked)
|
||||
|
@ -106,23 +106,26 @@ func (h *imageVerificationHandler) handleVerifyImages(logger logr.Logger, reques
|
|||
}
|
||||
}
|
||||
|
||||
go h.handleAudit(policyContext.NewResource, request, nil, engineResponses...)
|
||||
go h.handleAudit(policyContext.NewResource(), request, nil, engineResponses...)
|
||||
|
||||
warnings := webhookutils.GetWarningMessages(engineResponses)
|
||||
return true, "", jsonutils.JoinPatches(patches...), warnings
|
||||
}
|
||||
|
||||
func hasAnnotations(context *engine.PolicyContext) bool {
|
||||
annotations := context.NewResource.GetAnnotations()
|
||||
newResource := context.NewResource()
|
||||
annotations := newResource.GetAnnotations()
|
||||
return len(annotations) != 0
|
||||
}
|
||||
|
||||
func isResourceDeleted(policyContext *engine.PolicyContext) bool {
|
||||
var deletionTimeStamp *metav1.Time
|
||||
if reflect.DeepEqual(policyContext.NewResource, unstructured.Unstructured{}) {
|
||||
deletionTimeStamp = policyContext.NewResource.GetDeletionTimestamp()
|
||||
resource := policyContext.NewResource()
|
||||
deletionTimeStamp = resource.GetDeletionTimestamp()
|
||||
} else {
|
||||
deletionTimeStamp = policyContext.OldResource.GetDeletionTimestamp()
|
||||
resource := policyContext.OldResource()
|
||||
deletionTimeStamp = resource.GetDeletionTimestamp()
|
||||
}
|
||||
return deletionTimeStamp != nil
|
||||
}
|
||||
|
|
|
@ -100,8 +100,8 @@ func (v *mutationHandler) applyMutations(
|
|||
continue
|
||||
}
|
||||
v.log.V(3).Info("applying policy mutate rules", "policy", policy.GetName())
|
||||
policyContext.Policy = policy
|
||||
engineResponse, policyPatches, err := v.applyMutation(request, policyContext)
|
||||
currentContext := policyContext.WithPolicy(policy)
|
||||
engineResponse, policyPatches, err := v.applyMutation(request, currentContext)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("mutation policy %s error: %v", policy.GetName(), err)
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ func (v *mutationHandler) applyMutations(
|
|||
}
|
||||
}
|
||||
|
||||
policyContext.NewResource = engineResponse.PatchedResource
|
||||
policyContext = currentContext.WithNewResource(engineResponse.PatchedResource)
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
|
||||
// registering the kyverno_policy_results_total metric concurrently
|
||||
|
@ -141,20 +141,20 @@ func (v *mutationHandler) applyMutations(
|
|||
|
||||
func (h *mutationHandler) applyMutation(request *admissionv1.AdmissionRequest, policyContext *engine.PolicyContext) (*response.EngineResponse, [][]byte, error) {
|
||||
if request.Kind.Kind != "Namespace" && request.Namespace != "" {
|
||||
policyContext.NamespaceLabels = common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log)
|
||||
policyContext = policyContext.WithNamespaceLabels(common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log))
|
||||
}
|
||||
|
||||
engineResponse := engine.Mutate(policyContext)
|
||||
policyPatches := engineResponse.GetPatches()
|
||||
|
||||
if !engineResponse.IsSuccessful() {
|
||||
return nil, nil, fmt.Errorf("failed to apply policy %s rules %v", policyContext.Policy.GetName(), engineResponse.GetFailedRules())
|
||||
return nil, nil, fmt.Errorf("failed to apply policy %s rules %v", policyContext.Policy().GetName(), engineResponse.GetFailedRules())
|
||||
}
|
||||
|
||||
if policyContext.Policy.ValidateSchema() && engineResponse.PatchedResource.GetKind() != "*" {
|
||||
if policyContext.Policy().ValidateSchema() && engineResponse.PatchedResource.GetKind() != "*" {
|
||||
err := h.openApiManager.ValidateResource(*engineResponse.PatchedResource.DeepCopy(), engineResponse.PatchedResource.GetAPIVersion(), engineResponse.PatchedResource.GetKind())
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to validate resource mutated by policy %s", policyContext.Policy.GetName())
|
||||
return nil, nil, errors.Wrapf(err, "failed to validate resource mutated by policy %s", policyContext.Policy().GetName())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,9 +175,11 @@ func logMutationResponse(patches [][]byte, engineResponses []*response.EngineRes
|
|||
func isResourceDeleted(policyContext *engine.PolicyContext) bool {
|
||||
var deletionTimeStamp *metav1.Time
|
||||
if reflect.DeepEqual(policyContext.NewResource, unstructured.Unstructured{}) {
|
||||
deletionTimeStamp = policyContext.NewResource.GetDeletionTimestamp()
|
||||
resource := policyContext.NewResource()
|
||||
deletionTimeStamp = resource.GetDeletionTimestamp()
|
||||
} else {
|
||||
deletionTimeStamp = policyContext.OldResource.GetDeletionTimestamp()
|
||||
resource := policyContext.OldResource()
|
||||
deletionTimeStamp = resource.GetDeletionTimestamp()
|
||||
}
|
||||
return deletionTimeStamp != nil
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@ func (h *handlers) createUpdateRequests(logger logr.Logger, request *admissionv1
|
|||
|
||||
func (h *handlers) handleMutateExisting(logger logr.Logger, request *admissionv1.AdmissionRequest, policies []kyvernov1.PolicyInterface, policyContext *engine.PolicyContext, admissionRequestTimestamp time.Time) {
|
||||
if request.Operation == admissionv1.Delete {
|
||||
policyContext.NewResource = policyContext.OldResource
|
||||
policyContext = policyContext.WithNewResource(policyContext.OldResource())
|
||||
}
|
||||
|
||||
if request.Operation == admissionv1.Update && policyContext.NewResource.GetDeletionTimestamp() != nil {
|
||||
resource := policyContext.NewResource()
|
||||
if request.Operation == admissionv1.Update && resource.GetDeletionTimestamp() != nil {
|
||||
logger.V(4).Info("skip creating UR for the trigger resource that is in termination")
|
||||
return
|
||||
}
|
||||
|
@ -41,7 +42,7 @@ func (h *handlers) handleMutateExisting(logger logr.Logger, request *admissionv1
|
|||
logger.V(4).Info("update request for mutateExisting policy")
|
||||
|
||||
var rules []response.RuleResponse
|
||||
policyContext.Policy = policy
|
||||
policyContext := policyContext.WithPolicy(policy)
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
|
@ -61,10 +62,11 @@ func (h *handlers) handleMutateExisting(logger logr.Logger, request *admissionv1
|
|||
go webhookutils.RegisterPolicyExecutionDurationMetricMutate(context.TODO(), logger, h.metricsConfig, string(request.Operation), policy, *engineResponse)
|
||||
}
|
||||
|
||||
if failedResponse := applyUpdateRequest(request, kyvernov1beta1.Mutate, h.urGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
if failedResponse := applyUpdateRequest(request, kyvernov1beta1.Mutate, h.urGenerator, policyContext.AdmissionInfo(), request.Operation, engineResponses...); failedResponse != nil {
|
||||
for _, failedUR := range failedResponse {
|
||||
err := fmt.Errorf("failed to create update request: %v", failedUR.err)
|
||||
events := event.NewBackgroundFailedEvent(err, failedUR.ur.Policy, "", event.GeneratePolicyController, &policyContext.NewResource)
|
||||
resource := policyContext.NewResource()
|
||||
events := event.NewBackgroundFailedEvent(err, failedUR.ur.Policy, "", event.GeneratePolicyController, &resource)
|
||||
h.eventGen.Add(events...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func (v *validationHandler) HandleValidation(
|
|||
) (bool, string, []string) {
|
||||
if len(policies) == 0 {
|
||||
// invoke handleAudit as we may have some policies in audit mode to consider
|
||||
go v.handleAudit(policyContext.NewResource, request, namespaceLabels)
|
||||
go v.handleAudit(policyContext.NewResource(), request, namespaceLabels)
|
||||
return true, "", nil
|
||||
}
|
||||
|
||||
|
@ -76,9 +76,11 @@ func (v *validationHandler) HandleValidation(
|
|||
|
||||
var deletionTimeStamp *metav1.Time
|
||||
if reflect.DeepEqual(policyContext.NewResource, unstructured.Unstructured{}) {
|
||||
deletionTimeStamp = policyContext.NewResource.GetDeletionTimestamp()
|
||||
resource := policyContext.NewResource()
|
||||
deletionTimeStamp = resource.GetDeletionTimestamp()
|
||||
} else {
|
||||
deletionTimeStamp = policyContext.OldResource.GetDeletionTimestamp()
|
||||
resource := policyContext.OldResource()
|
||||
deletionTimeStamp = resource.GetDeletionTimestamp()
|
||||
}
|
||||
|
||||
if deletionTimeStamp != nil && request.Operation == admissionv1.Update {
|
||||
|
@ -88,8 +90,7 @@ func (v *validationHandler) HandleValidation(
|
|||
var engineResponses []*response.EngineResponse
|
||||
failurePolicy := kyvernov1.Ignore
|
||||
for _, policy := range policies {
|
||||
policyContext.Policy = policy
|
||||
policyContext.NamespaceLabels = namespaceLabels
|
||||
policyContext := policyContext.WithPolicy(policy).WithNamespaceLabels(namespaceLabels)
|
||||
if policy.GetSpec().GetFailurePolicy() == kyvernov1.Fail {
|
||||
failurePolicy = kyvernov1.Fail
|
||||
}
|
||||
|
@ -101,8 +102,8 @@ func (v *validationHandler) HandleValidation(
|
|||
continue
|
||||
}
|
||||
|
||||
go webhookutils.RegisterPolicyResultsMetricValidation(context.TODO(), logger, metricsConfig, string(request.Operation), policyContext.Policy, *engineResponse)
|
||||
go webhookutils.RegisterPolicyExecutionDurationMetricValidate(context.TODO(), logger, metricsConfig, string(request.Operation), policyContext.Policy, *engineResponse)
|
||||
go webhookutils.RegisterPolicyResultsMetricValidation(context.TODO(), logger, metricsConfig, string(request.Operation), policyContext.Policy(), *engineResponse)
|
||||
go webhookutils.RegisterPolicyExecutionDurationMetricValidate(context.TODO(), logger, metricsConfig, string(request.Operation), policyContext.Policy(), *engineResponse)
|
||||
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
if !engineResponse.IsSuccessful() {
|
||||
|
@ -126,7 +127,7 @@ func (v *validationHandler) HandleValidation(
|
|||
return false, webhookutils.GetBlockedMessages(engineResponses), nil
|
||||
}
|
||||
|
||||
go v.handleAudit(policyContext.NewResource, request, namespaceLabels, engineResponses...)
|
||||
go v.handleAudit(policyContext.NewResource(), request, namespaceLabels, engineResponses...)
|
||||
|
||||
warnings := webhookutils.GetWarningMessages(engineResponses)
|
||||
return true, "", warnings
|
||||
|
@ -134,14 +135,13 @@ func (v *validationHandler) HandleValidation(
|
|||
|
||||
func (v *validationHandler) buildAuditResponses(resource unstructured.Unstructured, request *admissionv1.AdmissionRequest, namespaceLabels map[string]string) ([]*response.EngineResponse, error) {
|
||||
policies := v.pCache.GetPolicies(policycache.ValidateAudit, request.Kind.Kind, request.Namespace)
|
||||
policyContext, err := v.pcBuilder.Build(request, policies...)
|
||||
policyContext, err := v.pcBuilder.Build(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var responses []*response.EngineResponse
|
||||
for _, policy := range policies {
|
||||
policyContext.Policy = policy
|
||||
policyContext.NamespaceLabels = namespaceLabels
|
||||
policyContext := policyContext.WithPolicy(policy).WithNamespaceLabels(namespaceLabels)
|
||||
responses = append(responses, engine.Validate(policyContext))
|
||||
}
|
||||
return responses, nil
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils"
|
||||
|
@ -531,7 +530,9 @@ func TestValidate_failure_action_overrides(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(tc.rawResource)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := engine.Validate(&engine.PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
|
||||
er := engine.Validate(
|
||||
engine.NewPolicyContext().WithPolicy(&policy).WithNewResource(*resourceUnstructured),
|
||||
)
|
||||
if tc.blocked && tc.messages != nil {
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
msg := tc.messages[r.Name]
|
||||
|
@ -589,7 +590,8 @@ func Test_RuleSelector(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
assert.Assert(t, resourceUnstructured != nil)
|
||||
|
||||
ctx := &engine.PolicyContext{Policy: &policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()}
|
||||
ctx := engine.NewPolicyContext().WithPolicy(&policy).WithNewResource(*resourceUnstructured)
|
||||
|
||||
resp := engine.Validate(ctx)
|
||||
assert.Assert(t, resp.PolicyResponse.RulesAppliedCount == 2)
|
||||
assert.Assert(t, resp.PolicyResponse.RulesErrorCount == 0)
|
||||
|
|
|
@ -1,35 +1,18 @@
|
|||
package utils
|
||||
|
||||
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"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/userinfo"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
rbacv1listers "k8s.io/client-go/listers/rbac/v1"
|
||||
)
|
||||
|
||||
type PolicyContextBuilder interface {
|
||||
Build(*admissionv1.AdmissionRequest, ...kyvernov1.PolicyInterface) (*engine.PolicyContext, error)
|
||||
}
|
||||
|
||||
func newVariablesContext(request *admissionv1.AdmissionRequest, userRequestInfo *kyvernov1beta1.RequestInfo) (enginectx.Interface, error) {
|
||||
ctx := enginectx.NewContext()
|
||||
if err := ctx.AddRequest(request); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load incoming request in context")
|
||||
}
|
||||
if err := ctx.AddUserInfo(*userRequestInfo); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load userInfo in context")
|
||||
}
|
||||
if err := ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load service account in context")
|
||||
}
|
||||
return ctx, nil
|
||||
Build(*admissionv1.AdmissionRequest) (*engine.PolicyContext, error)
|
||||
}
|
||||
|
||||
type policyContextBuilder struct {
|
||||
|
@ -53,7 +36,7 @@ func NewPolicyContextBuilder(
|
|||
}
|
||||
}
|
||||
|
||||
func (b *policyContextBuilder) Build(request *admissionv1.AdmissionRequest, policies ...kyvernov1.PolicyInterface) (*engine.PolicyContext, error) {
|
||||
func (b *policyContextBuilder) Build(request *admissionv1.AdmissionRequest) (*engine.PolicyContext, error) {
|
||||
userRequestInfo := kyvernov1beta1.RequestInfo{
|
||||
AdmissionUserInfo: *request.UserInfo.DeepCopy(),
|
||||
}
|
||||
|
@ -63,26 +46,5 @@ func (b *policyContextBuilder) Build(request *admissionv1.AdmissionRequest, poli
|
|||
userRequestInfo.Roles = roles
|
||||
userRequestInfo.ClusterRoles = clusterRoles
|
||||
}
|
||||
ctx, err := newVariablesContext(request, &userRequestInfo)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create policy rule context")
|
||||
}
|
||||
newResource, oldResource, err := utils.ExtractResources(nil, request)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse resource")
|
||||
}
|
||||
if err := ctx.AddImageInfos(&newResource); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to add image information to the policy rule context")
|
||||
}
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: newResource,
|
||||
OldResource: oldResource,
|
||||
AdmissionInfo: userRequestInfo,
|
||||
ExcludeGroupRole: b.configuration.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: b.configuration.ToFilter,
|
||||
JSONContext: ctx,
|
||||
Client: b.client,
|
||||
AdmissionOperation: true,
|
||||
}
|
||||
return policyContext, nil
|
||||
return engine.NewPolicyContextFromAdmissionRequest(request, userRequestInfo, b.configuration, b.client)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue