diff --git a/api/v1alpha1/envoyextensionypolicy_types.go b/api/v1alpha1/envoyextensionypolicy_types.go
index cbab194b24e..b4fc751b80d 100644
--- a/api/v1alpha1/envoyextensionypolicy_types.go
+++ b/api/v1alpha1/envoyextensionypolicy_types.go
@@ -32,16 +32,15 @@ type EnvoyExtensionPolicy struct {
Status gwapiv1a2.PolicyStatus `json:"status,omitempty"`
}
-// +kubebuilder:validation:XValidation:rule="(has(self.targetRef) && !has(self.targetRefs)) || (!has(self.targetRef) && has(self.targetRefs)) || (has(self.targetSelectors) && self.targetSelectors.size() > 0) ", message="either targetRef or targetRefs must be used"
+// EnvoyExtensionPolicySpec defines the desired state of EnvoyExtensionPolicy.
//
+// +kubebuilder:validation:XValidation:rule="(has(self.targetRef) && !has(self.targetRefs)) || (!has(self.targetRef) && has(self.targetRefs)) || (has(self.targetSelectors) && self.targetSelectors.size() > 0) ", message="either targetRef or targetRefs must be used"
// +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? self.targetRef.group == 'gateway.networking.k8s.io' : true", message="this policy can only have a targetRef.group of gateway.networking.k8s.io"
// +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? self.targetRef.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', 'TCPRoute', 'TLSRoute'] : true", message="this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute"
// +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? !has(self.targetRef.sectionName) : true",message="this policy does not yet support the sectionName field"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.group == 'gateway.networking.k8s.io') : true ", message="this policy can only have a targetRefs[*].group of gateway.networking.k8s.io"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'UDPRoute', 'TCPRoute', 'TLSRoute']) : true ", message="this policy can only have a targetRefs[*].kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute/UDPRoute/TLSRoute"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, !has(ref.sectionName)) : true",message="this policy does not yet support the sectionName field"
-//
-// EnvoyExtensionPolicySpec defines the desired state of EnvoyExtensionPolicy.
type EnvoyExtensionPolicySpec struct {
PolicyTargetReferences `json:",inline"`
@@ -54,11 +53,19 @@ type EnvoyExtensionPolicySpec struct {
Wasm []Wasm `json:"wasm,omitempty"`
// ExtProc is an ordered list of external processing filters
- // that should added to the envoy filter chain
+ // that should be added to the envoy filter chain
//
// +kubebuilder:validation:MaxItems=16
// +optional
ExtProc []ExtProc `json:"extProc,omitempty"`
+
+ // Lua is an ordered list of Lua filters
+ // that should be added to the envoy filter chain
+ //
+ // +kubebuilder:validation:MaxItems=16
+ // +optional
+ // +notImplementedHide
+ Lua []Lua `json:"lua,omitempty"`
}
//+kubebuilder:object:root=true
diff --git a/api/v1alpha1/lua_types.go b/api/v1alpha1/lua_types.go
new file mode 100644
index 00000000000..84202fb5df5
--- /dev/null
+++ b/api/v1alpha1/lua_types.go
@@ -0,0 +1,41 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+package v1alpha1
+
+import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
+
+// Lua defines a Lua extension
+// Only one of Source or Disabled must be set
+//
+// +kubebuilder:validation:XValidation:rule="has(self.source) ? (!has(self.disabled) || self.disabled == false) : (has(self.disabled) && self.disabled == true)",message="Exactly one of source or disabled must be set."
+type Lua struct {
+ // Source is the LuaSource that will be executed for this extension.
+ //
+ // +optional
+ Source *LuaSource `json:"source"`
+ // Disabled is the status of the extension.
+ // Used for disabling Lua extensions at a route level.
+ //
+ // +optional
+ Disabled *bool `json:"disabled,omitempty"`
+}
+
+// LuaSource contains source code information for a user defined Lua script
+// Only one of Inline or ValueRef must be set
+//
+// +kubebuilder:validation:XValidation:rule="has(self.inline) ? !has(self.valueRef) : has(self.valueRef)",message="Exactly one of inline or valueRef must be set."
+type LuaSource struct {
+ // Inline contains the value as an inline string.
+ //
+ // +optional
+ Inline *string `json:"inline,omitempty"`
+ // ValueRef contains the contents of the body
+ // specified as a local object reference.
+ // Only a reference to ConfigMap is supported.
+ //
+ // +optional
+ ValueRef *gwapiv1.LocalObjectReference `json:"valueRef,omitempty"`
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index dbc28e6aca2..fc7585e07e5 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -1380,6 +1380,13 @@ func (in *EnvoyExtensionPolicySpec) DeepCopyInto(out *EnvoyExtensionPolicySpec)
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
+ if in.Lua != nil {
+ in, out := &in.Lua, &out.Lua
+ *out = make([]Lua, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyExtensionPolicySpec.
@@ -3841,6 +3848,56 @@ func (in *LocalRateLimit) DeepCopy() *LocalRateLimit {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Lua) DeepCopyInto(out *Lua) {
+ *out = *in
+ if in.Source != nil {
+ in, out := &in.Source, &out.Source
+ *out = new(LuaSource)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Disabled != nil {
+ in, out := &in.Disabled, &out.Disabled
+ *out = new(bool)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Lua.
+func (in *Lua) DeepCopy() *Lua {
+ if in == nil {
+ return nil
+ }
+ out := new(Lua)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *LuaSource) DeepCopyInto(out *LuaSource) {
+ *out = *in
+ if in.Inline != nil {
+ in, out := &in.Inline, &out.Inline
+ *out = new(string)
+ **out = **in
+ }
+ if in.ValueRef != nil {
+ in, out := &in.ValueRef, &out.ValueRef
+ *out = new(apisv1.LocalObjectReference)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LuaSource.
+func (in *LuaSource) DeepCopy() *LuaSource {
+ if in == nil {
+ return nil
+ }
+ out := new(LuaSource)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OIDC) DeepCopyInto(out *OIDC) {
*out = *in
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
index 0fbbcafe94e..3d369b021a4 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -49,7 +49,7 @@ spec:
extProc:
description: |-
ExtProc is an ordered list of external processing filters
- that should added to the envoy filter chain
+ that should be added to the envoy filter chain
items:
description: ExtProc defines the configuration for External Processing
filter.
@@ -973,6 +973,68 @@ spec:
== "" || f.group == ''gateway.envoyproxy.io'')) : true'
maxItems: 16
type: array
+ lua:
+ description: |-
+ Lua is an ordered list of Lua filters
+ that should be added to the envoy filter chain
+ items:
+ description: |-
+ Lua defines a Lua extension
+ Only one of Source or Disabled must be set
+ properties:
+ disabled:
+ description: |-
+ Disabled is the status of the extension.
+ Used for disabling Lua extensions at a route level.
+ type: boolean
+ source:
+ description: Source is the LuaSource that will be executed for
+ this extension.
+ properties:
+ inline:
+ description: Inline contains the value as an inline string.
+ type: string
+ valueRef:
+ description: |-
+ ValueRef contains the contents of the body
+ specified as a local object reference.
+ Only a reference to ConfigMap is supported.
+ properties:
+ group:
+ description: |-
+ Group is the group of the referent. For example, "gateway.networking.k8s.io".
+ When unspecified or empty string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent. For example
+ "HTTPRoute" or "Service".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ type: object
+ x-kubernetes-validations:
+ - message: Exactly one of inline or valueRef must be set.
+ rule: 'has(self.inline) ? !has(self.valueRef) : has(self.valueRef)'
+ type: object
+ x-kubernetes-validations:
+ - message: Exactly one of source or disabled must be set.
+ rule: 'has(self.source) ? (!has(self.disabled) || self.disabled
+ == false) : (has(self.disabled) && self.disabled == true)'
+ maxItems: 16
+ type: array
targetRef:
description: |-
TargetRef is the name of the resource this policy is being attached to.
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 5119d756646..a373396205b 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -980,7 +980,7 @@ _Appears in:_
| `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | TargetRefs are the names of the Gateway resources this policy
is being attached to. |
| `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | TargetSelectors allow targeting resources for this policy based on labels |
| `wasm` | _[Wasm](#wasm) array_ | false | Wasm is a list of Wasm extensions to be loaded by the Gateway.
Order matters, as the extensions will be loaded in the order they are
defined in this list. |
-| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should added to the envoy filter chain |
+| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should be added to the envoy filter chain |
#### EnvoyFilter
@@ -2738,6 +2738,38 @@ _Appears in:_
| `error` | LogLevelError defines the "Error" logging level.
|
+#### Lua
+
+
+
+Lua defines a Lua extension
+Only one of Source or Disabled must be set
+
+_Appears in:_
+- [EnvoyExtensionPolicySpec](#envoyextensionpolicyspec)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `source` | _[LuaSource](#luasource)_ | false | Source is the LuaSource that will be executed for this extension. |
+| `disabled` | _boolean_ | false | Disabled is the status of the extension.
Used for disabling Lua extensions at a route level. |
+
+
+#### LuaSource
+
+
+
+LuaSource contains source code information for a user defined Lua script
+Only one of Inline or ValueRef must be set
+
+_Appears in:_
+- [Lua](#lua)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `inline` | _string_ | false | Inline contains the value as an inline string. |
+| `valueRef` | _[LocalObjectReference](#localobjectreference)_ | false | ValueRef contains the contents of the body
specified as a local object reference.
Only a reference to ConfigMap is supported. |
+
+
#### MergeType
_Underlying type:_ _string_
diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md
index 5119d756646..a373396205b 100644
--- a/site/content/zh/latest/api/extension_types.md
+++ b/site/content/zh/latest/api/extension_types.md
@@ -980,7 +980,7 @@ _Appears in:_
| `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | TargetRefs are the names of the Gateway resources this policy
is being attached to. |
| `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | TargetSelectors allow targeting resources for this policy based on labels |
| `wasm` | _[Wasm](#wasm) array_ | false | Wasm is a list of Wasm extensions to be loaded by the Gateway.
Order matters, as the extensions will be loaded in the order they are
defined in this list. |
-| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should added to the envoy filter chain |
+| `extProc` | _[ExtProc](#extproc) array_ | false | ExtProc is an ordered list of external processing filters
that should be added to the envoy filter chain |
#### EnvoyFilter
@@ -2738,6 +2738,38 @@ _Appears in:_
| `error` | LogLevelError defines the "Error" logging level.
|
+#### Lua
+
+
+
+Lua defines a Lua extension
+Only one of Source or Disabled must be set
+
+_Appears in:_
+- [EnvoyExtensionPolicySpec](#envoyextensionpolicyspec)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `source` | _[LuaSource](#luasource)_ | false | Source is the LuaSource that will be executed for this extension. |
+| `disabled` | _boolean_ | false | Disabled is the status of the extension.
Used for disabling Lua extensions at a route level. |
+
+
+#### LuaSource
+
+
+
+LuaSource contains source code information for a user defined Lua script
+Only one of Inline or ValueRef must be set
+
+_Appears in:_
+- [Lua](#lua)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `inline` | _string_ | false | Inline contains the value as an inline string. |
+| `valueRef` | _[LocalObjectReference](#localobjectreference)_ | false | ValueRef contains the contents of the body
specified as a local object reference.
Only a reference to ConfigMap is supported. |
+
+
#### MergeType
_Underlying type:_ _string_
diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go
index a1d435e55dc..c03b587dbda 100644
--- a/test/cel-validation/envoyextensionpolicy_test.go
+++ b/test/cel-validation/envoyextensionpolicy_test.go
@@ -414,6 +414,162 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) {
"spec.extProc[0].processingMode.request.body: Unsupported value: \"not-a-body-mode\": supported values: \"Streamed\", \"Buffered\", \"BufferedPartial\"",
},
},
+ {
+ desc: "Valid Lua filter (inline)",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ Lua: []egv1a1.Lua{
+ {
+ Source: &egv1a1.LuaSource{
+ Inline: ptr.To("function envoy_on_response(response_handle) -- Do something -- end"),
+ },
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: nil,
+ },
+ {
+ desc: "Valid Lua filter (configmap)",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ Lua: []egv1a1.Lua{
+ {
+ Source: &egv1a1.LuaSource{
+ ValueRef: &gwapiv1a2.LocalObjectReference{
+ Kind: gwapiv1a2.Kind("ConfigMap"),
+ Name: gwapiv1a2.ObjectName("eg"),
+ Group: gwapiv1a2.Group("core"),
+ },
+ },
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: nil,
+ },
+ {
+ desc: "Invalid Lua filter (both inline and configmap)",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ Lua: []egv1a1.Lua{
+ {
+ Source: &egv1a1.LuaSource{
+ Inline: ptr.To("function envoy_on_response(response_handle) -- Do something -- end"),
+ ValueRef: &gwapiv1a2.LocalObjectReference{
+ Kind: gwapiv1a2.Kind("ConfigMap"),
+ Name: gwapiv1a2.ObjectName("eg"),
+ Group: gwapiv1a2.Group("core"),
+ },
+ },
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: []string{
+ "spec.lua[0].source: Invalid value: \"object\": Exactly one of inline or valueRef must be set.",
+ },
+ },
+ {
+ desc: "Valid Lua filter for route (disabled)",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ Lua: []egv1a1.Lua{
+ {
+ Disabled: ptr.To(true),
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "HTTPRoute",
+ Name: "hr",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: nil,
+ },
+ {
+ desc: "Invalid Lua filter for route (disabled false)",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ Lua: []egv1a1.Lua{
+ {
+ Disabled: ptr.To(false),
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "HTTPRoute",
+ Name: "hr",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: []string{
+ "spec.lua[0]: Invalid value: \"object\": Exactly one of source or disabled must be set.",
+ },
+ },
+ {
+ desc: "Invalid Lua filter for route",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ Lua: []egv1a1.Lua{
+ {
+ Source: &egv1a1.LuaSource{
+ Inline: ptr.To("function envoy_on_response(response_handle) -- Do something -- end"),
+ },
+ Disabled: ptr.To(true),
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "HTTPRoute",
+ Name: "hr",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: []string{
+ "spec.lua[0]: Invalid value: \"object\": Exactly one of source or disabled must be set.",
+ },
+ },
{
desc: "target selectors without targetRefs or targetRef",
mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {