package variables import ( "encoding/json" "reflect" "testing" kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1" authenticationv1 "k8s.io/api/authentication/v1" "sigs.k8s.io/controller-runtime/pkg/log" "github.com/kyverno/kyverno/pkg/engine/context" ) func Test_variablesub1(t *testing.T) { patternMap := []byte(` { "kind": "ClusterRole", "name": "ns-owner-{{request.userInfo.username}}", "data": { "rules": [ { "apiGroups": [ "" ], "resources": [ "namespaces" ], "verbs": [ "*" ], "resourceNames": [ "{{request.object.metadata.name}}" ] } ] } } `) resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "name": "temp1" } } `) // userInfo userReqInfo := kyverno.RequestInfo{ AdmissionUserInfo: authenticationv1.UserInfo{ Username: "user1", }, } resultMap := []byte(`{"data":{"rules":[{"apiGroups":[""],"resourceNames":["temp"],"resources":["namespaces"],"verbs":["*"]}]},"kind":"ClusterRole","name":"ns-owner-user1"}`) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } err = ctx.AddUserInfo(userReqInfo) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultRaw, resultMap) { t.Log(string(resultMap)) t.Log(string(resultRaw)) t.Error("result does not match") } } func Test_variablesub_multiple(t *testing.T) { patternMap := []byte(` { "kind": "ClusterRole", "name": "ns-owner-{{request.object.metadata.namespace}}-{{request.userInfo.username}}-bindings", "data": { "rules": [ { "apiGroups": [ "" ], "resources": [ "namespaces" ], "verbs": [ "*" ], "resourceNames": [ "{{request.object.metadata.name}}" ] } ] } } `) resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "name": "temp1" } } `) // userInfo userReqInfo := kyverno.RequestInfo{ AdmissionUserInfo: authenticationv1.UserInfo{ Username: "user1", }, } resultMap := []byte(`{"data":{"rules":[{"apiGroups":[""],"resourceNames":["temp"],"resources":["namespaces"],"verbs":["*"]}]},"kind":"ClusterRole","name":"ns-owner-n1-user1-bindings"}`) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } err = ctx.AddUserInfo(userReqInfo) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultMap, resultRaw) { t.Log(string(resultMap)) t.Log(string(resultRaw)) t.Error("result does not match") } } func Test_variablesubstitution(t *testing.T) { patternMap := []byte(` { "name": "ns-owner-{{request.userInfo.username}}", "data": { "rules": [ { "apiGroups": [ "" ], "resources": [ "namespaces" ], "verbs": [ "*" ], "resourceNames": [ "{{request.object.metadata.name}}" ] } ] } } `) resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "name": "temp1" } } `) resultMap := []byte(`{"data":{"rules":[{"apiGroups":[""],"resourceNames":["temp"],"resources":["namespaces"],"verbs":["*"]}]},"name":"ns-owner-user1"}`) // userInfo userReqInfo := kyverno.RequestInfo{ AdmissionUserInfo: authenticationv1.UserInfo{ Username: "user1", }, } var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } err = ctx.AddUserInfo(userReqInfo) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultMap, resultRaw) { t.Log(string(resultMap)) t.Log(string(resultRaw)) t.Error("result does not match") } } func Test_variableSubstitutionValue(t *testing.T) { resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "name": "temp1" } } `) patternMap := []byte(` { "spec": { "name": "{{request.object.metadata.name}}" } } `) resultMap := []byte(`{"spec":{"name":"temp"}}`) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultMap, resultRaw) { t.Error("result does not match") } } func Test_variableSubstitutionValueOperatorNotEqual(t *testing.T) { resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "name": "temp1" } } `) patternMap := []byte(` { "spec": { "name": "!{{request.object.metadata.name}}" } } `) resultMap := []byte(`{"spec":{"name":"!temp"}}`) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultMap, resultRaw) { t.Log(string(resultRaw)) t.Log(string(resultMap)) t.Error("result does not match") } } func Test_variableSubstitutionValueFail(t *testing.T) { resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "name": "temp1" } } `) patternMap := []byte(` { "spec": { "name": "{{request.object.metadata.name1}}" } } `) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err == nil { t.Log("expected to fails") t.Fail() } } func Test_variableSubstitutionObject(t *testing.T) { resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "variable": { "var1": "temp1", "var2": "temp2", "varNested": { "var1": "temp1" } } } } `) patternMap := []byte(` { "spec": { "variable": "{{request.object.spec.variable}}" } } `) resultMap := []byte(`{"spec":{"variable":{"var1":"temp1","var2":"temp2","varNested":{"var1":"temp1"}}}}`) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultMap, resultRaw) { t.Log(string(resultRaw)) t.Log(string(resultMap)) t.Error("result does not match") } } func Test_variableSubstitutionObjectOperatorNotEqualFail(t *testing.T) { resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "variable": { "var1": "temp1", "var2": "temp2", "varNested": { "var1": "temp1" } } } } `) patternMap := []byte(` { "spec": { "variable": "!{{request.object.spec.variable}}" } } `) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err == nil { t.Error(err) } } func Test_variableSubstitutionMultipleObject(t *testing.T) { resourceRaw := []byte(` { "metadata": { "name": "temp", "namespace": "n1" }, "spec": { "namespace": "n1", "variable": { "var1": "temp1", "var2": "temp2", "varNested": { "var1": "temp1" } } } } `) patternMap := []byte(` { "spec": { "var": "{{request.object.spec.variable.varNested.var1}}", "variable": "{{request.object.spec.variable}}" } } `) resultMap := []byte(`{"spec":{"var":"temp1","variable":{"var1":"temp1","var2":"temp2","varNested":{"var1":"temp1"}}}}`) var pattern, patternCopy, resource interface{} var err error err = json.Unmarshal(patternMap, &pattern) if err != nil { t.Error(err) } err = json.Unmarshal(patternMap, &patternCopy) if err != nil { t.Error(err) } err = json.Unmarshal(resourceRaw, &resource) if err != nil { t.Error(err) } // context ctx := context.NewContext() err = ctx.AddResource(resourceRaw) if err != nil { t.Error(err) } if patternCopy, err = SubstituteVars(log.Log, ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) if err != nil { t.Error(err) } if !reflect.DeepEqual(resultMap, resultRaw) { t.Log(string(resultRaw)) t.Log(string(resultMap)) t.Error("result does not match") } }