diff --git a/pkg/autogen/autogen.go b/pkg/autogen/autogen.go index 4d6db9f2bf..ebeced6693 100644 --- a/pkg/autogen/autogen.go +++ b/pkg/autogen/autogen.go @@ -1,9 +1,9 @@ package autogen import ( + "encoding/json" "strings" - jsoniter "github.com/json-iterator/go" "github.com/kyverno/kyverno/api/kyverno" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" @@ -190,23 +190,14 @@ func generateRules(spec *kyvernov1.Spec, controllers string) []kyvernov1.Rule { } func convertRule(rule kyvernoRule, kind string) (*kyvernov1.Rule, error) { - json := jsoniter.ConfigCompatibleWithStandardLibrary - if bytes, err := json.Marshal(rule); err != nil { return nil, err } else { - bytes = updateGenRuleByte(bytes, kind) - if err := json.Unmarshal(bytes, &rule); err != nil { - return nil, err - } - // CEL variables are object, oldObject, request, params and authorizer. // Therefore CEL expressions can be either written as object.spec or request.object.spec - if rule.Validation != nil && rule.Validation.CEL != nil { - bytes = updateCELFields(bytes, kind) - if err := json.Unmarshal(bytes, &rule); err != nil { - return nil, err - } + bytes = updateFields(bytes, kind, rule.Validation != nil && rule.Validation.CEL != nil) + if err := json.Unmarshal(bytes, &rule); err != nil { + return nil, err } } diff --git a/pkg/autogen/autogen_test.go b/pkg/autogen/autogen_test.go index 6c5523aec4..b7c70283bb 100644 --- a/pkg/autogen/autogen_test.go +++ b/pkg/autogen/autogen_test.go @@ -343,7 +343,7 @@ func TestUpdateGenRuleByte(t *testing.T) { }, } for _, tt := range tests { - got := updateGenRuleByte(tt.pbyte, tt.kind) + got := updateFields(tt.pbyte, tt.kind, false) if !reflect.DeepEqual(got, tt.want) { t.Errorf("updateGenRuleByte() = %v, want %v", string(got), string(tt.want)) } @@ -384,7 +384,7 @@ func TestUpdateCELFields(t *testing.T) { }, } for _, tt := range tests { - got := updateCELFields(tt.pbyte, tt.kind) + got := updateFields(tt.pbyte, tt.kind, true) if !reflect.DeepEqual(got, tt.want) { t.Errorf("updateCELFields() = %v, want %v", string(got), string(tt.want)) } diff --git a/pkg/autogen/rule.go b/pkg/autogen/rule.go index 07c97fdf5a..698bfe2010 100644 --- a/pkg/autogen/rule.go +++ b/pkg/autogen/rule.go @@ -1,6 +1,7 @@ package autogen import ( + "bytes" "sort" "strings" @@ -312,34 +313,56 @@ func generateCronJobRule(rule *kyvernov1.Rule, controllers string) *kyvernov1.Ru ) } -func updateGenRuleByte(pbyte []byte, kind string) (obj []byte) { - if kind == "Pod" { - obj = []byte(strings.ReplaceAll(string(pbyte), "request.object.spec", "request.object.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "request.oldObject.spec", "request.oldObject.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "request.object.metadata", "request.object.spec.template.metadata")) - obj = []byte(strings.ReplaceAll(string(obj), "request.oldObject.metadata", "request.oldObject.spec.template.metadata")) +var ( + podReplacementRules [][2][]byte = [][2][]byte{ + {[]byte("request.object.spec"), []byte("request.object.spec.template.spec")}, + {[]byte("request.oldObject.spec"), []byte("request.oldObject.spec.template.spec")}, + {[]byte("request.object.metadata"), []byte("request.object.spec.template.metadata")}, + {[]byte("request.oldObject.metadata"), []byte("request.oldObject.spec.template.metadata")}, } - if kind == "Cronjob" { - obj = []byte(strings.ReplaceAll(string(pbyte), "request.object.spec", "request.object.spec.jobTemplate.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "request.oldObject.spec", "request.oldObject.spec.jobTemplate.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "request.object.metadata", "request.object.spec.jobTemplate.spec.template.metadata")) - obj = []byte(strings.ReplaceAll(string(obj), "request.oldObject.metadata", "request.oldObject.spec.jobTemplate.spec.template.metadata")) + podCELReplacementRules [][2][]byte = [][2][]byte{ + {[]byte("object.spec"), []byte("object.spec.template.spec")}, + {[]byte("oldObject.spec"), []byte("oldObject.spec.template.spec")}, + {[]byte("object.metadata"), []byte("object.spec.template.metadata")}, + {[]byte("oldObject.metadata"), []byte("oldObject.spec.template.metadata")}, } - return obj -} + cronJobReplacementRules [][2][]byte = [][2][]byte{ + {[]byte("request.object.spec"), []byte("request.object.spec.jobTemplate.spec.template.spec")}, + {[]byte("request.oldObject.spec"), []byte("request.oldObject.spec.jobTemplate.spec.template.spec")}, + {[]byte("request.object.metadata"), []byte("request.object.spec.jobTemplate.spec.template.metadata")}, + {[]byte("request.oldObject.metadata"), []byte("request.oldObject.spec.jobTemplate.spec.template.metadata")}, + } + cronJobCELReplacementRules [][2][]byte = [][2][]byte{ + {[]byte("object.spec"), []byte("object.spec.jobTemplate.spec.template.spec")}, + {[]byte("oldObject.spec"), []byte("oldObject.spec.jobTemplate.spec.template.spec")}, + {[]byte("object.metadata"), []byte("object.spec.jobTemplate.spec.template.metadata")}, + {[]byte("oldObject.metadata"), []byte("oldObject.spec.jobTemplate.spec.template.metadata")}, + } +) -func updateCELFields(pbyte []byte, kind string) (obj []byte) { - if kind == "Pod" { - obj = []byte(strings.ReplaceAll(string(pbyte), "object.spec", "object.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "oldObject.spec", "oldObject.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "object.metadata", "object.spec.template.metadata")) - obj = []byte(strings.ReplaceAll(string(obj), "oldObject.metadata", "oldObject.spec.template.metadata")) +func updateFields(data []byte, kind string, cel bool) []byte { + switch kind { + case "Pod": + if cel { + for _, replacement := range podCELReplacementRules { + data = bytes.ReplaceAll(data, replacement[0], replacement[1]) + } + } else { + for _, replacement := range podReplacementRules { + data = bytes.ReplaceAll(data, replacement[0], replacement[1]) + } + } + case "Cronjob": + if cel { + for _, replacement := range cronJobCELReplacementRules { + data = bytes.ReplaceAll(data, replacement[0], replacement[1]) + } + } else { + for _, replacement := range cronJobReplacementRules { + data = bytes.ReplaceAll(data, replacement[0], replacement[1]) + } + } } - if kind == "Cronjob" { - obj = []byte(strings.ReplaceAll(string(pbyte), "object.spec", "object.spec.jobTemplate.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "oldObject.spec", "oldObject.spec.jobTemplate.spec.template.spec")) - obj = []byte(strings.ReplaceAll(string(obj), "object.metadata", "object.spec.jobTemplate.spec.template.metadata")) - obj = []byte(strings.ReplaceAll(string(obj), "oldObject.metadata", "oldObject.spec.jobTemplate.spec.template.metadata")) - } - return obj + + return data }