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

refactor: add a few response helpers in engine internal (#6262)

* refactor: context loading and engine methods

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

* fix

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

* fix

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

* refactor: add a few response helpers in engine internal

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

* fix

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

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-02-09 14:39:38 +01:00 committed by GitHub
parent c6b7d53b33
commit 4ccb7b6bbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 27 additions and 43 deletions

View file

@ -27,7 +27,7 @@ func (e *engine) processImageValidationRule(
log = log.WithValues("rule", rule.Name)
matchingImages, _, err := e.extractMatchingImages(enginectx, rule)
if err != nil {
return internal.RuleResponse(*rule, engineapi.Validation, err.Error(), engineapi.RuleStatusError)
return internal.RuleError(rule, engineapi.Validation, "", err)
}
if len(matchingImages) == 0 {
return internal.RuleSkip(rule, engineapi.Validation, "image verified")
@ -76,7 +76,7 @@ func (e *engine) processImageValidationRule(
}
log.V(4).Info("validated image", "rule", rule.Name)
return internal.RuleResponse(*rule, engineapi.Validation, "image verified", engineapi.RuleStatusPass)
return internal.RulePass(rule, engineapi.Validation, "image verified")
}
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) error {
@ -102,24 +102,15 @@ func isImageVerified(resource unstructured.Unstructured, image string, log logr.
if reflect.DeepEqual(resource, unstructured.Unstructured{}) {
return false, fmt.Errorf("nil resource")
}
annotations := resource.GetAnnotations()
if len(annotations) == 0 {
if annotations := resource.GetAnnotations(); len(annotations) == 0 {
return false, nil
}
key := engineapi.ImageVerifyAnnotationKey
data, ok := annotations[key]
if !ok {
log.V(2).Info("missing image metadata in annotation", "key", key)
} else if data, ok := annotations[engineapi.ImageVerifyAnnotationKey]; !ok {
log.V(2).Info("missing image metadata in annotation", "key", engineapi.ImageVerifyAnnotationKey)
return false, fmt.Errorf("image is not verified")
}
ivm, err := engineapi.ParseImageMetadata(data)
if err != nil {
} else if ivm, err := engineapi.ParseImageMetadata(data); err != nil {
log.Error(err, "failed to parse image verification metadata", "data", data)
return false, fmt.Errorf("failed to parse image metadata: %w", err)
} else {
return ivm.IsVerified(image), nil
}
return ivm.IsVerified(image), nil
}

View file

@ -222,7 +222,7 @@ func (iv *ImageVerifier) Verify(
responses = append(responses, RuleError(iv.rule, engineapi.ImageVerify, "failed to update digest", err))
} else if patch != nil {
if ruleResp == nil {
ruleResp = RuleResponse(*iv.rule, engineapi.ImageVerify, "mutated image digest", engineapi.RuleStatusPass)
ruleResp = RulePass(iv.rule, engineapi.ImageVerify, "mutated image digest")
}
ruleResp.Patches = append(ruleResp.Patches, patch)
imageInfo.Digest = retrievedDigest
@ -253,8 +253,7 @@ func (iv *ImageVerifier) verifyImage(
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, cfg); 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, engineapi.ImageVerify, msg, engineapi.RuleStatusError), ""
return RuleError(iv.rule, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err), ""
}
if len(imageVerify.Attestors) > 0 {
if !matchImageReferences(imageVerify.ImageReferences, image) {
@ -303,7 +302,7 @@ func (iv *ImageVerifier) verifyAttestors(
return RuleError(iv.rule, engineapi.ImageVerify, "invalid response", fmt.Errorf("nil")), nil
}
msg := fmt.Sprintf("verified image signatures for %s", image)
return RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusPass), cosignResponse
return RulePass(iv.rule, engineapi.ImageVerify, msg), cosignResponse
}
// handle registry network errors as a rule error (instead of a policy failure)
@ -311,7 +310,7 @@ func (iv *ImageVerifier) handleRegistryErrors(image string, err error) *engineap
msg := fmt.Sprintf("failed to verify image %s: %s", image, err.Error())
var netErr *net.OpError
if errors.As(err, &netErr) {
return RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusError)
return RuleError(iv.rule, engineapi.ImageVerify, fmt.Sprintf("failed to verify image %s", image), err)
}
return RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail)
}
@ -378,7 +377,7 @@ func (iv *ImageVerifier) verifyAttestations(
msg := fmt.Sprintf("verified image attestations for %s", image)
iv.logger.V(2).Info(msg)
return RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusPass), imageInfo.Digest
return RulePass(iv.rule, engineapi.ImageVerify, msg), imageInfo.Digest
}
func (iv *ImageVerifier) verifyAttestorSet(

View file

@ -18,6 +18,10 @@ func RuleSkip(rule *kyvernov1.Rule, ruleType engineapi.RuleType, msg string) *en
return RuleResponse(*rule, ruleType, msg, engineapi.RuleStatusSkip)
}
func RulePass(rule *kyvernov1.Rule, ruleType engineapi.RuleType, msg string) *engineapi.RuleResponse {
return RuleResponse(*rule, ruleType, msg, engineapi.RuleStatusPass)
}
func RuleResponse(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, status engineapi.RuleStatus) *engineapi.RuleResponse {
resp := &engineapi.RuleResponse{
Name: rule.Name,

View file

@ -63,7 +63,7 @@ func handleVerifyManifest(
if !verified {
return internal.RuleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusFail)
}
return internal.RuleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusPass)
return internal.RulePass(rule, engineapi.Validation, reason)
}
func verifyManifest(

View file

@ -105,7 +105,7 @@ func (e *engine) mutate(
if !policyContext.AdmissionOperation() && rule.IsMutateExisting() {
targets, err := loadTargets(e.client, ruleCopy.Mutation.Targets, policyContext, logger)
if err != nil {
rr := internal.RuleResponse(rule, engineapi.Mutation, err.Error(), engineapi.RuleStatusError)
rr := internal.RuleError(ruleCopy, engineapi.Mutation, "", err)
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *rr)
} else {
patchedResources = append(patchedResources, targets...)

View file

@ -4,7 +4,6 @@ import (
"fmt"
"reflect"
"strings"
"time"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
@ -19,14 +18,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// EngineStats stores in the statistics for a single application of resource
type EngineStats struct {
// average time required to process the policy rules on a resource
ExecutionTime time.Duration
// Count of rules that were applied successfully
RulesAppliedCount int
}
func checkNameSpace(namespaces []string, resource unstructured.Unstructured) bool {
resourceNameSpace := resource.GetNamespace()
if resource.GetKind() == "Namespace" {

View file

@ -260,7 +260,7 @@ func (v *validator) validateForEach(ctx context.Context) *engineapi.RuleResponse
}
return internal.RuleSkip(v.rule, engineapi.Validation, "rule skipped")
}
return internal.RuleResponse(*v.rule, engineapi.Validation, "rule passed", engineapi.RuleStatusPass)
return internal.RulePass(v.rule, engineapi.Validation, "rule passed")
}
func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForEachValidation, elements []interface{}, elementScope *bool) (*engineapi.RuleResponse, int) {
@ -308,7 +308,7 @@ func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForE
applyCount++
}
return internal.RuleResponse(*v.rule, engineapi.Validation, "", engineapi.RuleStatusPass), applyCount
return internal.RulePass(v.rule, engineapi.Validation, ""), applyCount
}
func addElementToContext(ctx engineapi.PolicyContext, element interface{}, index, nesting int, elementScope *bool) error {
@ -364,7 +364,7 @@ func (v *validator) validateDeny() *engineapi.RuleResponse {
if deny {
return internal.RuleResponse(*v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusFail)
}
return internal.RuleResponse(*v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusPass)
return internal.RulePass(v.rule, engineapi.Validation, v.getDenyMessage(deny))
}
}
@ -464,7 +464,7 @@ func (v *validator) validatePodSecurity() *engineapi.RuleResponse {
}
if allowed {
msg := fmt.Sprintf("Validation rule '%s' passed.", v.rule.Name)
rspn := internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
rspn := internal.RulePass(v.rule, engineapi.Validation, msg)
rspn.PodSecurityChecks = podSecurityChecks
return rspn
} else {
@ -554,7 +554,7 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
v.log.V(4).Info("successfully processed rule")
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
return internal.RulePass(v.rule, engineapi.Validation, msg)
}
if v.anyPattern != nil {
@ -564,15 +564,14 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
anyPatterns, err := deserializeAnyPattern(v.anyPattern)
if err != nil {
msg := fmt.Sprintf("failed to deserialize anyPattern, expected type array: %v", err)
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusError)
return internal.RuleError(v.rule, engineapi.Validation, "failed to deserialize anyPattern, expected type array", err)
}
for idx, pattern := range anyPatterns {
err := validate.MatchPattern(v.log, resource.Object, pattern)
if err == nil {
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
return internal.RulePass(v.rule, engineapi.Validation, msg)
}
if pe, ok := err.(*validate.PatternError); ok {
@ -613,7 +612,7 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
}
}
return internal.RuleResponse(*v.rule, engineapi.Validation, v.rule.Validation.Message, engineapi.RuleStatusPass)
return internal.RulePass(v.rule, engineapi.Validation, v.rule.Validation.Message)
}
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {