Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions internal/gatewayapi/envoyextensionpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,6 @@ func (t *Translator) buildLua(
envoyProxy *egv1a1.EnvoyProxy,
) (*ir.Lua, error) {
var luaCode *string
var luaValidation egv1a1.LuaValidation
var err error
if lua.Type == egv1a1.LuaValueTypeValueRef {
luaCode, err = getLuaBodyFromLocalObjectReference(lua.ValueRef, resources, policy.Namespace)
Expand All @@ -645,12 +644,8 @@ func (t *Translator) buildLua(
if err != nil {
return nil, err
}
if envoyProxy != nil && envoyProxy.Spec.LuaValidation != nil {
luaValidation = *envoyProxy.Spec.LuaValidation
} else {
luaValidation = egv1a1.LuaValidationStrict
}
if err = luavalidator.NewLuaValidator(*luaCode, luaValidation).Validate(); err != nil {

if err = luavalidator.NewLuaValidator(*luaCode, envoyProxy).Validate(); err != nil {
return nil, fmt.Errorf("validation failed for lua body in policy with name %v: %w", name, err)
}
return &ir.Lua{
Expand Down
30 changes: 24 additions & 6 deletions internal/gatewayapi/luavalidator/lua_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ var mockData []byte
// Validation strictness is controlled by the validation field
type LuaValidator struct {
code string
validation egv1a1.LuaValidation
envoyProxy *egv1a1.EnvoyProxy
}

// NewLuaValidator returns a LuaValidator for user provided Lua code
func NewLuaValidator(code string, validation egv1a1.LuaValidation) *LuaValidator {
func NewLuaValidator(code string, envoyProxy *egv1a1.EnvoyProxy) *LuaValidator {
return &LuaValidator{
code: code,
validation: validation,
envoyProxy: envoyProxy,
}
}

Expand All @@ -61,7 +61,7 @@ func (l *LuaValidator) Validate() error {

// validate runs the validation on given code
func (l *LuaValidator) validate(code string) error {
switch l.validation {
switch l.getLuaValidation() {
case egv1a1.LuaValidationSyntax:
return l.loadLua(code)
case egv1a1.LuaValidationDisabled:
Expand All @@ -71,10 +71,28 @@ func (l *LuaValidator) validate(code string) error {
}
}

// getLuaValidation returns the Lua validation level, defaulting to strict if not configured
func (l *LuaValidator) getLuaValidation() egv1a1.LuaValidation {
if l.envoyProxy != nil && l.envoyProxy.Spec.LuaValidation != nil {
return *l.envoyProxy.Spec.LuaValidation
}
return egv1a1.LuaValidationStrict
}

// newLuaState creates a new Lua state with global settings applied
func (l *LuaValidator) newLuaState() *lua.LState {
L := lua.NewState()
// Suppress all print statements
L.SetGlobal("print", L.NewFunction(func(L *lua.LState) int {
return 0
}))
return L
}

// runLua interprets and runs the provided Lua code in runtime using gopher-lua
// Refer: https://github.com/yuin/gopher-lua?tab=readme-ov-file#differences-between-lua-and-gopherlua
func (l *LuaValidator) runLua(code string) error {
L := lua.NewState()
L := l.newLuaState()
defer L.Close()
if err := L.DoString(code); err != nil {
return err
Expand All @@ -85,7 +103,7 @@ func (l *LuaValidator) runLua(code string) error {
// loadLua loads the Lua code into the Lua state, does not run it
// This is used to check for syntax errors in the Lua code
func (l *LuaValidator) loadLua(code string) error {
L := lua.NewState()
L := l.newLuaState()
defer L.Close()
if _, err := L.LoadString(code); err != nil {
return err
Expand Down
26 changes: 20 additions & 6 deletions internal/gatewayapi/luavalidator/lua_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import (
"strings"
"testing"

"k8s.io/utils/ptr"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)

func Test_Validate(t *testing.T) {
type args struct {
name string
code string
validation egv1a1.LuaValidation
proxy *egv1a1.EnvoyProxy
expectedErrSubstring string
}
tests := []args{
Expand All @@ -28,7 +30,7 @@ func Test_Validate(t *testing.T) {
{
name: "logInfo: envoy_on_response",
code: `function envoy_on_response(response_handle)
response_handle:logInfo("Goodbye.")
response_handle:logInfo("This log should not be printed.")
end`,
expectedErrSubstring: "",
},
Expand Down Expand Up @@ -156,7 +158,11 @@ func Test_Validate(t *testing.T) {
code: `function envoy_on_request(request_handle)
request_handle:unknownApi()
end`,
validation: egv1a1.LuaValidationSyntax,
proxy: &egv1a1.EnvoyProxy{
Spec: egv1a1.EnvoyProxySpec{
LuaValidation: ptr.To(egv1a1.LuaValidationSyntax),
},
},
expectedErrSubstring: "",
},
{
Expand All @@ -173,7 +179,11 @@ func Test_Validate(t *testing.T) {
last:setBytes("<html><b>Not Found<b></html>")
end`,
validation: egv1a1.LuaValidationSyntax,
proxy: &egv1a1.EnvoyProxy{
Spec: egv1a1.EnvoyProxySpec{
LuaValidation: ptr.To(egv1a1.LuaValidationSyntax),
},
},
expectedErrSubstring: "<string> at EOF: syntax error",
},
{
Expand All @@ -190,13 +200,17 @@ func Test_Validate(t *testing.T) {
last:setBytes("<html><b>Not Found<b></html>")
end`,
validation: egv1a1.LuaValidationDisabled,
proxy: &egv1a1.EnvoyProxy{
Spec: egv1a1.EnvoyProxySpec{
LuaValidation: ptr.To(egv1a1.LuaValidationDisabled),
},
},
expectedErrSubstring: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := NewLuaValidator(tt.code, tt.validation)
l := NewLuaValidator(tt.code, tt.proxy)
if err := l.Validate(); err != nil && tt.expectedErrSubstring == "" {
t.Errorf("Unexpected error: %v", err)
} else if err != nil && !strings.Contains(err.Error(), tt.expectedErrSubstring) {
Expand Down
1 change: 1 addition & 0 deletions release-notes/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ bug fixes: |
Fixed handling of context-related transient errors to prevent incorrect state reconciliation and unintended behavior.
Fixed the controller cannot read the EnvoyProxy attached gatewayclass only.
Fixed indexer and controller crashing when BackendTrafficPolicy has a redirect response override.
Fixed Lua validator log level to be suppressed by default.

# Enhancements that improve performance.
performance improvements: |
Expand Down