diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go
index cbdaf97ba45..ca78b619c4d 100644
--- a/api/v1alpha1/ext_proc_types.go
+++ b/api/v1alpha1/ext_proc_types.go
@@ -22,11 +22,21 @@ const (
)
// ProcessingModeOptions defines if headers or body should be processed by the external service
+// and which attributes are sent to the processor
type ProcessingModeOptions struct {
// Defines body processing mode
//
// +optional
Body *ExtProcBodyProcessingMode `json:"body,omitempty"`
+
+ // Defines which attributes are sent to the external processor. Envoy Gateway currently
+ // supports only the following attribute prefixes: connection, source, destination,
+ // request, response, upstream and xds.route.
+ // https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
+ //
+ // +optional
+ // +kubebuilder:validation:items:Pattern=`^(connection\.|source\.|destination\.|request\.|response\.|upstream\.|xds\.route_)[a-z_1-9]*$`
+ Attributes []string `json:"attributes,omitempty"`
}
// ExtProcProcessingMode defines if and how headers and bodies are sent to the service.
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 12f634586c6..457afa58ac4 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -4124,6 +4124,11 @@ func (in *ProcessingModeOptions) DeepCopyInto(out *ProcessingModeOptions) {
*out = new(ExtProcBodyProcessingMode)
**out = **in
}
+ if in.Attributes != nil {
+ in, out := &in.Attributes, &out.Attributes
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProcessingModeOptions.
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 e6cb298d3a8..0fbbcafe94e 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -918,6 +918,16 @@ spec:
Defines processing mode for requests. If present, request headers are sent. Request body is processed according
to the specified mode.
properties:
+ attributes:
+ description: |-
+ Defines which attributes are sent to the external processor. Envoy Gateway currently
+ supports only the following attribute prefixes: connection, source, destination,
+ request, response, upstream and xds.route.
+ https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
+ items:
+ pattern: ^(connection\.|source\.|destination\.|request\.|response\.|upstream\.|xds\.route_)[a-z_1-9]*$
+ type: string
+ type: array
body:
description: Defines body processing mode
enum:
@@ -931,6 +941,16 @@ spec:
Defines processing mode for responses. If present, response headers are sent. Response body is processed according
to the specified mode.
properties:
+ attributes:
+ description: |-
+ Defines which attributes are sent to the external processor. Envoy Gateway currently
+ supports only the following attribute prefixes: connection, source, destination,
+ request, response, upstream and xds.route.
+ https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
+ items:
+ pattern: ^(connection\.|source\.|destination\.|request\.|response\.|upstream\.|xds\.route_)[a-z_1-9]*$
+ type: string
+ type: array
body:
description: Defines body processing mode
enum:
diff --git a/release-notes/current.yaml b/release-notes/current.yaml
index 7b9d547d839..9ec82fc249b 100644
--- a/release-notes/current.yaml
+++ b/release-notes/current.yaml
@@ -14,7 +14,8 @@ security updates: |
# New features or capabilities added in this release.
new features: |
- - Added support for trusted CIDRs in the ClientIPDetectionSettings API
+ Added support for trusted CIDRs in the ClientIPDetectionSettings API
+ Added support for sending attributes to external processor in EnvoyExtensionPolicy API
# Fixes for bugs identified in previous versions.
bug fixes: |
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 80614c2645e..fc7142446c1 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -2960,6 +2960,7 @@ _Appears in:_
ProcessingModeOptions defines if headers or body should be processed by the external service
+and which attributes are sent to the processor
_Appears in:_
- [ExtProcProcessingMode](#extprocprocessingmode)
@@ -2967,6 +2968,7 @@ _Appears in:_
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `body` | _[ExtProcBodyProcessingMode](#extprocbodyprocessingmode)_ | false | Defines body processing mode |
+| `attributes` | _string array_ | false | Defines which attributes are sent to the external processor. Envoy Gateway currently
supports only the following attribute prefixes: connection, source, destination,
request, response, upstream and xds.route.
https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes |
#### ProviderType
diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md
index 80614c2645e..fc7142446c1 100644
--- a/site/content/zh/latest/api/extension_types.md
+++ b/site/content/zh/latest/api/extension_types.md
@@ -2960,6 +2960,7 @@ _Appears in:_
ProcessingModeOptions defines if headers or body should be processed by the external service
+and which attributes are sent to the processor
_Appears in:_
- [ExtProcProcessingMode](#extprocprocessingmode)
@@ -2967,6 +2968,7 @@ _Appears in:_
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `body` | _[ExtProcBodyProcessingMode](#extprocbodyprocessingmode)_ | false | Defines body processing mode |
+| `attributes` | _string array_ | false | Defines which attributes are sent to the external processor. Envoy Gateway currently
supports only the following attribute prefixes: connection, source, destination,
request, response, upstream and xds.route.
https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes |
#### ProviderType
diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go
index 7c9c168df10..a1d435e55dc 100644
--- a/test/cel-validation/envoyextensionpolicy_test.go
+++ b/test/cel-validation/envoyextensionpolicy_test.go
@@ -433,6 +433,157 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) {
},
wantErrors: []string{},
},
+ {
+ desc: "ExtProc with valid attributes",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ ExtProc: []egv1a1.ExtProc{
+ {
+ BackendCluster: egv1a1.BackendCluster{
+ BackendRefs: []egv1a1.BackendRef{
+ {
+ BackendObjectReference: gwapiv1.BackendObjectReference{
+ Name: "grpc-proc-service",
+ Port: ptr.To(gwapiv1.PortNumber(80)),
+ },
+ },
+ },
+ },
+ ProcessingMode: &egv1a1.ExtProcProcessingMode{
+ Request: &egv1a1.ProcessingModeOptions{
+ Attributes: []string{
+ "request.path",
+ "request.url_path",
+ "request.host",
+ "request.scheme",
+ "request.method",
+ "request.headers",
+ "request.referer",
+ "request.useragent",
+ "request.time",
+ "request.id",
+ "request.protocol",
+ "request.query",
+ "request.duration",
+ "request.size",
+ "request.total_size",
+ "response.code",
+ "response.code_details",
+ "response.flags",
+ "response.grpc_status",
+ "response.headers",
+ "response.trailers",
+ "response.size",
+ "response.total_size",
+ "response.backend_latency",
+ "source.address",
+ "source.port",
+ "destination.address",
+ "destination.port",
+ },
+ },
+ Response: &egv1a1.ProcessingModeOptions{
+ Attributes: []string{
+ "connection.id",
+ "connection.mtls",
+ "connection.requested_server_name",
+ "connection.tls_version",
+ "connection.subject_local_certificate",
+ "connection.subject_peer_certificate",
+ "connection.dns_san_local_certificate",
+ "connection.dns_san_peer_certificate",
+ "connection.uri_san_local_certificate",
+ "connection.uri_san_peer_certificate",
+ "connection.sha256_peer_certificate_digest",
+ "connection.transport_failure_reason",
+ "connection.termination_details",
+ "upstream.address",
+ "upstream.port",
+ "upstream.tls_version",
+ "upstream.subject_local_certificate",
+ "upstream.subject_peer_certificate",
+ "upstream.dns_san_local_certificate",
+ "upstream.dns_san_peer_certificate",
+ "upstream.uri_san_local_certificate",
+ "upstream.uri_san_peer_certificate",
+ "upstream.sha256_peer_certificate_digest",
+ "upstream.local_address",
+ "upstream.transport_failure_reason",
+ "upstream.request_attempt_count",
+ },
+ },
+ },
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: []string{},
+ },
+ {
+ desc: "ExtProc with invalid attributes",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ ExtProc: []egv1a1.ExtProc{
+ {
+ BackendCluster: egv1a1.BackendCluster{
+ BackendRefs: []egv1a1.BackendRef{
+ {
+ BackendObjectReference: gwapiv1.BackendObjectReference{
+ Name: "grpc-proc-service",
+ Port: ptr.To(gwapiv1.PortNumber(80)),
+ },
+ },
+ },
+ },
+ ProcessingMode: &egv1a1.ExtProcProcessingMode{
+ Request: &egv1a1.ProcessingModeOptions{
+ Attributes: []string{
+ "xds.node",
+ "metadata",
+ "filter_state",
+ "upstream_filter_state",
+ },
+ },
+ Response: &egv1a1.ProcessingModeOptions{
+ Attributes: []string{
+ "xds.node",
+ "xds.cluster",
+ "plugin_name",
+ },
+ },
+ },
+ },
+ },
+ PolicyTargetReferences: egv1a1.PolicyTargetReferences{
+ TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{
+ LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ },
+ }
+ },
+ wantErrors: []string{
+ "spec.extProc[0].processingMode.request.attributes[0]: Invalid value: \"xds.node\": spec.extProc[0].processingMode.request.attributes[0] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ "spec.extProc[0].processingMode.request.attributes[1]: Invalid value: \"metadata\": spec.extProc[0].processingMode.request.attributes[1] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ "spec.extProc[0].processingMode.request.attributes[2]: Invalid value: \"filter_state\": spec.extProc[0].processingMode.request.attributes[2] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ "spec.extProc[0].processingMode.request.attributes[3]: Invalid value: \"upstream_filter_state\": spec.extProc[0].processingMode.request.attributes[3] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ "spec.extProc[0].processingMode.response.attributes[0]: Invalid value: \"xds.node\": spec.extProc[0].processingMode.response.attributes[0] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ "spec.extProc[0].processingMode.response.attributes[1]: Invalid value: \"xds.cluster\": spec.extProc[0].processingMode.response.attributes[1] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ "spec.extProc[0].processingMode.response.attributes[2]: Invalid value: \"plugin_name\": spec.extProc[0].processingMode.response.attributes[2] in body should match '^(connection\\.|source\\.|destination\\.|request\\.|response\\.|upstream\\.|xds\\.route_)[a-z_1-9]*$'",
+ },
+ },
}
for _, tc := range cases {