mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
feat: assert rule autogen (#10780)
* Support autogen for assert validation rules Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de> * simplify assert autogen logic Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de> * add chainsaw test Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de> --------- Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>
This commit is contained in:
parent
cfef8a089a
commit
91ffbb6758
8 changed files with 191 additions and 0 deletions
|
@ -160,6 +160,11 @@ func (r *Rule) HasValidateCEL() bool {
|
|||
return r.Validation.CEL != nil && !datautils.DeepEqual(r.Validation.CEL, &CEL{})
|
||||
}
|
||||
|
||||
// HasValidateAssert checks for validate.assert rule
|
||||
func (r *Rule) HasValidateAssert() bool {
|
||||
return !datautils.DeepEqual(r.Validation.Assert, AssertionTree{})
|
||||
}
|
||||
|
||||
// HasValidate checks for validate rule
|
||||
func (r *Rule) HasValidate() bool {
|
||||
return !datautils.DeepEqual(r.Validation, Validation{})
|
||||
|
|
|
@ -19,6 +19,7 @@ const (
|
|||
var (
|
||||
PodControllers = sets.New("DaemonSet", "Deployment", "Job", "StatefulSet", "ReplicaSet", "ReplicationController", "CronJob")
|
||||
podControllersKindsSet = PodControllers.Union(sets.New("Pod"))
|
||||
assertAutogenNodes = []string{"object", "oldObject"}
|
||||
)
|
||||
|
||||
func isKindOtherthanPod(kinds []string) bool {
|
||||
|
@ -275,3 +276,38 @@ func computeRules(p kyvernov1.PolicyInterface, kind string) []kyvernov1.Rule {
|
|||
out = append(out, genRules...)
|
||||
return out
|
||||
}
|
||||
|
||||
func copyMap(m map[string]any) map[string]any {
|
||||
newMap := make(map[string]any, len(m))
|
||||
for k, v := range m {
|
||||
newMap[k] = v
|
||||
}
|
||||
|
||||
return newMap
|
||||
}
|
||||
|
||||
func createAutogenAssertion(tree kyvernov1.AssertionTree, tplKey string) kyvernov1.AssertionTree {
|
||||
v, ok := tree.Value.(map[string]any)
|
||||
if !ok {
|
||||
return tree
|
||||
}
|
||||
|
||||
value := copyMap(v)
|
||||
|
||||
for _, n := range assertAutogenNodes {
|
||||
object, ok := v[n].(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
value[n] = map[string]any{
|
||||
"spec": map[string]any{
|
||||
tplKey: copyMap(object),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return kyvernov1.AssertionTree{
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -596,3 +596,50 @@ func Test_ValidateWithCELExpressions(t *testing.T) {
|
|||
rules := computeRules(policies[0], "DaemonSet")
|
||||
assert.Equal(t, 2, len(rules))
|
||||
}
|
||||
|
||||
func Test_ValidateWithAssertion(t *testing.T) {
|
||||
policy := []byte(`
|
||||
{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {
|
||||
"name": "disallow-default-sa"
|
||||
},
|
||||
"spec": {
|
||||
"validationFailureAction": "Enforce",
|
||||
"background": false,
|
||||
"rules": [
|
||||
{
|
||||
"name": "default-sa",
|
||||
"match": {
|
||||
"any": [
|
||||
{
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Pod"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": {
|
||||
"assert": {
|
||||
"object": {
|
||||
"spec": {
|
||||
"(serviceAccountName == 'default')": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
policies, _, _, err := yamlutils.GetPolicy([]byte(policy))
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 1, len(policies))
|
||||
|
||||
rules := computeRules(policies[0], "")
|
||||
assert.Equal(t, 3, len(rules))
|
||||
}
|
||||
|
|
|
@ -207,6 +207,11 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
|
|||
rule.Validation.CEL = cel
|
||||
return rule
|
||||
}
|
||||
if rule.HasValidateAssert() {
|
||||
rule.Validation.Assert = createAutogenAssertion(*rule.Validation.Assert.DeepCopy(), tplKey)
|
||||
|
||||
return rule
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
## Description
|
||||
|
||||
The policy should contain autogen rules for cronjobs and deployments because it has the `pod-policies.kyverno.io/autogen-controllers: Deployment,CronJob` annotation.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
The policy gets created and contains a autogen rules for cronjobs and deployments in the status.
|
||||
|
13
test/conformance/chainsaw/autogen/assert-autogen/chainsaw-test.yaml
Executable file
13
test/conformance/chainsaw/autogen/assert-autogen/chainsaw-test.yaml
Executable file
|
@ -0,0 +1,13 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: assert-autogen
|
||||
spec:
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: policy.yaml
|
||||
- assert:
|
||||
file: policy-assert.yaml
|
|
@ -0,0 +1,56 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-default-sa
|
||||
spec:
|
||||
validationFailureAction: Audit
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
name: disallow-default-sa
|
||||
validate:
|
||||
message: default ServiceAccount should not be used
|
||||
assert:
|
||||
object:
|
||||
spec:
|
||||
(serviceAccountName == 'default'): false
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
||||
autogen:
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
name: autogen-disallow-default-sa
|
||||
validate:
|
||||
message: default ServiceAccount should not be used
|
||||
assert:
|
||||
object:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
(serviceAccountName == 'default'): false
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- CronJob
|
||||
name: autogen-cronjob-disallow-default-sa
|
||||
validate:
|
||||
message: default ServiceAccount should not be used
|
||||
assert:
|
||||
object:
|
||||
spec:
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
(serviceAccountName == 'default'): false
|
21
test/conformance/chainsaw/autogen/assert-autogen/policy.yaml
Normal file
21
test/conformance/chainsaw/autogen/assert-autogen/policy.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-default-sa
|
||||
annotations:
|
||||
pod-policies.kyverno.io/autogen-controllers: Deployment,CronJob
|
||||
spec:
|
||||
validationFailureAction: Audit
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
name: disallow-default-sa
|
||||
validate:
|
||||
message: default ServiceAccount should not be used
|
||||
assert:
|
||||
object:
|
||||
spec:
|
||||
(serviceAccountName == 'default'): false
|
Loading…
Add table
Reference in a new issue