mirror of
https://github.com/kyverno/kyverno.git
synced 2025-04-08 18:15:48 +00:00
refactor: introduce internal engine package (#6241)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
60cf8afff9
commit
dbddc83cb6
12 changed files with 173 additions and 149 deletions
|
@ -7,6 +7,7 @@ import (
|
|||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
|
@ -131,7 +132,7 @@ func (e *engine) filterRule(
|
|||
policyContext.JSONContext().Checkpoint()
|
||||
defer policyContext.JSONContext().Restore()
|
||||
|
||||
if err := LoadContext(context.TODO(), e.contextLoader, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err := internal.LoadContext(context.TODO(), e.contextLoader, rule.Context, policyContext, rule.Name); err != nil {
|
||||
logger.V(4).Info("cannot add external data to the context", "reason", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/cosign"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
|
@ -43,7 +44,7 @@ func (e *engine) verifyAndPatchImages(
|
|||
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
buildResponse(policyContext, resp, startTime)
|
||||
internal.BuildResponse(policyContext, resp, startTime)
|
||||
logger.V(4).Info("processed image verification rules",
|
||||
"time", resp.PolicyResponse.ProcessingTime.String(),
|
||||
"applied", resp.PolicyResponse.RulesAppliedCount, "successful", resp.IsSuccessful())
|
||||
|
@ -100,7 +101,7 @@ func (e *engine) verifyAndPatchImages(
|
|||
}
|
||||
|
||||
policyContext.JSONContext().Restore()
|
||||
if err := LoadContext(ctx, e.contextLoader, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err := internal.LoadContext(ctx, e.contextLoader, rule.Context, policyContext, rule.Name); err != nil {
|
||||
appendResponse(resp, rule, fmt.Sprintf("failed to load context: %s", err.Error()), engineapi.RuleStatusError)
|
||||
return
|
||||
}
|
||||
|
@ -172,7 +173,7 @@ func (e *engine) extractMatchingImages(policyContext engineapi.PolicyContext, ru
|
|||
}
|
||||
|
||||
func appendResponse(resp *engineapi.EngineResponse, rule *kyvernov1.Rule, msg string, status engineapi.RuleStatus) {
|
||||
rr := ruleResponse(*rule, engineapi.ImageVerify, msg, status)
|
||||
rr := internal.RuleResponse(*rule, engineapi.ImageVerify, msg, status)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *rr)
|
||||
incrementErrorCount(resp)
|
||||
}
|
||||
|
@ -219,7 +220,7 @@ func (iv *imageVerifier) verify(ctx context.Context, imageVerify kyvernov1.Image
|
|||
if hasImageVerifiedAnnotationChanged(iv.policyContext, iv.logger) {
|
||||
msg := engineapi.ImageVerifyAnnotationKey + " annotation cannot be changed"
|
||||
iv.logger.Info("image verification error", "reason", msg)
|
||||
ruleResp := ruleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail)
|
||||
ruleResp := internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail)
|
||||
iv.resp.PolicyResponse.Rules = append(iv.resp.PolicyResponse.Rules, *ruleResp)
|
||||
incrementAppliedCount(iv.resp)
|
||||
continue
|
||||
|
@ -243,10 +244,10 @@ func (iv *imageVerifier) verify(ctx context.Context, imageVerify kyvernov1.Image
|
|||
if imageVerify.MutateDigest {
|
||||
patch, retrievedDigest, err := iv.handleMutateDigest(ctx, digest, imageInfo)
|
||||
if err != nil {
|
||||
ruleResp = ruleError(iv.rule, engineapi.ImageVerify, "failed to update digest", err)
|
||||
ruleResp = internal.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 = internal.RuleResponse(*iv.rule, engineapi.ImageVerify, "mutated image digest", engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
ruleResp.Patches = append(ruleResp.Patches, patch)
|
||||
|
@ -336,7 +337,7 @@ func (iv *imageVerifier) verifyImage(
|
|||
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 internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusError), ""
|
||||
}
|
||||
|
||||
if len(imageVerify.Attestors) > 0 {
|
||||
|
@ -391,11 +392,11 @@ func (iv *imageVerifier) verifyAttestors(
|
|||
}
|
||||
|
||||
if cosignResponse == nil {
|
||||
return ruleError(iv.rule, engineapi.ImageVerify, "invalid response", fmt.Errorf("nil")), nil
|
||||
return internal.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 internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusPass), cosignResponse
|
||||
}
|
||||
|
||||
// handle registry network errors as a rule error (instead of a policy failure)
|
||||
|
@ -403,10 +404,10 @@ 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 internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
return ruleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail)
|
||||
return internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail)
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyAttestations(
|
||||
|
@ -420,7 +421,7 @@ func (iv *imageVerifier) verifyAttestations(
|
|||
path := fmt.Sprintf(".attestations[%d]", i)
|
||||
|
||||
if attestation.PredicateType == "" {
|
||||
return ruleResponse(*iv.rule, engineapi.ImageVerify, path+": missing predicateType", engineapi.RuleStatusFail), ""
|
||||
return internal.RuleResponse(*iv.rule, engineapi.ImageVerify, path+": missing predicateType", engineapi.RuleStatusFail), ""
|
||||
}
|
||||
|
||||
if len(attestation.Attestors) == 0 {
|
||||
|
@ -450,7 +451,7 @@ func (iv *imageVerifier) verifyAttestations(
|
|||
attestationError = iv.verifyAttestation(cosignResp.Statements, attestation, imageInfo)
|
||||
if attestationError != nil {
|
||||
attestationError = fmt.Errorf("%s: %w", entryPath+subPath, attestationError)
|
||||
return ruleResponse(*iv.rule, engineapi.ImageVerify, attestationError.Error(), engineapi.RuleStatusFail), ""
|
||||
return internal.RuleResponse(*iv.rule, engineapi.ImageVerify, attestationError.Error(), engineapi.RuleStatusFail), ""
|
||||
}
|
||||
|
||||
verifiedCount++
|
||||
|
@ -462,7 +463,7 @@ func (iv *imageVerifier) verifyAttestations(
|
|||
|
||||
if verifiedCount < requiredCount {
|
||||
msg := fmt.Sprintf("image attestations verification failed, verifiedCount: %v, requiredCount: %v", verifiedCount, requiredCount)
|
||||
return ruleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail), ""
|
||||
return internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail), ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,7 +472,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 internal.RuleResponse(*iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusPass), imageInfo.Digest
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyAttestorSet(
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
gojmespath "github.com/jmespath/go-jmespath"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
@ -26,24 +27,24 @@ func (e *engine) processImageValidationRule(
|
|||
log = log.WithValues("rule", rule.Name)
|
||||
matchingImages, _, err := e.extractMatchingImages(enginectx, rule)
|
||||
if err != nil {
|
||||
return ruleResponse(*rule, engineapi.Validation, err.Error(), engineapi.RuleStatusError)
|
||||
return internal.RuleResponse(*rule, engineapi.Validation, err.Error(), engineapi.RuleStatusError)
|
||||
}
|
||||
if len(matchingImages) == 0 {
|
||||
return ruleResponse(*rule, engineapi.Validation, "image verified", engineapi.RuleStatusSkip)
|
||||
return internal.RuleResponse(*rule, engineapi.Validation, "image verified", engineapi.RuleStatusSkip)
|
||||
}
|
||||
if err := LoadContext(ctx, e.contextLoader, rule.Context, enginectx, rule.Name); err != nil {
|
||||
if err := internal.LoadContext(ctx, e.contextLoader, rule.Context, enginectx, rule.Name); err != nil {
|
||||
if _, ok := err.(gojmespath.NotFoundError); ok {
|
||||
log.V(3).Info("failed to load context", "reason", err.Error())
|
||||
} else {
|
||||
log.Error(err, "failed to load context")
|
||||
}
|
||||
|
||||
return ruleError(rule, engineapi.Validation, "failed to load context", err)
|
||||
return internal.RuleError(rule, engineapi.Validation, "failed to load context", err)
|
||||
}
|
||||
|
||||
preconditionsPassed, err := checkPreconditions(log, enginectx, rule.RawAnyAllConditions)
|
||||
if err != nil {
|
||||
return ruleError(rule, engineapi.Validation, "failed to evaluate preconditions", err)
|
||||
return internal.RuleError(rule, engineapi.Validation, "failed to evaluate preconditions", err)
|
||||
}
|
||||
|
||||
if !preconditionsPassed {
|
||||
|
@ -51,7 +52,7 @@ func (e *engine) processImageValidationRule(
|
|||
return nil
|
||||
}
|
||||
|
||||
return ruleResponse(*rule, engineapi.Validation, "preconditions not met", engineapi.RuleStatusSkip)
|
||||
return internal.RuleResponse(*rule, engineapi.Validation, "preconditions not met", engineapi.RuleStatusSkip)
|
||||
}
|
||||
|
||||
for _, v := range rule.VerifyImages {
|
||||
|
@ -68,14 +69,14 @@ func (e *engine) processImageValidationRule(
|
|||
|
||||
log.V(4).Info("validating image", "image", image)
|
||||
if err := validateImage(enginectx, imageVerify, name, imageInfo, log); err != nil {
|
||||
return ruleResponse(*rule, engineapi.ImageVerify, err.Error(), engineapi.RuleStatusFail)
|
||||
return internal.RuleResponse(*rule, engineapi.ImageVerify, err.Error(), engineapi.RuleStatusFail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.V(4).Info("validated image", "rule", rule.Name)
|
||||
return ruleResponse(*rule, engineapi.Validation, "image verified", engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*rule, engineapi.Validation, "image verified", engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) error {
|
||||
|
|
12
pkg/engine/internal/context.go
Normal file
12
pkg/engine/internal/context.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
)
|
||||
|
||||
func LoadContext(ctx context.Context, factory engineapi.ContextLoaderFactory, contextEntries []kyvernov1.ContextEntry, pContext engineapi.PolicyContext, ruleName string) error {
|
||||
return factory(pContext, ruleName).Load(ctx, contextEntries, pContext.JSONContext())
|
||||
}
|
22
pkg/engine/internal/logging.go
Normal file
22
pkg/engine/internal/logging.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func BuildLogger(ctx engineapi.PolicyContext) logr.Logger {
|
||||
logger := logging.WithName("EngineValidate").WithValues("policy", ctx.Policy().GetName())
|
||||
newResource := ctx.NewResource()
|
||||
oldResource := ctx.OldResource()
|
||||
if reflect.DeepEqual(newResource, unstructured.Unstructured{}) {
|
||||
logger = logger.WithValues("kind", oldResource.GetKind(), "namespace", oldResource.GetNamespace(), "name", oldResource.GetName())
|
||||
} else {
|
||||
logger = logger.WithValues("kind", newResource.GetKind(), "namespace", newResource.GetNamespace(), "name", newResource.GetName())
|
||||
}
|
||||
return logger
|
||||
}
|
57
pkg/engine/internal/response.go
Normal file
57
pkg/engine/internal/response.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func RuleError(rule *kyvernov1.Rule, ruleType engineapi.RuleType, msg string, err error) *engineapi.RuleResponse {
|
||||
msg = fmt.Sprintf("%s: %s", msg, err.Error())
|
||||
return RuleResponse(*rule, ruleType, msg, engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
func RuleResponse(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, status engineapi.RuleStatus) *engineapi.RuleResponse {
|
||||
resp := &engineapi.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: ruleType,
|
||||
Message: msg,
|
||||
Status: status,
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func BuildResponse(ctx engineapi.PolicyContext, resp *engineapi.EngineResponse, startTime time.Time) *engineapi.EngineResponse {
|
||||
resp.NamespaceLabels = ctx.NamespaceLabels()
|
||||
if reflect.DeepEqual(resp, engineapi.EngineResponse{}) {
|
||||
return resp
|
||||
}
|
||||
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(resource, unstructured.Unstructured{}) {
|
||||
resource = ctx.OldResource()
|
||||
}
|
||||
resp.PatchedResource = resource
|
||||
}
|
||||
policy := ctx.Policy()
|
||||
resp.Policy = policy
|
||||
resp.PolicyResponse.Policy.Name = policy.GetName()
|
||||
resp.PolicyResponse.Policy.Namespace = 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 = policy.GetSpec().ValidationFailureAction
|
||||
for _, v := range policy.GetSpec().ValidationFailureActionOverrides {
|
||||
newOverrides := engineapi.ValidationFailureActionOverride{Action: v.Action, Namespaces: v.Namespaces, NamespaceSelector: v.NamespaceSelector}
|
||||
resp.PolicyResponse.ValidationFailureActionOverrides = append(resp.PolicyResponse.ValidationFailureActionOverrides, newOverrides)
|
||||
}
|
||||
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
||||
resp.PolicyResponse.Timestamp = startTime.Unix()
|
||||
return resp
|
||||
}
|
|
@ -122,10 +122,6 @@ func (l *mockContextLoader) Load(ctx context.Context, contextEntries []kyvernov1
|
|||
return nil
|
||||
}
|
||||
|
||||
func LoadContext(ctx context.Context, factory engineapi.ContextLoaderFactory, contextEntries []kyvernov1.ContextEntry, pContext engineapi.PolicyContext, ruleName string) error {
|
||||
return factory(pContext, ruleName).Load(ctx, contextEntries, pContext.JSONContext())
|
||||
}
|
||||
|
||||
func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx enginecontext.Interface) (err error) {
|
||||
path := ""
|
||||
if entry.Variable.JMESPath != "" {
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
"github.com/sigstore/k8s-manifest-sigstore/pkg/k8smanifest"
|
||||
"go.uber.org/multierr"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
|
@ -46,13 +47,13 @@ func handleVerifyManifest(ctx engineapi.PolicyContext, rule *kyvernov1.Rule, log
|
|||
verified, reason, err := verifyManifest(ctx, *rule.Validation.Manifests, logger)
|
||||
if err != nil {
|
||||
logger.V(3).Info("verifyManifest return err", "error", err.Error())
|
||||
return ruleError(rule, engineapi.Validation, "error occurred during manifest verification", err)
|
||||
return internal.RuleError(rule, engineapi.Validation, "error occurred during manifest verification", err)
|
||||
}
|
||||
logger.V(3).Info("verifyManifest result", "verified", strconv.FormatBool(verified), "reason", reason)
|
||||
if !verified {
|
||||
return ruleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusFail)
|
||||
return internal.RuleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusFail)
|
||||
}
|
||||
return ruleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*rule, engineapi.Validation, reason, engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func verifyManifest(policyContext engineapi.PolicyContext, verifyRule kyvernov1.Manifests, logger logr.Logger) (bool, string, error) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"gotest.tools/assert"
|
||||
v1 "k8s.io/api/admission/v1"
|
||||
|
@ -626,7 +627,7 @@ func Test_VerifyManifest_SignedYAML(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
logger := buildLogger(policyContext)
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
|
@ -648,7 +649,7 @@ func Test_VerifyManifest_UnsignedYAML(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
logger := buildLogger(policyContext)
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, false)
|
||||
|
@ -670,7 +671,7 @@ func Test_VerifyManifest_InvalidYAML(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
logger := buildLogger(policyContext)
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, false)
|
||||
|
@ -697,7 +698,7 @@ func Test_VerifyManifest_MustAll_InvalidYAML(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
logger := buildLogger(policyContext)
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
errMsg := `.attestors[0].entries[1].keys: failed to verify signature: verification failed for 1 signature. all trials: ["[publickey 1/1] [signature 1/1] error: cosign.VerifyBlobCmd() returned an error: invalid signature when validating ASN.1 encoded signature"]`
|
||||
assert.Error(t, err, errMsg)
|
||||
|
@ -730,7 +731,7 @@ func Test_VerifyManifest_MustAll_ValidYAML(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
logger := buildLogger(policyContext)
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
|
@ -759,7 +760,7 @@ func Test_VerifyManifest_AtLeastOne(t *testing.T) {
|
|||
},
|
||||
},
|
||||
})
|
||||
logger := buildLogger(policyContext)
|
||||
logger := logr.Discard()
|
||||
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
"github.com/kyverno/kyverno/pkg/engine/mutate"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/tracing"
|
||||
|
@ -91,7 +92,7 @@ func (e *engine) mutate(
|
|||
logger.Error(err, "failed to query resource object")
|
||||
}
|
||||
|
||||
if err := LoadContext(ctx, e.contextLoader, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err := internal.LoadContext(ctx, e.contextLoader, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if _, ok := err.(gojmespath.NotFoundError); ok {
|
||||
logger.V(3).Info("failed to load context", "reason", err.Error())
|
||||
} else {
|
||||
|
@ -105,7 +106,7 @@ func (e *engine) mutate(
|
|||
if !policyContext.AdmissionOperation() && rule.IsMutateExisting() {
|
||||
targets, err := loadTargets(ruleCopy.Mutation.Targets, policyContext, logger)
|
||||
if err != nil {
|
||||
rr := ruleResponse(rule, engineapi.Mutation, err.Error(), engineapi.RuleStatusError)
|
||||
rr := internal.RuleResponse(rule, engineapi.Mutation, err.Error(), engineapi.RuleStatusError)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *rr)
|
||||
} else {
|
||||
patchedResources = append(patchedResources, targets...)
|
||||
|
@ -213,7 +214,7 @@ func (f *forEachMutator) mutateForEach(ctx context.Context) *mutate.Response {
|
|||
allPatches := make([][]byte, 0)
|
||||
|
||||
for _, foreach := range f.foreach {
|
||||
if err := LoadContext(ctx, f.contextLoader, f.rule.Context, f.policyContext, f.rule.Name); err != nil {
|
||||
if err := internal.LoadContext(ctx, f.contextLoader, f.rule.Context, f.policyContext, f.rule.Name); err != nil {
|
||||
f.log.Error(err, "failed to load context")
|
||||
return mutate.NewErrorResponse("failed to load context", err)
|
||||
}
|
||||
|
@ -278,7 +279,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F
|
|||
return mutate.NewErrorResponse(fmt.Sprintf("failed to add element to mutate.foreach[%d].context", index), err)
|
||||
}
|
||||
|
||||
if err := LoadContext(ctx, f.contextLoader, foreach.Context, policyContext, f.rule.Name); err != nil {
|
||||
if err := internal.LoadContext(ctx, f.contextLoader, foreach.Context, policyContext, f.rule.Name); err != nil {
|
||||
return mutate.NewErrorResponse(fmt.Sprintf("failed to load to mutate.foreach[%d].context", index), err)
|
||||
}
|
||||
|
||||
|
@ -328,7 +329,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F
|
|||
}
|
||||
|
||||
func buildRuleResponse(rule *kyvernov1.Rule, mutateResp *mutate.Response, info resourceInfo) *engineapi.RuleResponse {
|
||||
resp := ruleResponse(*rule, engineapi.Mutation, mutateResp.Message, mutateResp.Status)
|
||||
resp := internal.RuleResponse(*rule, engineapi.Mutation, mutateResp.Message, mutateResp.Status)
|
||||
if resp.Status == engineapi.RuleStatusPass {
|
||||
resp.Patches = mutateResp.Patches
|
||||
resp.Message = buildSuccessMessage(mutateResp.PatchedResource)
|
||||
|
|
|
@ -353,21 +353,6 @@ func evaluateList(jmesPath string, ctx context.EvalInterface) ([]interface{}, er
|
|||
return l, nil
|
||||
}
|
||||
|
||||
func ruleError(rule *kyvernov1.Rule, ruleType engineapi.RuleType, msg string, err error) *engineapi.RuleResponse {
|
||||
msg = fmt.Sprintf("%s: %s", msg, err.Error())
|
||||
return ruleResponse(*rule, ruleType, msg, engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
func ruleResponse(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, status engineapi.RuleStatus) *engineapi.RuleResponse {
|
||||
resp := &engineapi.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: ruleType,
|
||||
Message: msg,
|
||||
Status: status,
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func incrementAppliedCount(resp *engineapi.EngineResponse) {
|
||||
resp.PolicyResponse.RulesAppliedCount++
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/validate"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/pss"
|
||||
"github.com/kyverno/kyverno/pkg/tracing"
|
||||
"github.com/kyverno/kyverno/pkg/utils/api"
|
||||
|
@ -34,66 +34,13 @@ import (
|
|||
func (e *engine) validate(
|
||||
ctx context.Context,
|
||||
policyContext engineapi.PolicyContext,
|
||||
) (resp *engineapi.EngineResponse) {
|
||||
resp = &engineapi.EngineResponse{}
|
||||
) *engineapi.EngineResponse {
|
||||
startTime := time.Now()
|
||||
|
||||
logger := buildLogger(policyContext)
|
||||
logger := internal.BuildLogger(policyContext)
|
||||
logger.V(4).Info("start validate policy processing", "startTime", startTime)
|
||||
defer func() {
|
||||
buildResponse(policyContext, resp, startTime)
|
||||
logger.V(4).Info("finished policy processing", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||
}()
|
||||
|
||||
resp = e.validateResource(ctx, logger, policyContext)
|
||||
resp.NamespaceLabels = policyContext.NamespaceLabels()
|
||||
return
|
||||
}
|
||||
|
||||
func buildLogger(ctx engineapi.PolicyContext) logr.Logger {
|
||||
logger := logging.WithName("EngineValidate").WithValues("policy", ctx.Policy().GetName())
|
||||
newResource := ctx.NewResource()
|
||||
oldResource := ctx.OldResource()
|
||||
if reflect.DeepEqual(newResource, unstructured.Unstructured{}) {
|
||||
logger = logger.WithValues("kind", oldResource.GetKind(), "namespace", oldResource.GetNamespace(), "name", oldResource.GetName())
|
||||
} else {
|
||||
logger = logger.WithValues("kind", newResource.GetKind(), "namespace", newResource.GetNamespace(), "name", newResource.GetName())
|
||||
}
|
||||
|
||||
return logger
|
||||
}
|
||||
|
||||
func buildResponse(ctx engineapi.PolicyContext, resp *engineapi.EngineResponse, startTime time.Time) {
|
||||
if reflect.DeepEqual(resp, engineapi.EngineResponse{}) {
|
||||
return
|
||||
}
|
||||
|
||||
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(resource, unstructured.Unstructured{}) {
|
||||
resource = ctx.OldResource()
|
||||
}
|
||||
|
||||
resp.PatchedResource = resource
|
||||
}
|
||||
policy := ctx.Policy()
|
||||
resp.Policy = policy
|
||||
resp.PolicyResponse.Policy.Name = policy.GetName()
|
||||
resp.PolicyResponse.Policy.Namespace = 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 = policy.GetSpec().ValidationFailureAction
|
||||
|
||||
for _, v := range policy.GetSpec().ValidationFailureActionOverrides {
|
||||
newOverrides := engineapi.ValidationFailureActionOverride{Action: v.Action, Namespaces: v.Namespaces, NamespaceSelector: v.NamespaceSelector}
|
||||
resp.PolicyResponse.ValidationFailureActionOverrides = append(resp.PolicyResponse.ValidationFailureActionOverrides, newOverrides)
|
||||
}
|
||||
|
||||
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
||||
resp.PolicyResponse.Timestamp = startTime.Unix()
|
||||
resp := e.validateResource(ctx, logger, policyContext)
|
||||
defer logger.V(4).Info("finished policy processing", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||
return internal.BuildResponse(policyContext, resp, startTime)
|
||||
}
|
||||
|
||||
func (e *engine) validateResource(
|
||||
|
@ -265,16 +212,16 @@ func newForEachValidator(
|
|||
|
||||
func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
||||
if err := v.loadContext(ctx); err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to load context", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to load context", err)
|
||||
}
|
||||
|
||||
preconditionsPassed, err := checkPreconditions(v.log, v.policyContext, v.anyAllConditions)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to evaluate preconditions", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to evaluate preconditions", err)
|
||||
}
|
||||
|
||||
if !preconditionsPassed {
|
||||
return ruleResponse(*v.rule, engineapi.Validation, "preconditions not met", engineapi.RuleStatusSkip)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, "preconditions not met", engineapi.RuleStatusSkip)
|
||||
}
|
||||
|
||||
if v.deny != nil {
|
||||
|
@ -283,7 +230,7 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
|||
|
||||
if v.pattern != nil || v.anyPattern != nil {
|
||||
if err = v.substitutePatterns(); err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "variable substitution failed", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "variable substitution failed", err)
|
||||
}
|
||||
|
||||
ruleResponse := v.validateResourceWithRule()
|
||||
|
@ -309,12 +256,11 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
|||
func (v *validator) validateForEach(ctx context.Context) *engineapi.RuleResponse {
|
||||
applyCount := 0
|
||||
for _, foreach := range v.forEach {
|
||||
elements, err := evaluateList(foreach.List, (v.policyContext.JSONContext()))
|
||||
elements, err := evaluateList(foreach.List, v.policyContext.JSONContext())
|
||||
if err != nil {
|
||||
v.log.V(2).Info("failed to evaluate list", "list", foreach.List, "error", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
resp, count := v.validateElements(ctx, foreach, elements, foreach.ElementScope)
|
||||
if resp.Status != engineapi.RuleStatusPass {
|
||||
return resp
|
||||
|
@ -325,9 +271,9 @@ func (v *validator) validateForEach(ctx context.Context) *engineapi.RuleResponse
|
|||
if v.forEach == nil {
|
||||
return nil
|
||||
}
|
||||
return ruleResponse(*v.rule, engineapi.Validation, "rule skipped", engineapi.RuleStatusSkip)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, "rule skipped", engineapi.RuleStatusSkip)
|
||||
}
|
||||
return ruleResponse(*v.rule, engineapi.Validation, "rule passed", engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, "rule passed", engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForEachValidation, elements []interface{}, elementScope *bool) (*engineapi.RuleResponse, int) {
|
||||
|
@ -344,13 +290,13 @@ func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForE
|
|||
policyContext := v.policyContext.Copy()
|
||||
if err := addElementToContext(policyContext, element, index, v.nesting, elementScope); err != nil {
|
||||
v.log.Error(err, "failed to add element to context")
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to process foreach", err), applyCount
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to process foreach", err), applyCount
|
||||
}
|
||||
|
||||
foreachValidator, err := newForEachValidator(foreach, v.contextLoader, v.nesting+1, v.rule, policyContext, v.log)
|
||||
if err != nil {
|
||||
v.log.Error(err, "failed to create foreach validator")
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to create foreach validator", err), applyCount
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to create foreach validator", err), applyCount
|
||||
}
|
||||
|
||||
r := foreachValidator.validate(ctx)
|
||||
|
@ -366,16 +312,16 @@ func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForE
|
|||
continue
|
||||
}
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
||||
return ruleResponse(*v.rule, engineapi.Validation, msg, r.Status), applyCount
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, r.Status), applyCount
|
||||
}
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
||||
return ruleResponse(*v.rule, engineapi.Validation, msg, r.Status), applyCount
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, r.Status), applyCount
|
||||
}
|
||||
|
||||
applyCount++
|
||||
}
|
||||
|
||||
return ruleResponse(*v.rule, engineapi.Validation, "", engineapi.RuleStatusPass), applyCount
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, "", engineapi.RuleStatusPass), applyCount
|
||||
}
|
||||
|
||||
func addElementToContext(ctx engineapi.PolicyContext, element interface{}, index, nesting int, elementScope *bool) error {
|
||||
|
@ -411,7 +357,7 @@ func addElementToContext(ctx engineapi.PolicyContext, element interface{}, index
|
|||
}
|
||||
|
||||
func (v *validator) loadContext(ctx context.Context) error {
|
||||
if err := LoadContext(ctx, v.contextLoader, v.contextEntries, v.policyContext, v.rule.Name); err != nil {
|
||||
if err := internal.LoadContext(ctx, v.contextLoader, v.contextEntries, v.policyContext, v.rule.Name); err != nil {
|
||||
if _, ok := err.(gojmespath.NotFoundError); ok {
|
||||
v.log.V(3).Info("failed to load context", "reason", err.Error())
|
||||
} else {
|
||||
|
@ -428,24 +374,24 @@ func (v *validator) validateDeny() *engineapi.RuleResponse {
|
|||
anyAllCond := v.deny.GetAnyAllConditions()
|
||||
anyAllCond, err := variables.SubstituteAll(v.log, v.policyContext.JSONContext(), anyAllCond)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to substitute variables in deny conditions", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to substitute variables in deny conditions", err)
|
||||
}
|
||||
|
||||
if err = v.substituteDeny(); err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to substitute variables in rule", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to substitute variables in rule", err)
|
||||
}
|
||||
|
||||
denyConditions, err := utils.TransformConditions(anyAllCond)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "invalid deny conditions", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "invalid deny conditions", err)
|
||||
}
|
||||
|
||||
deny := variables.EvaluateConditions(v.log, v.policyContext.JSONContext(), denyConditions)
|
||||
if deny {
|
||||
return ruleResponse(*v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusFail)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusFail)
|
||||
}
|
||||
|
||||
return ruleResponse(*v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func (v *validator) getDenyMessage(deny bool) string {
|
||||
|
@ -526,7 +472,7 @@ func (v *validator) validatePodSecurity() *engineapi.RuleResponse {
|
|||
// Marshal pod metadata and spec
|
||||
podSpec, metadata, err := getSpec(v)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "Error while getting new resource", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "Error while getting new resource", err)
|
||||
}
|
||||
|
||||
pod := &corev1.Pod{
|
||||
|
@ -535,7 +481,7 @@ func (v *validator) validatePodSecurity() *engineapi.RuleResponse {
|
|||
}
|
||||
allowed, pssChecks, err := pss.EvaluatePod(v.podSecurity, pod)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, engineapi.Validation, "failed to parse pod security api version", err)
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to parse pod security api version", err)
|
||||
}
|
||||
podSecurityChecks := &engineapi.PodSecurityChecks{
|
||||
Level: v.podSecurity.Level,
|
||||
|
@ -544,12 +490,12 @@ func (v *validator) validatePodSecurity() *engineapi.RuleResponse {
|
|||
}
|
||||
if allowed {
|
||||
msg := fmt.Sprintf("Validation rule '%s' passed.", v.rule.Name)
|
||||
rspn := ruleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
|
||||
rspn := internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
|
||||
rspn.PodSecurityChecks = podSecurityChecks
|
||||
return rspn
|
||||
} else {
|
||||
msg := fmt.Sprintf(`Validation rule '%s' failed. It violates PodSecurity "%s:%s": %s`, v.rule.Name, v.podSecurity.Level, v.podSecurity.Version, pss.FormatChecksPrint(pssChecks))
|
||||
rspn := ruleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusFail)
|
||||
rspn := internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusFail)
|
||||
rspn.PodSecurityChecks = podSecurityChecks
|
||||
return rspn
|
||||
}
|
||||
|
@ -619,22 +565,22 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
|
||||
|
||||
if pe.Skip {
|
||||
return ruleResponse(*v.rule, engineapi.Validation, pe.Error(), engineapi.RuleStatusSkip)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, pe.Error(), engineapi.RuleStatusSkip)
|
||||
}
|
||||
|
||||
if pe.Path == "" {
|
||||
return ruleResponse(*v.rule, engineapi.Validation, v.buildErrorMessage(err, ""), engineapi.RuleStatusError)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, v.buildErrorMessage(err, ""), engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
return ruleResponse(*v.rule, engineapi.Validation, v.buildErrorMessage(err, pe.Path), engineapi.RuleStatusFail)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, v.buildErrorMessage(err, pe.Path), engineapi.RuleStatusFail)
|
||||
}
|
||||
|
||||
return ruleResponse(*v.rule, engineapi.Validation, v.buildErrorMessage(err, pe.Path), engineapi.RuleStatusError)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, v.buildErrorMessage(err, pe.Path), engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
v.log.V(4).Info("successfully processed rule")
|
||||
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
|
||||
return ruleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
if v.anyPattern != nil {
|
||||
|
@ -645,14 +591,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 ruleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusError)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
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 ruleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
if pe, ok := err.(*validate.PatternError); ok {
|
||||
|
@ -681,7 +627,7 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
}
|
||||
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' skipped. %s", v.rule.Name, errorStr))
|
||||
return ruleResponse(*v.rule, engineapi.Validation, strings.Join(errorStr, " "), engineapi.RuleStatusSkip)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, strings.Join(errorStr, " "), engineapi.RuleStatusSkip)
|
||||
} else if len(failedAnyPatternsErrors) > 0 {
|
||||
var errorStr []string
|
||||
for _, err := range failedAnyPatternsErrors {
|
||||
|
@ -690,11 +636,11 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", v.rule.Name, errorStr))
|
||||
msg := buildAnyPatternErrorMessage(v.rule, errorStr)
|
||||
return ruleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusFail)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, msg, engineapi.RuleStatusFail)
|
||||
}
|
||||
}
|
||||
|
||||
return ruleResponse(*v.rule, engineapi.Validation, v.rule.Validation.Message, engineapi.RuleStatusPass)
|
||||
return internal.RuleResponse(*v.rule, engineapi.Validation, v.rule.Validation.Message, engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {
|
||||
|
|
Loading…
Add table
Reference in a new issue