1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-29 10:55:05 +00:00

Fix variable substitution when curly braces are used in jmespath (#3133)

* Fix variable substitution when inline jmespath objects are defined

Signed-off-by: Sambhav Kothari <sambhavs.email@gmail.com>

* Add additional test cases which use brackets

Signed-off-by: Sambhav Kothari <sambhavs.email@gmail.com>

Co-authored-by: Jim Bugwadia <jim@nirmata.com>
This commit is contained in:
Sambhav Kothari 2022-01-31 17:11:19 +00:00 committed by GitHub
parent a1daf167e7
commit 2b1e7189b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 174 additions and 3 deletions

View file

@ -18,9 +18,9 @@ import (
"github.com/kyverno/kyverno/pkg/engine/operator"
)
var RegexVariables = regexp.MustCompile(`^\{\{[^{}]*\}\}|[^\\]\{\{[^{}]*\}\}`)
var RegexVariables = regexp.MustCompile(`^\{\{(\{[^{}]*\}|[^{}])*\}\}|[^\\]\{\{(\{[^{}]*\}|[^{}])*\}\}`)
var RegexEscpVariables = regexp.MustCompile(`\\\{\{[^{}]*\}\}`)
var RegexEscpVariables = regexp.MustCompile(`\\\{\{(\{[^{}]*\}|[^{}])*\}\}`)
// RegexReferences is the Regex for '$(...)' at the beginning of the string, and 'x$(...)' where 'x' is not '\'
var RegexReferences = regexp.MustCompile(`^\$\(.[^\ ]*\)|[^\\]\$\(.[^\ ]*\)`)
@ -28,7 +28,7 @@ var RegexReferences = regexp.MustCompile(`^\$\(.[^\ ]*\)|[^\\]\$\(.[^\ ]*\)`)
// RegexEscpReferences is the Regex for '\$(...)'
var RegexEscpReferences = regexp.MustCompile(`\\\$\(.[^\ ]*\)`)
var regexVariableInit = regexp.MustCompile(`^\{\{[^{}]*\}\}`)
var regexVariableInit = regexp.MustCompile(`^\{\{(\{[^{}]*\}|[^{}])*\}\}`)
var regexElementIndex = regexp.MustCompile(`{{\s*elementIndex\s*}}`)

View file

@ -289,6 +289,36 @@ func Test_subVars_withRegexMatch(t *testing.T) {
assert.Equal(t, string(out), expected.String())
}
func Test_subVars_withMerge(t *testing.T) {
patternMap := []byte(`{"map": "{{ merge(` + "`{\\\"a\\\": 1}`, `{\\\"b\\\": 1}`" + `)}}"}`)
resourceRaw := []byte(`{}`)
expectedRaw := []byte(`{"map": {"a":1,"b":1}}`)
var err error
expected := new(bytes.Buffer)
err = json.Compact(expected, expectedRaw)
assert.NilError(t, err)
var pattern, resource interface{}
err = json.Unmarshal(patternMap, &pattern)
assert.NilError(t, err)
err = json.Unmarshal(resourceRaw, &resource)
assert.NilError(t, err)
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
assert.NilError(t, err)
output, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
out, err := json.Marshal(output)
assert.NilError(t, err)
assert.Equal(t, string(out), expected.String())
}
func Test_subVars_withRegexReplaceAll(t *testing.T) {
patternMap := []byte(`{
"mutate": {

View file

@ -0,0 +1,36 @@
name: test-preconditions
policies:
- policy.yaml
resources:
- resources.yaml
results:
- policy: test-jmespath
rule: test-jmespath
resource: test-valid1
kind: Pod
status: pass
- policy: test-jmespath
rule: test-jmespath
resource: test-valid2
kind: Pod
status: pass
- policy: test-jmespath
rule: test-jmespath
resource: test-valid3
kind: Pod
status: pass
- policy: test-jmespath
rule: test-jmespath
resource: test-invalid
kind: Pod
status: fail
- policy: namespace-validation
rule: namespace-validation
resource: test-invalid
kind: Namespace
status: fail
- policy: namespace-validation
rule: namespace-validation
resource: test-valid
kind: Namespace
status: pass

View file

@ -0,0 +1,47 @@
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: test-jmespath
annotations:
pod-policies.kyverno.io/autogen-controllers: none
spec:
validationFailureAction: enforce
background: false
rules:
- name: test-jmespath
match:
resources:
kinds:
- Pod
validate:
message: 'All pod labels must match except test'
deny:
conditions:
all:
- key: '{{ request.object.metadata.labels | merge(@, `{"test": ""}`)}}'
operator: NotEquals
value:
a: "1"
test: ""
---
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: namespace-validation
namespace: kyverno
spec:
validationFailureAction: enforce
background: false
rules:
- name: namespace-validation
match:
resources:
kinds:
- Namespace
validate:
message: "For creating a namespace you need to set the objectid of the Azure AD Group that needs access to this namespace as the aadobjectid label"
deny:
conditions:
- key: "{{regex_match('^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$', '{{request.object.metadata.labels.aadobjectid}}')}}"
operator: Equals
value: false

View file

@ -0,0 +1,58 @@
apiVersion: v1
kind: Pod
metadata:
name: test-valid1
labels:
a: "1"
spec:
containers:
- image: busybox:1.28
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: test-valid2
labels:
a: "1"
test: "not-equal"
spec:
containers:
- image: busybox:1.28
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: test-valid3
labels:
a: "1"
spec:
containers:
- image: busybox:1.28
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: test-invalid
labels:
a: "2"
spec:
containers:
- image: busybox:1.28
name: busybox
---
apiVersion: v1
kind: Namespace
metadata:
labels:
aadobjectid: 51e5fe10-5325-4a32-bce8-7ebe9708
name: test-invalid
---
apiVersion: v1
kind: Namespace
metadata:
labels:
aadobjectid: 51e5fe10-5325-4a32-9ce8-7ebe97087ebe
name: test-valid