Skip to content

Commit

Permalink
allow wildcards in condition values
Browse files Browse the repository at this point in the history
  • Loading branch information
JimBugwadia committed Nov 29, 2020
1 parent ec95724 commit e67779e
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 51 deletions.
21 changes: 11 additions & 10 deletions pkg/engine/variables/operator/equal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package operator

import (
"fmt"
"github.com/minio/minio/pkg/wildcard"
"math"
"reflect"
"strconv"
Expand Down Expand Up @@ -45,15 +46,15 @@ func (eh EqualHandler) Evaluate(key, value interface{}) bool {
// key and value need to be of same type
switch typedKey := key.(type) {
case bool:
return eh.validateValuewithBoolPattern(typedKey, value)
return eh.validateValueWithBoolPattern(typedKey, value)
case int:
return eh.validateValuewithIntPattern(int64(typedKey), value)
return eh.validateValueWithIntPattern(int64(typedKey), value)
case int64:
return eh.validateValuewithIntPattern(typedKey, value)
return eh.validateValueWithIntPattern(typedKey, value)
case float64:
return eh.validateValuewithFloatPattern(typedKey, value)
return eh.validateValueWithFloatPattern(typedKey, value)
case string:
return eh.validateValuewithStringPattern(typedKey, value)
return eh.validateValueWithStringPattern(typedKey, value)
case map[string]interface{}:
return eh.validateValueWithMapPattern(typedKey, value)
case []interface{}:
Expand All @@ -80,16 +81,16 @@ func (eh EqualHandler) validateValueWithMapPattern(key map[string]interface{}, v
return false
}

func (eh EqualHandler) validateValuewithStringPattern(key string, value interface{}) bool {
func (eh EqualHandler) validateValueWithStringPattern(key string, value interface{}) bool {
if val, ok := value.(string); ok {
return key == val
return wildcard.Match(key, val)
}

eh.log.Info("Expected type string", "value", value, "type", fmt.Sprintf("%T", value))
return false
}

func (eh EqualHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
func (eh EqualHandler) validateValueWithFloatPattern(key float64, value interface{}) bool {
switch typedValue := value.(type) {
case int:
// check that float has not fraction
Expand Down Expand Up @@ -120,7 +121,7 @@ func (eh EqualHandler) validateValuewithFloatPattern(key float64, value interfac
return false
}

func (eh EqualHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
func (eh EqualHandler) validateValueWithBoolPattern(key bool, value interface{}) bool {
typedValue, ok := value.(bool)
if !ok {
eh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value))
Expand All @@ -129,7 +130,7 @@ func (eh EqualHandler) validateValuewithBoolPattern(key bool, value interface{})
return key == typedValue
}

func (eh EqualHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
func (eh EqualHandler) validateValueWithIntPattern(key int64, value interface{}) bool {
switch typedValue := value.(type) {
case int:
return int64(typedValue) == key
Expand Down
66 changes: 38 additions & 28 deletions pkg/engine/variables/operator/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package operator
import (
"encoding/json"
"fmt"
"reflect"
"github.com/minio/minio/pkg/wildcard"

"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/engine/context"
Expand Down Expand Up @@ -40,15 +40,15 @@ func (in InHandler) Evaluate(key, value interface{}) bool {

switch typedKey := key.(type) {
case string:
return in.validateValuewithStringPattern(typedKey, value)
return in.validateValueWithStringPattern(typedKey, value)
default:
in.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
return false
}
}

func (in InHandler) validateValuewithStringPattern(key string, value interface{}) (keyExists bool) {
invalidType, keyExists := ValidateStringPattern(key, value, in.log)
func (in InHandler) validateValueWithStringPattern(key string, value interface{}) (keyExists bool) {
invalidType, keyExists := keyExistsInArray(key, value, in.log)
if invalidType {
in.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
return false
Expand All @@ -57,60 +57,70 @@ func (in InHandler) validateValuewithStringPattern(key string, value interface{}
return keyExists
}

// ValidateStringPattern ...
func ValidateStringPattern(key string, value interface{}, log logr.Logger) (invalidType bool, keyExists bool) {
stringType := reflect.TypeOf("")
switch valuesAvaliable := value.(type) {
// keyExistsInArray checks if the key exists in the array value
// The value can be a string, an array of strings, or a JSON format
// array of strings (e.g. ["val1", "val2", "val3"].
func keyExistsInArray(key string, value interface{}, log logr.Logger) (invalidType bool, keyExists bool) {
switch valuesAvailable := value.(type) {

case []interface{}:
for _, val := range valuesAvaliable {
if reflect.TypeOf(val) != stringType {
return true, false
}
if key == val {
keyExists = true
invalidType = false
for _, val := range valuesAvailable {
if v, ok := val.(string); ok {
if wildcard.Match(key, v) {
keyExists = true
return
}
}
}

// add to handle the configMap lookup, as configmap.data
// takes string-string map, when looking for a value of array
// data:
// key: "[\"value1\", \"value2\"]"
// it will first unmarshal it to string slice, then compare
case string:

if wildcard.Match(key, valuesAvailable) {
keyExists = true
return
}

var arr []string
if err := json.Unmarshal([]byte(valuesAvaliable), &arr); err != nil {
if err := json.Unmarshal([]byte(valuesAvailable), &arr); err != nil {
log.Error(err, "failed to unmarshal to string slice", "value", value)
return invalidType, keyExists
invalidType = true
return
}

for _, val := range arr {
if key == val {
keyExists = true
return
}
}

default:
return true, false
invalidType = true
return
}

return invalidType, keyExists
invalidType = true
keyExists = false
return
}

func (in InHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
func (in InHandler) validateValueWithBoolPattern(_ bool, _ interface{}) bool {
return false
}

func (in InHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
func (in InHandler) validateValueWithIntPattern(_ int64, _ interface{}) bool {
return false
}

func (in InHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
func (in InHandler) validateValueWithFloatPattern(_ float64, _ interface{}) bool {
return false
}

func (in InHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
func (in InHandler) validateValueWithMapPattern(_ map[string]interface{}, _ interface{}) bool {
return false
}

func (in InHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
func (in InHandler) validateValueWithSlicePattern(_ []interface{}, _ interface{}) bool {
return false
}
21 changes: 11 additions & 10 deletions pkg/engine/variables/operator/notequal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package operator

import (
"fmt"
"github.com/minio/minio/pkg/wildcard"
"math"
"reflect"
"strconv"
Expand Down Expand Up @@ -44,15 +45,15 @@ func (neh NotEqualHandler) Evaluate(key, value interface{}) bool {
// key and value need to be of same type
switch typedKey := key.(type) {
case bool:
return neh.validateValuewithBoolPattern(typedKey, value)
return neh.validateValueWithBoolPattern(typedKey, value)
case int:
return neh.validateValuewithIntPattern(int64(typedKey), value)
return neh.validateValueWithIntPattern(int64(typedKey), value)
case int64:
return neh.validateValuewithIntPattern(typedKey, value)
return neh.validateValueWithIntPattern(typedKey, value)
case float64:
return neh.validateValuewithFloatPattern(typedKey, value)
return neh.validateValueWithFloatPattern(typedKey, value)
case string:
return neh.validateValuewithStringPattern(typedKey, value)
return neh.validateValueWithStringPattern(typedKey, value)
case map[string]interface{}:
return neh.validateValueWithMapPattern(typedKey, value)
case []interface{}:
Expand All @@ -79,15 +80,15 @@ func (neh NotEqualHandler) validateValueWithMapPattern(key map[string]interface{
return false
}

func (neh NotEqualHandler) validateValuewithStringPattern(key string, value interface{}) bool {
func (neh NotEqualHandler) validateValueWithStringPattern(key string, value interface{}) bool {
if val, ok := value.(string); ok {
return key != val
return !wildcard.Match(key, val)
}
neh.log.Info("Expected type string", "value", value, "type", fmt.Sprintf("%T", value))
return false
}

func (neh NotEqualHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
func (neh NotEqualHandler) validateValueWithFloatPattern(key float64, value interface{}) bool {
switch typedValue := value.(type) {
case int:
// check that float has not fraction
Expand Down Expand Up @@ -118,7 +119,7 @@ func (neh NotEqualHandler) validateValuewithFloatPattern(key float64, value inte
return false
}

func (neh NotEqualHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
func (neh NotEqualHandler) validateValueWithBoolPattern(key bool, value interface{}) bool {
typedValue, ok := value.(bool)
if !ok {
neh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value))
Expand All @@ -127,7 +128,7 @@ func (neh NotEqualHandler) validateValuewithBoolPattern(key bool, value interfac
return key != typedValue
}

func (neh NotEqualHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
func (neh NotEqualHandler) validateValueWithIntPattern(key int64, value interface{}) bool {
switch typedValue := value.(type) {
case int:
return int64(typedValue) != key
Expand Down
7 changes: 4 additions & 3 deletions pkg/engine/variables/operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
//OperatorHandler provides interface to manage types
type OperatorHandler interface {
Evaluate(key, value interface{}) bool
validateValuewithBoolPattern(key bool, value interface{}) bool
validateValuewithIntPattern(key int64, value interface{}) bool
validateValuewithFloatPattern(key float64, value interface{}) bool
validateValueWithStringPattern(key string, value interface{}) bool
validateValueWithBoolPattern(key bool, value interface{}) bool
validateValueWithIntPattern(key int64, value interface{}) bool
validateValueWithFloatPattern(key float64, value interface{}) bool
validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool
validateValueWithSlicePattern(key []interface{}, value interface{}) bool
}
Expand Down

0 comments on commit e67779e

Please sign in to comment.