1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

feat: add more policy validation around policies using kyverno-json (#10777)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2024-08-02 13:47:03 +02:00 committed by GitHub
parent fc694bc24c
commit a1510d9db1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 218 additions and 0 deletions

View file

@ -49,6 +49,7 @@ var (
allowedVariablesInTarget = regexp.MustCompile(`request\.|serviceAccountName|serviceAccountNamespace|element|elementIndex|@|images|images\.|image\.|target\.|([a-z_0-9]+\()[^{}]`)
allowedVariablesBackgroundInTarget = regexp.MustCompile(`request\.|element|elementIndex|@|images|images\.|image\.|target\.|([a-z_0-9]+\()[^{}]`)
regexVariables = regexp.MustCompile(`\{\{[^{}]*\}\}`)
bindingIdentifier = regexp.MustCompile(`^\w+$`)
// wildCardAllowedVariables represents regex for the allowed fields in wildcards
wildCardAllowedVariables = regexp.MustCompile(`\{\{\s*(request\.|serviceAccountName|serviceAccountNamespace)[^{}]*\}\}`)
errOperationForbidden = errors.New("variables are forbidden in the path of a JSONPatch")
@ -1221,6 +1222,13 @@ func validateRuleContext(rule kyvernov1.Rule) error {
if entry.Name == "" {
return fmt.Errorf("a name is required for context entries")
}
// if it the rule uses kyverno-json we add some constraints on the name of context entries to make
// sure we can create the corresponding bindings
if rule.Validation.Assert.Value != nil {
if !bindingIdentifier.MatchString(entry.Name) {
return fmt.Errorf("context entry name %s is invalid, it must be a single word when the validation rule uses `assert`", entry.Name)
}
}
for _, v := range []string{"images", "request", "serviceAccountName", "serviceAccountNamespace", "element", "elementIndex"} {
if entry.Name == v || strings.HasPrefix(entry.Name, v+".") {
return fmt.Errorf("entry name %s is invalid as it conflicts with a pre-defined variable %s", entry.Name, v)

View file

@ -0,0 +1,9 @@
## Description
This test tries to create cluster policies that are potentially not valid and verifies the creation outcome.
## Expected Behavior
- `ok` policy should be accepted
- `foreach` policy should be rejected
- `bad-context-name` policy should be rejected

View file

@ -0,0 +1,24 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: bad-context-name
spec:
rules:
- name: test
match:
all:
- resources:
kinds:
- Namespace
context:
- name: bad-name
variable:
value: dummy
validate:
validationFailureAction: Enforce
message: "namespace must have an env label"
assert:
object:
metadata:
labels:
env: {}

View file

@ -0,0 +1,29 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
name: assert-validation
spec:
steps:
- try:
- create:
file: ok.yaml
- try:
- create:
file: no-foreach.yaml
bindings:
- name: errPattern
value: |-
*path: spec.rules[0].validate..: only one of pattern, anyPattern, deny, foreach, cel can be specified
expect:
- check:
(wildcard($errPattern, $error)): true
- try:
- create:
file: bad-context-name.yaml
bindings:
- name: errPattern
value: |-
*path: spec.rules[0]: context entry name bad-name is invalid, it must be a single word when the validation rule uses `assert`
expect:
- check:
(wildcard($errPattern, $error)): true

View file

@ -0,0 +1,23 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: foreach
spec:
rules:
- name: test
match:
all:
- resources:
kinds:
- Namespace
validate:
validationFailureAction: Enforce
message: "namespace must have an env label"
foreach:
- list: "['dummy']"
deny: {}
assert:
object:
metadata:
labels:
env: {}

View file

@ -0,0 +1,20 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: ok
spec:
rules:
- name: test
match:
all:
- resources:
kinds:
- Namespace
validate:
validationFailureAction: Enforce
message: "namespace must have an env label"
assert:
object:
metadata:
labels:
env: {}

View file

@ -0,0 +1,9 @@
## Description
This test tries to create policies that are potentially not valid and verifies the creation outcome.
## Expected Behavior
- `ok` policy should be accepted
- `foreach` policy should be rejected
- `bad-context-name` policy should be rejected

View file

@ -0,0 +1,24 @@
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: bad-context-name
spec:
rules:
- name: test
match:
all:
- resources:
kinds:
- Pod
context:
- name: bad-name
variable:
value: dummy
validate:
validationFailureAction: Enforce
message: "pod must have an env label"
assert:
object:
metadata:
labels:
env: {}

View file

@ -0,0 +1,29 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
name: assert-validation
spec:
steps:
- try:
- create:
file: ok.yaml
- try:
- create:
file: no-foreach.yaml
bindings:
- name: errPattern
value: |-
*path: spec.rules[0].validate..: only one of pattern, anyPattern, deny, foreach, cel can be specified
expect:
- check:
(wildcard($errPattern, $error)): true
- try:
- create:
file: bad-context-name.yaml
bindings:
- name: errPattern
value: |-
*path: spec.rules[0]: context entry name bad-name is invalid, it must be a single word when the validation rule uses `assert`
expect:
- check:
(wildcard($errPattern, $error)): true

View file

@ -0,0 +1,23 @@
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: foreach
spec:
rules:
- name: test
match:
all:
- resources:
kinds:
- Pod
validate:
validationFailureAction: Enforce
message: "pod must have an env label"
foreach:
- list: "['dummy']"
deny: {}
assert:
object:
metadata:
labels:
env: {}

View file

@ -0,0 +1,20 @@
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: ok
spec:
rules:
- name: test
match:
all:
- resources:
kinds:
- Pod
validate:
validationFailureAction: Enforce
message: "pod must have an env label"
assert:
object:
metadata:
labels:
env: {}