From ac86045216b4c2a432d39ca365664f6aabdf2923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Pillevesse?= Date: Fri, 6 Dec 2024 00:15:10 +0100 Subject: [PATCH] feat: add body to ext auth (#4671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add BodyToExtAuth Signed-off-by: Aurélien Pillevesse --- api/v1alpha1/ext_auth_types.go | 15 + api/v1alpha1/zz_generated.deepcopy.go | 20 ++ ...ateway.envoyproxy.io_securitypolicies.yaml | 15 + internal/gatewayapi/securitypolicy.go | 7 + .../securitypolicy-with-extauth-body.in.yaml | 112 ++++++ .../securitypolicy-with-extauth-body.out.yaml | 335 ++++++++++++++++++ internal/ir/xds.go | 14 + internal/ir/zz_generated.deepcopy.go | 20 ++ internal/xds/translator/extauth.go | 6 + .../testdata/in/xds-ir/ext-auth-body.yaml | 125 +++++++ .../out/xds-ir/ext-auth-body.clusters.yaml | 115 ++++++ .../out/xds-ir/ext-auth-body.endpoints.yaml | 36 ++ .../out/xds-ir/ext-auth-body.listeners.yaml | 71 ++++ .../out/xds-ir/ext-auth-body.routes.yaml | 44 +++ site/content/en/latest/api/extension_types.md | 15 + site/content/zh/latest/api/extension_types.md | 15 + 16 files changed, 965 insertions(+) create mode 100644 internal/gatewayapi/testdata/securitypolicy-with-extauth-body.in.yaml create mode 100644 internal/gatewayapi/testdata/securitypolicy-with-extauth-body.out.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/ext-auth-body.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/ext-auth-body.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/ext-auth-body.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/ext-auth-body.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/ext-auth-body.routes.yaml diff --git a/api/v1alpha1/ext_auth_types.go b/api/v1alpha1/ext_auth_types.go index faa0897e300..16652c9fd28 100644 --- a/api/v1alpha1/ext_auth_types.go +++ b/api/v1alpha1/ext_auth_types.go @@ -33,6 +33,10 @@ type ExtAuth struct { // +optional HeadersToExtAuth []string `json:"headersToExtAuth,omitempty"` + // BodyToExtAuth defines the Body to Ext Auth configuration. + // +optional + BodyToExtAuth *BodyToExtAuth `json:"bodyToExtAuth,omitempty"` + // FailOpen is a switch used to control the behavior when a response from the External Authorization service cannot be obtained. // If FailOpen is set to true, the system allows the traffic to pass through. // Otherwise, if it is set to false or not set (defaulting to false), @@ -85,3 +89,14 @@ type HTTPExtAuthService struct { // +optional HeadersToBackend []string `json:"headersToBackend,omitempty"` } + +// BodyToExtAuth defines the Body to Ext Auth configuration +type BodyToExtAuth struct { + // MaxRequestBytes is the maximum size of a message body that the filter will hold in memory. + // Envoy will return HTTP 413 and will not initiate the authorization process when buffer + // reaches the number set in this field. + // Note that this setting will have precedence over failOpen mode. + // + // +kubebuilder:validation:Minimum=1 + MaxRequestBytes uint32 `json:"maxRequestBytes"` +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 457afa58ac4..742ffed1b25 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -595,6 +595,21 @@ func (in *BasicAuth) DeepCopy() *BasicAuth { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BodyToExtAuth) DeepCopyInto(out *BodyToExtAuth) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BodyToExtAuth. +func (in *BodyToExtAuth) DeepCopy() *BodyToExtAuth { + if in == nil { + return nil + } + out := new(BodyToExtAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CORS) DeepCopyInto(out *CORS) { *out = *in @@ -2115,6 +2130,11 @@ func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.BodyToExtAuth != nil { + in, out := &in.BodyToExtAuth, &out.BodyToExtAuth + *out = new(BodyToExtAuth) + **out = **in + } if in.FailOpen != nil { in, out := &in.FailOpen, &out.FailOpen *out = new(bool) diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 840c8d59d30..e611a00ce10 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -336,6 +336,21 @@ spec: extAuth: description: ExtAuth defines the configuration for External Authorization. properties: + bodyToExtAuth: + description: BodyToExtAuth defines the Body to Ext Auth configuration. + properties: + maxRequestBytes: + description: |- + MaxRequestBytes is the maximum size of a message body that the filter will hold in memory. + Envoy will return HTTP 413 and will not initiate the authorization process when buffer + reaches the number set in this field. + Note that this setting will have precedence over failOpen mode. + format: int32 + minimum: 1 + type: integer + required: + - maxRequestBytes + type: object failOpen: default: false description: |- diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 3219f816da5..d21f240f1fa 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -933,6 +933,13 @@ func (t *Translator) buildExtAuth( Authority: authority, } } + + if policy.Spec.ExtAuth.BodyToExtAuth != nil { + extAuth.BodyToExtAuth = &ir.BodyToExtAuth{ + MaxRequestBytes: policy.Spec.ExtAuth.BodyToExtAuth.MaxRequestBytes, + } + } + return extAuth, nil } diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-body.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-body.in.yaml new file mode 100644 index 00000000000..d45b50c8835 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-body.in.yaml @@ -0,0 +1,112 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo1 + backendRefs: + - name: service-1 + port: 8080 + - matches: + - path: + value: /foo2 + backendRefs: + - name: service-2 + port: 8080 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - www.bar.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /bar + backendRefs: + - name: service-3 + port: 8080 +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: 'primary.foo.com' + port: 3000 +referenceGrants: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + namespace: envoy-gateway + name: referencegrant-1 + spec: + from: + - group: gateway.envoyproxy.io + kind: SecurityPolicy + namespace: default + to: + - group: "" + kind: Service +securityPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-http-route-1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + extAuth: + failOpen: true + headersToExtAuth: + - header1 + - header2 + bodyToExtAuth: + maxRequestBytes: 32768 + grpc: + backendRefs: + - name: service-2 + kind: Service + port: 8080 + - name: backend-fqdn + kind: Backend + group: gateway.envoyproxy.io + port: 3000 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-body.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-body.out.yaml new file mode 100644 index 00000000000..ac4dfe7f306 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-body.out.yaml @@ -0,0 +1,335 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo1 + - backendRefs: + - name: service-2 + port: 8080 + matches: + - path: + value: /foo2 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - www.bar.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-3 + port: 8080 + matches: + - path: + value: /bar + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-http-route-1 + namespace: default + spec: + extAuth: + bodyToExtAuth: + maxRequestBytes: 32768 + failOpen: true + grpc: + backendRefs: + - kind: Service + name: service-2 + port: 8080 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + port: 3000 + headersToExtAuth: + - header1 + - header2 + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo1 + security: + extAuth: + bodyToExtAuth: + maxRequestBytes: 32768 + failOpen: true + grpc: + authority: service-2.default:8080 + destination: + name: securitypolicy/default/policy-for-http-route-1/extauth/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + name: securitypolicy/default/policy-for-http-route-1 + - destination: + name: httproute/default/httproute-1/rule/1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/1/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo2 + security: + extAuth: + bodyToExtAuth: + maxRequestBytes: 32768 + failOpen: true + grpc: + authority: service-2.default:8080 + destination: + name: securitypolicy/default/policy-for-http-route-1/extauth/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + name: securitypolicy/default/policy-for-http-route-1 + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 486b7514cd4..00924ed9f32 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -1000,6 +1000,10 @@ type ExtAuth struct { // +optional HeadersToExtAuth []string `json:"headersToExtAuth,omitempty"` + // BodyToExtAuth defines the Body to Ext Auth configuration. + // +optional + BodyToExtAuth *BodyToExtAuth `json:"bodyToExtAuth,omitempty"` + // FailOpen is a switch used to control the behavior when a response from the External Authorization service cannot be obtained. // If FailOpen is set to true, the system allows the traffic to pass through. // Otherwise, if it is set to false or not set (defaulting to false), @@ -1016,6 +1020,16 @@ type ExtAuth struct { RecomputeRoute *bool `json:"recomputeRoute,omitempty"` } +// BodyToExtAuth defines the Body to Ext Auth configuration +// +k8s:deepcopy-gen=true +type BodyToExtAuth struct { + // MaxRequestBytes is the maximum size of a message body that the filter will hold in memory. + // Envoy will return HTTP 413 and will not initiate the authorization process when buffer + // reaches the number set in this field. + // Note that this setting will have precedence over failOpen mode. + MaxRequestBytes uint32 `json:"maxRequestBytes"` +} + // HTTPExtAuthService defines the HTTP External Authorization service // +k8s:deepcopy-gen=true type HTTPExtAuthService struct { diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 6db14262456..fbdb444e430 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -330,6 +330,21 @@ func (in *BasicAuth) DeepCopy() *BasicAuth { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BodyToExtAuth) DeepCopyInto(out *BodyToExtAuth) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BodyToExtAuth. +func (in *BodyToExtAuth) DeepCopy() *BodyToExtAuth { + if in == nil { + return nil + } + out := new(BodyToExtAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CORS) DeepCopyInto(out *CORS) { *out = *in @@ -898,6 +913,11 @@ func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.BodyToExtAuth != nil { + in, out := &in.BodyToExtAuth, &out.BodyToExtAuth + *out = new(BodyToExtAuth) + **out = **in + } if in.FailOpen != nil { in, out := &in.FailOpen, &out.FailOpen *out = new(bool) diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go index 2f8766fe91c..f65cc0875f3 100644 --- a/internal/xds/translator/extauth.go +++ b/internal/xds/translator/extauth.go @@ -117,6 +117,12 @@ func extAuthConfig(extAuth *ir.ExtAuth) *extauthv3.ExtAuthz { }) } + if extAuth.BodyToExtAuth != nil { + config.WithRequestBody = &extauthv3.BufferSettings{ + MaxRequestBytes: extAuth.BodyToExtAuth.MaxRequestBytes, + } + } + if len(headersToExtAuth) > 0 { config.AllowedHeaders = &matcherv3.ListStringMatcher{ Patterns: headersToExtAuth, diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-auth-body.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-auth-body.yaml new file mode 100644 index 00000000000..f3ce1bd3477 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/ext-auth-body.yaml @@ -0,0 +1,125 @@ +http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + hostname: www.foo.com + isHTTP2: false + pathMatch: + distinct: false + name: "" + prefix: /foo1 + backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + security: + extAuth: + name: securitypolicy/default/policy-for-http-route-1 + failOpen: false + grpc: + authority: primary.foo.com + destination: + name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 9000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + - name: httproute/default/httproute-1/rule/1/match/0/www_foo_com + hostname: www.foo.com + isHTTP2: false + pathMatch: + distinct: false + name: "" + prefix: /foo2 + backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + security: + extAuth: + name: securitypolicy/default/policy-for-http-route-1 + failOpen: false + grpc: + authority: primary.foo.com + destination: + name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + settings: + - addressType: IP + endpoints: + - host: primary.foo.com + port: 3000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + - name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + hostname: www.bar.com + isHTTP2: false + pathMatch: + distinct: false + name: "" + prefix: /bar + backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + security: + extAuth: + name: securitypolicy/default/policy-for-gateway-1 + failOpen: true + bodyToExtAuth: + maxRequestBytes: 32768 + http: + authority: primary.foo.com + destination: + name: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 80 + protocol: HTTP + weight: 1 + headersToBackend: + - header1 + - header2 + path: /auth diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.clusters.yaml new file mode 100644 index 00000000000..79e1aed5ebe --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.clusters.yaml @@ -0,0 +1,115 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-1/rule/0 + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-1/rule/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-1/rule/1 + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-1/rule/1 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-2/rule/0 + ignoreHealthOnHostRemoval: true + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-2/rule/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + dnsRefreshRate: 30s + lbPolicy: LEAST_REQUEST + loadAssignment: + clusterName: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: primary.foo.com + portValue: 9000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: securitypolicy/default/policy-for-http-route-1/default/grpc-backend/backend/0 + name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + dnsRefreshRate: 30s + lbPolicy: LEAST_REQUEST + loadAssignment: + clusterName: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: primary.foo.com + portValue: 80 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend/backend/0 + name: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.endpoints.yaml new file mode 100644 index 00000000000..bf9f0023789 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.endpoints.yaml @@ -0,0 +1,36 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/0/backend/0 +- clusterName: httproute/default/httproute-1/rule/1 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/1/backend/0 +- clusterName: httproute/default/httproute-2/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-2/rule/0/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.listeners.yaml new file mode 100644 index 00000000000..84bea029d0b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.listeners.yaml @@ -0,0 +1,71 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - disabled: true + name: envoy.filters.http.ext_authz/securitypolicy/default/policy-for-http-route-1 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + allowedHeaders: + patterns: + - exact: header1 + ignoreCase: true + - exact: header2 + ignoreCase: true + grpcService: + envoyGrpc: + authority: primary.foo.com + clusterName: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + timeout: 10s + transportApiVersion: V3 + - disabled: true + name: envoy.filters.http.ext_authz/securitypolicy/default/policy-for-gateway-1 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + failureModeAllow: true + httpService: + authorizationResponse: + allowedUpstreamHeaders: + patterns: + - exact: header1 + ignoreCase: true + - exact: header2 + ignoreCase: true + pathPrefix: /auth + serverUri: + cluster: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + timeout: 10s + uri: http://primary.foo.com/auth + transportApiVersion: V3 + withRequestBody: + maxRequestBytes: 32768 + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: default/gateway-1/http + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: default/gateway-1/http + name: default/gateway-1/http + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.routes.yaml new file mode 100644 index 00000000000..08edfc3c406 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-body.routes.yaml @@ -0,0 +1,44 @@ +- ignorePortInHostMatching: true + name: default/gateway-1/http + virtualHosts: + - domains: + - www.foo.com + name: default/gateway-1/http/www_foo_com + routes: + - match: + pathSeparatedPrefix: /foo1 + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_authz/securitypolicy/default/policy-for-http-route-1: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - match: + pathSeparatedPrefix: /foo2 + name: httproute/default/httproute-1/rule/1/match/0/www_foo_com + route: + cluster: httproute/default/httproute-1/rule/1 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_authz/securitypolicy/default/policy-for-http-route-1: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - domains: + - www.bar.com + name: default/gateway-1/http/www_bar_com + routes: + - match: + pathSeparatedPrefix: /bar + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + route: + cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_authz/securitypolicy/default/policy-for-gateway-1: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index fc7142446c1..c6a7121d7ca 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -468,6 +468,20 @@ _Appears in:_ | `users` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | true | The Kubernetes secret which contains the username-password pairs in
htpasswd format, used to verify user credentials in the "Authorization"
header.

This is an Opaque secret. The username-password pairs should be stored in
the key ".htpasswd". As the key name indicates, the value needs to be the
htpasswd format, for example: "user1:\{SHA\}hashed_user1_password".
Right now, only SHA hash algorithm is supported.
Reference to https://httpd.apache.org/docs/2.4/programs/htpasswd.html
for more details.

Note: The secret must be in the same namespace as the SecurityPolicy. | +#### BodyToExtAuth + + + +BodyToExtAuth defines the Body to Ext Auth configuration + +_Appears in:_ +- [ExtAuth](#extauth) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `maxRequestBytes` | _integer_ | true | MaxRequestBytes is the maximum size of a message body that the filter will hold in memory.
Envoy will return HTTP 413 and will not initiate the authorization process when buffer
reaches the number set in this field.
Note that this setting will have precedence over failOpen mode. | + + #### BootstrapType _Underlying type:_ _string_ @@ -1478,6 +1492,7 @@ _Appears in:_ | `grpc` | _[GRPCExtAuthService](#grpcextauthservice)_ | true | GRPC defines the gRPC External Authorization service.
Either GRPCService or HTTPService must be specified,
and only one of them can be provided. | | `http` | _[HTTPExtAuthService](#httpextauthservice)_ | true | HTTP defines the HTTP External Authorization service.
Either GRPCService or HTTPService must be specified,
and only one of them can be provided. | | `headersToExtAuth` | _string array_ | false | HeadersToExtAuth defines the client request headers that will be included
in the request to the external authorization service.
Note: If not specified, the default behavior for gRPC and HTTP external
authorization services is different due to backward compatibility reasons.
All headers will be included in the check request to a gRPC authorization server.
Only the following headers will be included in the check request to an HTTP
authorization server: Host, Method, Path, Content-Length, and Authorization.
And these headers will always be included to the check request to an HTTP
authorization server by default, no matter whether they are specified
in HeadersToExtAuth or not. | +| `bodyToExtAuth` | _[BodyToExtAuth](#bodytoextauth)_ | false | BodyToExtAuth defines the Body to Ext Auth configuration. | | `failOpen` | _boolean_ | false | FailOpen is a switch used to control the behavior when a response from the External Authorization service cannot be obtained.
If FailOpen is set to true, the system allows the traffic to pass through.
Otherwise, if it is set to false or not set (defaulting to false),
the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
This setting determines whether to prioritize accessibility over strict security in case of authorization service failure. | | `recomputeRoute` | _boolean_ | false | RecomputeRoute clears the route cache and recalculates the routing decision.
This field must be enabled if the headers added or modified by the ExtAuth are used for
route matching decisions. If the recomputation selects a new route, features targeting
the new matched route will be applied. | diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md index fc7142446c1..c6a7121d7ca 100644 --- a/site/content/zh/latest/api/extension_types.md +++ b/site/content/zh/latest/api/extension_types.md @@ -468,6 +468,20 @@ _Appears in:_ | `users` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | true | The Kubernetes secret which contains the username-password pairs in
htpasswd format, used to verify user credentials in the "Authorization"
header.

This is an Opaque secret. The username-password pairs should be stored in
the key ".htpasswd". As the key name indicates, the value needs to be the
htpasswd format, for example: "user1:\{SHA\}hashed_user1_password".
Right now, only SHA hash algorithm is supported.
Reference to https://httpd.apache.org/docs/2.4/programs/htpasswd.html
for more details.

Note: The secret must be in the same namespace as the SecurityPolicy. | +#### BodyToExtAuth + + + +BodyToExtAuth defines the Body to Ext Auth configuration + +_Appears in:_ +- [ExtAuth](#extauth) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `maxRequestBytes` | _integer_ | true | MaxRequestBytes is the maximum size of a message body that the filter will hold in memory.
Envoy will return HTTP 413 and will not initiate the authorization process when buffer
reaches the number set in this field.
Note that this setting will have precedence over failOpen mode. | + + #### BootstrapType _Underlying type:_ _string_ @@ -1478,6 +1492,7 @@ _Appears in:_ | `grpc` | _[GRPCExtAuthService](#grpcextauthservice)_ | true | GRPC defines the gRPC External Authorization service.
Either GRPCService or HTTPService must be specified,
and only one of them can be provided. | | `http` | _[HTTPExtAuthService](#httpextauthservice)_ | true | HTTP defines the HTTP External Authorization service.
Either GRPCService or HTTPService must be specified,
and only one of them can be provided. | | `headersToExtAuth` | _string array_ | false | HeadersToExtAuth defines the client request headers that will be included
in the request to the external authorization service.
Note: If not specified, the default behavior for gRPC and HTTP external
authorization services is different due to backward compatibility reasons.
All headers will be included in the check request to a gRPC authorization server.
Only the following headers will be included in the check request to an HTTP
authorization server: Host, Method, Path, Content-Length, and Authorization.
And these headers will always be included to the check request to an HTTP
authorization server by default, no matter whether they are specified
in HeadersToExtAuth or not. | +| `bodyToExtAuth` | _[BodyToExtAuth](#bodytoextauth)_ | false | BodyToExtAuth defines the Body to Ext Auth configuration. | | `failOpen` | _boolean_ | false | FailOpen is a switch used to control the behavior when a response from the External Authorization service cannot be obtained.
If FailOpen is set to true, the system allows the traffic to pass through.
Otherwise, if it is set to false or not set (defaulting to false),
the system blocks the traffic and returns a HTTP 5xx error, reflecting a fail-closed approach.
This setting determines whether to prioritize accessibility over strict security in case of authorization service failure. | | `recomputeRoute` | _boolean_ | false | RecomputeRoute clears the route cache and recalculates the routing decision.
This field must be enabled if the headers added or modified by the ExtAuth are used for
route matching decisions. If the recomputation selects a new route, features targeting
the new matched route will be applied. |