Skip to content

Commit ad3785a

Browse files
committed
split lua with listener and route
- Added a Luas field to the listener-level EnvoyExtensions struct so listener-scoped Lua policies can be represented separately from per-route ones. - Refactored to add HCM placeholder filters for both per-route Lua slots and listener-level Lua filters (using named Lua HCM filters with empty default source). Listener filters are appended after route-slot filters to preserve ordering after HCM filter reversal. The Disabled: true flag was removed from listener Lua HCM filters since they are always active for the listener. - New implementation that injects listener-level Lua source code and filter context into RouteConfiguration.TypedPerFilterConfig, delivering script changes via RDS to avoid listener drains. Signed-off-by: zirain <zirain2009@gmail.com>
1 parent 39850aa commit ad3785a

41 files changed

Lines changed: 619 additions & 142 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

internal/gatewayapi/envoyextensionpolicy.go

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,17 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(
667667

668668
policyTarget := irStringKey(policy.Namespace, string(target.Name))
669669

670-
routesWithDirectResponse := sets.New[string]()
670+
failed := luaError != nil
671+
if wasmError != nil {
672+
failed = failed || !wasmFailOpen
673+
}
674+
if extProcError != nil {
675+
failed = failed || !extProcFailOpen
676+
}
677+
if dynamicModuleError != nil {
678+
failed = true
679+
}
680+
671681
for _, http := range x.HTTP {
672682
gatewayName := extractGatewayNameFromListener(http.Name)
673683
if t.MergeGateways && gatewayName != policyTarget {
@@ -678,6 +688,19 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(
678688
continue
679689
}
680690

691+
// if already set - there's a specific level policy, so skip
692+
if http.EnvoyExtensions != nil {
693+
continue
694+
}
695+
696+
// TODO: move other extensions to listener level.
697+
totalExtensions := len(luas)
698+
if totalExtensions > 0 {
699+
http.EnvoyExtensions = &ir.EnvoyExtensionFeatures{
700+
Luas: luas,
701+
}
702+
}
703+
681704
// A Policy targeting the specific scope(xRoute rule, xRoute, Gateway listener) wins over a policy
682705
// targeting a lesser specific scope(Gateway).
683706
for _, r := range http.Routes {
@@ -686,43 +709,19 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(
686709
continue
687710
}
688711

689-
failRoute := false
690-
// Lua extension doesn't have a fail open option, so fail the route if there is a lua error
691-
// TODO: we may also add fail open option for Lua extension to align with other extensions
692-
if luaError != nil {
693-
failRoute = true
694-
}
695-
if wasmError != nil {
696-
failRoute = failRoute || !wasmFailOpen
697-
}
698-
if extProcError != nil {
699-
failRoute = failRoute || !extProcFailOpen
700-
}
701-
if dynamicModuleError != nil {
702-
failRoute = true
703-
}
704-
if failRoute {
712+
if failed {
705713
r.DirectResponse = &ir.CustomResponse{
706714
StatusCode: new(uint32(500)),
707715
}
708-
routesWithDirectResponse.Insert(r.Name)
709716
} else {
710717
r.EnvoyExtensions = &ir.EnvoyExtensionFeatures{
711718
ExtProcs: extProcs,
712719
Wasms: wasms,
713-
Luas: luas,
714720
DynamicModules: dynamicModules,
715721
}
716722
}
717723
}
718724
}
719-
if len(routesWithDirectResponse) > 0 {
720-
t.Logger.Info("setting 500 direct response in routes due to errors in EnvoyExtensionPolicy",
721-
"policy", fmt.Sprintf("%s/%s", policy.Namespace, policy.Name),
722-
"routes", sets.List(routesWithDirectResponse),
723-
"error", errs,
724-
)
725-
}
726725

727726
return errs
728727
}

internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-disabled.out.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,14 @@ xdsIR:
208208
weight: 1
209209
envoyExtensions:
210210
luas:
211-
- Code: |
211+
- code: |
212212
function envoy_on_response(response_handle)
213213
local value = 10
214214
if value > 5
215215
print("Value is greater than 5")
216216
end
217217
end
218-
FilterContext: null
219-
Name: envoyextensionpolicy/default/policy-for-http-route/lua/0
218+
name: envoyextensionpolicy/default/policy-for-http-route/lua/0
220219
hostname: www.example.com
221220
isHTTP2: false
222221
metadata:

internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ xdsIR:
298298
weight: 1
299299
envoyExtensions:
300300
luas:
301-
- Code: |
301+
- code: |
302302
local json = require("json")
303303
function envoy_on_response(response_handle)
304304
local content_type = response_handle:headers():get("content-type")
@@ -317,8 +317,7 @@ xdsIR:
317317
end
318318
return envoy.lua.ResponseStatus.Continue
319319
end
320-
FilterContext: null
321-
Name: envoyextensionpolicy/default/policy-for-http-route/lua/0
320+
name: envoyextensionpolicy/default/policy-for-http-route/lua/0
322321
hostname: www.example.com
323322
isHTTP2: false
324323
metadata:

internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua.out.yaml

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,11 @@ xdsIR:
253253
protocol: TCP
254254
http:
255255
- address: 0.0.0.0
256+
envoyExtensions:
257+
luas:
258+
- code: function envoy_on_request(request_handle) request_handle:logInfo('Goodbye.')
259+
end
260+
name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
256261
externalPort: 80
257262
hostnames:
258263
- '*'
@@ -288,12 +293,7 @@ xdsIR:
288293
weight: 1
289294
directResponse:
290295
statusCode: 500
291-
envoyExtensions:
292-
luas:
293-
- Code: function envoy_on_request(request_handle) request_handle:logInfo('Goodbye.')
294-
end
295-
FilterContext: null
296-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
296+
envoyExtensions: {}
297297
hostname: www.example.com
298298
isHTTP2: false
299299
metadata:
@@ -324,12 +324,7 @@ xdsIR:
324324
name: httproute/default/httproute-2/rule/0/backend/0
325325
protocol: HTTP
326326
weight: 1
327-
envoyExtensions:
328-
luas:
329-
- Code: function envoy_on_request(request_handle) request_handle:logInfo('Goodbye.')
330-
end
331-
FilterContext: null
332-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
327+
envoyExtensions: {}
333328
hostname: www.example.com
334329
isHTTP2: false
335330
metadata:

internal/gatewayapi/testdata/envoyextensionpolicy-with-lua-configmap.out.yaml

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,13 @@ xdsIR:
425425
protocol: TCP
426426
http:
427427
- address: 0.0.0.0
428+
envoyExtensions:
429+
luas:
430+
- code: |
431+
function envoy_on_request(request_handle)
432+
request_handle:logInfo('Goodbye.')
433+
end
434+
name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
428435
externalPort: 80
429436
hostnames:
430437
- '*'
@@ -460,14 +467,7 @@ xdsIR:
460467
weight: 1
461468
directResponse:
462469
statusCode: 500
463-
envoyExtensions:
464-
luas:
465-
- Code: |
466-
function envoy_on_request(request_handle)
467-
request_handle:logInfo('Goodbye.')
468-
end
469-
FilterContext: null
470-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
470+
envoyExtensions: {}
471471
hostname: www.example.com
472472
isHTTP2: false
473473
metadata:
@@ -500,14 +500,7 @@ xdsIR:
500500
weight: 1
501501
directResponse:
502502
statusCode: 500
503-
envoyExtensions:
504-
luas:
505-
- Code: |
506-
function envoy_on_request(request_handle)
507-
request_handle:logInfo('Goodbye.')
508-
end
509-
FilterContext: null
510-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
503+
envoyExtensions: {}
511504
hostname: www.example.com
512505
isHTTP2: false
513506
metadata:
@@ -540,14 +533,7 @@ xdsIR:
540533
weight: 1
541534
directResponse:
542535
statusCode: 500
543-
envoyExtensions:
544-
luas:
545-
- Code: |
546-
function envoy_on_request(request_handle)
547-
request_handle:logInfo('Goodbye.')
548-
end
549-
FilterContext: null
550-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
536+
envoyExtensions: {}
551537
hostname: www.example.com
552538
isHTTP2: false
553539
metadata:
@@ -580,13 +566,13 @@ xdsIR:
580566
weight: 1
581567
envoyExtensions:
582568
luas:
583-
- Code: |
569+
- code: |
584570
function envoy_on_response(response_handle)
585571
response_handle:logWarn('Goodbye.')
586572
end
587-
FilterContext:
573+
filterContext:
588574
token_header: x-session-token
589-
Name: envoyextensionpolicy/default/policy-for-http-route/lua/0
575+
name: envoyextensionpolicy/default/policy-for-http-route/lua/0
590576
hostname: www.example.com
591577
isHTTP2: false
592578
metadata:
@@ -617,14 +603,7 @@ xdsIR:
617603
name: httproute/default/httproute-2/rule/0/backend/0
618604
protocol: HTTP
619605
weight: 1
620-
envoyExtensions:
621-
luas:
622-
- Code: |
623-
function envoy_on_request(request_handle)
624-
request_handle:logInfo('Goodbye.')
625-
end
626-
FilterContext: null
627-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
606+
envoyExtensions: {}
628607
hostname: www.example.com
629608
isHTTP2: false
630609
metadata:

internal/gatewayapi/testdata/envoyextensionpolicy-with-lua.out.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ xdsIR:
244244
protocol: TCP
245245
http:
246246
- address: 0.0.0.0
247+
envoyExtensions:
248+
luas:
249+
- code: function envoy_on_request(request_handle) request_handle:logInfo('Goodbye.')
250+
end
251+
name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
247252
externalPort: 80
248253
hostnames:
249254
- '*'
@@ -279,12 +284,12 @@ xdsIR:
279284
weight: 1
280285
envoyExtensions:
281286
luas:
282-
- Code: function envoy_on_response(response_handle) response_handle:logWarn('Goodbye.')
287+
- code: function envoy_on_response(response_handle) response_handle:logWarn('Goodbye.')
283288
end
284-
FilterContext:
289+
filterContext:
285290
mode: strict
286291
token_header: x-api-key
287-
Name: envoyextensionpolicy/default/policy-for-http-route/lua/0
292+
name: envoyextensionpolicy/default/policy-for-http-route/lua/0
288293
hostname: www.example.com
289294
isHTTP2: false
290295
metadata:
@@ -315,12 +320,7 @@ xdsIR:
315320
name: httproute/default/httproute-2/rule/0/backend/0
316321
protocol: HTTP
317322
weight: 1
318-
envoyExtensions:
319-
luas:
320-
- Code: function envoy_on_request(request_handle) request_handle:logInfo('Goodbye.')
321-
end
322-
FilterContext: null
323-
Name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/lua/0
323+
envoyExtensions: {}
324324
hostname: www.example.com
325325
isHTTP2: false
326326
metadata:

internal/ir/xds.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ type HTTPListener struct {
341341
MatchBackendScheme bool `json:"matchBackendScheme,omitempty" yaml:"matchBackendScheme,omitempty"`
342342
// RequestID defines configuration for the UUID request ID extension.
343343
RequestID *RequestIDExtensionAction `json:"requestID,omitempty" yaml:"requestID,omitempty"`
344+
// EnvoyExtension holds the features associated with EnvoyExtensionPolicy
345+
EnvoyExtensions *EnvoyExtensionFeatures `json:"envoyExtensions,omitempty" yaml:"envoyExtensions,omitempty"`
344346
}
345347

346348
// Validate the fields within the HTTPListener structure
@@ -3715,12 +3717,12 @@ type ExtProc struct {
37153717
// +k8s:deepcopy-gen=true
37163718
type Lua struct {
37173719
// Name is a unique name for the Lua configuration.
3718-
Name string
3720+
Name string `json:"name" yaml:"name"`
37193721
// Code is the Lua source code
3720-
Code *string
3722+
Code *string `json:"code,omitempty" yaml:"code,omitempty"`
37213723
// FilterContext is the filter context configuration for the Lua script.
37223724
// This is a JSON object passed to the Lua script via request_handle:filterContext().
3723-
FilterContext *apiextensionsv1.JSON
3725+
FilterContext *apiextensionsv1.JSON `json:"filterContext,omitempty" yaml:"filterContext,omitempty"`
37243726
}
37253727

37263728
// Wasm holds the information associated with the Wasm extensions.

internal/ir/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/xds/translator/api_key_auth.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,7 @@ func buildAPIKeyAuthFilterPerRouteConfig(apiKeyAuth *ir.APIKeyAuth) *apikeyauthv
176176
Forwarding: apiKeyAuthProto.Forwarding,
177177
}
178178
}
179+
180+
func (*apiKeyAuth) patchRouteConfiguration(_ *routev3.RouteConfiguration, _ *ir.HTTPListener) error {
181+
return nil
182+
}

internal/xds/translator/authorization.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,3 +855,7 @@ func wrapPredicateWithNot(predicate *matcherv3.Matcher_MatcherList_Predicate, in
855855
},
856856
}
857857
}
858+
859+
func (*rbac) patchRouteConfiguration(_ *routev3.RouteConfiguration, _ *ir.HTTPListener) error {
860+
return nil
861+
}

0 commit comments

Comments
 (0)