mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 14:13:48 +03:00
caddyhttp: upgrade to cel v0.20.0 (#6161)
* upgrade to cel v0.20.0 * Attempt to address feedback and fix linter * Let's try this * Take that, you linter! * Oh there's more --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com> Co-authored-by: Tristan Swadell @TristonianJones
This commit is contained in:
parent
5b5f8feaf7
commit
52822a41cb
4 changed files with 129 additions and 135 deletions
5
go.mod
5
go.mod
|
@ -12,7 +12,7 @@ require (
|
||||||
github.com/caddyserver/certmagic v0.20.0
|
github.com/caddyserver/certmagic v0.20.0
|
||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/go-chi/chi/v5 v5.0.10
|
github.com/go-chi/chi/v5 v5.0.10
|
||||||
github.com/google/cel-go v0.15.1
|
github.com/google/cel-go v0.20.0
|
||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.3.1
|
||||||
github.com/klauspost/compress v1.17.0
|
github.com/klauspost/compress v1.17.0
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5
|
github.com/klauspost/cpuid/v2 v2.2.5
|
||||||
|
@ -49,7 +49,7 @@ require (
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/iam v1.1.2 // indirect
|
cloud.google.com/go/iam v1.1.2 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
|
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
||||||
github.com/golang/glog v1.1.2 // indirect
|
github.com/golang/glog v1.1.2 // indirect
|
||||||
|
@ -70,6 +70,7 @@ require (
|
||||||
go.opentelemetry.io/contrib/propagators/jaeger v1.17.0 // indirect
|
go.opentelemetry.io/contrib/propagators/jaeger v1.17.0 // indirect
|
||||||
go.opentelemetry.io/contrib/propagators/ot v1.17.0 // indirect
|
go.opentelemetry.io/contrib/propagators/ot v1.17.0 // indirect
|
||||||
go.uber.org/mock v0.3.0 // indirect
|
go.uber.org/mock v0.3.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -44,8 +44,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
|
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
|
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
@ -199,8 +199,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/cel-go v0.15.1 h1:iTgVZor2x9okXtmTrqO8cg4uvqIeaBcWhXtruaWFMYQ=
|
github.com/google/cel-go v0.20.0 h1:h4n6DOCppEMpWERzllyNkntl7JrDyxoE543KWS6BLpc=
|
||||||
github.com/google/cel-go v0.15.1/go.mod h1:YzWEoI07MC/a/wj9in8GeVatqfypkldgBlwXh9bCwqY=
|
github.com/google/cel-go v0.20.0/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
|
||||||
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||||
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745 h1:heyoXNxkRT155x4jTAiSv5BVSVkueifPUm+Q8LUXMRo=
|
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745 h1:heyoXNxkRT155x4jTAiSv5BVSVkueifPUm+Q8LUXMRo=
|
||||||
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745/go.mod h1:zN0wUQgV9LjwLZeFHnrAbQi8hzMVvEWePyk+MhPOk7k=
|
github.com/google/certificate-transparency-go v1.1.8-0.20240110162603-74a5dd331745/go.mod h1:zN0wUQgV9LjwLZeFHnrAbQi8hzMVvEWePyk+MhPOk7k=
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/google/cel-go/cel"
|
"github.com/google/cel-go/cel"
|
||||||
"github.com/google/cel-go/common"
|
"github.com/google/cel-go/common"
|
||||||
|
"github.com/google/cel-go/common/ast"
|
||||||
"github.com/google/cel-go/common/operators"
|
"github.com/google/cel-go/common/operators"
|
||||||
"github.com/google/cel-go/common/types"
|
"github.com/google/cel-go/common/types"
|
||||||
"github.com/google/cel-go/common/types/ref"
|
"github.com/google/cel-go/common/types/ref"
|
||||||
|
@ -36,7 +37,6 @@ import (
|
||||||
"github.com/google/cel-go/interpreter/functions"
|
"github.com/google/cel-go/interpreter/functions"
|
||||||
"github.com/google/cel-go/parser"
|
"github.com/google/cel-go/parser"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||||
|
@ -66,7 +66,7 @@ type MatchExpression struct {
|
||||||
|
|
||||||
expandedExpr string
|
expandedExpr string
|
||||||
prg cel.Program
|
prg cel.Program
|
||||||
ta ref.TypeAdapter
|
ta types.Adapter
|
||||||
|
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ func (m MatchExpression) caddyPlaceholderFunc(lhs, rhs ref.Val) ref.Val {
|
||||||
}
|
}
|
||||||
|
|
||||||
// httpRequestCELType is the type representation of a native HTTP request.
|
// httpRequestCELType is the type representation of a native HTTP request.
|
||||||
var httpRequestCELType = types.NewTypeValue("http.Request", traits.ReceiverType)
|
var httpRequestCELType = cel.ObjectType("http.Request", traits.ReceiverType)
|
||||||
|
|
||||||
// celHTTPRequest wraps an http.Request with ref.Val interface methods.
|
// celHTTPRequest wraps an http.Request with ref.Val interface methods.
|
||||||
//
|
//
|
||||||
|
@ -263,7 +263,7 @@ func (cr celHTTPRequest) Equal(other ref.Val) ref.Val {
|
||||||
func (celHTTPRequest) Type() ref.Type { return httpRequestCELType }
|
func (celHTTPRequest) Type() ref.Type { return httpRequestCELType }
|
||||||
func (cr celHTTPRequest) Value() any { return cr }
|
func (cr celHTTPRequest) Value() any { return cr }
|
||||||
|
|
||||||
var pkixNameCELType = types.NewTypeValue("pkix.Name", traits.ReceiverType)
|
var pkixNameCELType = cel.ObjectType("pkix.Name", traits.ReceiverType)
|
||||||
|
|
||||||
// celPkixName wraps an pkix.Name with
|
// celPkixName wraps an pkix.Name with
|
||||||
// methods to satisfy the ref.Val interface.
|
// methods to satisfy the ref.Val interface.
|
||||||
|
@ -472,25 +472,20 @@ func CELMatcherRuntimeFunction(funcName string, fac CELMatcherFactory) functions
|
||||||
//
|
//
|
||||||
// The arguments are collected into a single list argument the following
|
// The arguments are collected into a single list argument the following
|
||||||
// function call returned: <funcName>(request, [args])
|
// function call returned: <funcName>(request, [args])
|
||||||
func celMatcherStringListMacroExpander(funcName string) parser.MacroExpander {
|
func celMatcherStringListMacroExpander(funcName string) cel.MacroFactory {
|
||||||
return func(eh parser.ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
|
return func(eh cel.MacroExprFactory, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error) {
|
||||||
matchArgs := []*exprpb.Expr{}
|
matchArgs := []ast.Expr{}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(0, "matcher requires at least one argument")
|
||||||
Message: "matcher requires at least one argument",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if isCELStringExpr(arg) {
|
if isCELStringExpr(arg) {
|
||||||
matchArgs = append(matchArgs, arg)
|
matchArgs = append(matchArgs, arg)
|
||||||
} else {
|
} else {
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(arg.ID(), "matcher arguments must be string constants")
|
||||||
Location: eh.OffsetLocation(arg.GetId()),
|
|
||||||
Message: "matcher arguments must be string constants",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return eh.GlobalCall(funcName, eh.Ident("request"), eh.NewList(matchArgs...)), nil
|
return eh.NewCall(funcName, eh.NewIdent("request"), eh.NewList(matchArgs...)), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,19 +494,14 @@ func celMatcherStringListMacroExpander(funcName string) parser.MacroExpander {
|
||||||
//
|
//
|
||||||
// The following function call is returned: <funcName>(request, arg)
|
// The following function call is returned: <funcName>(request, arg)
|
||||||
func celMatcherStringMacroExpander(funcName string) parser.MacroExpander {
|
func celMatcherStringMacroExpander(funcName string) parser.MacroExpander {
|
||||||
return func(eh parser.ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
|
return func(eh cel.MacroExprFactory, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(0, "matcher requires one argument")
|
||||||
Message: "matcher requires one argument",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if isCELStringExpr(args[0]) {
|
if isCELStringExpr(args[0]) {
|
||||||
return eh.GlobalCall(funcName, eh.Ident("request"), args[0]), nil
|
return eh.NewCall(funcName, eh.NewIdent("request"), args[0]), nil
|
||||||
}
|
|
||||||
return nil, &common.Error{
|
|
||||||
Location: eh.OffsetLocation(args[0].GetId()),
|
|
||||||
Message: "matcher argument must be a string literal",
|
|
||||||
}
|
}
|
||||||
|
return nil, eh.NewError(args[0].ID(), "matcher argument must be a string literal")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,49 +510,35 @@ func celMatcherStringMacroExpander(funcName string) parser.MacroExpander {
|
||||||
//
|
//
|
||||||
// The following function call is returned: <funcName>(request, arg)
|
// The following function call is returned: <funcName>(request, arg)
|
||||||
func celMatcherJSONMacroExpander(funcName string) parser.MacroExpander {
|
func celMatcherJSONMacroExpander(funcName string) parser.MacroExpander {
|
||||||
return func(eh parser.ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
|
return func(eh cel.MacroExprFactory, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(0, "matcher requires a map literal argument")
|
||||||
Message: "matcher requires a map literal argument",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch arg.GetExprKind().(type) {
|
|
||||||
case *exprpb.Expr_StructExpr:
|
switch arg.Kind() {
|
||||||
structExpr := arg.GetStructExpr()
|
case ast.StructKind:
|
||||||
if structExpr.GetMessageName() != "" {
|
return nil, eh.NewError(arg.ID(),
|
||||||
return nil, &common.Error{
|
fmt.Sprintf("matcher input must be a map literal, not a %s", arg.AsStruct().TypeName()))
|
||||||
Location: eh.OffsetLocation(arg.GetId()),
|
case ast.MapKind:
|
||||||
Message: fmt.Sprintf(
|
mapExpr := arg.AsMap()
|
||||||
"matcher input must be a map literal, not a %s",
|
for _, entry := range mapExpr.Entries() {
|
||||||
structExpr.GetMessageName(),
|
isStringPlaceholder := isCELStringExpr(entry.AsMapEntry().Key())
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, entry := range structExpr.GetEntries() {
|
|
||||||
isStringPlaceholder := isCELStringExpr(entry.GetMapKey())
|
|
||||||
if !isStringPlaceholder {
|
if !isStringPlaceholder {
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(entry.ID(), "matcher map keys must be string literals")
|
||||||
Location: eh.OffsetLocation(entry.GetId()),
|
|
||||||
Message: "matcher map keys must be string literals",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
isStringListPlaceholder := isCELStringExpr(entry.GetValue()) ||
|
isStringListPlaceholder := isCELStringExpr(entry.AsMapEntry().Value()) ||
|
||||||
isCELStringListLiteral(entry.GetValue())
|
isCELStringListLiteral(entry.AsMapEntry().Value())
|
||||||
if !isStringListPlaceholder {
|
if !isStringListPlaceholder {
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(entry.AsMapEntry().Value().ID(), "matcher map values must be string or list literals")
|
||||||
Location: eh.OffsetLocation(entry.GetValue().GetId()),
|
|
||||||
Message: "matcher map values must be string or list literals",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return eh.GlobalCall(funcName, eh.Ident("request"), arg), nil
|
return eh.NewCall(funcName, eh.NewIdent("request"), arg), nil
|
||||||
|
case ast.UnspecifiedExprKind, ast.CallKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.LiteralKind, ast.SelectKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &common.Error{
|
return nil, eh.NewError(arg.ID(), "matcher requires a map literal argument")
|
||||||
Location: eh.OffsetLocation(arg.GetId()),
|
|
||||||
Message: "matcher requires a map literal argument",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,69 +583,77 @@ func CELValueToMapStrList(data ref.Val) (map[string][]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELStringExpr indicates whether the expression is a supported string expression
|
// isCELStringExpr indicates whether the expression is a supported string expression
|
||||||
func isCELStringExpr(e *exprpb.Expr) bool {
|
func isCELStringExpr(e ast.Expr) bool {
|
||||||
return isCELStringLiteral(e) || isCELCaddyPlaceholderCall(e) || isCELConcatCall(e)
|
return isCELStringLiteral(e) || isCELCaddyPlaceholderCall(e) || isCELConcatCall(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELStringLiteral returns whether the expression is a CEL string literal.
|
// isCELStringLiteral returns whether the expression is a CEL string literal.
|
||||||
func isCELStringLiteral(e *exprpb.Expr) bool {
|
func isCELStringLiteral(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_ConstExpr:
|
case ast.LiteralKind:
|
||||||
constant := e.GetConstExpr()
|
constant := e.AsLiteral()
|
||||||
switch constant.GetConstantKind().(type) {
|
switch constant.Type() {
|
||||||
case *exprpb.Constant_StringValue:
|
case types.StringType:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
case ast.UnspecifiedExprKind, ast.CallKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELCaddyPlaceholderCall returns whether the expression is a caddy placeholder call.
|
// isCELCaddyPlaceholderCall returns whether the expression is a caddy placeholder call.
|
||||||
func isCELCaddyPlaceholderCall(e *exprpb.Expr) bool {
|
func isCELCaddyPlaceholderCall(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_CallExpr:
|
case ast.CallKind:
|
||||||
call := e.GetCallExpr()
|
call := e.AsCall()
|
||||||
if call.GetFunction() == "caddyPlaceholder" {
|
if call.FunctionName() == "caddyPlaceholder" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
case ast.UnspecifiedExprKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.LiteralKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELConcatCall tests whether the expression is a concat function (+) with string, placeholder, or
|
// isCELConcatCall tests whether the expression is a concat function (+) with string, placeholder, or
|
||||||
// other concat call arguments.
|
// other concat call arguments.
|
||||||
func isCELConcatCall(e *exprpb.Expr) bool {
|
func isCELConcatCall(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_CallExpr:
|
case ast.CallKind:
|
||||||
call := e.GetCallExpr()
|
call := e.AsCall()
|
||||||
if call.GetTarget() != nil {
|
if call.Target().Kind() != ast.UnspecifiedExprKind {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if call.GetFunction() != operators.Add {
|
if call.FunctionName() != operators.Add {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, arg := range call.GetArgs() {
|
for _, arg := range call.Args() {
|
||||||
if !isCELStringExpr(arg) {
|
if !isCELStringExpr(arg) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
case ast.UnspecifiedExprKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.LiteralKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELStringListLiteral returns whether the expression resolves to a list literal
|
// isCELStringListLiteral returns whether the expression resolves to a list literal
|
||||||
// containing only string constants or a placeholder call.
|
// containing only string constants or a placeholder call.
|
||||||
func isCELStringListLiteral(e *exprpb.Expr) bool {
|
func isCELStringListLiteral(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_ListExpr:
|
case ast.ListKind:
|
||||||
list := e.GetListExpr()
|
list := e.AsList()
|
||||||
for _, elem := range list.GetElements() {
|
for _, elem := range list.Elements() {
|
||||||
if !isCELStringExpr(elem) {
|
if !isCELStringExpr(elem) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
case ast.UnspecifiedExprKind, ast.CallKind, ast.ComprehensionKind, ast.IdentKind, ast.LiteralKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,12 @@ import (
|
||||||
|
|
||||||
"github.com/google/cel-go/cel"
|
"github.com/google/cel-go/cel"
|
||||||
"github.com/google/cel-go/common"
|
"github.com/google/cel-go/common"
|
||||||
|
"github.com/google/cel-go/common/ast"
|
||||||
"github.com/google/cel-go/common/operators"
|
"github.com/google/cel-go/common/operators"
|
||||||
|
"github.com/google/cel-go/common/types"
|
||||||
"github.com/google/cel-go/common/types/ref"
|
"github.com/google/cel-go/common/types/ref"
|
||||||
"github.com/google/cel-go/parser"
|
"github.com/google/cel-go/parser"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
||||||
|
@ -220,30 +221,30 @@ func (MatchFile) CELLibrary(ctx caddy.Context) (cel.Library, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func celFileMatcherMacroExpander() parser.MacroExpander {
|
func celFileMatcherMacroExpander() parser.MacroExpander {
|
||||||
return func(eh parser.ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) {
|
return func(eh parser.ExprHelper, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return eh.GlobalCall("file",
|
return eh.NewCall("file",
|
||||||
eh.Ident("request"),
|
eh.NewIdent("request"),
|
||||||
eh.NewMap(),
|
eh.NewMap(),
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
if isCELStringLiteral(arg) || isCELCaddyPlaceholderCall(arg) {
|
if isCELStringLiteral(arg) || isCELCaddyPlaceholderCall(arg) {
|
||||||
return eh.GlobalCall("file",
|
return eh.NewCall("file",
|
||||||
eh.Ident("request"),
|
eh.NewIdent("request"),
|
||||||
eh.NewMap(eh.NewMapEntry(
|
eh.NewMap(eh.NewMapEntry(
|
||||||
eh.LiteralString("try_files"),
|
eh.NewLiteral(types.String("try_files")),
|
||||||
eh.NewList(arg),
|
eh.NewList(arg),
|
||||||
false,
|
false,
|
||||||
)),
|
)),
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
if isCELTryFilesLiteral(arg) {
|
if isCELTryFilesLiteral(arg) {
|
||||||
return eh.GlobalCall("file", eh.Ident("request"), arg), nil
|
return eh.NewCall("file", eh.NewIdent("request"), arg), nil
|
||||||
}
|
}
|
||||||
return nil, &common.Error{
|
return nil, &common.Error{
|
||||||
Location: eh.OffsetLocation(arg.GetId()),
|
Location: eh.OffsetLocation(arg.ID()),
|
||||||
Message: "matcher requires either a map or string literal argument",
|
Message: "matcher requires either a map or string literal argument",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,15 +252,15 @@ func celFileMatcherMacroExpander() parser.MacroExpander {
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if !(isCELStringLiteral(arg) || isCELCaddyPlaceholderCall(arg)) {
|
if !(isCELStringLiteral(arg) || isCELCaddyPlaceholderCall(arg)) {
|
||||||
return nil, &common.Error{
|
return nil, &common.Error{
|
||||||
Location: eh.OffsetLocation(arg.GetId()),
|
Location: eh.OffsetLocation(arg.ID()),
|
||||||
Message: "matcher only supports repeated string literal arguments",
|
Message: "matcher only supports repeated string literal arguments",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return eh.GlobalCall("file",
|
return eh.NewCall("file",
|
||||||
eh.Ident("request"),
|
eh.NewIdent("request"),
|
||||||
eh.NewMap(eh.NewMapEntry(
|
eh.NewMap(eh.NewMapEntry(
|
||||||
eh.LiteralString("try_files"),
|
eh.NewLiteral(types.String("try_files")),
|
||||||
eh.NewList(args...),
|
eh.NewList(args...),
|
||||||
false,
|
false,
|
||||||
)),
|
)),
|
||||||
|
@ -569,20 +570,17 @@ func indexFold(haystack, needle string) int {
|
||||||
|
|
||||||
// isCELTryFilesLiteral returns whether the expression resolves to a map literal containing
|
// isCELTryFilesLiteral returns whether the expression resolves to a map literal containing
|
||||||
// only string keys with or a placeholder call.
|
// only string keys with or a placeholder call.
|
||||||
func isCELTryFilesLiteral(e *exprpb.Expr) bool {
|
func isCELTryFilesLiteral(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_StructExpr:
|
case ast.MapKind:
|
||||||
structExpr := e.GetStructExpr()
|
mapExpr := e.AsMap()
|
||||||
if structExpr.GetMessageName() != "" {
|
for _, entry := range mapExpr.Entries() {
|
||||||
return false
|
mapKey := entry.AsMapEntry().Key()
|
||||||
}
|
mapVal := entry.AsMapEntry().Value()
|
||||||
for _, entry := range structExpr.GetEntries() {
|
|
||||||
mapKey := entry.GetMapKey()
|
|
||||||
mapVal := entry.GetValue()
|
|
||||||
if !isCELStringLiteral(mapKey) {
|
if !isCELStringLiteral(mapKey) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mapKeyStr := mapKey.GetConstExpr().GetStringValue()
|
mapKeyStr := mapKey.AsLiteral().ConvertToType(types.StringType).Value()
|
||||||
if mapKeyStr == "try_files" || mapKeyStr == "split_path" {
|
if mapKeyStr == "try_files" || mapKeyStr == "split_path" {
|
||||||
if !isCELStringListLiteral(mapVal) {
|
if !isCELStringListLiteral(mapVal) {
|
||||||
return false
|
return false
|
||||||
|
@ -596,74 +594,85 @@ func isCELTryFilesLiteral(e *exprpb.Expr) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case ast.UnspecifiedExprKind, ast.CallKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.LiteralKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELStringExpr indicates whether the expression is a supported string expression
|
// isCELStringExpr indicates whether the expression is a supported string expression
|
||||||
func isCELStringExpr(e *exprpb.Expr) bool {
|
func isCELStringExpr(e ast.Expr) bool {
|
||||||
return isCELStringLiteral(e) || isCELCaddyPlaceholderCall(e) || isCELConcatCall(e)
|
return isCELStringLiteral(e) || isCELCaddyPlaceholderCall(e) || isCELConcatCall(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELStringLiteral returns whether the expression is a CEL string literal.
|
// isCELStringLiteral returns whether the expression is a CEL string literal.
|
||||||
func isCELStringLiteral(e *exprpb.Expr) bool {
|
func isCELStringLiteral(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_ConstExpr:
|
case ast.LiteralKind:
|
||||||
constant := e.GetConstExpr()
|
constant := e.AsLiteral()
|
||||||
switch constant.GetConstantKind().(type) {
|
switch constant.Type() {
|
||||||
case *exprpb.Constant_StringValue:
|
case types.StringType:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
case ast.UnspecifiedExprKind, ast.CallKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELCaddyPlaceholderCall returns whether the expression is a caddy placeholder call.
|
// isCELCaddyPlaceholderCall returns whether the expression is a caddy placeholder call.
|
||||||
func isCELCaddyPlaceholderCall(e *exprpb.Expr) bool {
|
func isCELCaddyPlaceholderCall(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_CallExpr:
|
case ast.CallKind:
|
||||||
call := e.GetCallExpr()
|
call := e.AsCall()
|
||||||
if call.GetFunction() == "caddyPlaceholder" {
|
if call.FunctionName() == "caddyPlaceholder" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
case ast.UnspecifiedExprKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.LiteralKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELConcatCall tests whether the expression is a concat function (+) with string, placeholder, or
|
// isCELConcatCall tests whether the expression is a concat function (+) with string, placeholder, or
|
||||||
// other concat call arguments.
|
// other concat call arguments.
|
||||||
func isCELConcatCall(e *exprpb.Expr) bool {
|
func isCELConcatCall(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_CallExpr:
|
case ast.CallKind:
|
||||||
call := e.GetCallExpr()
|
call := e.AsCall()
|
||||||
if call.GetTarget() != nil {
|
if call.Target().Kind() != ast.UnspecifiedExprKind {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if call.GetFunction() != operators.Add {
|
if call.FunctionName() != operators.Add {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, arg := range call.GetArgs() {
|
for _, arg := range call.Args() {
|
||||||
if !isCELStringExpr(arg) {
|
if !isCELStringExpr(arg) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
case ast.UnspecifiedExprKind, ast.ComprehensionKind, ast.IdentKind, ast.ListKind, ast.LiteralKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCELStringListLiteral returns whether the expression resolves to a list literal
|
// isCELStringListLiteral returns whether the expression resolves to a list literal
|
||||||
// containing only string constants or a placeholder call.
|
// containing only string constants or a placeholder call.
|
||||||
func isCELStringListLiteral(e *exprpb.Expr) bool {
|
func isCELStringListLiteral(e ast.Expr) bool {
|
||||||
switch e.GetExprKind().(type) {
|
switch e.Kind() {
|
||||||
case *exprpb.Expr_ListExpr:
|
case ast.ListKind:
|
||||||
list := e.GetListExpr()
|
list := e.AsList()
|
||||||
for _, elem := range list.GetElements() {
|
for _, elem := range list.Elements() {
|
||||||
if !isCELStringExpr(elem) {
|
if !isCELStringExpr(elem) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
case ast.UnspecifiedExprKind, ast.CallKind, ast.ComprehensionKind, ast.IdentKind, ast.LiteralKind, ast.MapKind, ast.SelectKind, ast.StructKind:
|
||||||
|
// appeasing the linter :)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue