package policymutation import ( "io/ioutil" "os" "path/filepath" "strings" "testing" "github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/utils" "gotest.tools/assert" "sigs.k8s.io/controller-runtime/pkg/log" ) func currentDir() (string, error) { homedir, err := os.UserHomeDir() if err != nil { return "", nil } return filepath.Join(homedir, "github.com/kyverno/kyverno"), nil } func Test_Exclude(t *testing.T) { dir, err := os.Getwd() baseDir := filepath.Dir(filepath.Dir(dir)) assert.NilError(t, err) file, err := ioutil.ReadFile(baseDir + "/samples/best_practices/disallow_bind_mounts.yaml") if err != nil { t.Log(err) } policies, err := utils.GetPolicy(file) if err != nil { t.Log(err) } policy := policies[0] policy.Spec.Rules[0].ExcludeResources.Namespaces = []string{"fake-namespce"} rulePatches, errs := generateRulePatches(*policy, engine.PodControllers, log.Log) if len(errs) != 0 { t.Log(errs) } expectedPatches := [][]byte{ []byte(`{"path":"/spec/rules/1","op":"add","value":{"name":"autogen-validate-hostPath","match":{"resources":{"kinds":["DaemonSet","Deployment","Job","StatefulSet"]}},"exclude":{"resources":{"namespaces":["fake-namespce"]}},"validate":{"message":"Host path volumes are not allowed","pattern":{"spec":{"template":{"spec":{"=(volumes)":[{"X(hostPath)":"null"}]}}}}}}}`), []byte(`{"path":"/spec/rules/2","op":"add","value":{"name":"autogen-cronjob-validate-hostPath","match":{"resources":{"kinds":["CronJob"]}},"exclude":{"resources":{"namespaces":["fake-namespce"]}},"validate":{"message":"Host path volumes are not allowed","pattern":{"spec":{"jobTemplate":{"spec":{"template":{"spec":{"=(volumes)":[{"X(hostPath)":"null"}]}}}}}}}}}`), } assert.DeepEqual(t, rulePatches, expectedPatches) } func Test_CronJobOnly(t *testing.T) { controllers := engine.PodControllerCronJob dir, err := os.Getwd() baseDir := filepath.Dir(filepath.Dir(dir)) assert.NilError(t, err) file, err := ioutil.ReadFile(baseDir + "/samples/best_practices/disallow_bind_mounts.yaml") if err != nil { t.Log(err) } policies, err := utils.GetPolicy(file) if err != nil { t.Log(err) } policy := policies[0] policy.SetAnnotations(map[string]string{ engine.PodControllersAnnotation: controllers, }) rulePatches, errs := generateRulePatches(*policy, controllers, log.Log) if len(errs) != 0 { t.Log(errs) } expectedPatches := [][]byte{ []byte(`{"path":"/spec/rules/1","op":"add","value":{"name":"autogen-cronjob-validate-hostPath","match":{"resources":{"kinds":["CronJob"]}},"validate":{"message":"Host path volumes are not allowed","pattern":{"spec":{"jobTemplate":{"spec":{"template":{"spec":{"=(volumes)":[{"X(hostPath)":"null"}]}}}}}}}}}`), } assert.DeepEqual(t, rulePatches, expectedPatches) } func Test_CronJob_hasExclude(t *testing.T) { controllers := engine.PodControllerCronJob dir, err := os.Getwd() baseDir := filepath.Dir(filepath.Dir(dir)) assert.NilError(t, err) file, err := ioutil.ReadFile(baseDir + "/samples/best_practices/disallow_bind_mounts.yaml") if err != nil { t.Log(err) } policies, err := utils.GetPolicy(file) if err != nil { t.Log(err) } policy := policies[0] policy.SetAnnotations(map[string]string{ engine.PodControllersAnnotation: controllers, }) rule := policy.Spec.Rules[0].DeepCopy() rule.ExcludeResources.Kinds = []string{"Pod"} rule.ExcludeResources.Namespaces = []string{"test"} policy.Spec.Rules[0] = *rule rulePatches, errs := generateRulePatches(*policy, controllers, log.Log) if len(errs) != 0 { t.Log(errs) } expectedPatches := [][]byte{ []byte(`{"path":"/spec/rules/1","op":"add","value":{"name":"autogen-cronjob-validate-hostPath","match":{"resources":{"kinds":["CronJob"]}},"exclude":{"resources":{"kinds":["CronJob"],"namespaces":["test"]}},"validate":{"message":"Host path volumes are not allowed","pattern":{"spec":{"jobTemplate":{"spec":{"template":{"spec":{"=(volumes)":[{"X(hostPath)":"null"}]}}}}}}}}}`), } assert.DeepEqual(t, rulePatches, expectedPatches) } func Test_CronJobAndDeployment(t *testing.T) { controllers := strings.Join([]string{engine.PodControllerCronJob, "Deployment"}, ",") dir, err := os.Getwd() baseDir := filepath.Dir(filepath.Dir(dir)) assert.NilError(t, err) file, err := ioutil.ReadFile(baseDir + "/samples/best_practices/disallow_bind_mounts.yaml") if err != nil { t.Log(err) } policies, err := utils.GetPolicy(file) if err != nil { t.Log(err) } policy := policies[0] policy.SetAnnotations(map[string]string{ engine.PodControllersAnnotation: controllers, }) rulePatches, errs := generateRulePatches(*policy, controllers, log.Log) if len(errs) != 0 { t.Log(errs) } expectedPatches := [][]byte{ []byte(`{"path":"/spec/rules/1","op":"add","value":{"name":"autogen-validate-hostPath","match":{"resources":{"kinds":["Deployment"]}},"validate":{"message":"Host path volumes are not allowed","pattern":{"spec":{"template":{"spec":{"=(volumes)":[{"X(hostPath)":"null"}]}}}}}}}`), []byte(`{"path":"/spec/rules/2","op":"add","value":{"name":"autogen-cronjob-validate-hostPath","match":{"resources":{"kinds":["CronJob"]}},"validate":{"message":"Host path volumes are not allowed","pattern":{"spec":{"jobTemplate":{"spec":{"template":{"spec":{"=(volumes)":[{"X(hostPath)":"null"}]}}}}}}}}}`), } assert.DeepEqual(t, rulePatches, expectedPatches) }