Integrate CEL in wired off state to appease verify vendor

This commit is contained in:
Joe Betz 2021-11-09 11:19:22 -05:00
parent 89d0623b65
commit 7a593e49ff
6 changed files with 88 additions and 5 deletions

View File

@ -21,7 +21,6 @@ require (
google.golang.org/grpc v1.40.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/api v0.0.0
k8s.io/apimachinery v0.0.0
k8s.io/apiserver v0.0.0

View File

@ -18,15 +18,24 @@ package validation
import (
"encoding/json"
"fmt"
"strings"
"github.com/google/cel-go/cel"
"github.com/google/cel-go/checker/decls"
"github.com/google/cel-go/common/types"
"github.com/google/cel-go/ext"
expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
"k8s.io/apiextensions-apiserver/third_party/forked/celopenapi/model"
"k8s.io/apimachinery/pkg/util/validation/field"
openapierrors "k8s.io/kube-openapi/pkg/validation/errors"
"k8s.io/kube-openapi/pkg/validation/spec"
"k8s.io/kube-openapi/pkg/validation/strfmt"
"k8s.io/kube-openapi/pkg/validation/validate"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"k8s.io/apimachinery/pkg/util/validation/field"
)
// NewSchemaValidator creates an openapi schema validator for the given CRD validation.
@ -330,3 +339,45 @@ func convertJSONSchemaPropsOrStringArray(in *apiextensions.JSONSchemaPropsOrStri
}
return nil
}
// CompileAndValidate provides a sanity check of the CEL validation functionality until we wire in the
// full functionality.
func CompileAndValidate(s *schema.Structural, bindings map[string]interface{}, rule string) (bool, error) {
env, err := cel.NewEnv()
if err != nil {
return false, err
}
reg := model.NewRegistry(env)
rt, err := model.NewRuleTypes("testType", s, reg)
if err != nil {
return false, err
}
opts, err := rt.EnvOptions(env.TypeProvider())
if err != nil {
return false, err
}
root, ok := rt.FindDeclType("testType")
if !ok {
root = model.SchemaDeclType(s).MaybeAssignTypeName("testType")
}
propDecls := []*expr.Decl{decls.NewVar("self", root.ExprType())}
opts = append(opts, cel.Declarations(propDecls...))
opts = append(opts, ext.Strings())
env, err = env.Extend(opts...)
if err != nil {
return false, err
}
ast, issues := env.Compile(rule)
if issues != nil {
return false, fmt.Errorf("issues: %v", issues)
}
prog, err := env.Program(ast)
if err != nil {
return false, err
}
evalResult, _, err := prog.Eval(bindings)
if err != nil {
return false, err
}
return evalResult == types.True, nil
}

View File

@ -23,6 +23,7 @@ import (
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
apiextensionsfuzzer "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
@ -484,3 +485,32 @@ func TestItemsProperty(t *testing.T) {
})
}
}
// TestCompileAndValidate is a placeholder test of CEL validation that will be removed when the actual functionality
// is wired in.
func TestCompileAndValidate(t *testing.T) {
s := &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"name": {
Generic: schema.Generic{
Type: "string",
},
},
},
}
bindings := map[string]interface{}{
"self": map[string]interface{}{
"name": "kube",
},
}
result, err := CompileAndValidate(s, bindings, "self.name == 'kube'")
if err != nil {
t.Fatal(err)
}
if !result {
t.Error("Expected expression to evaluate to true")
}
}

View File

@ -23,6 +23,8 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
)
// TODO: replace escaping with new rules described in kEP update
// celReservedSymbols is a list of RESERVED symbols defined in the CEL lexer.
// No identifiers are allowed to collide with these symbols.
// https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax

View File

@ -128,6 +128,8 @@ var (
})
)
// TODO: embedded objects should have objectMeta only, and name and generateName are both optional
// WithTypeAndObjectMeta ensures the kind, apiVersion and
// metadata.name and metadata.generateName properties are specified, making a shallow copy of the provided schema if needed.
func WithTypeAndObjectMeta(s *schema.Structural) *schema.Structural {

1
vendor/modules.txt vendored
View File

@ -1354,7 +1354,6 @@ k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation
k8s.io/apiextensions-apiserver/pkg/apiserver
k8s.io/apiextensions-apiserver/pkg/apiserver/conversion
k8s.io/apiextensions-apiserver/pkg/apiserver/schema
k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel
k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting
k8s.io/apiextensions-apiserver/pkg/apiserver/schema/listtype
k8s.io/apiextensions-apiserver/pkg/apiserver/schema/objectmeta