mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
refactor: move common utils (#3553)
Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
3bc0e062f9
commit
29d7010e25
8 changed files with 121 additions and 131 deletions
|
@ -9,25 +9,22 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
|
||||||
|
|
||||||
"github.com/sigstore/cosign/cmd/cosign/cli/rekor"
|
|
||||||
|
|
||||||
"github.com/sigstore/cosign/cmd/cosign/cli/fulcio"
|
|
||||||
"github.com/sigstore/cosign/pkg/oci/remote"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"github.com/google/go-containerregistry/pkg/name"
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
"github.com/in-toto/in-toto-golang/in_toto"
|
"github.com/in-toto/in-toto-golang/in_toto"
|
||||||
wildcard "github.com/kyverno/go-wildcard"
|
wildcard "github.com/kyverno/go-wildcard"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
|
"github.com/kyverno/kyverno/pkg/utils"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sigstore/cosign/cmd/cosign/cli/fulcio"
|
||||||
"github.com/sigstore/cosign/cmd/cosign/cli/options"
|
"github.com/sigstore/cosign/cmd/cosign/cli/options"
|
||||||
|
"github.com/sigstore/cosign/cmd/cosign/cli/rekor"
|
||||||
"github.com/sigstore/cosign/pkg/cosign"
|
"github.com/sigstore/cosign/pkg/cosign"
|
||||||
"github.com/sigstore/cosign/pkg/cosign/attestation"
|
"github.com/sigstore/cosign/pkg/cosign/attestation"
|
||||||
"github.com/sigstore/cosign/pkg/oci"
|
"github.com/sigstore/cosign/pkg/oci"
|
||||||
|
"github.com/sigstore/cosign/pkg/oci/remote"
|
||||||
sigs "github.com/sigstore/cosign/pkg/signature"
|
sigs "github.com/sigstore/cosign/pkg/signature"
|
||||||
"github.com/sigstore/sigstore/pkg/cryptoutils"
|
"github.com/sigstore/sigstore/pkg/cryptoutils"
|
||||||
"github.com/sigstore/sigstore/pkg/signature"
|
"github.com/sigstore/sigstore/pkg/signature"
|
||||||
|
@ -269,7 +266,7 @@ func decodeStatement(payloadBase64 string) (map[string]interface{}, error) {
|
||||||
// - in_toto.PredicateLinkV1
|
// - in_toto.PredicateLinkV1
|
||||||
// - in_toto.PredicateSPDX
|
// - in_toto.PredicateSPDX
|
||||||
// any other custom predicate
|
// any other custom predicate
|
||||||
return common.ToMap(statement)
|
return utils.ToMap(statement)
|
||||||
}
|
}
|
||||||
|
|
||||||
return decodeCosignCustomProvenanceV01(statement)
|
return decodeCosignCustomProvenanceV01(statement)
|
||||||
|
@ -297,7 +294,7 @@ func decodeCosignCustomProvenanceV01(statement in_toto.Statement) (map[string]in
|
||||||
statement.Predicate = predicate
|
statement.Predicate = predicate
|
||||||
}
|
}
|
||||||
|
|
||||||
return common.ToMap(statement)
|
return utils.ToMap(statement)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringToJSONMap(i interface{}) (map[string]interface{}, error) {
|
func stringToJSONMap(i interface{}) (map[string]interface{}, error) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
@ -10,53 +9,6 @@ import (
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CopyMap creates a full copy of the target map
|
|
||||||
func CopyMap(m map[string]interface{}) map[string]interface{} {
|
|
||||||
mapCopy := make(map[string]interface{})
|
|
||||||
for k, v := range m {
|
|
||||||
mapCopy[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopySlice creates a full copy of the target slice
|
|
||||||
func CopySlice(s []interface{}) []interface{} {
|
|
||||||
sliceCopy := make([]interface{}, len(s))
|
|
||||||
copy(sliceCopy, s)
|
|
||||||
|
|
||||||
return sliceCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopySliceOfMaps creates a full copy of the target slice
|
|
||||||
func CopySliceOfMaps(s []map[string]interface{}) []interface{} {
|
|
||||||
sliceCopy := make([]interface{}, len(s))
|
|
||||||
for i, v := range s {
|
|
||||||
sliceCopy[i] = CopyMap(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sliceCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToMap(data interface{}) (map[string]interface{}, error) {
|
|
||||||
if m, ok := data.(map[string]interface{}); ok {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mapData := make(map[string]interface{})
|
|
||||||
err = json.Unmarshal(b, &mapData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRawKeyIfWrappedWithAttributes(str string) string {
|
func GetRawKeyIfWrappedWithAttributes(str string) string {
|
||||||
if len(str) < 2 {
|
if len(str) < 2 {
|
||||||
return str
|
return str
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gotest.tools/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_OriginalMapMustNotBeChanged(t *testing.T) {
|
|
||||||
// no variables
|
|
||||||
originalMap := map[string]interface{}{
|
|
||||||
"rsc": 3711,
|
|
||||||
"r": 2138,
|
|
||||||
"gri": 1908,
|
|
||||||
"adg": 912,
|
|
||||||
}
|
|
||||||
|
|
||||||
mapCopy := CopyMap(originalMap)
|
|
||||||
mapCopy["r"] = 1
|
|
||||||
|
|
||||||
assert.Equal(t, originalMap["r"], 2138)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_OriginalSliceMustNotBeChanged(t *testing.T) {
|
|
||||||
// no variables
|
|
||||||
originalSlice := []interface{}{
|
|
||||||
3711,
|
|
||||||
2138,
|
|
||||||
1908,
|
|
||||||
912,
|
|
||||||
}
|
|
||||||
|
|
||||||
sliceCopy := CopySlice(originalSlice)
|
|
||||||
sliceCopy[0] = 1
|
|
||||||
|
|
||||||
assert.Equal(t, originalSlice[0], 3711)
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
"github.com/kyverno/kyverno/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActionData represents data available for action on current element
|
// ActionData represents data available for action on current element
|
||||||
|
@ -69,13 +69,13 @@ func (t *Traversal) traverseJSON(element interface{}, path string) (interface{},
|
||||||
// traverse further
|
// traverse further
|
||||||
switch typed := element.(type) {
|
switch typed := element.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
return t.traverseObject(common.CopyMap(typed), path)
|
return t.traverseObject(utils.CopyMap(typed), path)
|
||||||
|
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
return t.traverseList(common.CopySlice(typed), path)
|
return t.traverseList(utils.CopySlice(typed), path)
|
||||||
|
|
||||||
case []map[string]interface{}:
|
case []map[string]interface{}:
|
||||||
return t.traverseList(common.CopySliceOfMaps(typed), path)
|
return t.traverseList(utils.CopySliceOfMaps(typed), path)
|
||||||
|
|
||||||
case Key:
|
case Key:
|
||||||
return typed.Key, nil
|
return typed.Key, nil
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
|
||||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/mutate/patch"
|
"github.com/kyverno/kyverno/pkg/engine/mutate/patch"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||||
|
"github.com/kyverno/kyverno/pkg/utils"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func ForEach(name string, foreach *kyverno.ForEachMutation, ctx *context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func substituteAllInForEach(fe *kyverno.ForEachMutation, ctx *context.Context, logger logr.Logger) (*kyverno.ForEachMutation, error) {
|
func substituteAllInForEach(fe *kyverno.ForEachMutation, ctx *context.Context, logger logr.Logger) (*kyverno.ForEachMutation, error) {
|
||||||
jsonObj, err := common.ToMap(fe)
|
jsonObj, err := utils.ToMap(fe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@ import (
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
gojmespath "github.com/jmespath/go-jmespath"
|
gojmespath "github.com/jmespath/go-jmespath"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/validate"
|
"github.com/kyverno/kyverno/pkg/engine/validate"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||||
|
"github.com/kyverno/kyverno/pkg/utils"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
)
|
)
|
||||||
|
@ -179,7 +180,7 @@ func newValidator(log logr.Logger, ctx *PolicyContext, rule *kyverno.Rule) *vali
|
||||||
|
|
||||||
func newForeachValidator(foreach *kyverno.ForEachValidation, rule *kyverno.Rule, ctx *PolicyContext, log logr.Logger) *validator {
|
func newForeachValidator(foreach *kyverno.ForEachValidation, rule *kyverno.Rule, ctx *PolicyContext, log logr.Logger) *validator {
|
||||||
ruleCopy := rule.DeepCopy()
|
ruleCopy := rule.DeepCopy()
|
||||||
anyAllConditions, err := common.ToMap(foreach.AnyAllConditions)
|
anyAllConditions, err := utils.ToMap(foreach.AnyAllConditions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "failed to convert ruleCopy.Validation.ForEachValidation.AnyAllConditions")
|
log.Error(err, "failed to convert ruleCopy.Validation.ForEachValidation.AnyAllConditions")
|
||||||
}
|
}
|
||||||
|
@ -198,16 +199,16 @@ func newForeachValidator(foreach *kyverno.ForEachValidation, rule *kyverno.Rule,
|
||||||
|
|
||||||
func (v *validator) validate() *response.RuleResponse {
|
func (v *validator) validate() *response.RuleResponse {
|
||||||
if err := v.loadContext(); err != nil {
|
if err := v.loadContext(); err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to load context", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to load context", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
preconditionsPassed, err := checkPreconditions(v.log, v.ctx, v.anyAllConditions)
|
preconditionsPassed, err := checkPreconditions(v.log, v.ctx, v.anyAllConditions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to evaluate preconditions", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to evaluate preconditions", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !preconditionsPassed && v.ctx.Policy.GetSpec().ValidationFailureAction != kyverno.Audit {
|
if !preconditionsPassed && v.ctx.Policy.GetSpec().ValidationFailureAction != kyverno.Audit {
|
||||||
return ruleResponse(v.rule, utils.Validation, "preconditions not met", response.RuleStatusSkip)
|
return ruleResponse(v.rule, engineutils.Validation, "preconditions not met", response.RuleStatusSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.deny != nil {
|
if v.deny != nil {
|
||||||
|
@ -216,14 +217,14 @@ func (v *validator) validate() *response.RuleResponse {
|
||||||
|
|
||||||
if v.pattern != nil || v.anyPattern != nil {
|
if v.pattern != nil || v.anyPattern != nil {
|
||||||
if err = v.substitutePatterns(); err != nil {
|
if err = v.substitutePatterns(); err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "variable substitution failed", err)
|
return ruleError(v.rule, engineutils.Validation, "variable substitution failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleResponse := v.validateResourceWithRule()
|
ruleResponse := v.validateResourceWithRule()
|
||||||
if isUpdateRequest(v.ctx) {
|
if isUpdateRequest(v.ctx) {
|
||||||
priorResp, err := validateOldObject(v.log, v.ctx, v.rule)
|
priorResp, err := validateOldObject(v.log, v.ctx, v.rule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to validate old object", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to validate old object", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSameRuleResponse(ruleResponse, priorResp) {
|
if isSameRuleResponse(ruleResponse, priorResp) {
|
||||||
|
@ -241,14 +242,14 @@ func (v *validator) validate() *response.RuleResponse {
|
||||||
|
|
||||||
func (v *validator) validateForEach() *response.RuleResponse {
|
func (v *validator) validateForEach() *response.RuleResponse {
|
||||||
if err := v.loadContext(); err != nil {
|
if err := v.loadContext(); err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to load context", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to load context", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
preconditionsPassed, err := checkPreconditions(v.log, v.ctx, v.anyAllConditions)
|
preconditionsPassed, err := checkPreconditions(v.log, v.ctx, v.anyAllConditions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to evaluate preconditions", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to evaluate preconditions", err)
|
||||||
} else if !preconditionsPassed && v.ctx.Policy.GetSpec().ValidationFailureAction != kyverno.Audit {
|
} else if !preconditionsPassed && v.ctx.Policy.GetSpec().ValidationFailureAction != kyverno.Audit {
|
||||||
return ruleResponse(v.rule, utils.Validation, "preconditions not met", response.RuleStatusSkip)
|
return ruleResponse(v.rule, engineutils.Validation, "preconditions not met", response.RuleStatusSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
foreachList := v.rule.Validation.ForEachValidation
|
foreachList := v.rule.Validation.ForEachValidation
|
||||||
|
@ -278,10 +279,10 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
if applyCount == 0 {
|
if applyCount == 0 {
|
||||||
return ruleResponse(v.rule, utils.Validation, "rule skipped", response.RuleStatusSkip)
|
return ruleResponse(v.rule, engineutils.Validation, "rule skipped", response.RuleStatusSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleResponse(v.rule, utils.Validation, "rule passed", response.RuleStatusPass)
|
return ruleResponse(v.rule, engineutils.Validation, "rule passed", response.RuleStatusPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *validator) validateElements(foreach *kyverno.ForEachValidation, elements []interface{}, elementScope bool) (*response.RuleResponse, int) {
|
func (v *validator) validateElements(foreach *kyverno.ForEachValidation, elements []interface{}, elementScope bool) (*response.RuleResponse, int) {
|
||||||
|
@ -295,7 +296,7 @@ func (v *validator) validateElements(foreach *kyverno.ForEachValidation, element
|
||||||
ctx := v.ctx.Copy()
|
ctx := v.ctx.Copy()
|
||||||
if err := addElementToContext(ctx, e, i, elementScope); err != nil {
|
if err := addElementToContext(ctx, e, i, elementScope); err != nil {
|
||||||
v.log.Error(err, "failed to add element to context")
|
v.log.Error(err, "failed to add element to context")
|
||||||
return ruleError(v.rule, utils.Validation, "failed to process foreach", err), applyCount
|
return ruleError(v.rule, engineutils.Validation, "failed to process foreach", err), applyCount
|
||||||
}
|
}
|
||||||
|
|
||||||
foreachValidator := newForeachValidator(foreach, v.rule, ctx, v.log)
|
foreachValidator := newForeachValidator(foreach, v.rule, ctx, v.log)
|
||||||
|
@ -308,17 +309,17 @@ func (v *validator) validateElements(foreach *kyverno.ForEachValidation, element
|
||||||
continue
|
continue
|
||||||
} else if r.Status != response.RuleStatusPass {
|
} else if r.Status != response.RuleStatusPass {
|
||||||
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
||||||
return ruleResponse(v.rule, utils.Validation, msg, r.Status), applyCount
|
return ruleResponse(v.rule, engineutils.Validation, msg, r.Status), applyCount
|
||||||
}
|
}
|
||||||
|
|
||||||
applyCount++
|
applyCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleResponse(v.rule, utils.Validation, "", response.RuleStatusPass), applyCount
|
return ruleResponse(v.rule, engineutils.Validation, "", response.RuleStatusPass), applyCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, elementScope bool) error {
|
func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, elementScope bool) error {
|
||||||
data, err := common.ToMap(e)
|
data, err := utils.ToMap(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -359,24 +360,24 @@ func (v *validator) validateDeny() *response.RuleResponse {
|
||||||
anyAllCond := v.deny.GetAnyAllConditions()
|
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 {
|
if err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to substitute variables in deny conditions", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to substitute variables in deny conditions", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = v.substituteDeny(); err != nil {
|
if err = v.substituteDeny(); err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "failed to substitute variables in rule", err)
|
return ruleError(v.rule, engineutils.Validation, "failed to substitute variables in rule", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
denyConditions, err := common.TransformConditions(anyAllCond)
|
denyConditions, err := common.TransformConditions(anyAllCond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleError(v.rule, utils.Validation, "invalid deny conditions", err)
|
return ruleError(v.rule, engineutils.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 {
|
if deny {
|
||||||
return ruleResponse(v.rule, utils.Validation, v.getDenyMessage(deny), response.RuleStatusFail)
|
return ruleResponse(v.rule, engineutils.Validation, v.getDenyMessage(deny), response.RuleStatusFail)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleResponse(v.rule, utils.Validation, v.getDenyMessage(deny), response.RuleStatusPass)
|
return ruleResponse(v.rule, engineutils.Validation, v.getDenyMessage(deny), response.RuleStatusPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *validator) getDenyMessage(deny bool) string {
|
func (v *validator) getDenyMessage(deny bool) string {
|
||||||
|
@ -480,22 +481,22 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
|
||||||
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
|
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
|
||||||
|
|
||||||
if pe.Skip {
|
if pe.Skip {
|
||||||
return ruleResponse(v.rule, utils.Validation, pe.Error(), response.RuleStatusSkip)
|
return ruleResponse(v.rule, engineutils.Validation, pe.Error(), response.RuleStatusSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pe.Path == "" {
|
if pe.Path == "" {
|
||||||
return ruleResponse(v.rule, utils.Validation, v.buildErrorMessage(err, ""), response.RuleStatusError)
|
return ruleResponse(v.rule, engineutils.Validation, v.buildErrorMessage(err, ""), response.RuleStatusError)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleResponse(v.rule, utils.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusFail)
|
return ruleResponse(v.rule, engineutils.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusFail)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleResponse(v.rule, utils.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusError)
|
return ruleResponse(v.rule, engineutils.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusError)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.log.V(4).Info("successfully processed rule")
|
v.log.V(4).Info("successfully processed rule")
|
||||||
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
|
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
|
||||||
return ruleResponse(v.rule, utils.Validation, msg, response.RuleStatusPass)
|
return ruleResponse(v.rule, engineutils.Validation, msg, response.RuleStatusPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.anyPattern != nil {
|
if v.anyPattern != nil {
|
||||||
|
@ -505,14 +506,14 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
|
||||||
anyPatterns, err := deserializeAnyPattern(v.anyPattern)
|
anyPatterns, err := deserializeAnyPattern(v.anyPattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("failed to deserialize anyPattern, expected type array: %v", err)
|
msg := fmt.Sprintf("failed to deserialize anyPattern, expected type array: %v", err)
|
||||||
return ruleResponse(v.rule, utils.Validation, msg, response.RuleStatusError)
|
return ruleResponse(v.rule, engineutils.Validation, msg, response.RuleStatusError)
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, pattern := range anyPatterns {
|
for idx, pattern := range anyPatterns {
|
||||||
err := validate.MatchPattern(v.log, resource.Object, pattern)
|
err := validate.MatchPattern(v.log, resource.Object, pattern)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
||||||
return ruleResponse(v.rule, utils.Validation, msg, response.RuleStatusPass)
|
return ruleResponse(v.rule, engineutils.Validation, msg, response.RuleStatusPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pe, ok := err.(*validate.PatternError); ok {
|
if pe, ok := err.(*validate.PatternError); ok {
|
||||||
|
@ -536,11 +537,11 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
|
||||||
|
|
||||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", v.rule.Name, errorStr))
|
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", v.rule.Name, errorStr))
|
||||||
msg := buildAnyPatternErrorMessage(v.rule, errorStr)
|
msg := buildAnyPatternErrorMessage(v.rule, errorStr)
|
||||||
return ruleResponse(v.rule, utils.Validation, msg, response.RuleStatusFail)
|
return ruleResponse(v.rule, engineutils.Validation, msg, response.RuleStatusFail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ruleResponse(v.rule, utils.Validation, v.rule.Validation.Message, response.RuleStatusPass)
|
return ruleResponse(v.rule, engineutils.Validation, v.rule.Validation.Message, response.RuleStatusPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {
|
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {
|
||||||
|
|
|
@ -25,6 +25,53 @@ import (
|
||||||
|
|
||||||
var regexVersion = regexp.MustCompile(`v(\d+).(\d+).(\d+)\.*`)
|
var regexVersion = regexp.MustCompile(`v(\d+).(\d+).(\d+)\.*`)
|
||||||
|
|
||||||
|
// CopyMap creates a full copy of the target map
|
||||||
|
func CopyMap(m map[string]interface{}) map[string]interface{} {
|
||||||
|
mapCopy := make(map[string]interface{})
|
||||||
|
for k, v := range m {
|
||||||
|
mapCopy[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopySlice creates a full copy of the target slice
|
||||||
|
func CopySlice(s []interface{}) []interface{} {
|
||||||
|
sliceCopy := make([]interface{}, len(s))
|
||||||
|
copy(sliceCopy, s)
|
||||||
|
|
||||||
|
return sliceCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopySliceOfMaps creates a full copy of the target slice
|
||||||
|
func CopySliceOfMaps(s []map[string]interface{}) []interface{} {
|
||||||
|
sliceCopy := make([]interface{}, len(s))
|
||||||
|
for i, v := range s {
|
||||||
|
sliceCopy[i] = CopyMap(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sliceCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToMap(data interface{}) (map[string]interface{}, error) {
|
||||||
|
if m, ok := data.(map[string]interface{}); ok {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mapData := make(map[string]interface{})
|
||||||
|
err = json.Unmarshal(b, &mapData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapData, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Contains checks if a string is contained in a list of string
|
// Contains checks if a string is contained in a list of string
|
||||||
func contains(list []string, element string, fn func(string, string) bool) bool {
|
func contains(list []string, element string, fn func(string, string) bool) bool {
|
||||||
for _, e := range list {
|
for _, e := range list {
|
||||||
|
|
|
@ -6,6 +6,36 @@ import (
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Test_OriginalMapMustNotBeChanged(t *testing.T) {
|
||||||
|
// no variables
|
||||||
|
originalMap := map[string]interface{}{
|
||||||
|
"rsc": 3711,
|
||||||
|
"r": 2138,
|
||||||
|
"gri": 1908,
|
||||||
|
"adg": 912,
|
||||||
|
}
|
||||||
|
|
||||||
|
mapCopy := CopyMap(originalMap)
|
||||||
|
mapCopy["r"] = 1
|
||||||
|
|
||||||
|
assert.Equal(t, originalMap["r"], 2138)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_OriginalSliceMustNotBeChanged(t *testing.T) {
|
||||||
|
// no variables
|
||||||
|
originalSlice := []interface{}{
|
||||||
|
3711,
|
||||||
|
2138,
|
||||||
|
1908,
|
||||||
|
912,
|
||||||
|
}
|
||||||
|
|
||||||
|
sliceCopy := CopySlice(originalSlice)
|
||||||
|
sliceCopy[0] = 1
|
||||||
|
|
||||||
|
assert.Equal(t, originalSlice[0], 3711)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_allEmpty(t *testing.T) {
|
func Test_allEmpty(t *testing.T) {
|
||||||
var list []string
|
var list []string
|
||||||
var element string
|
var element string
|
||||||
|
|
Loading…
Reference in a new issue