1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

change matchGVK logic (#2736)

* change matchGVK logic

* fix issue

* add testcases

* add testcase core

* format code

* fix comment
This commit is contained in:
Vyankatesh Kudtarkar 2021-11-24 19:47:32 +05:30 committed by GitHub
parent 9e10eef422
commit 5c50191d8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 28 deletions

View file

@ -183,6 +183,7 @@ func (o *Controller) ValidatePolicyMutation(policy v1.ClusterPolicy) error {
func (o *Controller) useOpenAPIDocument(doc *openapiv2.Document) error {
for _, definition := range doc.GetDefinitions().AdditionalProperties {
definitionName := definition.GetName()
o.definitions.Set(definitionName, definition.GetValue())
gvk, preferredGVK, err := o.getGVKByDefinitionName(definitionName)
@ -239,8 +240,36 @@ func (o *Controller) getGVKByDefinitionName(definitionName string) (gvk string,
return "", preferredGVK, fmt.Errorf("gvk not found by the given definition name %s, %v", definitionName, versionsTyped.gvks)
}
func parseGVK(str string) (group, apiVersion, kind string) {
if strings.Count(str, "/") == 0 {
return "", "", str
}
splitString := strings.Split(str, "/")
if strings.Count(str, "/") == 1 {
return "", splitString[0], splitString[1]
}
return splitString[0], splitString[1], splitString[2]
}
func groupMatches(gvkMap map[string]bool, group, kind string) bool {
if group == "" {
ok := gvkMap["core"]
if ok {
return true
}
} else {
elements := strings.Split(group, ".")
ok := gvkMap[elements[0]]
if ok {
return true
}
}
return false
}
// matchGVK is a helper function that checks if the
// given GVK matches the definition name
func matchGVK(definitionName, gvk string) bool {
paths := strings.Split(definitionName, ".")
@ -249,35 +278,19 @@ func matchGVK(definitionName, gvk string) bool {
gvkMap[p] = true
}
gvkList := strings.Split(gvk, "/")
// group can be a dot-seperated string
// here we allow at most 1 missing element in group elements, except for Ingress
// as a specific element could be missing in apiDocs name
// io.k8s.api.rbac.v1.Role - rbac.authorization.k8s.io/v1/Role
missingMoreThanOneElement := false
for i, element := range gvkList {
if i == 0 {
items := strings.Split(element, ".")
for _, item := range items {
_, ok := gvkMap[item]
if !ok {
if gvkList[len(gvkList)-1] == "Ingress" {
return false
}
group, version, kind := parseGVK(gvk)
if missingMoreThanOneElement {
return false
}
missingMoreThanOneElement = true
}
}
continue
}
ok := gvkMap[kind]
if !ok {
return false
}
ok = gvkMap[version]
if !ok {
return false
}
_, ok := gvkMap[element]
if !ok {
return false
}
if !groupMatches(gvkMap, group, kind) {
return false
}
return true

View file

@ -86,11 +86,27 @@ func Test_matchGVK(t *testing.T) {
gvk string
match bool
}{
{
"io.k8s.api.networking.v1.Ingress",
"networking.k8s.io/v1/Ingress",
true,
},
{
"io.k8s.api.extensions.v1beta1.Ingress",
"extensions/v1beta1/Ingress",
true,
},
{
"io.crossplane.gcp.iam.v1.ServiceAccount",
"v1/ServiceAccount",
false,
},
{
"io.k8s.api.core.v1.Secret",
"v1/Secret",
true,
},
{
"io.wgpolicyk8s.v1alpha1.PolicyReport",
"wgpolicyk8s.io/v1alpha1/PolicyReport",
@ -106,6 +122,21 @@ func Test_matchGVK(t *testing.T) {
"rbac.authorization.k8s.io/v1beta1/ClusterRoleBinding",
true,
},
{
"io.crossplane.gcp.iam.v1alpha1.ServiceAccount",
"iam.gcp.crossplane.io/v1alpha1/ServiceAccount",
true,
},
{
"io.crossplane.gcp.iam.v1alpha1.ServiceAccount",
"v1/ServiceAccount",
false,
},
{
"v1.ServiceAccount",
"iam.gcp.crossplane.io/v1alpha1/ServiceAccount",
false,
},
{
"io.k8s.api.rbac.v1.Role",
"rbac.authorization.k8s.io/v1/Role",
@ -124,13 +155,18 @@ func Test_matchGVK(t *testing.T) {
{
"io.k8s.api.policy.v1beta1.Eviction",
"v1/Eviction",
true,
false,
},
{
"io.k8s.api.rbac.v1beta1.ClusterRole",
"rbac.authorization.k8s.io/v1beta1/ClusterRole",
true,
},
{
"io.k8s.api.policy.v1.Eviction",
"v1/Eviction",
false,
},
}
for i, test := range testCases {