cel: use generic env from https://codeberg.org/gone/http-cel
This commit is contained in:
7
go.mod
7
go.mod
@@ -5,6 +5,7 @@ go 1.24.0
|
|||||||
toolchain go1.24.2
|
toolchain go1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
codeberg.org/gone/http-cel v1.0.0
|
||||||
codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756
|
codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756
|
||||||
github.com/alphadose/haxmap v1.4.1
|
github.com/alphadose/haxmap v1.4.1
|
||||||
github.com/go-jose/go-jose/v4 v4.1.0
|
github.com/go-jose/go-jose/v4 v4.1.0
|
||||||
@@ -26,9 +27,9 @@ require (
|
|||||||
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
||||||
github.com/kevinpollet/nego v0.0.0-20211010160919-a65cd48cee43 // indirect
|
github.com/kevinpollet/nego v0.0.0-20211010160919-a65cd48cee43 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.62.0 // indirect
|
github.com/prometheus/common v0.63.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||||
golang.org/x/net v0.39.0 // indirect
|
golang.org/x/net v0.39.0 // indirect
|
||||||
|
14
go.sum
14
go.sum
@@ -1,5 +1,7 @@
|
|||||||
cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
|
cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
|
||||||
cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||||
|
codeberg.org/gone/http-cel v1.0.0 h1:flEv/KzEye4W7vjwkdAkwo7VCbuj9xZLjyTn/rjWFDQ=
|
||||||
|
codeberg.org/gone/http-cel v1.0.0/go.mod h1:uRkxygsQp5EFE3e9dRkJ4HK453G5YZDHCq9DEG5CoDw=
|
||||||
codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756 h1:bDqEUEYt4UJy8mfLCZeJuXx+xNJvdqTbkE4Ci11NQYU=
|
codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756 h1:bDqEUEYt4UJy8mfLCZeJuXx+xNJvdqTbkE4Ci11NQYU=
|
||||||
codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756/go.mod h1:aJ/ghJW7viYfwZ6OizDst+uJgbb6r/Hvoqhmi1OPTTw=
|
codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756/go.mod h1:aJ/ghJW7viYfwZ6OizDst+uJgbb6r/Hvoqhmi1OPTTw=
|
||||||
github.com/alphadose/haxmap v1.4.1 h1:VtD6VCxUkjNIfJk/aWdYFfOzrRddDFjmvmRmILg7x8Q=
|
github.com/alphadose/haxmap v1.4.1 h1:VtD6VCxUkjNIfJk/aWdYFfOzrRddDFjmvmRmILg7x8Q=
|
||||||
@@ -39,12 +41,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
package challenge
|
package challenge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
http_cel "codeberg.org/gone/http-cel"
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.gammaspectra.live/git/go-away/lib/condition"
|
|
||||||
"git.gammaspectra.live/git/go-away/utils"
|
"git.gammaspectra.live/git/go-away/utils"
|
||||||
"github.com/google/cel-go/cel"
|
"github.com/google/cel-go/cel"
|
||||||
"github.com/google/cel-go/common/types"
|
"github.com/google/cel-go/common/types"
|
||||||
@@ -73,8 +73,8 @@ func CreateRequestData(r *http.Request, state StateInterface) (*http.Request, *R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.query = condition.NewValuesMap(r.URL.Query())
|
data.query = http_cel.NewValuesMap(r.URL.Query())
|
||||||
data.header = condition.NewMIMEMap(textproto.MIMEHeader(r.Header))
|
data.header = http_cel.NewMIMEMap(textproto.MIMEHeader(r.Header))
|
||||||
|
|
||||||
sum := sha256.New()
|
sum := sha256.New()
|
||||||
sum.Write([]byte(r.Host))
|
sum.Write([]byte(r.Host))
|
||||||
|
@@ -2,10 +2,10 @@ package challenge
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
http_cel "codeberg.org/gone/http-cel"
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.gammaspectra.live/git/go-away/lib/condition"
|
|
||||||
"git.gammaspectra.live/git/go-away/lib/policy"
|
"git.gammaspectra.live/git/go-away/lib/policy"
|
||||||
"github.com/go-jose/go-jose/v4"
|
"github.com/go-jose/go-jose/v4"
|
||||||
"github.com/go-jose/go-jose/v4/jwt"
|
"github.com/go-jose/go-jose/v4/jwt"
|
||||||
@@ -67,11 +67,11 @@ func (r Register) Create(state StateInterface, name string, pol policy.Challenge
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(conditions) > 0 {
|
if len(conditions) > 0 {
|
||||||
ast, err := condition.FromStrings(state.ProgramEnv(), condition.OperatorOr, conditions...)
|
ast, err := http_cel.NewAst(state.ProgramEnv(), http_cel.OperatorOr, conditions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("error compiling conditions: %v", err)
|
return nil, 0, fmt.Errorf("error compiling conditions: %v", err)
|
||||||
}
|
}
|
||||||
reg.Condition, err = condition.Program(state.ProgramEnv(), ast)
|
reg.Condition, err = http_cel.ProgramAst(state.ProgramEnv(), ast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("error compiling program: %v", err)
|
return nil, 0, fmt.Errorf("error compiling program: %v", err)
|
||||||
}
|
}
|
||||||
|
@@ -1,177 +0,0 @@
|
|||||||
package condition
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/google/cel-go/cel"
|
|
||||||
"github.com/google/cel-go/common/types"
|
|
||||||
"github.com/google/cel-go/common/types/ref"
|
|
||||||
"github.com/google/cel-go/ext"
|
|
||||||
"github.com/yl2chen/cidranger"
|
|
||||||
"log/slog"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Condition struct {
|
|
||||||
Expression *cel.Ast
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
OperatorOr = "||"
|
|
||||||
OperatorAnd = "&&"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewRulesEnvironment(networks map[string]cidranger.Ranger) (*cel.Env, error) {
|
|
||||||
|
|
||||||
return cel.NewEnv(
|
|
||||||
ext.Strings(
|
|
||||||
ext.StringsLocale("en_US"),
|
|
||||||
ext.StringsValidateFormatCalls(true),
|
|
||||||
),
|
|
||||||
cel.DefaultUTCTimeZone(true),
|
|
||||||
//TODO: custom type for remoteAddress
|
|
||||||
cel.Variable("remoteAddress", cel.BytesType),
|
|
||||||
cel.Variable("host", cel.StringType),
|
|
||||||
cel.Variable("method", cel.StringType),
|
|
||||||
cel.Variable("userAgent", cel.StringType),
|
|
||||||
cel.Variable("path", cel.StringType),
|
|
||||||
cel.Variable("query", cel.MapType(cel.StringType, cel.StringType)),
|
|
||||||
cel.Variable("fp", cel.MapType(cel.StringType, cel.StringType)),
|
|
||||||
// http.Header
|
|
||||||
cel.Variable("headers", cel.MapType(cel.StringType, cel.StringType)),
|
|
||||||
//TODO: dynamic type?
|
|
||||||
cel.Function("inDNSBL",
|
|
||||||
cel.Overload("inDNSBL_ip",
|
|
||||||
[]*cel.Type{cel.AnyType},
|
|
||||||
cel.BoolType,
|
|
||||||
cel.UnaryBinding(func(val ref.Val) ref.Val {
|
|
||||||
slog.Error("inDNSBL function has been deprecated, replace with dnsbl challenge")
|
|
||||||
return types.Bool(false)
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
cel.Function("network",
|
|
||||||
cel.MemberOverload("netIP_network_string",
|
|
||||||
[]*cel.Type{cel.BytesType, cel.StringType},
|
|
||||||
cel.BoolType,
|
|
||||||
cel.BinaryBinding(func(lhs ref.Val, rhs ref.Val) ref.Val {
|
|
||||||
var ip net.IP
|
|
||||||
switch v := lhs.Value().(type) {
|
|
||||||
case []byte:
|
|
||||||
ip = v
|
|
||||||
case net.IP:
|
|
||||||
ip = v
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip == nil {
|
|
||||||
panic(fmt.Errorf("invalid ip %v", lhs.Value()))
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok := rhs.Value().(string)
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("invalid network value %v", rhs.Value()))
|
|
||||||
}
|
|
||||||
|
|
||||||
network, ok := networks[val]
|
|
||||||
if !ok {
|
|
||||||
_, ipNet, err := net.ParseCIDR(val)
|
|
||||||
if err != nil {
|
|
||||||
panic("network not found")
|
|
||||||
}
|
|
||||||
return types.Bool(ipNet.Contains(ip))
|
|
||||||
} else {
|
|
||||||
ok, err := network.Contains(ip)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return types.Bool(ok)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
cel.Function("inNetwork",
|
|
||||||
cel.Overload("inNetwork_string_ip",
|
|
||||||
[]*cel.Type{cel.StringType, cel.BytesType},
|
|
||||||
cel.BoolType,
|
|
||||||
cel.BinaryBinding(func(lhs ref.Val, rhs ref.Val) ref.Val {
|
|
||||||
var ip net.IP
|
|
||||||
switch v := rhs.Value().(type) {
|
|
||||||
case []byte:
|
|
||||||
ip = v
|
|
||||||
case net.IP:
|
|
||||||
ip = v
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip == nil {
|
|
||||||
panic(fmt.Errorf("invalid ip %v", rhs.Value()))
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok := lhs.Value().(string)
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("invalid value %v", lhs.Value()))
|
|
||||||
}
|
|
||||||
slog.Debug(fmt.Sprintf("inNetwork function has been deprecated and will be removed in a future release, use remoteAddress.network(\"%s\") instead", val))
|
|
||||||
|
|
||||||
network, ok := networks[val]
|
|
||||||
if !ok {
|
|
||||||
_, ipNet, err := net.ParseCIDR(val)
|
|
||||||
if err != nil {
|
|
||||||
panic("network not found")
|
|
||||||
}
|
|
||||||
return types.Bool(ipNet.Contains(ip))
|
|
||||||
} else {
|
|
||||||
ok, err := network.Contains(ip)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return types.Bool(ok)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Program(env *cel.Env, ast *cel.Ast) (cel.Program, error) {
|
|
||||||
return env.Program(ast,
|
|
||||||
cel.EvalOptions(cel.OptOptimize),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromStrings(env *cel.Env, operator string, conditions ...string) (*cel.Ast, error) {
|
|
||||||
var asts []*cel.Ast
|
|
||||||
for _, c := range conditions {
|
|
||||||
ast, issues := env.Compile(c)
|
|
||||||
if issues != nil && issues.Err() != nil {
|
|
||||||
return nil, fmt.Errorf("condition %s: %s", issues.Err(), c)
|
|
||||||
}
|
|
||||||
asts = append(asts, ast)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Merge(env, operator, asts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Merge(env *cel.Env, operator string, conditions ...*cel.Ast) (*cel.Ast, error) {
|
|
||||||
if len(conditions) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
} else if len(conditions) == 1 {
|
|
||||||
return conditions[0], nil
|
|
||||||
}
|
|
||||||
var asts []string
|
|
||||||
for _, c := range conditions {
|
|
||||||
ast, err := cel.AstToString(c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
asts = append(asts, "("+ast+")")
|
|
||||||
}
|
|
||||||
|
|
||||||
condition := strings.Join(asts, " "+operator+" ")
|
|
||||||
ast, issues := env.Compile(condition)
|
|
||||||
if issues != nil && issues.Err() != nil {
|
|
||||||
return nil, issues.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ast, nil
|
|
||||||
}
|
|
@@ -1,158 +0,0 @@
|
|||||||
package condition
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/google/cel-go/common/types"
|
|
||||||
"github.com/google/cel-go/common/types/ref"
|
|
||||||
"github.com/google/cel-go/common/types/traits"
|
|
||||||
"net/textproto"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mimeLike struct {
|
|
||||||
m textproto.MIMEHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
|
||||||
return nil, fmt.Errorf("type conversion error from map to '%v'", typeDesc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) ConvertToType(typeVal ref.Type) ref.Val {
|
|
||||||
switch typeVal {
|
|
||||||
case types.MapType:
|
|
||||||
return a
|
|
||||||
case types.TypeType:
|
|
||||||
return types.MapType
|
|
||||||
}
|
|
||||||
return types.NewErr("type conversion error from '%s' to '%s'", types.MapType, typeVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Equal(other ref.Val) ref.Val {
|
|
||||||
return types.Bool(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Type() ref.Type {
|
|
||||||
return types.MapType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Value() any {
|
|
||||||
return a.m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Contains(key ref.Val) ref.Val {
|
|
||||||
_, found := a.Find(key)
|
|
||||||
return types.Bool(found)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Get(key ref.Val) ref.Val {
|
|
||||||
v, found := a.Find(key)
|
|
||||||
if !found {
|
|
||||||
return types.ValOrErr(v, "no such key: %v", key)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Iterator() traits.Iterator {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) IsZeroValue() bool {
|
|
||||||
return len(a.m) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Size() ref.Val {
|
|
||||||
return types.Int(len(a.m))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a mimeLike) Find(key ref.Val) (ref.Val, bool) {
|
|
||||||
k, ok := key.(types.String)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return singleVal(a.m.Values(string(k)), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
type valuesLike struct {
|
|
||||||
m map[string][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
|
||||||
return nil, fmt.Errorf("type conversion error from map to '%v'", typeDesc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) ConvertToType(typeVal ref.Type) ref.Val {
|
|
||||||
switch typeVal {
|
|
||||||
case types.MapType:
|
|
||||||
return a
|
|
||||||
case types.TypeType:
|
|
||||||
return types.MapType
|
|
||||||
}
|
|
||||||
return types.NewErr("type conversion error from '%s' to '%s'", types.MapType, typeVal)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Equal(other ref.Val) ref.Val {
|
|
||||||
return types.Bool(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Type() ref.Type {
|
|
||||||
return types.MapType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Value() any {
|
|
||||||
return a.m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Contains(key ref.Val) ref.Val {
|
|
||||||
_, found := a.Find(key)
|
|
||||||
return types.Bool(found)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Get(key ref.Val) ref.Val {
|
|
||||||
v, found := a.Find(key)
|
|
||||||
if !found {
|
|
||||||
return types.ValOrErr(v, "no such key: %v", key)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Iterator() traits.Iterator {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) IsZeroValue() bool {
|
|
||||||
return len(a.m) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Size() ref.Val {
|
|
||||||
return types.Int(len(a.m))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a valuesLike) Find(key ref.Val) (ref.Val, bool) {
|
|
||||||
k, ok := key.(types.String)
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok := a.m[string(k)]
|
|
||||||
return singleVal(val, ok)
|
|
||||||
}
|
|
||||||
|
|
||||||
func singleVal(values []string, ok bool) (ref.Val, bool) {
|
|
||||||
if len(values) == 0 || !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
if len(values) > 1 {
|
|
||||||
return types.String(strings.Join(values, ",")), true
|
|
||||||
}
|
|
||||||
return types.String(values[0]), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMIMEMap(m textproto.MIMEHeader) traits.Mapper {
|
|
||||||
return mimeLike{m: m}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewValuesMap(m map[string][]string) traits.Mapper {
|
|
||||||
return valuesLike{m: m}
|
|
||||||
}
|
|
@@ -1,11 +1,111 @@
|
|||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gammaspectra.live/git/go-away/lib/condition"
|
http_cel "codeberg.org/gone/http-cel"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/cel-go/cel"
|
||||||
|
"github.com/google/cel-go/common/types"
|
||||||
|
"github.com/google/cel-go/common/types/ref"
|
||||||
|
"log/slog"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (state *State) initConditions() (err error) {
|
func (state *State) initConditions() (err error) {
|
||||||
state.programEnv, err = condition.NewRulesEnvironment(state.networks)
|
state.programEnv, err = http_cel.NewEnvironment(
|
||||||
|
|
||||||
|
cel.Variable("fp", cel.MapType(cel.StringType, cel.StringType)),
|
||||||
|
cel.Function("inDNSBL",
|
||||||
|
cel.Overload("inDNSBL_ip",
|
||||||
|
[]*cel.Type{cel.AnyType},
|
||||||
|
cel.BoolType,
|
||||||
|
cel.UnaryBinding(func(val ref.Val) ref.Val {
|
||||||
|
slog.Error("inDNSBL function has been deprecated, replace with dnsbl challenge")
|
||||||
|
return types.Bool(false)
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
cel.Function("network",
|
||||||
|
cel.MemberOverload("netIP_network_string",
|
||||||
|
[]*cel.Type{cel.BytesType, cel.StringType},
|
||||||
|
cel.BoolType,
|
||||||
|
cel.BinaryBinding(func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||||
|
var ip net.IP
|
||||||
|
switch v := lhs.Value().(type) {
|
||||||
|
case []byte:
|
||||||
|
ip = v
|
||||||
|
case net.IP:
|
||||||
|
ip = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip == nil {
|
||||||
|
panic(fmt.Errorf("invalid ip %v", lhs.Value()))
|
||||||
|
}
|
||||||
|
|
||||||
|
val, ok := rhs.Value().(string)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("invalid network value %v", rhs.Value()))
|
||||||
|
}
|
||||||
|
|
||||||
|
network, ok := state.networks[val]
|
||||||
|
if !ok {
|
||||||
|
_, ipNet, err := net.ParseCIDR(val)
|
||||||
|
if err != nil {
|
||||||
|
panic("network not found")
|
||||||
|
}
|
||||||
|
return types.Bool(ipNet.Contains(ip))
|
||||||
|
} else {
|
||||||
|
ok, err := network.Contains(ip)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return types.Bool(ok)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
cel.Function("inNetwork",
|
||||||
|
cel.Overload("inNetwork_string_ip",
|
||||||
|
[]*cel.Type{cel.StringType, cel.BytesType},
|
||||||
|
cel.BoolType,
|
||||||
|
cel.BinaryBinding(func(lhs ref.Val, rhs ref.Val) ref.Val {
|
||||||
|
var ip net.IP
|
||||||
|
switch v := rhs.Value().(type) {
|
||||||
|
case []byte:
|
||||||
|
ip = v
|
||||||
|
case net.IP:
|
||||||
|
ip = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip == nil {
|
||||||
|
panic(fmt.Errorf("invalid ip %v", rhs.Value()))
|
||||||
|
}
|
||||||
|
|
||||||
|
val, ok := lhs.Value().(string)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("invalid value %v", lhs.Value()))
|
||||||
|
}
|
||||||
|
slog.Debug(fmt.Sprintf("inNetwork function has been deprecated and will be removed in a future release, use remoteAddress.network(\"%s\") instead", val))
|
||||||
|
|
||||||
|
network, ok := state.networks[val]
|
||||||
|
if !ok {
|
||||||
|
_, ipNet, err := net.ParseCIDR(val)
|
||||||
|
if err != nil {
|
||||||
|
panic("network not found")
|
||||||
|
}
|
||||||
|
return types.Bool(ipNet.Contains(ip))
|
||||||
|
} else {
|
||||||
|
ok, err := network.Contains(ip)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return types.Bool(ok)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
http_cel "codeberg.org/gone/http-cel"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.gammaspectra.live/git/go-away/lib/action"
|
"git.gammaspectra.live/git/go-away/lib/action"
|
||||||
"git.gammaspectra.live/git/go-away/lib/challenge"
|
"git.gammaspectra.live/git/go-away/lib/challenge"
|
||||||
"git.gammaspectra.live/git/go-away/lib/condition"
|
|
||||||
"git.gammaspectra.live/git/go-away/lib/policy"
|
"git.gammaspectra.live/git/go-away/lib/policy"
|
||||||
"github.com/google/cel-go/cel"
|
"github.com/google/cel-go/cel"
|
||||||
"github.com/google/cel-go/common/types"
|
"github.com/google/cel-go/common/types"
|
||||||
@@ -66,12 +66,12 @@ func NewRuleState(state challenge.StateInterface, r policy.Rule, replacer *strin
|
|||||||
conditions = append(conditions, cond)
|
conditions = append(conditions, cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast, err := condition.FromStrings(state.ProgramEnv(), condition.OperatorOr, conditions...)
|
ast, err := http_cel.NewAst(state.ProgramEnv(), http_cel.OperatorOr, conditions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RuleState{}, fmt.Errorf("error compiling conditions: %w", err)
|
return RuleState{}, fmt.Errorf("error compiling conditions: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
program, err := condition.Program(state.ProgramEnv(), ast)
|
program, err := http_cel.ProgramAst(state.ProgramEnv(), ast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RuleState{}, fmt.Errorf("error compiling program: %w", err)
|
return RuleState{}, fmt.Errorf("error compiling program: %w", err)
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
http_cel "codeberg.org/gone/http-cel"
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.gammaspectra.live/git/go-away/lib/challenge"
|
"git.gammaspectra.live/git/go-away/lib/challenge"
|
||||||
"git.gammaspectra.live/git/go-away/lib/condition"
|
|
||||||
"git.gammaspectra.live/git/go-away/lib/policy"
|
"git.gammaspectra.live/git/go-away/lib/policy"
|
||||||
"git.gammaspectra.live/git/go-away/lib/settings"
|
"git.gammaspectra.live/git/go-away/lib/settings"
|
||||||
"git.gammaspectra.live/git/go-away/utils"
|
"git.gammaspectra.live/git/go-away/utils"
|
||||||
@@ -191,7 +191,7 @@ func NewState(p policy.Policy, opt settings.Settings, settings policy.StateSetti
|
|||||||
|
|
||||||
var replacements []string
|
var replacements []string
|
||||||
for k, entries := range p.Conditions {
|
for k, entries := range p.Conditions {
|
||||||
ast, err := condition.FromStrings(state.programEnv, condition.OperatorOr, entries...)
|
ast, err := http_cel.NewAst(state.programEnv, http_cel.OperatorOr, entries...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("conditions %s: error compiling conditions: %v", k, err)
|
return nil, fmt.Errorf("conditions %s: error compiling conditions: %v", k, err)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user