diff --git a/go.sum b/go.sum index e51d9d3d8e..835f1b4a2f 100644 --- a/go.sum +++ b/go.sum @@ -170,6 +170,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= @@ -685,10 +686,13 @@ go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWK go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/pkg/engine/utils.go b/pkg/engine/utils.go index aa115daae0..a31ea07471 100644 --- a/pkg/engine/utils.go +++ b/pkg/engine/utils.go @@ -110,7 +110,7 @@ func doesResourceMatchConditionBlock(conditionBlock kyverno.ResourceDescription, var errs []error if len(conditionBlock.Kinds) > 0 { if !checkKind(conditionBlock.Kinds, resource.GetKind()) { - errs = append(errs, fmt.Errorf("kind does not match")) + errs = append(errs, fmt.Errorf("kind does not match %v", conditionBlock.Kinds)) } } if conditionBlock.Name != "" { diff --git a/pkg/engine/validate/validate.go b/pkg/engine/validate/validate.go index 3d0072ec61..359b1b1ebf 100644 --- a/pkg/engine/validate/validate.go +++ b/pkg/engine/validate/validate.go @@ -82,7 +82,6 @@ func validateResourceElement(log logr.Logger, resourceElement, patternElement, o // For each element of the map we must detect the type again, so we pass these elements to validateResourceElement func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{}, origPattern interface{}, path string, ac *common.AnchorKey) (string, error) { - // patternMap = wildcards.ExpandInMetadata(patternMap, resourceMap) // check if there is anchor in pattern diff --git a/pkg/engine/validate/validate_test.go b/pkg/engine/validate/validate_test.go index 048e0449ba..7e73c0a435 100644 --- a/pkg/engine/validate/validate_test.go +++ b/pkg/engine/validate/validate_test.go @@ -1360,42 +1360,50 @@ func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) { func TestValidateMapWildcardKeys(t *testing.T) { pattern := []byte(`{"metadata" : {"annotations": {"test/*": "value1"}}}`) resource := []byte(`{"metadata" : {"annotations": {"test/bar": "value1"}}}`) - testValidationPattern(t, pattern, resource, "", true) + testValidationPattern(t, "1", pattern, resource, "", true) pattern = []byte(`{"metadata" : {"annotations": {"test/b??": "v*"}}}`) resource = []byte(`{"metadata" : {"annotations": {"test/bar": "value1"}}}`) - testValidationPattern(t, pattern, resource, "", true) + testValidationPattern(t, "2", pattern, resource, "", true) pattern = []byte(`{}`) resource = []byte(`{"metadata" : {"annotations": {"test/bar": "value1"}}}`) - testValidationPattern(t, pattern, resource, "", true) + testValidationPattern(t, "3", pattern, resource, "", true) pattern = []byte(`{"metadata" : {"annotations": {"test/b??": "v*"}}}`) resource = []byte(`{"metadata" : {"labels": {"test/bar": "value1"}}}`) - testValidationPattern(t, pattern, resource, "/metadata/annotations/", false) + testValidationPattern(t, "4", pattern, resource, "/metadata/annotations/", false) pattern = []byte(`{"metadata" : {"labels": {"*/test": "foo"}}}`) resource = []byte(`{"metadata" : {"labels": {"foo/test": "foo"}}}`) - testValidationPattern(t, pattern, resource, "", true) + testValidationPattern(t, "5", pattern, resource, "", true) - pattern = []byte(`{"metadata" : {"labels": {"foo/123*": "bar"}}}`) - resource = []byte(`{"metadata" : {"labels": {"foo/12?": "bar", "foo/123": "bar"}}}`) - testValidationPattern(t, pattern, resource, "", true) + pattern = []byte(`{"metadata" : {"labels": {"foo/a*": "bar"}}}`) + resource = []byte(`{"metadata" : {"labels": {"foo/aa?": "bar", "foo/789": "bar"}}}`) + testValidationPattern(t, "6", pattern, resource, "", true) - pattern = []byte(`{"metadata" : {"labels": {"foo/123*": "bar"}}}`) - resource = []byte(`{"metadata" : {"labels": {"foo/12?": "bar", "foo/123": "bar2"}}}`) - testValidationPattern(t, pattern, resource, "/metadata/labels/foo/123*/", false) + pattern = []byte(`{"metadata" : {"labels": {"foo/ABC*": "bar"}}}`) + resource = []byte(`{"metadata" : {"labels": {"foo/AB?": "bar", "foo/ABC": "bar2"}}}`) + testValidationPattern(t, "7", pattern, resource, "/metadata/labels/foo/ABC/", false) - pattern = []byte(`{"metadata" : {"labels": {"foo/1*": "bar", "foo/4*": "bar2"}}}`) - resource = []byte(`{"metadata" : {"labels": {"foo/123": "bar", "foo/456": "bar2"}}}`) - testValidationPattern(t, pattern, resource, "", true) + pattern = []byte(`{"=(metadata)" : {"=(labels)": {"foo/P*": "bar", "foo/Q*": "bar2"}}}`) + resource = []byte(`{"metadata" : {"labels": {"foo/PQR": "bar", "foo/QR": "bar2"}}}`) + testValidationPattern(t, "8", pattern, resource, "", true) - pattern = []byte(`{"metadata" : {"labels": {"foo/1*": "bar", "foo/4*": "bar2"}}}`) + pattern = []byte(`{"metadata" : {"labels": {"foo/1*": "bar"}}}`) + resource = []byte(`{"metadata" : {"labels": {"foo/123": "bar222"}}}`) + testValidationPattern(t, "9", pattern, resource, "/metadata/labels/foo/123/", false) + + pattern = []byte(`{"metadata" : {"labels": {"foo/X*": "bar", "foo/A*": "bar2"}}}`) + resource = []byte(`{"metadata" : {"labels": {"foo/XYZ": "bar"}}}`) + testValidationPattern(t, "10", pattern, resource, "/metadata/labels/foo/A*/", false) + + pattern = []byte(`{"=(metadata)" : {"=(labels)": {"foo/1*": "bar", "foo/4*": "bar2"}}}`) resource = []byte(`{"metadata" : {"labels": {"foo/123": "bar"}}}`) - testValidationPattern(t, pattern, resource, "/metadata/labels/foo/4*/", false) + testValidationPattern(t, "11", pattern, resource, "/metadata/labels/foo/4*/", false) } -func testValidationPattern(t *testing.T, patternBytes []byte, resourceBytes []byte, path string, nilErr bool) { +func testValidationPattern(t *testing.T, num string, patternBytes []byte, resourceBytes []byte, path string, nilErr bool) { var pattern, resource interface{} err := json.Unmarshal(patternBytes, &pattern) assert.NilError(t, err) @@ -1403,10 +1411,10 @@ func testValidationPattern(t *testing.T, patternBytes []byte, resourceBytes []by assert.NilError(t, err) p, err := validateResourceElement(log.Log, resource, pattern, pattern, "/", common.NewAnchorMap()) - assert.Equal(t, p, path) + assert.Equal(t, p, path, num) if nilErr { - assert.NilError(t, err) + assert.NilError(t, err, num) } else { - assert.Assert(t, err != nil) + assert.Assert(t, err != nil, num) } } diff --git a/pkg/engine/wildcards/wildcards.go b/pkg/engine/wildcards/wildcards.go index 872f5a2010..4cc71637ae 100644 --- a/pkg/engine/wildcards/wildcards.go +++ b/pkg/engine/wildcards/wildcards.go @@ -18,7 +18,7 @@ func replaceWildcardsInMap(patternMap map[string]string, resourceMap map[string] result := map[string]string{} for k, v := range patternMap { if hasWildcards(k) || hasWildcards(v) { - matchK, matchV := expandWildcards(k, v, resourceMap, true) + matchK, matchV := expandWildcards(k, v, resourceMap, true, true) result[matchK] = matchV } else { result[k] = v @@ -32,10 +32,12 @@ func hasWildcards(s string) bool { return strings.Contains(s, "*") || strings.Contains(s, "?") } -func expandWildcards(k, v string, resourceMap map[string]string, replace bool) (key string, val string) { +func expandWildcards(k, v string, resourceMap map[string]string, matchValue, replace bool) (key string, val string) { for k1, v1 := range resourceMap { if wildcard.Match(k, k1) { - if wildcard.Match(v, v1) { + if !matchValue { + return k1, v1 + } else if wildcard.Match(v, v1) { return k1, v1 } } @@ -62,7 +64,7 @@ func replaceWildCardChars(s string) string { // here, as they are evaluated separately while processing the validation pattern. func ExpandInMetadata(patternMap, resourceMap map[string]interface{}) map[string]interface{} { - patternMetadata := patternMap["metadata"] + _, patternMetadata := getPatternValue("metadata", patternMap) if patternMetadata == nil { return patternMap } @@ -73,53 +75,64 @@ func ExpandInMetadata(patternMap, resourceMap map[string]interface{}) map[string } metadata := patternMetadata.(map[string]interface{}) - labels := expandWildcardsInTag("labels", patternMetadata, resourceMetadata) + labelsKey, labels := expandWildcardsInTag("labels", patternMetadata, resourceMetadata) if labels != nil { - metadata["labels"] = labels + metadata[labelsKey] = labels } - annotations := expandWildcardsInTag("annotations", patternMetadata, resourceMetadata) + annotationsKey, annotations := expandWildcardsInTag("annotations", patternMetadata, resourceMetadata) if annotations != nil { - metadata["annotations"] = annotations + metadata[annotationsKey] = annotations } return patternMap } -func expandWildcardsInTag(tag string, patternMetadata, resourceMetadata interface{}) map[string]interface{} { - patternData := getValueAsStringMap(tag, patternMetadata) - if patternData == nil { - return nil +func getPatternValue(tag string, pattern map[string]interface{}) (string, interface{}) { + for k, v := range pattern { + if commonAnchor.RemoveAnchor(k) == tag { + return k, v + } } - resourceData := getValueAsStringMap(tag, resourceMetadata) + return "", nil +} + +func expandWildcardsInTag(tag string, patternMetadata, resourceMetadata interface{}) (string, map[string]interface{}) { + patternKey, patternData := getValueAsStringMap(tag, patternMetadata) + if patternData == nil { + return "", nil + } + + _, resourceData := getValueAsStringMap(tag, resourceMetadata) if resourceData == nil { - return nil + return "", nil } results := map[string]interface{}{} for k, v := range patternData { if hasWildcards(k) { - newKey := commonAnchor.RemoveAnchor(k) - matchK, _ := expandWildcards(newKey, v, resourceData, false) - matchK = strings.Replace(k, newKey, matchK, 1) + anchorFreeKey := commonAnchor.RemoveAnchor(k) + matchK, _ := expandWildcards(anchorFreeKey, v, resourceData, false, false) results[matchK] = v } else { results[k] = v } } - return results + return patternKey, results } -func getValueAsStringMap(key string, dataMap interface{}) map[string]string { - if dataMap == nil { - return nil +func getValueAsStringMap(key string, data interface{}) (string, map[string]string) { + if data == nil { + return "", nil } - val := dataMap.(map[string]interface{})[key] + dataMap := data.(map[string]interface{}) + patternKey, val := getPatternValue(key, dataMap) + if val == nil { - return nil + return "", nil } result := map[string]string{} @@ -127,5 +140,5 @@ func getValueAsStringMap(key string, dataMap interface{}) map[string]string { result[k] = v.(string) } - return result + return patternKey, result }