1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-15 17:51:20 +00:00

fix: load policy and add tests (#4515)

* fix: load policy and add tests

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* fix callers

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com>
This commit is contained in:
Charles-Edouard Brétéché 2022-09-06 17:16:44 +02:00 committed by GitHub
parent 3beb4fee28
commit 1947dafed6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 284 additions and 34 deletions

View file

@ -30,7 +30,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/policymutation" "github.com/kyverno/kyverno/pkg/policymutation"
"github.com/kyverno/kyverno/pkg/policyreport" "github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/utils" yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
yamlv2 "gopkg.in/yaml.v2" yamlv2 "gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -164,7 +164,7 @@ func GetPolicies(paths []string) (policies []kyvernov1.PolicyInterface, errors [
} }
} }
policiesFromFile, errFromFile := utils.GetPolicy(fileBytes) policiesFromFile, errFromFile := yamlutils.GetPolicy(fileBytes)
if errFromFile != nil { if errFromFile != nil {
err := fmt.Errorf("failed to process %s: %v", path, errFromFile.Error()) err := fmt.Errorf("failed to process %s: %v", path, errFromFile.Error())
errors = append(errors, err) errors = append(errors, err)
@ -631,7 +631,7 @@ func GetPoliciesFromPaths(fs billy.Filesystem, dirPath []string, isGit bool, pol
fmt.Printf("failed to convert to JSON: %v", err) fmt.Printf("failed to convert to JSON: %v", err)
continue continue
} }
policiesFromFile, errFromFile := utils.GetPolicy(policyBytes) policiesFromFile, errFromFile := yamlutils.GetPolicy(policyBytes)
if errFromFile != nil { if errFromFile != nil {
fmt.Printf("failed to process : %v", errFromFile.Error()) fmt.Printf("failed to process : %v", errFromFile.Error())
continue continue
@ -647,7 +647,7 @@ func GetPoliciesFromPaths(fs billy.Filesystem, dirPath []string, isGit bool, pol
policyStr = policyStr + scanner.Text() + "\n" policyStr = policyStr + scanner.Text() + "\n"
} }
yamlBytes := []byte(policyStr) yamlBytes := []byte(policyStr)
policies, err = utils.GetPolicy(yamlBytes) policies, err = yamlutils.GetPolicy(yamlBytes)
if err != nil { if err != nil {
return nil, sanitizederror.NewWithError("failed to extract the resources", err) return nil, sanitizederror.NewWithError("failed to extract the resources", err)
} }

View file

@ -5,7 +5,7 @@ import (
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/toggle" "github.com/kyverno/kyverno/pkg/toggle"
ut "github.com/kyverno/kyverno/pkg/utils" yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
"gotest.tools/assert" "gotest.tools/assert"
) )
@ -98,7 +98,7 @@ func Test_NamespaceSelector(t *testing.T) {
rc := &ResultCounts{} rc := &ResultCounts{}
for _, tc := range testcases { for _, tc := range testcases {
policyArray, _ := ut.GetPolicy(tc.policy) policyArray, _ := yamlutils.GetPolicy(tc.policy)
resourceArray, _ := GetResource(tc.resource) resourceArray, _ := GetResource(tc.resource)
ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, v1beta1.RequestInfo{}, false, tc.namespaceSelectorMap, false, rc, false, nil) ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, v1beta1.RequestInfo{}, false, tc.namespaceSelectorMap, false, rc, false, nil)
assert.Equal(t, int64(rc.Pass), int64(tc.result.Pass)) assert.Equal(t, int64(rc.Pass), int64(tc.result.Pass))

View file

@ -10,7 +10,7 @@ import (
"testing" "testing"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1" kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/utils" yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
"gotest.tools/assert" "gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -298,7 +298,7 @@ func Test_Any(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -336,7 +336,7 @@ func Test_All(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -375,7 +375,7 @@ func Test_Exclude(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -409,7 +409,7 @@ func Test_CronJobOnly(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -439,7 +439,7 @@ func Test_ForEachPod(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -474,7 +474,7 @@ func Test_CronJob_hasExclude(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -511,7 +511,7 @@ func Test_CronJobAndDeployment(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -542,7 +542,7 @@ func Test_UpdateVariablePath(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -572,7 +572,7 @@ func Test_Deny(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -610,7 +610,7 @@ func Test_ValidatePodSecurity(t *testing.T) {
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
policies, err := utils.GetPolicy(file) policies, err := yamlutils.GetPolicy(file)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@ -810,7 +810,7 @@ kA==
} }
for _, test := range testCases { for _, test := range testCases {
policies, err := utils.GetPolicy([]byte(test.policy)) policies, err := yamlutils.GetPolicy([]byte(test.policy))
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, 1, len(policies)) assert.Equal(t, 1, len(policies))
rules := computeRules(policies[0]) rules := computeRules(policies[0])

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"testing" "testing"
ut "github.com/kyverno/kyverno/pkg/utils" yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
"gotest.tools/assert" "gotest.tools/assert"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
) )
@ -54,7 +54,7 @@ func TestNotAllowedVars_MatchSection(t *testing.T) {
} }
`) `)
policy, err := ut.GetPolicy(policyWithVarInMatch) policy, err := yamlutils.GetPolicy(policyWithVarInMatch)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -106,7 +106,7 @@ func TestNotAllowedVars_ExcludeSection(t *testing.T) {
} }
`) `)
policy, err := ut.GetPolicy(policyWithVarInExclude) policy, err := yamlutils.GetPolicy(policyWithVarInExclude)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -159,7 +159,7 @@ func TestNotAllowedVars_ExcludeSection_PositiveCase(t *testing.T) {
} }
`) `)
policy, err := ut.GetPolicy(policyWithVarInExclude) policy, err := yamlutils.GetPolicy(policyWithVarInExclude)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -193,7 +193,7 @@ func TestNotAllowedVars_JSONPatchPath(t *testing.T) {
} }
}`) }`)
policy, err := ut.GetPolicy(policyWithVarInExclude) policy, err := yamlutils.GetPolicy(policyWithVarInExclude)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -236,7 +236,7 @@ func TestNotAllowedVars_JSONPatchPath_ContextPositive(t *testing.T) {
} }
}`) }`)
policy, err := ut.GetPolicy(policyWithVarInExclude) policy, err := yamlutils.GetPolicy(policyWithVarInExclude)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -270,7 +270,7 @@ func TestNotAllowedVars_JSONPatchPath_PositiveCase(t *testing.T) {
} }
}`) }`)
policy, err := ut.GetPolicy(policyWithVarInExclude) policy, err := yamlutils.GetPolicy(policyWithVarInExclude)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -302,7 +302,7 @@ spec:
policyJSON, err := yaml.ToJSON(policyYAML) policyJSON, err := yaml.ToJSON(policyYAML)
assert.NilError(t, err) assert.NilError(t, err)
policy, err := ut.GetPolicy(policyJSON) policy, err := yamlutils.GetPolicy(policyJSON)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -389,7 +389,7 @@ func TestNotAllowedVars_VariableFormats(t *testing.T) {
value: "foo.com" value: "foo.com"
`, tc.input)) `, tc.input))
policy, err := ut.GetPolicy(policyYAML) policy, err := yamlutils.GetPolicy(policyYAML)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)
@ -435,7 +435,7 @@ spec:
policyJSON, err := yaml.ToJSON(policyYAML) policyJSON, err := yaml.ToJSON(policyYAML)
assert.NilError(t, err) assert.NilError(t, err)
policy, err := ut.GetPolicy(policyJSON) policy, err := yamlutils.GetPolicy(policyJSON)
assert.NilError(t, err) assert.NilError(t, err)
err = hasInvalidVariables(policy[0], false) err = hasInvalidVariables(policy[0], false)

