mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
handle anchors in keys
This commit is contained in:
parent
44afdf2f95
commit
f3b644f624
5 changed files with 70 additions and 46 deletions
4
go.sum
4
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=
|
||||
|
|
|
@ -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 != "" {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue