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-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 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
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-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.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
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.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 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.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/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 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/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 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=
|
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-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/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
|
var errs []error
|
||||||
if len(conditionBlock.Kinds) > 0 {
|
if len(conditionBlock.Kinds) > 0 {
|
||||||
if !checkKind(conditionBlock.Kinds, resource.GetKind()) {
|
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 != "" {
|
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
|
// 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) {
|
func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{}, origPattern interface{}, path string, ac *common.AnchorKey) (string, error) {
|
||||||
|
|
||||||
//
|
|
||||||
patternMap = wildcards.ExpandInMetadata(patternMap, resourceMap)
|
patternMap = wildcards.ExpandInMetadata(patternMap, resourceMap)
|
||||||
|
|
||||||
// check if there is anchor in pattern
|
// check if there is anchor in pattern
|
||||||
|
|
|
@ -1360,42 +1360,50 @@ func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) {
|
||||||
func TestValidateMapWildcardKeys(t *testing.T) {
|
func TestValidateMapWildcardKeys(t *testing.T) {
|
||||||
pattern := []byte(`{"metadata" : {"annotations": {"test/*": "value1"}}}`)
|
pattern := []byte(`{"metadata" : {"annotations": {"test/*": "value1"}}}`)
|
||||||
resource := []byte(`{"metadata" : {"annotations": {"test/bar": "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*"}}}`)
|
pattern = []byte(`{"metadata" : {"annotations": {"test/b??": "v*"}}}`)
|
||||||
resource = []byte(`{"metadata" : {"annotations": {"test/bar": "value1"}}}`)
|
resource = []byte(`{"metadata" : {"annotations": {"test/bar": "value1"}}}`)
|
||||||
testValidationPattern(t, pattern, resource, "", true)
|
testValidationPattern(t, "2", pattern, resource, "", true)
|
||||||
|
|
||||||
pattern = []byte(`{}`)
|
pattern = []byte(`{}`)
|
||||||
resource = []byte(`{"metadata" : {"annotations": {"test/bar": "value1"}}}`)
|
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*"}}}`)
|
pattern = []byte(`{"metadata" : {"annotations": {"test/b??": "v*"}}}`)
|
||||||
resource = []byte(`{"metadata" : {"labels": {"test/bar": "value1"}}}`)
|
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"}}}`)
|
pattern = []byte(`{"metadata" : {"labels": {"*/test": "foo"}}}`)
|
||||||
resource = []byte(`{"metadata" : {"labels": {"foo/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"}}}`)
|
pattern = []byte(`{"metadata" : {"labels": {"foo/a*": "bar"}}}`)
|
||||||
resource = []byte(`{"metadata" : {"labels": {"foo/12?": "bar", "foo/123": "bar"}}}`)
|
resource = []byte(`{"metadata" : {"labels": {"foo/aa?": "bar", "foo/789": "bar"}}}`)
|
||||||
testValidationPattern(t, pattern, resource, "", true)
|
testValidationPattern(t, "6", pattern, resource, "", true)
|
||||||
|
|
||||||
pattern = []byte(`{"metadata" : {"labels": {"foo/123*": "bar"}}}`)
|
pattern = []byte(`{"metadata" : {"labels": {"foo/ABC*": "bar"}}}`)
|
||||||
resource = []byte(`{"metadata" : {"labels": {"foo/12?": "bar", "foo/123": "bar2"}}}`)
|
resource = []byte(`{"metadata" : {"labels": {"foo/AB?": "bar", "foo/ABC": "bar2"}}}`)
|
||||||
testValidationPattern(t, pattern, resource, "/metadata/labels/foo/123*/", false)
|
testValidationPattern(t, "7", pattern, resource, "/metadata/labels/foo/ABC/", false)
|
||||||
|
|
||||||
pattern = []byte(`{"metadata" : {"labels": {"foo/1*": "bar", "foo/4*": "bar2"}}}`)
|
pattern = []byte(`{"=(metadata)" : {"=(labels)": {"foo/P*": "bar", "foo/Q*": "bar2"}}}`)
|
||||||
resource = []byte(`{"metadata" : {"labels": {"foo/123": "bar", "foo/456": "bar2"}}}`)
|
resource = []byte(`{"metadata" : {"labels": {"foo/PQR": "bar", "foo/QR": "bar2"}}}`)
|
||||||
testValidationPattern(t, pattern, resource, "", true)
|
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"}}}`)
|
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{}
|
var pattern, resource interface{}
|
||||||
err := json.Unmarshal(patternBytes, &pattern)
|
err := json.Unmarshal(patternBytes, &pattern)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -1403,10 +1411,10 @@ func testValidationPattern(t *testing.T, patternBytes []byte, resourceBytes []by
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
p, err := validateResourceElement(log.Log, resource, pattern, pattern, "/", common.NewAnchorMap())
|
p, err := validateResourceElement(log.Log, resource, pattern, pattern, "/", common.NewAnchorMap())
|
||||||
assert.Equal(t, p, path)
|
assert.Equal(t, p, path, num)
|
||||||
if nilErr {
|
if nilErr {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err, num)
|
||||||
} else {
|
} 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{}
|
result := map[string]string{}
|
||||||
for k, v := range patternMap {
|
for k, v := range patternMap {
|
||||||
if hasWildcards(k) || hasWildcards(v) {
|
if hasWildcards(k) || hasWildcards(v) {
|
||||||
matchK, matchV := expandWildcards(k, v, resourceMap, true)
|
matchK, matchV := expandWildcards(k, v, resourceMap, true, true)
|
||||||
result[matchK] = matchV
|
result[matchK] = matchV
|
||||||
} else {
|
} else {
|
||||||
result[k] = v
|
result[k] = v
|
||||||
|
@ -32,10 +32,12 @@ func hasWildcards(s string) bool {
|
||||||
return strings.Contains(s, "*") || strings.Contains(s, "?")
|
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 {
|
for k1, v1 := range resourceMap {
|
||||||
if wildcard.Match(k, k1) {
|
if wildcard.Match(k, k1) {
|
||||||
if wildcard.Match(v, v1) {
|
if !matchValue {
|
||||||
|
return k1, v1
|
||||||
|
} else if wildcard.Match(v, v1) {
|
||||||
return k1, v1
|
return k1, v1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +64,7 @@ func replaceWildCardChars(s string) string {
|
||||||
// here, as they are evaluated separately while processing the validation pattern.
|
// here, as they are evaluated separately while processing the validation pattern.
|
||||||
func ExpandInMetadata(patternMap, resourceMap map[string]interface{}) map[string]interface{} {
|
func ExpandInMetadata(patternMap, resourceMap map[string]interface{}) map[string]interface{} {
|
||||||
|
|
||||||
patternMetadata := patternMap["metadata"]
|
_, patternMetadata := getPatternValue("metadata", patternMap)
|
||||||
if patternMetadata == nil {
|
if patternMetadata == nil {
|
||||||
return patternMap
|
return patternMap
|
||||||
}
|
}
|
||||||
|
@ -73,53 +75,64 @@ func ExpandInMetadata(patternMap, resourceMap map[string]interface{}) map[string
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata := patternMetadata.(map[string]interface{})
|
metadata := patternMetadata.(map[string]interface{})
|
||||||
labels := expandWildcardsInTag("labels", patternMetadata, resourceMetadata)
|
labelsKey, labels := expandWildcardsInTag("labels", patternMetadata, resourceMetadata)
|
||||||
if labels != nil {
|
if labels != nil {
|
||||||
metadata["labels"] = labels
|
metadata[labelsKey] = labels
|
||||||
}
|
}
|
||||||
|
|
||||||
annotations := expandWildcardsInTag("annotations", patternMetadata, resourceMetadata)
|
annotationsKey, annotations := expandWildcardsInTag("annotations", patternMetadata, resourceMetadata)
|
||||||
if annotations != nil {
|
if annotations != nil {
|
||||||
metadata["annotations"] = annotations
|
metadata[annotationsKey] = annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
return patternMap
|
return patternMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandWildcardsInTag(tag string, patternMetadata, resourceMetadata interface{}) map[string]interface{} {
|
func getPatternValue(tag string, pattern map[string]interface{}) (string, interface{}) {
|
||||||
patternData := getValueAsStringMap(tag, patternMetadata)
|
for k, v := range pattern {
|
||||||
if patternData == nil {
|
if commonAnchor.RemoveAnchor(k) == tag {
|
||||||
return nil
|
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 {
|
if resourceData == nil {
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
results := map[string]interface{}{}
|
results := map[string]interface{}{}
|
||||||
for k, v := range patternData {
|
for k, v := range patternData {
|
||||||
if hasWildcards(k) {
|
if hasWildcards(k) {
|
||||||
newKey := commonAnchor.RemoveAnchor(k)
|
anchorFreeKey := commonAnchor.RemoveAnchor(k)
|
||||||
matchK, _ := expandWildcards(newKey, v, resourceData, false)
|
matchK, _ := expandWildcards(anchorFreeKey, v, resourceData, false, false)
|
||||||
matchK = strings.Replace(k, newKey, matchK, 1)
|
|
||||||
results[matchK] = v
|
results[matchK] = v
|
||||||
} else {
|
} else {
|
||||||
results[k] = v
|
results[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
return patternKey, results
|
||||||
}
|
}
|
||||||
|
|
||||||
func getValueAsStringMap(key string, dataMap interface{}) map[string]string {
|
func getValueAsStringMap(key string, data interface{}) (string, map[string]string) {
|
||||||
if dataMap == nil {
|
if data == nil {
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
val := dataMap.(map[string]interface{})[key]
|
dataMap := data.(map[string]interface{})
|
||||||
|
patternKey, val := getPatternValue(key, dataMap)
|
||||||
|
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result := map[string]string{}
|
result := map[string]string{}
|
||||||
|
@ -127,5 +140,5 @@ func getValueAsStringMap(key string, dataMap interface{}) map[string]string {
|
||||||
result[k] = v.(string)
|
result[k] = v.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return patternKey, result
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue