From 6af7ab89058a79f6a6ed56da3c9dcd74f209d5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Tue, 14 Jan 2025 15:57:55 +0100 Subject: [PATCH] feat: add CEL variables type checking (#11920) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add CEL variables support Signed-off-by: Charles-Edouard Brétéché * feat: add CEL variables type checking Signed-off-by: Charles-Edouard Brétéché * more types Signed-off-by: Charles-Edouard Brétéché * provider Signed-off-by: Charles-Edouard Brétéché --------- Signed-off-by: Charles-Edouard Brétéché --- pkg/cel/policy/compiler.go | 24 ++++++++++++++++-------- pkg/cel/policy/types.go | 10 ++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 pkg/cel/policy/types.go diff --git a/pkg/cel/policy/compiler.go b/pkg/cel/policy/compiler.go index 00f90c9041..5def2cc130 100644 --- a/pkg/cel/policy/compiler.go +++ b/pkg/cel/policy/compiler.go @@ -10,6 +10,7 @@ import ( "github.com/kyverno/kyverno/pkg/cel/libs/context" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/util/validation/field" + apiservercel "k8s.io/apiserver/pkg/cel" ) const ( @@ -37,17 +38,24 @@ func (c *compiler) Compile(policy *kyvernov2alpha1.ValidatingPolicy) (*CompiledP if err != nil { return nil, append(allErrs, field.InternalError(nil, err)) } - provider := NewVariablesProvider(base.CELTypeProvider()) - env, err := base.Extend( + options := []cel.EnvOption{ cel.Variable(ContextKey, context.ContextType), - cel.Variable(NamespaceObjectKey, cel.DynType), + cel.Variable(NamespaceObjectKey, namespaceType.CelType()), cel.Variable(ObjectKey, cel.DynType), cel.Variable(OldObjectKey, cel.DynType), - cel.Variable(RequestKey, cel.DynType), + cel.Variable(RequestKey, requestType.CelType()), cel.Variable(VariablesKey, VariablesType), - // TODO: params, authorizer, authorizer.requestResource ? - cel.CustomTypeProvider(provider), - ) + } + variablesProvider := NewVariablesProvider(base.CELTypeProvider()) + declProvider := apiservercel.NewDeclTypeProvider(namespaceType, requestType) + declOptions, err := declProvider.EnvOptions(variablesProvider) + if err != nil { + // TODO: proper error handling + panic(err) + } + options = append(options, declOptions...) + // TODO: params, authorizer, authorizer.requestResource ? + env, err := base.Extend(options...) if err != nil { return nil, append(allErrs, field.InternalError(nil, err)) } @@ -81,7 +89,7 @@ func (c *compiler) Compile(policy *kyvernov2alpha1.ValidatingPolicy) (*CompiledP if err := issues.Err(); err != nil { return nil, append(allErrs, field.Invalid(path, variable.Expression, err.Error())) } - provider.RegisterField(variable.Name, ast.OutputType()) + variablesProvider.RegisterField(variable.Name, ast.OutputType()) prog, err := env.Program(ast) if err != nil { return nil, append(allErrs, field.Invalid(path, variable.Expression, err.Error())) diff --git a/pkg/cel/policy/types.go b/pkg/cel/policy/types.go new file mode 100644 index 0000000000..9ec78f4fa4 --- /dev/null +++ b/pkg/cel/policy/types.go @@ -0,0 +1,10 @@ +package policy + +import ( + apiservercel "k8s.io/apiserver/pkg/admission/plugin/cel" +) + +var ( + namespaceType = apiservercel.BuildNamespaceType() + requestType = apiservercel.BuildRequestType() +)