View file

@ -1,18 +1,17 @@
package utils package yaml
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
) )
// GetPolicy - extracts policies from YAML bytes // GetPolicy extracts policies from YAML bytes
func GetPolicy(bytes []byte) (policies []kyvernov1.PolicyInterface, err error) { func GetPolicy(bytes []byte) (policies []kyvernov1.PolicyInterface, err error) {
documents, err := yamlutils.SplitDocuments(bytes) documents, err := SplitDocuments(bytes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,11 +31,12 @@ func GetPolicy(bytes []byte) (policies []kyvernov1.PolicyInterface, err error) {
if policy.TypeMeta.Kind != "ClusterPolicy" && policy.TypeMeta.Kind != "Policy" { if policy.TypeMeta.Kind != "ClusterPolicy" && policy.TypeMeta.Kind != "Policy" {
return nil, fmt.Errorf("resource %s/%s is not a Policy or a ClusterPolicy", policy.Kind, policy.Name) return nil, fmt.Errorf("resource %s/%s is not a Policy or a ClusterPolicy", policy.Kind, policy.Name)
} }
if policy.Namespace != "" || (policy.Namespace == "" && policy.Kind == "Policy") { if policy.Kind == "Policy" {
if policy.Namespace == "" { if policy.Namespace == "" {
policy.Namespace = "default" policy.Namespace = "default"
} }
policy.Kind = "ClusterPolicy" } else {
policy.Namespace = ""
} }
policies = append(policies, policy) policies = append(policies, policy)
} }

View file

@ -0,0 +1,250 @@
package yaml
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetPolicy(t *testing.T) {
type args struct {
bytes []byte
}
type policy struct {
kind string
namespace string
}
tests := []struct {
name string
args args
wantPolicies []policy
wantErr bool
}{{
name: "policy",
args: args{
[]byte(`
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: generate-policy
namespace: ns-1
spec:
rules:
- name: copy-game-demo
match:
resources:
kinds:
- Namespace
exclude:
resources:
namespaces:
- kube-system
- default
- kube-public
- kyverno
generate:
kind: ConfigMap
name: game-demo
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: game-demo
`),
},
wantPolicies: []policy{
{"Policy", "ns-1"},
},
wantErr: false,
}, {
name: "policy without ns",
args: args{
[]byte(`
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: generate-policy
spec:
rules:
- name: copy-game-demo
match:
resources:
kinds:
- Namespace
exclude:
resources:
namespaces:
- kube-system
- default
- kube-public
- kyverno
generate:
kind: ConfigMap
name: game-demo
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: game-demo
`),
},
wantPolicies: []policy{
{"Policy", "default"},
},
wantErr: false,
}, {
name: "cluster policy",
args: args{
[]byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-policy
spec:
rules:
- name: copy-game-demo
match:
resources:
kinds:
- Namespace
exclude:
resources:
namespaces:
- kube-system
- default
- kube-public
- kyverno
generate:
kind: ConfigMap
name: game-demo
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: game-demo
`),
},
wantPolicies: []policy{
{"ClusterPolicy", ""},
},
wantErr: false,
}, {
name: "cluster policy with ns",
args: args{
[]byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-policy
namespace: ns-1
spec:
rules:
- name: copy-game-demo
match:
resources:
kinds:
- Namespace
exclude:
resources:
namespaces:
- kube-system
- default
- kube-public
- kyverno
generate:
kind: ConfigMap
name: game-demo
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: game-demo
`),
},
wantPolicies: []policy{
{"ClusterPolicy", ""},
},
wantErr: false,
}, {
name: "policy and cluster policy",
args: args{
[]byte(`
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: generate-policy
namespace: ns-1
spec:
rules:
- name: copy-game-demo
match:
resources:
kinds:
- Namespace
exclude:
resources:
namespaces:
- kube-system
- default
- kube-public
- kyverno
generate:
kind: ConfigMap
name: game-demo
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: game-demo
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-policy
spec:
rules:
- name: copy-game-demo
match:
resources:
kinds:
- Namespace
exclude:
resources:
namespaces:
- kube-system
- default
- kube-public
- kyverno
generate:
kind: ConfigMap
name: game-demo
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: game-demo
`),
},
wantPolicies: []policy{
{"Policy", "ns-1"},
{"ClusterPolicy", ""},
},
wantErr: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotPolicies, err := GetPolicy(tt.args.bytes)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
if assert.Equal(t, len(tt.wantPolicies), len(gotPolicies)) {
for i := range tt.wantPolicies {
assert.Equal(t, tt.wantPolicies[i].kind, gotPolicies[i].GetKind())
assert.Equal(t, tt.wantPolicies[i].namespace, gotPolicies[i].GetNamespace())
}
}
}
})
}
}