From a2fbbad5db9a6fe4a1afa0bc20d0217d022275ca Mon Sep 17 00:00:00 2001 From: Dingkang Li Date: Wed, 15 May 2024 13:20:09 +0800 Subject: [PATCH 01/25] refactor: refactor UDP IR (#3373) * Refactor IR creation for UDPRoute Signed-off-by: Dingkang Li * Remove duplicate code to generate UDP route name Signed-off-by: Dingkang Li * Fix comment Co-authored-by: Arko Dasgupta Signed-off-by: Dingkang Li --------- Signed-off-by: Dingkang Li Co-authored-by: Arko Dasgupta --- .../translate/out/default-resources.all.yaml | 2 +- .../out/from-gateway-api-to-xds.all.json | 2 +- .../out/from-gateway-api-to-xds.all.yaml | 2 +- .../out/from-gateway-api-to-xds.listener.yaml | 2 +- internal/gatewayapi/backendtrafficpolicy.go | 24 +++++++--- internal/gatewayapi/helpers.go | 8 ++-- internal/gatewayapi/listener.go | 7 +++ internal/gatewayapi/route.go | 25 +++++----- ...cp-udp-listeners-apply-on-gateway.out.yaml | 40 ++++++++-------- ...-tcp-udp-listeners-apply-on-route.out.yaml | 40 ++++++++-------- ...route-with-mismatch-port-protocol.out.yaml | 12 +++-- ...h-udproute-with-multiple-backends.out.yaml | 34 ++++++------- ...with-udproute-with-multiple-rules.out.yaml | 4 ++ ...-listener-with-unmatched-udproute.out.yaml | 4 ++ ...-listener-with-multiple-udproutes.out.yaml | 22 +++++---- ...th-two-listeners-on-same-udp-port.out.yaml | 22 +++++---- ...-with-same-port-http-udp-protocol.out.yaml | 22 +++++---- ...s-with-udproutes-with-sectionname.out.yaml | 44 +++++++++-------- ...ith-udproutes-without-sectionname.out.yaml | 44 +++++++++-------- .../merge-invalid-multiple-gateways.out.yaml | 4 ++ internal/ir/xds.go | 30 +++++++++++- internal/ir/xds_test.go | 34 +++++++------ internal/ir/zz_generated.deepcopy.go | 26 ++++++++-- .../in/xds-ir/udp-endpoint-stats.yaml | 18 +++---- .../testdata/in/xds-ir/udp-route-invalid.yaml | 16 ++++--- .../testdata/in/xds-ir/udp-route.yaml | 18 +++---- internal/xds/translator/translator.go | 48 ++++++++++--------- 27 files changed, 332 insertions(+), 222 deletions(-) diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml index 7b8319b6376f..cacca5bb7c4f 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -1041,7 +1041,7 @@ xds: '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route cluster: udproute/default/backend/rule/-1 statPrefix: service - name: default/eg/udp/backend + name: default/eg/udp - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump dynamicRouteConfigs: - routeConfig: diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json index 80be0dae6299..476f6cdae771 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json @@ -942,7 +942,7 @@ } } ], - "name": "default/eg/udp/backend" + "name": "default/eg/udp" } } } diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml index 05c22f5ab882..4481d9989ffd 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml @@ -560,7 +560,7 @@ xds: '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route cluster: udproute/default/backend/rule/-1 statPrefix: service - name: default/eg/udp/backend + name: default/eg/udp - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump dynamicRouteConfigs: - routeConfig: diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml index 61288c6e1309..2b1c410cd963 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml @@ -255,4 +255,4 @@ xds: '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route cluster: udproute/default/backend/rule/-1 statPrefix: service - name: default/eg/udp/backend + name: default/eg/udp diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index 1a2df010dae6..d29f7d10656f 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -354,9 +354,13 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen } for _, udp := range x.UDP { - if strings.HasPrefix(udp.Destination.Name, prefix) { - udp.LoadBalancer = lb - udp.Timeout = to + if udp.Route != nil { + route := udp.Route + + if strings.HasPrefix(route.Destination.Name, prefix) { + route.LoadBalancer = lb + route.Timeout = to + } } } @@ -490,14 +494,20 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back continue } + if udp.Route == nil { + continue + } + + route := udp.Route + // policy(targeting xRoute) has already set it, so we skip it. - if udp.LoadBalancer != nil || udp.Timeout != nil { + if route.LoadBalancer != nil || route.Timeout != nil { continue } - udp.LoadBalancer = lb - if udp.Timeout == nil { - udp.Timeout = ct + route.LoadBalancer = lb + if route.Timeout == nil { + route.Timeout = ct } } diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index 246c1f12251d..2dfc04a18428 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -347,10 +347,6 @@ func irListenerName(listener *ListenerContext) string { return fmt.Sprintf("%s/%s/%s", listener.gateway.Namespace, listener.gateway.Name, listener.Name) } -func irUDPListenerName(listener *ListenerContext, udpRoute *UDPRouteContext) string { - return fmt.Sprintf("%s/%s/%s/%s", listener.gateway.Namespace, listener.gateway.Name, listener.Name, udpRoute.Name) -} - func irListenerPortName(proto ir.ProtocolType, port int32) string { return strings.ToLower(fmt.Sprintf("%s-%d", proto, port)) } @@ -369,6 +365,10 @@ func irTCPRouteName(route RouteContext) string { return fmt.Sprintf("%s/%s/%s", strings.ToLower(string(GetRouteType(route))), route.GetNamespace(), route.GetName()) } +func irUDPRouteName(route RouteContext) string { + return irTCPRouteName(route) +} + func irRouteDestinationName(route RouteContext, ruleIdx int) string { return fmt.Sprintf("%srule/%d", irRoutePrefix(route), ruleIdx) } diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index 0d9b04a40277..62d60b75f1f5 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -124,6 +124,13 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR XdsIRMap Port: uint32(containerPort), } xdsIR[irKey].TCP = append(xdsIR[irKey].TCP, irListener) + case gwapiv1.UDPProtocolType: + irListener := &ir.UDPListener{ + Name: irListenerName(listener), + Address: "0.0.0.0", + Port: uint32(containerPort), + } + xdsIR[irKey].UDP = append(xdsIR[irKey].UDP, irListener) } // Add the listener to the Infra IR. Infra IR ports must have a unique port number per layer-4 protocol diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 5edcf53af013..aa1d2091b63f 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -929,21 +929,18 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour irKey := t.getIRKey(listener.gateway) - containerPort := servicePortToContainerPort(int32(listener.Port)) - // Create the UDP Listener while parsing the UDPRoute since - // the listener directly links to a routeDestination. - irListener := &ir.UDPListener{ - Name: irUDPListenerName(listener, udpRoute), - Address: "0.0.0.0", - Port: uint32(containerPort), - Destination: &ir.RouteDestination{ - Name: irRouteDestinationName(udpRoute, -1 /*rule index*/), - Settings: destSettings, - }, - } gwXdsIR := xdsIR[irKey] - gwXdsIR.UDP = append(gwXdsIR.UDP, irListener) - + irListener := gwXdsIR.GetUDPListener(irListenerName(listener)) + if irListener != nil { + irRoute := &ir.UDPRoute{ + Name: irUDPRouteName(udpRoute), + Destination: &ir.RouteDestination{ + Name: irRouteDestinationName(udpRoute, -1 /*rule index*/), + Settings: destSettings, + }, + } + irListener.Route = irRoute + } } // If no negative conditions have been set, the route is considered "Accepted=True". diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml index 857ec1e89d1b..660c8d7d800f 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-gateway.out.yaml @@ -293,23 +293,25 @@ xdsIR: connectTimeout: 15s udp: - address: 0.0.0.0 - destination: - name: udproute/default/udp-app-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - loadBalancer: - consistentHash: - sourceIP: true - name: default/tcp-gateway/foo/udp-app-1 + name: default/tcp-gateway/foo port: 8162 - timeout: - http: - connectionIdleTimeout: 16s - maxConnectionDuration: 17s - tcp: - connectTimeout: 15s + route: + destination: + name: udproute/default/udp-app-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + loadBalancer: + consistentHash: + sourceIP: true + name: udproute/default/udp-app-1 + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml index 5c0f2240bd6b..d2c691d719da 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcp-udp-listeners-apply-on-route.out.yaml @@ -366,23 +366,25 @@ xdsIR: connectTimeout: 15s udp: - address: 0.0.0.0 - destination: - name: udproute/default/udp-app-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - loadBalancer: - consistentHash: - sourceIP: true - name: default/tcp-gateway/foo/udp-app-1 + name: default/tcp-gateway/foo port: 8162 - timeout: - http: - connectionIdleTimeout: 16s - maxConnectionDuration: 17s - tcp: - connectTimeout: 15s + route: + destination: + name: udproute/default/udp-app-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + loadBalancer: + consistentHash: + sourceIP: true + name: udproute/default/udp-app-1 + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml index 2fbbe314fa5c..2603bbfad7d0 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml @@ -92,9 +92,11 @@ xdsIR: - path: /dev/stdout udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - weight: 1 - name: envoy-gateway/gateway-1/udp/udproute-1 + name: envoy-gateway/gateway-1/udp port: 10162 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - weight: 1 + name: udproute/default/udproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml index 7141e821a37c..70a5a2a85996 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-backends.out.yaml @@ -96,20 +96,22 @@ xdsIR: - path: /dev/stdout udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 50 - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 50 - name: envoy-gateway/gateway-1/udp/udproute-1 + name: envoy-gateway/gateway-1/udp port: 10080 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 50 + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 50 + name: udproute/default/udproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml index 56d9c366b021..850f9e64cba3 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-multiple-rules.out.yaml @@ -95,3 +95,7 @@ xdsIR: accessLog: text: - path: /dev/stdout + udp: + - address: 0.0.0.0 + name: envoy-gateway/gateway-1/udp + port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-unmatched-udproute.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-unmatched-udproute.out.yaml index 27d949d622e7..a30d7cf5a5b7 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-unmatched-udproute.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-unmatched-udproute.out.yaml @@ -58,3 +58,7 @@ xdsIR: accessLog: text: - path: /dev/stdout + udp: + - address: 0.0.0.0 + name: envoy-gateway/gateway-1/udp + port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml index 22e840d232a5..4f4555a87e89 100644 --- a/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-single-listener-with-multiple-udproutes.out.yaml @@ -123,14 +123,16 @@ xdsIR: - path: /dev/stdout udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp/udproute-1 + name: envoy-gateway/gateway-1/udp port: 10162 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml index 68f755e99ab4..5f904c3de3e3 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml @@ -119,14 +119,16 @@ xdsIR: - path: /dev/stdout udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp1/udproute-1 + name: envoy-gateway/gateway-1/udp1 port: 10162 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml index 88db8d64873d..ef9658f0f2af 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml @@ -191,14 +191,16 @@ xdsIR: prefix: / udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp/udproute-1 + name: envoy-gateway/gateway-1/udp port: 10080 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-1 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml index 418f7a0ad4e1..00a61415035f 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-with-sectionname.out.yaml @@ -161,26 +161,30 @@ xdsIR: - path: /dev/stdout udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp1/udproute-1 + name: envoy-gateway/gateway-1/udp1 port: 10162 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-1 - address: 0.0.0.0 - destination: - name: udproute/default/udproute-2/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp2/udproute-2 + name: envoy-gateway/gateway-1/udp2 port: 10163 + route: + destination: + name: udproute/default/udproute-2/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-2 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml index 17b9d4e22538..f6cb6959c4bf 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-udproutes-without-sectionname.out.yaml @@ -157,26 +157,30 @@ xdsIR: - path: /dev/stdout udp: - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp1/udproute-1 + name: envoy-gateway/gateway-1/udp1 port: 10161 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-1 - address: 0.0.0.0 - destination: - name: udproute/default/udproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8162 - protocol: UDP - weight: 1 - name: envoy-gateway/gateway-1/udp2/udproute-1 + name: envoy-gateway/gateway-1/udp2 port: 10162 + route: + destination: + name: udproute/default/udproute-1/rule/-1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8162 + protocol: UDP + weight: 1 + name: udproute/default/udproute-1 diff --git a/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml b/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml index c37bd4038e57..64eba4e494ac 100644 --- a/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml +++ b/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml @@ -145,3 +145,7 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 + udp: + - address: 0.0.0.0 + name: envoy-gateway/gateway-2/udp + port: 10080 diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 6d9ac357e735..b77d26cf7590 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -1332,6 +1332,15 @@ type UDPListener struct { Address string `json:"address" yaml:"address"` // Port on which the service can be expected to be accessed by clients. Port uint32 `json:"port" yaml:"port"` + // Route associated with UDP traffic to the listener. + Route *UDPRoute `json:"route,omitempty" yaml:"route,omitempty"` +} + +// UDPRoute holds the route information associated with the UDP Route. +// +k8s:deepcopy-gen=true +type UDPRoute struct { + // Name of the UDPRoute. + Name string `json:"name" yaml:"name"` // Destination associated with UDP traffic to the service. Destination *RouteDestination `json:"destination,omitempty" yaml:"destination,omitempty"` // load balancer policy to use when routing to the backend endpoints. @@ -1352,8 +1361,25 @@ func (h UDPListener) Validate() error { if h.Port == 0 { errs = errors.Join(errs, ErrListenerPortInvalid) } - if h.Destination != nil { - if err := h.Destination.Validate(); err != nil { + + if h.Route != nil { + if err := h.Route.Validate(); err != nil { + errs = errors.Join(errs, err) + } + } + + return errs +} + +func (u UDPRoute) Validate() error { + var errs error + + if u.Name == "" { + errs = errors.Join(errs, ErrRouteNameEmpty) + } + + if u.Destination != nil { + if err := u.Destination.Validate(); err != nil { errs = errors.Join(errs, err) } } diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index ec1b0f741326..d122f25c6e19 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -144,26 +144,32 @@ var ( // UDPListener happyUDPListener = UDPListener{ - Name: "happy", - Address: "0.0.0.0", - Port: 80, - Destination: &happyRouteDestination, + Name: "happy", + Address: "0.0.0.0", + Port: 80, + Route: &happyUDPRoute, } invalidNameUDPListener = UDPListener{ - Address: "0.0.0.0", - Port: 80, - Destination: &happyRouteDestination, + Address: "0.0.0.0", + Port: 80, + Route: &happyUDPRoute, } invalidAddrUDPListener = UDPListener{ - Name: "invalid-addr", - Address: "1.0.0", - Port: 80, - Destination: &happyRouteDestination, + Name: "invalid-addr", + Address: "1.0.0", + Port: 80, + Route: &happyUDPRoute, } invalidPortUDPListenerT = UDPListener{ - Name: "invalid-port", - Address: "0.0.0.0", - Port: 0, + Name: "invalid-port", + Address: "0.0.0.0", + Port: 0, + Route: &happyUDPRoute, + } + + // UDPRoute + happyUDPRoute = UDPRoute{ + Name: "happy", Destination: &happyRouteDestination, } diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 172ac9ec4938..0024414525f7 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -2445,6 +2445,26 @@ func (in *TrafficFeatures) DeepCopy() *TrafficFeatures { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UDPListener) DeepCopyInto(out *UDPListener) { + *out = *in + if in.Route != nil { + in, out := &in.Route, &out.Route + *out = new(UDPRoute) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDPListener. +func (in *UDPListener) DeepCopy() *UDPListener { + if in == nil { + return nil + } + out := new(UDPListener) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UDPRoute) DeepCopyInto(out *UDPRoute) { *out = *in if in.Destination != nil { in, out := &in.Destination, &out.Destination @@ -2463,12 +2483,12 @@ func (in *UDPListener) DeepCopyInto(out *UDPListener) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDPListener. -func (in *UDPListener) DeepCopy() *UDPListener { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDPRoute. +func (in *UDPRoute) DeepCopy() *UDPRoute { if in == nil { return nil } - out := new(UDPListener) + out := new(UDPRoute) in.DeepCopyInto(out) return out } diff --git a/internal/xds/translator/testdata/in/xds-ir/udp-endpoint-stats.yaml b/internal/xds/translator/testdata/in/xds-ir/udp-endpoint-stats.yaml index 4b5b9982aee3..fc597f289280 100644 --- a/internal/xds/translator/testdata/in/xds-ir/udp-endpoint-stats.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/udp-endpoint-stats.yaml @@ -5,11 +5,13 @@ udp: - name: "udp-route-enable-endpoint-stats" address: "0.0.0.0" port: 10080 - destination: - name: "udp-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - - host: "5.6.7.8" - port: 50001 + route: + name: "udp-route" + destination: + name: "udp-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - host: "5.6.7.8" + port: 50001 diff --git a/internal/xds/translator/testdata/in/xds-ir/udp-route-invalid.yaml b/internal/xds/translator/testdata/in/xds-ir/udp-route-invalid.yaml index 39ab4e7f4034..29841a984b83 100644 --- a/internal/xds/translator/testdata/in/xds-ir/udp-route-invalid.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/udp-route-invalid.yaml @@ -1,10 +1,12 @@ udp: - name: "udp-route" port: 10080 - destination: - name: "udp-reoute-dest" - settings: - - endpoints: - - host: "" - - host: "5.6.7.8" - port: 50001 + route: + name: "udp-route" + destination: + name: "udp-route-dest" + settings: + - endpoints: + - host: "" + - host: "5.6.7.8" + port: 50001 diff --git a/internal/xds/translator/testdata/in/xds-ir/udp-route.yaml b/internal/xds/translator/testdata/in/xds-ir/udp-route.yaml index fa4ffafc1386..a933bdd78a49 100644 --- a/internal/xds/translator/testdata/in/xds-ir/udp-route.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/udp-route.yaml @@ -2,11 +2,13 @@ udp: - name: "udp-route" address: "0.0.0.0" port: 10080 - destination: - name: "udp-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - - host: "5.6.7.8" - port: 50001 + route: + name: "udp-route" + destination: + name: "udp-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - host: "5.6.7.8" + port: 50001 diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index cab26d1f905a..373d4a7530ce 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -529,29 +529,33 @@ func processUDPListenerXdsTranslation(tCtx *types.ResourceVersionTable, udpListe for _, udpListener := range udpListeners { // There won't be multiple UDP listeners on the same port since it's already been checked at the gateway api // translator - xdsListener, err := buildXdsUDPListener(udpListener.Destination.Name, udpListener, accesslog) - if err != nil { - // skip this listener if failed to build xds listener - errs = errors.Join(errs, err) - continue - } - if err := tCtx.AddXdsResource(resourcev3.ListenerType, xdsListener); err != nil { - // skip this listener if failed to add xds listener to the resource version table - errs = errors.Join(errs, err) - continue - } + if udpListener.Route != nil { + route := udpListener.Route - // 1:1 between IR UDPListener and xDS Cluster - if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: udpListener.Destination.Name, - settings: udpListener.Destination.Settings, - loadBalancer: udpListener.LoadBalancer, - timeout: udpListener.Timeout, - tSocket: nil, - endpointType: buildEndpointType(udpListener.Destination.Settings), - metrics: metrics, - }); err != nil && !errors.Is(err, ErrXdsClusterExists) { - errs = errors.Join(errs, err) + xdsListener, err := buildXdsUDPListener(route.Destination.Name, udpListener, accesslog) + if err != nil { + // skip this listener if failed to build xds listener + errs = errors.Join(errs, err) + continue + } + if err := tCtx.AddXdsResource(resourcev3.ListenerType, xdsListener); err != nil { + // skip this listener if failed to add xds listener to the resource version table + errs = errors.Join(errs, err) + continue + } + + // 1:1 between IR UDPRoute and xDS Cluster + if err := addXdsCluster(tCtx, &xdsClusterArgs{ + name: route.Destination.Name, + settings: route.Destination.Settings, + loadBalancer: route.LoadBalancer, + timeout: route.Timeout, + tSocket: nil, + endpointType: buildEndpointType(route.Destination.Settings), + metrics: metrics, + }); err != nil && !errors.Is(err, ErrXdsClusterExists) { + errs = errors.Join(errs, err) + } } } return errs From 02e936741d80dc91789e11a61d41ed430eb36d12 Mon Sep 17 00:00:00 2001 From: Kobi Levi <56400138+levikobi@users.noreply.github.com> Date: Thu, 16 May 2024 00:24:24 +0300 Subject: [PATCH 02/25] feat: add supported features to gateway class (#2491) * feat: add supported features to gateway class Signed-off-by: Kobi Levi * remove skipped test features from supported features list Signed-off-by: Kobi Levi --------- Signed-off-by: Kobi Levi --- .../translate/out/default-resources.all.yaml | 21 +++++++ .../out/echo-gateway-api.cluster.yaml | 21 +++++++ .../translate/out/echo-gateway-api.route.json | 22 +++++++ .../translate/out/invalid-envoyproxy.all.yaml | 21 +++++++ .../out/rejected-http-route.route.yaml | 21 +++++++ .../translate/out/valid-envoyproxy.all.yaml | 21 +++++++ internal/cmd/egctl/translate_test.go | 8 +++ internal/gatewayapi/conformance/features.go | 37 ++++++++++++ internal/gatewayapi/status/gatewayclass.go | 26 ++++++++ .../gatewayapi/status/gatewayclass_test.go | 59 +++++++++++++++++++ .../provider/kubernetes/controller_test.go | 5 ++ test/conformance/conformance_test.go | 13 ++-- .../experimental_conformance_test.go | 13 ++-- 13 files changed, 272 insertions(+), 16 deletions(-) create mode 100644 internal/gatewayapi/conformance/features.go diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml index cacca5bb7c4f..de7dfd0e9c55 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -158,6 +158,27 @@ gatewayClass: reason: Accepted status: "True" type: Accepted + supportedFeatures: + - GRPCRoute + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - ReferenceGrant + - TLSRoute gateways: - metadata: creationTimestamp: null diff --git a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml index 3d88f20f51db..6afabda49f4c 100644 --- a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml +++ b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.cluster.yaml @@ -12,6 +12,27 @@ gatewayClass: reason: Accepted status: "True" type: Accepted + supportedFeatures: + - GRPCRoute + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - ReferenceGrant + - TLSRoute gateways: - metadata: creationTimestamp: null diff --git a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json index 41dfd6683e7f..472c02fcfdbd 100644 --- a/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json +++ b/internal/cmd/egctl/testdata/translate/out/echo-gateway-api.route.json @@ -17,6 +17,28 @@ "reason": "Accepted", "message": "Valid GatewayClass" } + ], + "supportedFeatures": [ + "GRPCRoute", + "GatewayPort8080", + "HTTPRouteBackendProtocolH2C", + "HTTPRouteBackendProtocolWebSocket", + "HTTPRouteBackendTimeout", + "HTTPRouteDestinationPortMatching", + "HTTPRouteHostRewrite", + "HTTPRouteMethodMatching", + "HTTPRouteParentRefPort", + "HTTPRoutePathRedirect", + "HTTPRoutePathRewrite", + "HTTPRoutePortRedirect", + "HTTPRouteQueryParamMatching", + "HTTPRouteRequestMirror", + "HTTPRouteRequestMultipleMirrors", + "HTTPRouteRequestTimeout", + "HTTPRouteResponseHeaderModification", + "HTTPRouteSchemeRedirect", + "ReferenceGrant", + "TLSRoute" ] } }, diff --git a/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml b/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml index c7ad9cde1334..a15d2481e9a1 100644 --- a/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/invalid-envoyproxy.all.yaml @@ -38,6 +38,27 @@ gatewayClass: reason: InvalidParameters status: "False" type: Accepted + supportedFeatures: + - GRPCRoute + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - ReferenceGrant + - TLSRoute gateways: - metadata: creationTimestamp: null diff --git a/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml b/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml index c578d14aef50..f45a99fa577c 100644 --- a/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml +++ b/internal/cmd/egctl/testdata/translate/out/rejected-http-route.route.yaml @@ -12,6 +12,27 @@ gatewayClass: reason: Accepted status: "True" type: Accepted + supportedFeatures: + - GRPCRoute + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - ReferenceGrant + - TLSRoute gateways: - metadata: creationTimestamp: null diff --git a/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml b/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml index ef42d68c93e8..feef2037c5b8 100644 --- a/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/valid-envoyproxy.all.yaml @@ -31,6 +31,27 @@ gatewayClass: reason: Accepted status: "True" type: Accepted + supportedFeatures: + - GRPCRoute + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - ReferenceGrant + - TLSRoute gateways: - metadata: creationTimestamp: null diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index 96707159a999..c7d51b0e83a2 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -22,6 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" + "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/utils/field" "github.com/envoyproxy/gateway/internal/utils/file" ) @@ -349,6 +350,13 @@ func TestTranslate(t *testing.T) { } want := &TranslationResult{} mustUnmarshal(t, requireTestDataOutFile(t, fn), want) + + // Supported features are dynamic, instead of hard-coding them in the output files + // we define them here. + if want.GatewayClass != nil { + want.GatewayClass.Status.SupportedFeatures = status.GatewaySupportedFeatures + } + opts := cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime") require.Empty(t, cmp.Diff(want, got, opts)) }) diff --git a/internal/gatewayapi/conformance/features.go b/internal/gatewayapi/conformance/features.go new file mode 100644 index 000000000000..93b13751d7cc --- /dev/null +++ b/internal/gatewayapi/conformance/features.go @@ -0,0 +1,37 @@ +// 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 conformance + +import ( + "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/gateway-api/conformance/tests" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +// SkipTests is a list of tests that are skipped in the conformance suite. +var SkipTests = []suite.ConformanceTest{ + tests.GatewayStaticAddresses, + tests.GatewayHTTPListenerIsolation, // https://github.com/kubernetes-sigs/gateway-api/issues/3049 + tests.HTTPRouteBackendRequestHeaderModifier, // https://github.com/envoyproxy/gateway/issues/3338 +} + +func skipTestsShortNames(skipTests []suite.ConformanceTest) []string { + shortNames := make([]string, len(skipTests)) + for i, test := range skipTests { + shortNames[i] = test.ShortName + } + return shortNames +} + +// EnvoyGatewaySuite is the conformance suite configuration for the Gateway API. +var EnvoyGatewaySuite = suite.ConformanceOptions{ + SupportedFeatures: features.AllFeatures, + ExemptFeatures: sets.New[features.SupportedFeature](). + Insert(features.MeshCoreFeatures.UnsortedList()...). + Insert(features.MeshExtendedFeatures.UnsortedList()...), + SkipTests: skipTestsShortNames(SkipTests), +} diff --git a/internal/gatewayapi/status/gatewayclass.go b/internal/gatewayapi/status/gatewayclass.go index 35813c4bc401..9bcc76f3a0c8 100644 --- a/internal/gatewayapi/status/gatewayclass.go +++ b/internal/gatewayapi/status/gatewayclass.go @@ -17,7 +17,11 @@ import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi/conformance" ) const ( @@ -32,6 +36,7 @@ const ( // for the provided GatewayClass. func SetGatewayClassAccepted(gc *gwapiv1.GatewayClass, accepted bool, reason, msg string) *gwapiv1.GatewayClass { gc.Status.Conditions = MergeConditions(gc.Status.Conditions, computeGatewayClassAcceptedCondition(gc, accepted, reason, msg)) + gc.Status.SupportedFeatures = GatewaySupportedFeatures return gc } @@ -61,3 +66,24 @@ func computeGatewayClassAcceptedCondition(gatewayClass *gwapiv1.GatewayClass, } } } + +// GatewaySupportedFeatures is a list of supported Gateway-API features, +// based on the running conformance tests suite. +var GatewaySupportedFeatures = getSupportedFeatures(conformance.EnvoyGatewaySuite, conformance.SkipTests) + +func getSupportedFeatures(gatewaySuite suite.ConformanceOptions, skippedTests []suite.ConformanceTest) []gwapiv1.SupportedFeature { + supportedFeatures := gatewaySuite.SupportedFeatures.Clone() + supportedFeatures.Delete(gatewaySuite.ExemptFeatures.UnsortedList()...) + + for _, skippedTest := range skippedTests { + for _, feature := range skippedTest.Features { + supportedFeatures.Delete(feature) + } + } + + ret := sets.New[gwapiv1.SupportedFeature]() + for _, feature := range supportedFeatures.UnsortedList() { + ret.Insert(gwapiv1.SupportedFeature(feature)) + } + return sets.List(ret) +} diff --git a/internal/gatewayapi/status/gatewayclass_test.go b/internal/gatewayapi/status/gatewayclass_test.go index 7b845408eccb..0ccce4263531 100644 --- a/internal/gatewayapi/status/gatewayclass_test.go +++ b/internal/gatewayapi/status/gatewayclass_test.go @@ -10,7 +10,11 @@ import ( "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" ) func TestComputeGatewayClassAcceptedCondition(t *testing.T) { @@ -66,3 +70,58 @@ func TestComputeGatewayClassAcceptedCondition(t *testing.T) { assert.Equal(t, gc.Generation, got.ObservedGeneration) } } + +func TestGetSupportedFeatures(t *testing.T) { + testCases := []struct { + name string + gatewaySuite suite.ConformanceOptions + skippedTests []suite.ConformanceTest + expectedResult []gwapiv1.SupportedFeature + }{ + { + name: "No exempt features", + gatewaySuite: suite.ConformanceOptions{ + SupportedFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute"), + ExemptFeatures: sets.New[features.SupportedFeature](), + }, + expectedResult: []gwapiv1.SupportedFeature{"Gateway", "HTTPRoute"}, + }, + { + name: "All features exempt", + gatewaySuite: suite.ConformanceOptions{ + SupportedFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute"), + ExemptFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute"), + }, + expectedResult: []gwapiv1.SupportedFeature{}, + }, + { + name: "Some features exempt", + gatewaySuite: suite.ConformanceOptions{ + SupportedFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute", "GRPCRoute"), + ExemptFeatures: sets.New[features.SupportedFeature]("GRPCRoute"), + }, + expectedResult: []gwapiv1.SupportedFeature{"Gateway", "HTTPRoute"}, + }, + { + name: "Some features exempt with skipped tests", + gatewaySuite: suite.ConformanceOptions{ + SupportedFeatures: sets.New[features.SupportedFeature]("Gateway", "HTTPRoute", "GRPCRoute"), + ExemptFeatures: sets.New[features.SupportedFeature]("GRPCRoute"), + }, + skippedTests: []suite.ConformanceTest{ + { + Features: []features.SupportedFeature{"HTTPRoute"}, + }, + }, + expectedResult: []gwapiv1.SupportedFeature{"Gateway"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := getSupportedFeatures(tc.gatewaySuite, tc.skippedTests) + + assert.ElementsMatch(t, tc.expectedResult, result, "The result should match the expected output for the test case.") + }) + } +} diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go index 8e3a5f9b56fd..860ba09e4b13 100644 --- a/internal/provider/kubernetes/controller_test.go +++ b/internal/provider/kubernetes/controller_test.go @@ -20,6 +20,7 @@ import ( "github.com/envoyproxy/gateway/internal/envoygateway" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/logging" ) @@ -189,6 +190,7 @@ func TestHasManagedClass(t *testing.T) { Status: metav1.ConditionTrue, }, }, + SupportedFeatures: status.GatewaySupportedFeatures, }, }, }, @@ -223,6 +225,7 @@ func TestHasManagedClass(t *testing.T) { Status: metav1.ConditionTrue, }, }, + SupportedFeatures: status.GatewaySupportedFeatures, }, }, }, @@ -275,6 +278,7 @@ func TestHasManagedClass(t *testing.T) { Status: metav1.ConditionTrue, }, }, + SupportedFeatures: status.GatewaySupportedFeatures, }, }, { @@ -297,6 +301,7 @@ func TestHasManagedClass(t *testing.T) { Status: metav1.ConditionFalse, }, }, + SupportedFeatures: status.GatewaySupportedFeatures, }, }, }, diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index 9faa95cf19b1..ce7dce052ab9 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -15,20 +15,17 @@ import ( "sigs.k8s.io/gateway-api/conformance" "sigs.k8s.io/gateway-api/conformance/tests" "sigs.k8s.io/gateway-api/conformance/utils/suite" - "sigs.k8s.io/gateway-api/pkg/features" + + internalconf "github.com/envoyproxy/gateway/internal/gatewayapi/conformance" ) func TestGatewayAPIConformance(t *testing.T) { flag.Parse() opts := conformance.DefaultOptions(t) - opts.SkipTests = []string{ - tests.GatewayStaticAddresses.ShortName, - tests.GatewayHTTPListenerIsolation.ShortName, // https://github.com/kubernetes-sigs/gateway-api/issues/3049 - tests.HTTPRouteBackendRequestHeaderModifier.ShortName, // https://github.com/envoyproxy/gateway/issues/3338 - } - opts.SupportedFeatures = features.AllFeatures - opts.ExemptFeatures = features.MeshCoreFeatures + opts.SkipTests = internalconf.EnvoyGatewaySuite.SkipTests + opts.SupportedFeatures = internalconf.EnvoyGatewaySuite.SupportedFeatures + opts.ExemptFeatures = internalconf.EnvoyGatewaySuite.ExemptFeatures cSuite, err := suite.NewConformanceTestSuite(opts) if err != nil { diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index 702e919bca48..770abbc1c8a6 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -20,21 +20,18 @@ import ( "sigs.k8s.io/gateway-api/conformance/tests" "sigs.k8s.io/gateway-api/conformance/utils/flags" "sigs.k8s.io/gateway-api/conformance/utils/suite" - "sigs.k8s.io/gateway-api/pkg/features" "sigs.k8s.io/yaml" + + internalconf "github.com/envoyproxy/gateway/internal/gatewayapi/conformance" ) func TestExperimentalConformance(t *testing.T) { flag.Parse() opts := conformance.DefaultOptions(t) - opts.SkipTests = []string{ - tests.GatewayStaticAddresses.ShortName, - tests.GatewayHTTPListenerIsolation.ShortName, // https://github.com/kubernetes-sigs/gateway-api/issues/3049 - tests.HTTPRouteBackendRequestHeaderModifier.ShortName, // https://github.com/envoyproxy/gateway/issues/3338 - } - opts.SupportedFeatures = features.AllFeatures - opts.ExemptFeatures = features.MeshCoreFeatures + opts.SkipTests = internalconf.EnvoyGatewaySuite.SkipTests + opts.SupportedFeatures = internalconf.EnvoyGatewaySuite.SupportedFeatures + opts.ExemptFeatures = internalconf.EnvoyGatewaySuite.ExemptFeatures opts.ConformanceProfiles = sets.New( suite.GatewayHTTPConformanceProfileName, suite.GatewayTLSConformanceProfileName, From 16f1b43aa8f65e8a9ead7b5ec1a5890a8cbc7f53 Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Wed, 15 May 2024 16:52:47 -0500 Subject: [PATCH 03/25] API: Backend (#3063) * start backend Signed-off-by: Guy Daich * update design Signed-off-by: Guy Daich * add section name Signed-off-by: Guy Daich * update doc Signed-off-by: Guy Daich * fix cel Signed-off-by: Guy Daich * set MaxItems=1 Signed-off-by: Guy Daich * fix links Signed-off-by: Guy Daich * remove support for named policy attachment Signed-off-by: Guy Daich * rename address proto to proto Signed-off-by: Guy Daich * fix review comments, change ApplicationProto scope and enum Signed-off-by: Guy Daich * add CEL test, optionals, list, init and hide from docs Signed-off-by: Guy Daich * remove IPv6 Signed-off-by: Guy Daich * add port validation Signed-off-by: Guy Daich * rm protocol, rename, update design Signed-off-by: Guy Daich * code review fixes Signed-off-by: Guy Daich * fix design and app protos json Signed-off-by: Guy Daich * fix test Signed-off-by: Guy Daich * rename backendAddresses to endpoints, ip to ipv4 Signed-off-by: Guy Daich * fix doc string to use address Signed-off-by: Guy Daich * improve all doc strings Signed-off-by: Guy Daich * fix ip => ipv4 Signed-off-by: Guy Daich * rename backendendpoints => endpoits Signed-off-by: Guy Daich * renamed fqdn.address => fqdn.hostname Signed-off-by: Guy Daich * add conditions, doc fixes Signed-off-by: Guy Daich --------- Signed-off-by: Guy Daich --- api/v1alpha1/backend_types.go | 193 +++++++++++++ api/v1alpha1/envoygateway_types.go | 3 + api/v1alpha1/zz_generated.deepcopy.go | 245 ++++++++++++++-- .../gateway.envoyproxy.io_backends.yaml | 224 +++++++++++++++ .../en/contributions/design/backend.md | 162 +++++++++++ site/content/en/latest/api/extension_types.md | 138 +++++++++ test/cel-validation/backend_test.go | 266 ++++++++++++++++++ 7 files changed, 1200 insertions(+), 31 deletions(-) create mode 100644 api/v1alpha1/backend_types.go create mode 100644 charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml create mode 100644 site/content/en/contributions/design/backend.md create mode 100644 test/cel-validation/backend_test.go diff --git a/api/v1alpha1/backend_types.go b/api/v1alpha1/backend_types.go new file mode 100644 index 000000000000..a35cd62b6e62 --- /dev/null +++ b/api/v1alpha1/backend_types.go @@ -0,0 +1,193 @@ +// 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 ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // KindBackend is the name of the Backend kind. + KindBackend = "Backend" +) + +// AppProtocolType defines various backend applications protocols supported by Envoy Gateway +// +// +kubebuilder:validation:Enum=gateway.envoyproxy.io/h2c;gateway.envoyproxy.io/ws;gateway.envoyproxy.io/wss +// +notImplementedHide +type AppProtocolType string + +const ( + // AppProtocolTypeH2C defines the HTTP/2 application protocol. + AppProtocolTypeH2C AppProtocolType = "gateway.envoyproxy.io/h2c" + // AppProtocolTypeWS defines the WebSocket over HTTP protocol. + AppProtocolTypeWS AppProtocolType = "gateway.envoyproxy.io/ws" + // AppProtocolTypeWSS defines the WebSocket over HTTPS protocol. + AppProtocolTypeWSS AppProtocolType = "gateway.envoyproxy.io/wss" +) + +// Backend allows the user to configure the endpoints of a backend and +// the behavior of the connection from Envoy Proxy to the backend. +// +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=envoy-gateway,shortName=be +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +notImplementedHide +type Backend struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of Backend. + Spec BackendSpec `json:"spec"` + + // Status defines the current status of Backend. + Status BackendStatus `json:"status,omitempty"` +} + +// BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket +// corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address +// +// +kubebuilder:validation:XValidation:rule="(has(self.fqdn) || has(self.ipv4) || has(self.unix))",message="one of fqdn, ipv4 or unix must be specified" +// +kubebuilder:validation:XValidation:rule="((has(self.fqdn) && !(has(self.ipv4) || has(self.unix))) || (has(self.ipv4) && !(has(self.fqdn) || has(self.unix))) || (has(self.unix) && !(has(self.ipv4) || has(self.fqdn))))",message="only one of fqdn, ipv4 or unix can be specified" +// +notImplementedHide +type BackendEndpoint struct { + // FQDN defines a FQDN endpoint + // + // +optional + FQDN *FQDNEndpoint `json:"fqdn,omitempty"` + + // IPv4 defines an IPv4 endpoint + // + // +optional + IPv4 *IPv4Endpoint `json:"ipv4,omitempty"` + + // Unix defines the unix domain socket endpoint + // + // +optional + Unix *UnixSocket `json:"unix,omitempty"` +} + +// IPv4Endpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress +// +// +notImplementedHide +type IPv4Endpoint struct { + // Address defines the IPv4 address of the backend endpoint. + // + // +kubebuilder:validation:MinLength=7 + // +kubebuilder:validation:MaxLength=15 + // +kubebuilder:validation:Pattern=`^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$` + Address string `json:"address"` + + // Port defines the port of the backend endpoint. + // + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + Port int32 `json:"port"` +} + +// FQDNEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress +// +// +notImplementedHide +type FQDNEndpoint struct { + // Hostname defines the FQDN hostname of the backend endpoint. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + Hostname string `json:"hostname"` + + // Port defines the port of the backend endpoint. + // + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + Port int32 `json:"port"` +} + +// UnixSocket describes TCP/UDP unix domain socket address, corresponding to Envoy's Pipe +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-pipe +// +// +notImplementedHide +type UnixSocket struct { + // Path defines the unix domain socket path of the backend endpoint. + Path string `json:"path"` +} + +// BackendSpec describes the desired state of BackendSpec. +// +// +notImplementedHide +type BackendSpec struct { + // Endpoints defines the endpoints to be used when connecting to the backend. + // + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=4 + // +kubebuilder:validation:XValidation:rule="self.all(f, has(f.fqdn)) || !self.exists(f, has(f.fqdn))",message="fqdn addresses cannot be mixed with other address types" + Endpoints []BackendEndpoint `json:"endpoints,omitempty"` + + // AppProtocols defines the application protocols to be supported when connecting to the backend. + // + // +optional + AppProtocols []AppProtocolType `json:"appProtocols,omitempty"` +} + +// BackendConditionType is a type of condition for a backend. This type should be +// used with a Backend resource Status.Conditions field. +type BackendConditionType string + +// BackendConditionReason is a reason for a backend condition. +type BackendConditionReason string + +const ( + // BackendConditionAccepted indicates whether the backend has been accepted or + // rejected by a targeted resource, and why. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // + BackendConditionAccepted BackendConditionType = "Accepted" + + // BackendReasonAccepted is used with the "Accepted" condition when the backend + // has been accepted by the targeted resource. + BackendReasonAccepted BackendConditionReason = "Accepted" + + // BackendReasonInvalid is used with the "Accepted" condition when the backend + // is syntactically or semantically invalid. + BackendReasonInvalid BackendConditionReason = "Invalid" +) + +// BackendStatus defines the state of Backend +// +notImplementedHide +type BackendStatus struct { + // Conditions describe the current conditions of the Backend. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// BackendList contains a list of Backend resources. +// +// +kubebuilder:object:root=true +// +notImplementedHide +type BackendList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Backend `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Backend{}, &BackendList{}) +} diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index b1de1937c61a..29b816c5fcb5 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -166,6 +166,9 @@ type ExtensionAPISettings struct { // EnableEnvoyPatchPolicy enables Envoy Gateway to // reconcile and implement the EnvoyPatchPolicy resources. EnableEnvoyPatchPolicy bool `json:"enableEnvoyPatchPolicy"` + // EnableBackend enables Envoy Gateway to + // reconcile and implement the Backend resources. + EnableBackend bool `json:"enableBackend"` } // EnvoyGatewayProvider defines the desired configuration of a provider. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index c584ae2d62a8..f3fd72c38d14 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -14,9 +14,9 @@ import ( "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/gateway-api/apis/v1" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -86,12 +86,12 @@ func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { *out = *in if in.Timeout != nil { in, out := &in.Timeout, &out.Timeout - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.Interval != nil { in, out := &in.Interval, &out.Interval - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.UnhealthyThreshold != nil { @@ -183,12 +183,12 @@ func (in *BackOffPolicy) DeepCopyInto(out *BackOffPolicy) { *out = *in if in.BaseInterval != nil { in, out := &in.BaseInterval, &out.BaseInterval - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.MaxInterval != nil { in, out := &in.MaxInterval, &out.MaxInterval - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } } @@ -203,6 +203,95 @@ func (in *BackOffPolicy) DeepCopy() *BackOffPolicy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Backend) DeepCopyInto(out *Backend) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backend. +func (in *Backend) DeepCopy() *Backend { + if in == nil { + return nil + } + out := new(Backend) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Backend) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendEndpoint) DeepCopyInto(out *BackendEndpoint) { + *out = *in + if in.FQDN != nil { + in, out := &in.FQDN, &out.FQDN + *out = new(FQDNEndpoint) + **out = **in + } + if in.IPv4 != nil { + in, out := &in.IPv4, &out.IPv4 + *out = new(IPv4Endpoint) + **out = **in + } + if in.Unix != nil { + in, out := &in.Unix, &out.Unix + *out = new(UnixSocket) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendEndpoint. +func (in *BackendEndpoint) DeepCopy() *BackendEndpoint { + if in == nil { + return nil + } + out := new(BackendEndpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendList) DeepCopyInto(out *BackendList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Backend, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendList. +func (in *BackendList) DeepCopy() *BackendList { + if in == nil { + return nil + } + out := new(BackendList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackendList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendRef) DeepCopyInto(out *BackendRef) { *out = *in @@ -219,12 +308,61 @@ func (in *BackendRef) DeepCopy() *BackendRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendSpec) DeepCopyInto(out *BackendSpec) { + *out = *in + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]BackendEndpoint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AppProtocols != nil { + in, out := &in.AppProtocols, &out.AppProtocols + *out = make([]AppProtocolType, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendSpec. +func (in *BackendSpec) DeepCopy() *BackendSpec { + if in == nil { + return nil + } + out := new(BackendSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendStatus) DeepCopyInto(out *BackendStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendStatus. +func (in *BackendStatus) DeepCopy() *BackendStatus { + if in == nil { + return nil + } + out := new(BackendStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendTLSConfig) DeepCopyInto(out *BackendTLSConfig) { *out = *in if in.ClientCertificateRef != nil { in, out := &in.ClientCertificateRef, &out.ClientCertificateRef - *out = new(v1.SecretObjectReference) + *out = new(apisv1.SecretObjectReference) (*in).DeepCopyInto(*out) } in.TLSSettings.DeepCopyInto(&out.TLSSettings) @@ -417,7 +555,7 @@ func (in *CORS) DeepCopyInto(out *CORS) { } if in.MaxAge != nil { in, out := &in.MaxAge, &out.MaxAge - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.AllowCredentials != nil { @@ -693,7 +831,7 @@ func (in *ClientValidationContext) DeepCopyInto(out *ClientValidationContext) { *out = *in if in.CACertificateRefs != nil { in, out := &in.CACertificateRefs, &out.CACertificateRefs - *out = make([]v1.SecretObjectReference, len(*in)) + *out = make([]apisv1.SecretObjectReference, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -760,7 +898,7 @@ func (in *ConnectionLimit) DeepCopyInto(out *ConnectionLimit) { *out = *in if in.CloseDelay != nil { in, out := &in.CloseDelay, &out.CloseDelay - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } } @@ -1692,7 +1830,7 @@ func (in *ExtProc) DeepCopyInto(out *ExtProc) { } if in.MessageTimeout != nil { in, out := &in.MessageTimeout, &out.MessageTimeout - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.FailOpen != nil { @@ -1843,6 +1981,21 @@ func (in *ExtensionTLS) DeepCopy() *ExtensionTLS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FQDNEndpoint) DeepCopyInto(out *FQDNEndpoint) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FQDNEndpoint. +func (in *FQDNEndpoint) DeepCopy() *FQDNEndpoint { + if in == nil { + return nil + } + out := new(FQDNEndpoint) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FaultInjection) DeepCopyInto(out *FaultInjection) { *out = *in @@ -1903,7 +2056,7 @@ func (in *FaultInjectionDelay) DeepCopyInto(out *FaultInjectionDelay) { *out = *in if in.FixedDelay != nil { in, out := &in.FixedDelay, &out.FixedDelay - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.Percentage != nil { @@ -2176,12 +2329,12 @@ func (in *HTTPClientTimeout) DeepCopyInto(out *HTTPClientTimeout) { *out = *in if in.RequestReceivedTimeout != nil { in, out := &in.RequestReceivedTimeout, &out.RequestReceivedTimeout - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.IdleTimeout != nil { in, out := &in.IdleTimeout, &out.IdleTimeout - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } } @@ -2227,12 +2380,12 @@ func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = *in if in.ConnectionIdleTimeout != nil { in, out := &in.ConnectionIdleTimeout, &out.ConnectionIdleTimeout - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.MaxConnectionDuration != nil { in, out := &in.MaxConnectionDuration, &out.MaxConnectionDuration - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } } @@ -2352,6 +2505,21 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPv4Endpoint) DeepCopyInto(out *IPv4Endpoint) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPv4Endpoint. +func (in *IPv4Endpoint) DeepCopy() *IPv4Endpoint { + if in == nil { + return nil + } + out := new(IPv4Endpoint) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageWasmCodeSource) DeepCopyInto(out *ImageWasmCodeSource) { *out = *in @@ -2846,7 +3014,7 @@ func (in *KubernetesWatchMode) DeepCopyInto(out *KubernetesWatchMode) { } if in.NamespaceSelector != nil { in, out := &in.NamespaceSelector, &out.NamespaceSelector - *out = new(metav1.LabelSelector) + *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } } @@ -2866,17 +3034,17 @@ func (in *LeaderElection) DeepCopyInto(out *LeaderElection) { *out = *in if in.LeaseDuration != nil { in, out := &in.LeaseDuration, &out.LeaseDuration - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.RenewDeadline != nil { in, out := &in.RenewDeadline, &out.RenewDeadline - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.RetryPeriod != nil { in, out := &in.RetryPeriod, &out.RetryPeriod - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.Disable != nil { @@ -3064,7 +3232,7 @@ func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { } if in.Interval != nil { in, out := &in.Interval, &out.Interval - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.ConsecutiveLocalOriginFailures != nil { @@ -3084,7 +3252,7 @@ func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { } if in.BaseEjectionTime != nil { in, out := &in.BaseEjectionTime, &out.BaseEjectionTime - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.MaxEjectionPercent != nil { @@ -3134,7 +3302,7 @@ func (in *PerRetryPolicy) DeepCopyInto(out *PerRetryPolicy) { *out = *in if in.Timeout != nil { in, out := &in.Timeout, &out.Timeout - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.BackOff != nil { @@ -3518,7 +3686,7 @@ func (in *RateLimit) DeepCopyInto(out *RateLimit) { in.Backend.DeepCopyInto(&out.Backend) if in.Timeout != nil { in, out := &in.Timeout, &out.Timeout - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.Telemetry != nil { @@ -3778,7 +3946,7 @@ func (in *RedisTLSSettings) DeepCopyInto(out *RedisTLSSettings) { *out = *in if in.CertificateRef != nil { in, out := &in.CertificateRef, &out.CertificateRef - *out = new(v1.SecretObjectReference) + *out = new(apisv1.SecretObjectReference) (*in).DeepCopyInto(*out) } } @@ -4009,12 +4177,12 @@ func (in *ShutdownConfig) DeepCopyInto(out *ShutdownConfig) { *out = *in if in.DrainTimeout != nil { in, out := &in.DrainTimeout, &out.DrainTimeout - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } if in.MinDrainDuration != nil { in, out := &in.MinDrainDuration, &out.MinDrainDuration - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } } @@ -4054,7 +4222,7 @@ func (in *SlowStart) DeepCopyInto(out *SlowStart) { *out = *in if in.Window != nil { in, out := &in.Window, &out.Window - *out = new(metav1.Duration) + *out = new(v1.Duration) **out = **in } } @@ -4144,12 +4312,12 @@ func (in *TCPKeepalive) DeepCopyInto(out *TCPKeepalive) { } if in.IdleTime != nil { in, out := &in.IdleTime, &out.IdleTime - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } if in.Interval != nil { in, out := &in.Interval, &out.Interval - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } } @@ -4169,7 +4337,7 @@ func (in *TCPTimeout) DeepCopyInto(out *TCPTimeout) { *out = *in if in.ConnectTimeout != nil { in, out := &in.ConnectTimeout, &out.ConnectTimeout - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } } @@ -4281,6 +4449,21 @@ func (in *TracingProvider) DeepCopy() *TracingProvider { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UnixSocket) DeepCopyInto(out *UnixSocket) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnixSocket. +func (in *UnixSocket) DeepCopy() *UnixSocket { + if in == nil { + return nil + } + out := new(UnixSocket) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Wasm) DeepCopyInto(out *Wasm) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml new file mode 100644 index 000000000000..cb3538d9874e --- /dev/null +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backends.yaml @@ -0,0 +1,224 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: backends.gateway.envoyproxy.io +spec: + group: gateway.envoyproxy.io + names: + categories: + - envoy-gateway + kind: Backend + listKind: BackendList + plural: backends + shortNames: + - be + singular: backend + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Accepted")].reason + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Backend allows the user to configure the endpoints of a backend and + the behavior of the connection from Envoy Proxy to the backend. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Backend. + properties: + appProtocols: + description: AppProtocols defines the application protocols to be + supported when connecting to the backend. + items: + description: AppProtocolType defines various backend applications + protocols supported by Envoy Gateway + enum: + - gateway.envoyproxy.io/h2c + - gateway.envoyproxy.io/ws + - gateway.envoyproxy.io/wss + type: string + type: array + endpoints: + description: Endpoints defines the endpoints to be used when connecting + to the backend. + items: + description: |- + BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket + corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address + properties: + fqdn: + description: FQDN defines a FQDN endpoint + properties: + hostname: + description: Hostname defines the FQDN hostname of the backend + endpoint. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: Port defines the port of the backend endpoint. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + required: + - hostname + - port + type: object + ipv4: + description: IPv4 defines an IPv4 endpoint + properties: + address: + description: Address defines the IPv4 address of the backend + endpoint. + maxLength: 15 + minLength: 7 + pattern: ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + type: string + port: + description: Port defines the port of the backend endpoint. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + required: + - address + - port + type: object + unix: + description: Unix defines the unix domain socket endpoint + properties: + path: + description: Path defines the unix domain socket path of + the backend endpoint. + type: string + required: + - path + type: object + type: object + x-kubernetes-validations: + - message: one of fqdn, ipv4 or unix must be specified + rule: (has(self.fqdn) || has(self.ipv4) || has(self.unix)) + - message: only one of fqdn, ipv4 or unix can be specified + rule: ((has(self.fqdn) && !(has(self.ipv4) || has(self.unix))) + || (has(self.ipv4) && !(has(self.fqdn) || has(self.unix))) || + (has(self.unix) && !(has(self.ipv4) || has(self.fqdn)))) + maxItems: 4 + minItems: 1 + type: array + x-kubernetes-validations: + - message: fqdn addresses cannot be mixed with other address types + rule: self.all(f, has(f.fqdn)) || !self.exists(f, has(f.fqdn)) + type: object + status: + description: Status defines the current status of Backend. + properties: + conditions: + description: Conditions describe the current conditions of the Backend. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/site/content/en/contributions/design/backend.md b/site/content/en/contributions/design/backend.md new file mode 100644 index 000000000000..32596bffd327 --- /dev/null +++ b/site/content/en/contributions/design/backend.md @@ -0,0 +1,162 @@ +--- +title: "Backend" +--- + +## Overview + +This design document introduces the `Backend` API allowing system administrators to represent backends without the use +of a K8s `Service` resource. + +Common use cases for non-Service backends in the K8s and Envoy ecosystem include: +- Cluster-external endpoints, which are currently second-class citizens in Gateway-API + (supported using [Services and FQDN endpoints][]). +- Host-local endpoints, such as sidecars or daemons that listen on [unix domain sockets][] or envoy [internal listeners][], + that cannot be represented by a K8s service at all. + +Several projects currently support backends that are not registered in the infrastructure-specific service registry. +- K8s Ingress: [Resource Backends][] +- Istio: [Service Entry][] +- Gloo Edge: [Upstream][] +- Consul: [External Services][] + +## Goals +* Add an API definition to hold settings for configuring Unix Domain Socket, FQDN and IP. +* Determine which resources may reference the new backend resource. +* Determine which existing Gateway-API and Envoy Gateway policies may attach to the new backend resource. + +## Non Goals +* Support specific backend types, such as S3 Bucket, Redis, AMQP, InfluxDB, etc. + +## Implementation + +The `Backend` resource is an implementation-specific Gateway-API [BackendObjectReference Extension][]. + +### Example +Here is an example highlighting how a user can configure a route that forwards traffic to both a K8s Service and a Backend +that has both unix domain socket and ipv4 endpoints. A [BackendTLSPolicy][] is attached to the backend resource, enabling TLS. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: backend +spec: + ports: + - name: http + port: 3000 + targetPort: 3000 + selector: + app: backend +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: backend-mixed-ip-uds +spec: + appProtocols: + - gateway.envoyproxy.io/h2c + endpoints: + - unix: + path: /var/run/backend.sock + - ipv4: + address: 10.244.0.28 + port: 3000 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backend +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-uds + weight: 1 + - group: "" + kind: Service + name: backend + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: BackendTLSPolicy +metadata: + name: policy-btls +spec: + targetRef: + group: gateway.envoyproxy.io + kind: Backend + name: backend-mixed-ip-uds + tls: + caCertRefs: + - name: backend-tls-checks-certificate + group: '' + kind: ConfigMap + hostname: example.com +``` + +## Design Decisions +* All instances of `BackendObjectReference` in Envoy Gateway MAY support referencing the `Backend` kind. +* For security reasons, Envoy Gateway MUST reject references to a `Backend` in xRoute resources. For example, UDS and + localhost references will not be supported for xRoutes. +* All attributes of the Envoy Gateway extended `BackendRef` resource MUST be implemented for the `Backend` resource. +* A `Backend` resource referenced by `BackendObjectReference` will be translated to Envoy Gateway's IR DestinationSetting. + As such, all `BackendAdresses` are treated as equivalent endpoints with identical weights, TLS settings, etc. +* Gateway-API and Envoy Gateway policies that attach to Services ([BackendTLSPolicy][], [BackendLBPolicy][]) + MUST support attachment to the `Backend` resource in Envoy Gateway. +* Policy attachment to a named section of the `Backend` resource is not supported at this time. Currently, + `BackendObjectReference` can only select ports, and not generic section names. Hence, a named section of `Backend` + cannot be referenced by routes, and so attachment of policies to named sections will create translation ambiguity. + Users that wish to attach policies to some of the `BackendAddresses` in a `Backend` resource can use multiple `Backend` + resources and pluralized `BackendRefs` instead. +* The `Backend` API SHOULD support other Gateway-API backend features, such as [Backend Protocol Selection][]. + Translation of explicit upstream application protocol setting SHOULD be consistent with the existing implementation for + `Service` resources. +* The `Backend` upstream transport protocol (TCP, UDP) is inferred from the xRoute kind: TCP is inferred for all routes + except for `UDPRoute` which is resolved to UDP. +* This API resource MUST be part of same namespace as the targetRef resource. The `Backend` API MUST be subject to + the same cross-namespace reference restriction as referenced `Service` resources. +* The `Backend` resource translation MUST NOT modify Infrastructure. Any change to infrastructure that is required to + achieve connectivity to a backend (mounting a socket, adding a sidecar container, modifying a network policy, ...) + MUST be implemented with an appropriate infrastructure patch in the [EnvoyProxy][] API. +* To limit the overall maintenance effort related to supporting of non-Service backends, the `Backend` API SHOULD + support multiple generic address types (UDS, FQDN, IPv4, IPv6), and MUST NOT support vendor-specific backend types. +* Both `Backend` and `Service` resources may appear in the same `BackendRefs` list. +* The Optional `Port` field SHOULD NOT be evaluated when referencing a `Backend`. +* Referenced `Backend` resources MUST be translated to envoy endpoints, similar to the current `Service` translation. +* Certain combinations of `Backend` and `Service` are incompatible. For example, a Unix Domain Socket and a FQDN service + require different cluster service discovery types (Static/EDS and Strict-DNS accordingly). +* If a Backend that is referenced by a route cannot be translated, the `Route` resource will have an `Accepted=False` + condition with a `UnsupportedValue` reason. +* This API needs to be explicitly enabled using the [EnvoyGateway][] API + +## Alternatives +* The project can indefinitely wait for these configuration parameters to be part of the [Gateway API][]. +* Users can leverage the existing [Envoy Patch Policy][] or [Envoy Extension Manager][] to inject custom envoy clusters + and route configuration. However, these features require a high level of envoy expertise, investment and maintenance. + +[BackendObjectReference Extension]: https://gateway-api.sigs.k8s.io/guides/migrating-from-ingress/?h=extensi#approach-to-extensibility +[internal listeners]: https://www.envoyproxy.io/docs/envoy/latest/configuration/other_features/internal_listener +[unix domain sockets]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#envoy-v3-api-msg-config-core-v3-pipe +[Resource Backends]: https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend +[Services and FQDN endpoints]: ./../../latest/tasks/traffic/routing-outside-kubernetes.md +[Service Entry]: https://istio.io/latest/docs/reference/config/networking/service-entry/ +[Upstream]: https://docs.solo.io/gloo-edge/1.7.23/reference/api/github.com/solo-io/gloo/projects/gloo/api/v1/upstream.proto.sk/ +[External Services]: https://developer.hashicorp.com/consul/tutorials/developer-mesh/terminating-gateways-connect-external-services +[BackendTLSPolicy]: https://gateway-api.sigs.k8s.io/geps/gep-1897/ +[BackendLBPolicy]: https://gateway-api.sigs.k8s.io/geps/gep-1619/ +[Backend Protocol Selection]: https://gateway-api.sigs.k8s.io/geps/gep-1911/ +[EnvoyProxy]:../../latest/api/extension_types#envoyproxy +[EnvoyGateway]: ../../latest/api/extension_types#envoygateway +[Gateway API]: https://gateway-api.sigs.k8s.io/ +[Envoy Patch Policy]: ../../latest/api/extension_types#envoypatchpolicy +[Envoy Extension Manager]: ./extending-envoy-gateway diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index cde865d9ab23..716ad0bc78d5 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -14,6 +14,8 @@ API group. ### Resource Types +- [Backend](#backend) +- [BackendList](#backendlist) - [BackendTrafficPolicy](#backendtrafficpolicy) - [BackendTrafficPolicyList](#backendtrafficpolicylist) - [ClientTrafficPolicy](#clienttrafficpolicy) @@ -171,6 +173,22 @@ _Appears in:_ | `TCP` | ActiveHealthCheckerTypeTCP defines the TCP type of health checking.
| +#### AppProtocolType + +_Underlying type:_ _string_ + +AppProtocolType defines various backend applications protocols supported by Envoy Gateway + +_Appears in:_ +- [BackendSpec](#backendspec) + +| Value | Description | +| ----- | ----------- | +| `gateway.envoyproxy.io/h2c` | AppProtocolTypeH2C defines the HTTP/2 application protocol.
| +| `gateway.envoyproxy.io/ws` | AppProtocolTypeWS defines the WebSocket over HTTP protocol.
| +| `gateway.envoyproxy.io/wss` | AppProtocolTypeWSS defines the WebSocket over HTTPS protocol.
| + + #### Authorization @@ -201,6 +219,61 @@ _Appears in:_ | `maxInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | MaxInterval is the maximum interval between retries. This parameter is optional, but must be greater than or equal to the base_interval if set.
The default is 10 times the base_interval | +#### Backend + + + +Backend allows the user to configure the endpoints of a backend and +the behavior of the connection from Envoy Proxy to the backend. + +_Appears in:_ +- [BackendList](#backendlist) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`Backend` +| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` | _[BackendSpec](#backendspec)_ | true | Spec defines the desired state of Backend. | + + + + + + +#### BackendEndpoint + + + +BackendEndpoint describes a backend endpoint, which can be either a fully-qualified domain name, IPv4 address or unix domain socket +corresponding to Envoy's Address: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-address + +_Appears in:_ +- [BackendSpec](#backendspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `fqdn` | _[FQDNEndpoint](#fqdnendpoint)_ | false | FQDN defines a FQDN endpoint | +| `ipv4` | _[IPv4Endpoint](#ipv4endpoint)_ | false | IPv4 defines an IPv4 endpoint | +| `unix` | _[UnixSocket](#unixsocket)_ | false | Unix defines the unix domain socket endpoint | + + +#### BackendList + + + +BackendList contains a list of Backend resources. + + + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`BackendList` +| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` | _[Backend](#backend) array_ | true | | + + #### BackendRef @@ -223,6 +296,23 @@ _Appears in:_ | `port` | _[PortNumber](#portnumber)_ | false | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | +#### BackendSpec + + + +BackendSpec describes the desired state of BackendSpec. + +_Appears in:_ +- [Backend](#backend) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `endpoints` | _[BackendEndpoint](#backendendpoint) array_ | true | Endpoints defines the endpoints to be used when connecting to the backend. | +| `appProtocols` | _[AppProtocolType](#appprotocoltype) array_ | false | AppProtocols defines the application protocols to be supported when connecting to the backend. | + + + + #### BackendTLSConfig @@ -1280,6 +1370,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `enableEnvoyPatchPolicy` | _boolean_ | true | EnableEnvoyPatchPolicy enables Envoy Gateway to
reconcile and implement the EnvoyPatchPolicy resources. | +| `enableBackend` | _boolean_ | true | EnableBackend enables Envoy Gateway to
reconcile and implement the Backend resources. | #### ExtensionHooks @@ -1344,6 +1435,22 @@ _Appears in:_ | `certificateRef` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | true | CertificateRef contains a references to objects (Kubernetes objects or otherwise) that
contains a TLS certificate and private keys. These certificates are used to
establish a TLS handshake to the extension server.

CertificateRef can only reference a Kubernetes Secret at this time. | +#### FQDNEndpoint + + + +FQDNEndpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress + +_Appears in:_ +- [BackendEndpoint](#backendendpoint) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `hostname` | _string_ | true | Hostname defines the FQDN hostname of the backend endpoint. | +| `port` | _integer_ | true | Port defines the port of the backend endpoint. | + + #### FaultInjection @@ -1707,6 +1814,22 @@ _Appears in:_ | `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | +#### IPv4Endpoint + + + +IPv4Endpoint describes TCP/UDP socket address, corresponding to Envoy's Socket Address +https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-socketaddress + +_Appears in:_ +- [BackendEndpoint](#backendendpoint) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `address` | _string_ | true | Address defines the IPv4 address of the backend endpoint. | +| `port` | _integer_ | true | Port defines the port of the backend endpoint. | + + #### ImageWasmCodeSource @@ -3283,6 +3406,21 @@ _Appears in:_ | `unavailable` | The gRPC status code in the response headers is “unavailable”.
| +#### UnixSocket + + + +UnixSocket describes TCP/UDP unix domain socket address, corresponding to Envoy's Pipe +https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#config-core-v3-pipe + +_Appears in:_ +- [BackendEndpoint](#backendendpoint) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `path` | _string_ | true | Path defines the unix domain socket path of the backend endpoint. | + + #### Wasm diff --git a/test/cel-validation/backend_test.go b/test/cel-validation/backend_test.go new file mode 100644 index 000000000000..ab8efd7e629d --- /dev/null +++ b/test/cel-validation/backend_test.go @@ -0,0 +1,266 @@ +// 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. + +//go:build celvalidation +// +build celvalidation + +package celvalidation + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +func TestBackend(t *testing.T) { + ctx := context.Background() + baseBackend := egv1a1.Backend{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backend", + Namespace: metav1.NamespaceDefault, + }, + Spec: egv1a1.BackendSpec{}, + } + + cases := []struct { + desc string + mutate func(backend *egv1a1.Backend) + mutateStatus func(backend *egv1a1.Backend) + wantErrors []string + }{ + { + desc: "Valid static", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{ + { + Unix: &egv1a1.UnixSocket{ + Path: "/path/to/service.sock", + }, + }, + { + IPv4: &egv1a1.IPv4Endpoint{ + Address: "1.1.1.1", + Port: 443, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "Valid DNS", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{ + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "example.com", + Port: 443, + }, + }, + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "example2.com", + Port: 443, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "unsupported application protocol type", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{"HTTP7"}, + Endpoints: []egv1a1.BackendEndpoint{ + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "example.com", + Port: 443, + }, + }, + }, + } + }, + wantErrors: []string{"spec.appProtocols[0]: Unsupported value: \"HTTP7\": supported values: \"gateway.envoyproxy.io/h2c\", \"gateway.envoyproxy.io/ws\", \"gateway.envoyproxy.io/wss\""}, + }, + { + desc: "No address", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{{}}, + } + }, + wantErrors: []string{"spec.endpoints[0]: Invalid value: \"object\": one of fqdn, ipv4 or unix must be specified"}, + }, + { + desc: "Multiple addresses", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{ + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "example.com", + Port: 443, + }, + Unix: &egv1a1.UnixSocket{ + Path: "/path/to/service.sock", + }, + }, + }, + } + }, + wantErrors: []string{"spec.endpoints[0]: Invalid value: \"object\": only one of fqdn, ipv4 or unix can be specified"}, + }, + { + desc: "Mixed types", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{ + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "example.com", + Port: 443, + }, + }, + { + IPv4: &egv1a1.IPv4Endpoint{ + Address: "1.1.1.1", + Port: 443, + }, + }, + }, + } + }, + wantErrors: []string{"spec.endpoints: Invalid value: \"array\": FQDN addresses cannot be mixed with other address types"}, + }, + { + desc: "Invalid hostname", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{ + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "host name", + Port: 443, + }, + }, + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "host_name", + Port: 443, + }, + }, + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "hostname:443", + Port: 443, + }, + }, + { + FQDN: &egv1a1.FQDNEndpoint{ + Hostname: "host.*.name", + Port: 443, + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.endpoints[0].fqdn.hostname: Invalid value: \"host name\": spec.endpoints[0].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", + "spec.endpoints[1].fqdn.hostname: Invalid value: \"host_name\": spec.endpoints[1].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", + "spec.endpoints[2].fqdn.hostname: Invalid value: \"hostname:443\": spec.endpoints[2].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", + "spec.endpoints[3].fqdn.hostname: Invalid value: \"host.*.name\": spec.endpoints[3].fqdn.hostname in body should match '^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'", + }, + }, + { + desc: "Invalid IPv4", + mutate: func(backend *egv1a1.Backend) { + backend.Spec = egv1a1.BackendSpec{ + AppProtocols: []egv1a1.AppProtocolType{egv1a1.AppProtocolTypeH2C}, + Endpoints: []egv1a1.BackendEndpoint{ + { + IPv4: &egv1a1.IPv4Endpoint{ + Address: "300.0.0.0", + Port: 443, + }, + }, + { + IPv4: &egv1a1.IPv4Endpoint{ + Address: "0.0.0.0:443", + Port: 443, + }, + }, + { + IPv4: &egv1a1.IPv4Endpoint{ + Address: "0.0.0.0/12", + Port: 443, + }, + }, + { + IPv4: &egv1a1.IPv4Endpoint{ + Address: "a.b.c.e", + Port: 443, + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.endpoints[0].ipv4.address: Invalid value: \"300.0.0.0\": spec.endpoints[0].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[1].ipv4.address: Invalid value: \"0.0.0.0:443\": spec.endpoints[1].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[2].ipv4.address: Invalid value: \"0.0.0.0/12\": spec.endpoints[2].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + "spec.endpoints[3].ipv4.address: Invalid value: \"a.b.c.e\": spec.endpoints[3].ipv4.address in body should match '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + backend := baseBackend.DeepCopy() + backend.Name = fmt.Sprintf("backend-%v", time.Now().UnixNano()) + + if tc.mutate != nil { + tc.mutate(backend) + } + err := c.Create(ctx, backend) + + if tc.mutateStatus != nil { + tc.mutateStatus(backend) + err = c.Status().Update(ctx, backend) + } + + if (len(tc.wantErrors) != 0) != (err != nil) { + t.Fatalf("Unexpected response while creating Backend; got err=\n%v\n;want error=%v", err, tc.wantErrors) + } + + var missingErrorStrings []string + for _, wantError := range tc.wantErrors { + if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(wantError)) { + missingErrorStrings = append(missingErrorStrings, wantError) + } + } + if len(missingErrorStrings) != 0 { + t.Errorf("Unexpected response while creating Backend; got err=\n%v\n;missing strings within error=%q", err, missingErrorStrings) + } + }) + } +} From 6912dc0bae944873d88a943c186b6b57787146bb Mon Sep 17 00:00:00 2001 From: Dingkang Li Date: Thu, 16 May 2024 06:17:51 +0800 Subject: [PATCH 04/25] feat(api): add idleTimeout to ClientTrafficPolicy for TCP listener (#3345) * Add tcp idle timeout api Signed-off-by: Dingkang Li * State tcp client timeout usage Signed-off-by: Dingkang Li --------- Signed-off-by: Dingkang Li --- api/v1alpha1/timeout_types.go | 15 +++++++++++ api/v1alpha1/zz_generated.deepcopy.go | 25 +++++++++++++++++++ ...y.envoyproxy.io_clienttrafficpolicies.yaml | 11 ++++++++ site/content/en/latest/api/extension_types.md | 15 +++++++++++ 4 files changed, 66 insertions(+) diff --git a/api/v1alpha1/timeout_types.go b/api/v1alpha1/timeout_types.go index ccf507243059..36c0c320ed28 100644 --- a/api/v1alpha1/timeout_types.go +++ b/api/v1alpha1/timeout_types.go @@ -43,12 +43,27 @@ type HTTPTimeout struct { } type ClientTimeout struct { + // Timeout settings for TCP. + // + // +optional + TCP *TCPClientTimeout `json:"tcp,omitempty"` + // Timeout settings for HTTP. // // +optional HTTP *HTTPClientTimeout `json:"http,omitempty"` } +// TCPClientTimeout only provides timeout configuration on the listener whose protocol is TCP or TLS. +type TCPClientTimeout struct { + // IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no + // bytes sent or received on either the upstream or downstream connection. + // Default: 1 hour. + // + // +optional + IdleTimeout *gwapiv1.Duration `json:"idleTimeout,omitempty"` +} + type HTTPClientTimeout struct { // RequestReceivedTimeout is the duration envoy waits for the complete request reception. This timer starts upon request // initiation and stops when either the last byte of the request is sent upstream or when the response begins. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f3fd72c38d14..f29855aab7e5 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -679,6 +679,11 @@ func (in *ClientTLSSettings) DeepCopy() *ClientTLSSettings { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientTimeout) DeepCopyInto(out *ClientTimeout) { *out = *in + if in.TCP != nil { + in, out := &in.TCP, &out.TCP + *out = new(TCPClientTimeout) + (*in).DeepCopyInto(*out) + } if in.HTTP != nil { in, out := &in.HTTP, &out.HTTP *out = new(HTTPClientTimeout) @@ -4302,6 +4307,26 @@ func (in *TCPActiveHealthChecker) DeepCopy() *TCPActiveHealthChecker { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPClientTimeout) DeepCopyInto(out *TCPClientTimeout) { + *out = *in + if in.IdleTimeout != nil { + in, out := &in.IdleTimeout, &out.IdleTimeout + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPClientTimeout. +func (in *TCPClientTimeout) DeepCopy() *TCPClientTimeout { + if in == nil { + return nil + } + out := new(TCPClientTimeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPKeepalive) DeepCopyInto(out *TCPKeepalive) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index b45522e3e39c..a9d3fb95fcf1 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -348,6 +348,17 @@ spec: pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string type: object + tcp: + description: Timeout settings for TCP. + properties: + idleTimeout: + description: |- + IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no + bytes sent or received on either the upstream or downstream connection. + Default: 1 hour. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object type: object tls: description: TLS settings configure TLS termination settings with diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 716ad0bc78d5..6ac4fe6b123b 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -518,6 +518,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `tcp` | _[TCPClientTimeout](#tcpclienttimeout)_ | false | Timeout settings for TCP. | | `http` | _[HTTPClientTimeout](#httpclienttimeout)_ | false | Timeout settings for HTTP. | @@ -3263,6 +3264,20 @@ _Appears in:_ | `receive` | _[ActiveHealthCheckPayload](#activehealthcheckpayload)_ | false | Receive defines the expected response payload. | +#### TCPClientTimeout + + + +TCPClientTimeout only provides timeout configuration on the listener whose protocol is TCP or TLS. + +_Appears in:_ +- [ClientTimeout](#clienttimeout) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `idleTimeout` | _[Duration](#duration)_ | false | IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no
bytes sent or received on either the upstream or downstream connection.
Default: 1 hour. | + + #### TCPKeepalive From 452063b5bf44baac48878149dfa0469413a31444 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Wed, 15 May 2024 17:39:08 -0700 Subject: [PATCH 05/25] fix: build is failing (#3402) fix build Signed-off-by: huabing zhao --- api/v1alpha1/zz_generated.deepcopy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f29855aab7e5..fd607c16af7e 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -4312,7 +4312,7 @@ func (in *TCPClientTimeout) DeepCopyInto(out *TCPClientTimeout) { *out = *in if in.IdleTimeout != nil { in, out := &in.IdleTimeout, &out.IdleTimeout - *out = new(v1.Duration) + *out = new(apisv1.Duration) **out = **in } } From 76a60574c9b38d0bc3064ff3cd1662b28788b365 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 11:13:03 +0800 Subject: [PATCH 06/25] build(deps): bump aquasecurity/trivy-action from 0.19.0 to 0.20.0 (#3380) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.19.0 to 0.20.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/d710430a6722f083d3b36b8339ff66b32f22ee55...b2933f565dbc598b29947660e66259e3c7bc8561) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zirain --- .github/workflows/trivy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 1529aaf24d60..f9218b9287a2 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -25,7 +25,7 @@ jobs: IMAGE=envoy-proxy/gateway-dev TAG=${{ github.sha }} make image - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 + uses: aquasecurity/trivy-action@b2933f565dbc598b29947660e66259e3c7bc8561 # v0.20.0 with: image-ref: envoy-proxy/gateway-dev:${{ github.sha }} exit-code: '1' From c5ec046be14c4bb9049a7d3633900d2b8207d40f Mon Sep 17 00:00:00 2001 From: Wilson Wu Date: Thu, 16 May 2024 11:13:24 +0800 Subject: [PATCH 07/25] docs(zh): translate Developer Guide and related docs into Chinese (#3384) * Translate Developer Guide and related docs into Chinese Signed-off-by: Wilson Wu * Update site/content/zh/contributions/DEVELOP.md Co-authored-by: sh2 Signed-off-by: Wilson Wu * Translate missed security policy design Signed-off-by: Wilson Wu * Update site/content/zh/contributions/design/security-policy.md Co-authored-by: sh2 Signed-off-by: Wilson Wu --------- Signed-off-by: Wilson Wu Co-authored-by: sh2 --- site/content/zh/contributions/DEVELOP.md | 156 ++++++++++ .../contributions/design/security-policy.md | 114 ++++++++ site/content/zh/latest/tasks/quickstart.md | 2 +- .../tasks/security/jwt-authentication.md | 164 +++++++++++ .../zh/latest/tasks/traffic/grpc-routing.md | 271 ++++++++++++++++++ 5 files changed, 706 insertions(+), 1 deletion(-) create mode 100644 site/content/zh/contributions/DEVELOP.md create mode 100644 site/content/zh/contributions/design/security-policy.md create mode 100644 site/content/zh/latest/tasks/security/jwt-authentication.md create mode 100644 site/content/zh/latest/tasks/traffic/grpc-routing.md diff --git a/site/content/zh/contributions/DEVELOP.md b/site/content/zh/contributions/DEVELOP.md new file mode 100644 index 000000000000..b1b270dbe972 --- /dev/null +++ b/site/content/zh/contributions/DEVELOP.md @@ -0,0 +1,156 @@ +--- +title: "开发者指南" +description: "本节介绍如何开发 Envoy Gateway。" +weight: 2 +--- + +Envoy Gateway 使用基于 [make][] 的构建系统进行构建。我们的 CI 使用基于 [Github Actions][] 的[工作流][]建设。 + +## 先决条件 {#prerequisites} + +### go {#go} + +* 版本:1.20 +* 安装指南:https://go.dev/doc/install + +### make {#make} + +* 推荐版本:4.0 或更高 +* 安装指南:https://www.gnu.org/software/make + +### docker {#docker} + +* 当您想要构建 Docker 镜像或在 Docker 内运行 `make` 时可选。 +* 推荐版本:20.10.16 +* 安装指南:https://docs.docker.com/engine/install + +### python3 {#python3} + +* 需要一个 `python3` 程序 +* 必须有一个正常运行的 `venv` 模块;这是标准库的一部分,但某些发行版使用 stub 将其替换(例如 Debian 和 Ubuntu), + 并要求您单独安装 `python3-venv` 包。 + +## 快速开始 {#quickstart} + +* 运行 `make help` 以查看构建、测试和运行 Envoy Gateway 的所有可用目标。 + +### 构建 {#building} + +* 运行 `make build` 来构建所有二进制文件。 +* 运行 `make build BINS="envoy-gateway"` 来构建 Envoy Gateway 二进制文件。 +* 运行 `make build BINS="egctl"` 来构建 egctl 二进制文件。 + +**注意:**二进制文件在 `bin/$OS/$ARCH` 目录中生成,例如,`bin/linux/amd64/`。 + +### 测试 {#testing} + +* 运行 `make test` 来运行 golang 测试。 + +* 运行 `make testdata` 生成标准的 YAML 测试数据文件。 + +### 运行 Linter {#running-linters} + +* 运行 `make lint` 以确保您的代码通过所有 Linter 检查。 + +**注意:**`golangci-lint` 配置位于[此处](https://github.com/envoyproxy/gateway/blob/main/tools/linter/golangci-lint/.golangci.yml)。 + +### 构建并推送镜像 {#building-and-pushing-the-image} + +* 运行 `IMAGE=docker.io/you/gateway-dev make image` 来构建 Docker 镜像。 +* 运行 `IMAGE=docker.io/you/gateway-dev make push-multiarch` 来构建并推送多架构 Docker 镜像。 + +**注意:**将 `IMAGE` 替换为您的仓库的镜像名称。 + +### 部署 Envoy Gateway 进行测试/开发 {#deploying-envoy-gateway-for-testdev} + +* 运行 `make create-cluster` 创建一个 [Kind][] 集群。 + +#### 选项 1:使用最新的 [gateway-dev][] 镜像 {#option-1-use-the-latest-gateway-dev-image} + +* 运行 `TAG=latest make kube-deploy` 以使用最新镜像在 Kind 集群中部署 Envoy Gateway。 + 替换 `latest` 以使用不同的镜像标签。 + +#### 选项 2:使用自定义镜像 {#option-2-use-a-custom-image} + +* 运行 `make kube-install-image` 从当前分支的最新构建镜像并将其加载到 Kind 集群中。 +* 运行 `IMAGE_PULL_POLICY=IfNotPresent make kube-deploy` 以使用自定义镜像将 Envoy Gateway 安装到 Kind 集群中。 + +### 在 Kubernetes 中部署 Envoy Gateway {#deploying-envoy-gateway-in-kubernetes} + +* 运行 `TAG=latest make kube-deploy` 以使用最新镜像将 Envoy Gateway 部署到 Kubernetes 集群(链接到当前 kube 上下文)。 + 在命令前面加上 `IMAGE` 或替换 `TAG` 以使用不同的 Envoy Gateway 镜像或标签。 +* 运行 `make kube-undeploy` 从集群中卸载 Envoy Gateway。 + +**注意:**Envoy Gateway 针对 Kubernetes v1.24.0 进行了测试。 + +### 演示设置 {#demo-setup} + +* 运行 `make kube-demo` 来部署演示后端服务、GatewayClass、Gateway 和 HTTPRoute 资源 + (类似于[快速入门][]文档中概述的步骤)并测试配置。 +* 运行 `make kube-demo-undeploy` 删除 `make kube-demo` 命令创建的资源。 + +### 运行 Gateway API 一致性测试 {#run-gateway-api-conformance-tests} + +通过以下命令将 Envoy Gateway 部署到 Kubernetes 集群并运行 Gateway API 一致性测试。 +请参阅 Gateway API [一致性主页][]以了解有关测试的更多信息。如果 Envoy Gateway 已安装, +请运行 `TAG=latest make run-conformance` 来运行一致性测试。 + +#### 在 Linux 主机上 {#on-a-linux-host} + +* 运行 `TAG=latest make conformance` 来创建 Kind 集群, + 使用最新的 [gateway-dev][] 镜像安装 Envoy Gateway,并运行 Gateway API 一致性测试。 + +#### 在 Mac 主机上 {#on-a-mac-host} + +由于 Mac 不支持将 Docker 网络[直接暴露][]到 Mac 主机,因此请使用以下解决方法之一来运行一致性测试: + +* 部署您自己的 Kubernetes 集群或使用具有 [Kubernetes 支持][] 的 Docker Desktop, + 然后运行 `TAG=latest make kube-deploy run-conformance`。这将使用最新的 [gateway-dev][] 镜像将 Envoy Gateway + 安装到使用当前 kubectl 上下文的 Kubernetes 集群,并运行一致性测试。使用 `make kube-undeploy` 卸载 Envoy Gateway。 +* 安装并运行 [Docker Mac Net Connect][mac_connect],然后运行 `TAG=latest make conformance`。 + +**注意:**在命令前加上 `IMAGE` 或替换 `TAG` 以使用不同的 Envoy Gateway 镜像或标签。如果未指定 `TAG`,则使用当前分支的短 SHA。 + +### 调试 Envoy 配置 {#debugging-the-envoy-config} + +查看 Envoy Gateway 正在使用的 Envoy 配置的一种简单方法是将端口转发到与 Gateway +对应的 Envoy 部署上的管理界面端口(当前为 `19000`),以便可以在本地访问它。 + +获取 Envoy 部署的名称。以下示例适用于 `default` 命名空间中的网关 `eg`: + +```shell +export ENVOY_DEPLOYMENT=$(kubectl get deploy -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +``` + +通过端口转发管理接口端口: + +```shell +kubectl port-forward deploy/${ENVOY_DEPLOYMENT} -n envoy-gateway-system 19000:19000 +``` + +现在,您可以通过导航到 `127.0.0.1:19000/config_dump` 来查看正在运行的 Envoy 配置。 + +[Envoy 管理接口][]上还有许多其他端点在调试时可能会有所帮助。 + +### JWT 测试 {#jwt-testing} + +[JSON Web Token(JWT)][jwt]和 [JSON Web Key Set(JWKS)][jwks]示例用于[请求身份验证][]任务。 +JWT 由 [JWT Debugger][] 使用 `RS256` 算法创建。JWT 验证签名中的公钥已复制到 [JWK Creator][] 以生成 JWK。 +JWK Creator 配置了匹配的设置,即 `Signing` 公钥使用和 `RS256` 算法。生成的 JWK 包装在 JWKS 结构中并托管在仓库中。 + +[快速入门]: https://github.com/envoyproxy/gateway/blob/main/docs/latest/user/quickstart.md +[make]: https://www.gnu.org/software/make/ +[Github Actions]: https://docs.github.com/en/actions +[工作流]: https://github.com/envoyproxy/gateway/tree/main/.github/workflows +[Kind]: https://kind.sigs.k8s.io/ +[一致性主页]: https://gateway-api.sigs.k8s.io/concepts/conformance/ +[直接暴露]: https://kind.sigs.k8s.io/docs/user/loadbalancer/ +[Kubernetes 支持]: https://docs.docker.com/desktop/kubernetes/ +[gateway-dev]: https://hub.docker.com/r/envoyproxy/gateway-dev/tags +[mac_connect]: https://github.com/chipmk/docker-mac-net-connect +[Envoy 管理接口]: https://www.envoyproxy.io/docs/envoy/latest/operations/admin#operations-admin-interface +[jwt]: https://tools.ietf.org/html/rfc7519 +[jwks]: https://tools.ietf.org/html/rfc7517 +[请求身份验证]: ../latest/tasks/security/jwt-authentication +[JWT Debugger]: https://jwt.io/ +[JWK Creator]: https://russelldavies.github.io/jwk-creator/ diff --git a/site/content/zh/contributions/design/security-policy.md b/site/content/zh/contributions/design/security-policy.md new file mode 100644 index 000000000000..50bacc040a52 --- /dev/null +++ b/site/content/zh/contributions/design/security-policy.md @@ -0,0 +1,114 @@ +--- +title: "SecurityPolicy" +--- + +## 概述 {#overview} + +本设计文档引入了 `SecurityPolicy` API,允许系统管理员为进入网关的流量配置身份验证和鉴权策略。 + +## 目标 {#goals} + +* 添加 API 定义以保存用于配置进入网关的流量的身份验证和鉴权规则的设置。 + +## 非目标 {#non-goals} + +* 定义该 API 中的 API 配置字段。 + +## 实现 {#implementation} + +`SecurityPolicy` 是一个[策略附件][]类型的 API,可用于扩展 [Gateway API][] 来定义身份验证和鉴权规则。 + +### 示例 {#example} + +以下示例重点介绍了用户如何配置此 API。 + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: eg +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: eg + namespace: default +spec: + gatewayClassName: eg + listeners: + - name: https + protocol: HTTPS + port: 443 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backend + namespace: default +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: backend + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: jwt-authn-policy + namespace: default +spec: + jwt: + providers: + - name: example + remoteJWKS: + uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: eg + namespace: default +``` + +## 功能及 API 字段 {#features-api-fields} + +以下是此 API 中包含的功能列表: +* JWT 基础鉴权 +* OIDC 鉴权 +* 外部认证 +* Basic Auth +* API Key Auth +* CORS(跨域) + +## 设计决策 {#design-decisions} + +* 此 API 仅支持单个 `targetRef`,并且可以绑定到 `Gateway` 资源或 `HTTPRoute` 或 `GRPCRoute`。 +* 此 API 资源**必须**与 targetRef 资源属于同一命名空间 +* 只能有**一个**策略资源附加到特定的 targetRef,例如 `Gateway` 内的 `Listener`(部分) +* 如果策略针对某个资源但无法附加到该资源,则应使用 `Conflicted=True` 条件将该信息反映在“策略状态”字段中。 +* 如果多个策略针对同一资源,则最旧的资源(基于创建时间戳)将附加到网关侦听器,其他资源则不会。 +* 如果策略 A 具有包含 `sectionName` 的 `targetRef`,即它以 `Gateway` 内的特定侦听器为目标, + 并且策略 B 具有以同一整个 Gateway 为目标的 `targetRef`,则 + * 策略 A 将应用/附加到 `targetRef.SectionName` 中定义的特定监听器 + * 策略 B 将应用于 Gateway 内的其余侦听器。策略 B 将具有附加状态条件 `Overridden=True`。 +* 针对拥有具体范围的策略胜过针对缺少具体范围的策略。即,针对 xRoute(`HTTPRoute` 或 `GRPCRoute`)的策略会覆盖针对侦听器的策略, + 该侦听器是该路由的 parentRef,而侦听器又会覆盖针对侦听器/部分所属 Gateway 的策略。 + +## 替代方案 {#alternatives} + +* 项目可以无限期地等待这些配置参数成为 [Gateway API][] 的一部分。 + +[策略附件]: https://gateway-api.sigs.k8s.io/references/policy-attachment +[Gateway API]: https://gateway-api.sigs.k8s.io/ diff --git a/site/content/zh/latest/tasks/quickstart.md b/site/content/zh/latest/tasks/quickstart.md index aa94962e71ae..8e32fdf5aa3d 100644 --- a/site/content/zh/latest/tasks/quickstart.md +++ b/site/content/zh/latest/tasks/quickstart.md @@ -1,5 +1,5 @@ --- -title: "快速开始" +title: "快速入门" weight: 1 description: 只需几个简单的步骤即可开始使用 Envoy Gateway。 --- diff --git a/site/content/zh/latest/tasks/security/jwt-authentication.md b/site/content/zh/latest/tasks/security/jwt-authentication.md new file mode 100644 index 000000000000..a06399bc33f1 --- /dev/null +++ b/site/content/zh/latest/tasks/security/jwt-authentication.md @@ -0,0 +1,164 @@ +--- +title: "JWT 身份验证" +--- + +此任务提供有关配置 [JSON Web Token(JWT)][jwt]身份验证的说明。 +JWT 身份验证在将请求路由到后端服务之前检查传入请求是否具有有效的 JWT。 +目前,Envoy Gateway 仅支持通过 HTTP 标头验证 JWT,例如 `Authorization: Bearer `。 + +Envoy Gateway 引入了一个名为 [SecurityPolicy][SecurityPolicy] 的新 CRD,允许用户配置 JWT 身份验证。 +该实例化资源可以链接到 [Gateway][Gateway]、[HTTPRoute][HTTPRoute] 或 [GRPCRoute][GRPCRoute] 资源。 + +## 先决条件 {#prerequisites} + +按照[快速入门](../quickstart)中的步骤安装 Envoy Gateway 和示例清单。 +对于 GRPC - 请按照 [GRPC 路由](../traffic/grpc-routing)示例中的步骤操作。 +在继续之前,您应该能够使用 HTTP 或 GRPC 查询示例程序后端。 + +## 配置 {#configuration} + +通过创建 [SecurityPolicy][SecurityPolicy] 并将其附加到示例 HTTPRoute 或 GRPCRoute,允许使用具有有效 JWT 的请求。 + +### HTTPRoute {#httproute} + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/jwt.yaml +``` + +已创建两个 HTTPRoute,一个用于 `/foo`,另一个用于 `/bar`。 +已创建 SecurityPolicy 并以 HTTPRoute foo 为目标来验证对 `/foo` 的请求。 +HTTPRoute bar 不是 SecurityPolicy 的目标,并且将允许未经身份验证的请求发送到 `/bar`。 + +验证 HTTPRoute 配置和状态: + +```shell +kubectl get httproute/foo -o yaml +kubectl get httproute/bar -o yaml +``` + +SecurityPolicy 配置为 JWT 身份验证,并使用单个 [JSON Web Key Set(JWKS)][jwks]提供程序来对 JWT 进行身份验证。 + +验证 SecurityPolicy 配置: + +```shell +kubectl get securitypolicy/jwt-example -o yaml +``` + +### GRPCRoute {#grpcroute} + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/grpc-jwt.yaml +``` + +已创建 SecurityPolicy 并针对 GRPCRoute yages 来验证 `yages` 服务的所有请求。 + +验证 GRPCRoute 配置和状态: + +```shell +kubectl get grpcroute/yages -o yaml +``` + +SecurityPolicy 配置为 JWT 身份验证,并使用单个 [JSON Web Key Set(JWKS)][jwks]提供程序来对 JWT 进行身份验证。 + +验证 SecurityPolicy 配置: + +```shell +kubectl get securitypolicy/jwt-example -o yaml +``` + +## 测试 {#testing} + +确保设置了[快速入门](../../quickstart) 中的 `GATEWAY_HOST` 环境变量。如果没有,请按照快速入门说明设置变量。 + +```shell +echo $GATEWAY_HOST +``` + +### HTTPRoute {#httproute-1} + +验证在没有 JWT 的情况下对 `/foo` 的请求是否被拒绝: + +```shell +curl -sS -o /dev/null -H "Host: www.example.com" -w "%{http_code}\n" http://$GATEWAY_HOST/foo +``` + +应返回一个 `401` HTTP 响应码。 + +获取用于测试请求身份验证的 JWT: + +```shell +TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - +``` + +**注意:**上述命令解码并返回令牌的有效内容。您可以将 `f2` 替换为 `f1` 来查看令牌的标头。 + +验证是否允许使用有效 JWT 向 `/foo` 发出请求: + +```shell +curl -sS -o /dev/null -H "Host: www.example.com" -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n" http://$GATEWAY_HOST/foo +``` + +应返回一个 `200` HTTP 响应码。 + +验证是否允许在**没有** JWT 的情况下向 `/bar` 发出请求: + +```shell +curl -sS -o /dev/null -H "Host: www.example.com" -w "%{http_code}\n" http://$GATEWAY_HOST/bar +``` + +### GRPCRoute {#grpcroute-1} + +验证是否在没有 JWT 的情况下拒绝对 `yages` 服务的请求: + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +您应该看到以下响应: + +```shell +Error invoking method "yages.Echo/Ping": rpc error: code = Unauthenticated desc = failed to query for service descriptor "yages.Echo": Jwt is missing +``` + +获取用于测试请求身份验证的 JWT: + +```shell +TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - +``` + +**注意:**上述命令解码并返回令牌的有效内容。您可以将 `f2` 替换为 `f1` 来查看令牌的标头。 + +验证是否允许使用有效 JWT 向 `yages` 服务发出请求: + +```shell +grpcurl -plaintext -H "authorization: Bearer $TOKEN" -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +您应该看到以下响应: + +```shell +{ + "text": "pong" +} +``` + +## 清理 {#clean-up} + +按照[快速入门](../../quickstart) 中的步骤卸载 Envoy Gateway 和示例清单。 + +删除 SecurityPolicy: + +```shell +kubectl delete securitypolicy/jwt-example +``` + +## 后续步骤 {#next-steps} + +查看[开发者指南](../../../contributions/develop)参与该项目。 + +[SecurityPolicy]: ../../../contributions/design/security-policy +[jwt]: https://tools.ietf.org/html/rfc7519 +[jwks]: https://tools.ietf.org/html/rfc7517 +[Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway +[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute +[GRPCRoute]: https://gateway-api.sigs.k8s.io/api-types/grpcroute diff --git a/site/content/zh/latest/tasks/traffic/grpc-routing.md b/site/content/zh/latest/tasks/traffic/grpc-routing.md new file mode 100644 index 000000000000..6acffe4e32a5 --- /dev/null +++ b/site/content/zh/latest/tasks/traffic/grpc-routing.md @@ -0,0 +1,271 @@ +--- +title: "GRPC 路由" +--- + +[GRPCRoute][] 资源允许用户通过匹配 HTTP/2 流量并将其转发到后端 gRPC 服务器来配置 gRPC 路由。 +要了解有关 gRPC 路由的更多信息,请参阅[Gateway API 文档][]。 + +## 先决条件 {#prerequisites} + +按照[快速入门](../quickstart)中的步骤安装 Envoy Gateway 和示例清单。 +在继续之前,您应该能够使用 HTTP 查询示例程序后端。 + +## 安装 {#installation} + +安装 gRPC 路由示例资源: + +```shell +kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/grpc-routing.yaml +``` + +该清单安装 [GatewayClass][]、[Gateway][]、Deployment、Service 和 GRPCRoute 资源。 +GatewayClass 是集群范围的资源,表示可以被实例化的一类 Gateway。 + +**注意:**Envoy Gateway 默认被配置为使用 `controllerName: gateway.envoyproxy.io/gatewayclass-controller` 管理 GatewayClass。 + +## 验证 {#verification} + +检查 GatewayClass 的状态: + +```shell +kubectl get gc --selector=example=grpc-routing +``` + +状态应反映为 `Accepted=True`,表示 Envoy Gateway 正在管理 GatewayClass。 + +Gateway 代表基础设施的配置。创建 Gateway 时,[Envoy 代理][]基础设施由 Envoy Gateway 预配或配置。 +`gatewayClassName` 定义此 Gateway 使用的 GatewayClass 的名称。检查 Gateway 状态: + +```shell +kubectl get gateways --selector=example=grpc-routing +``` + +状态应反映为 `Ready=True`,表示 Envoy 代理基础设施已被配置。 +该状态还提供 Gateway 的地址。该地址稍后用于测试与代理后端服务的连接。 + +检查 GRPCRoute 的状态: + +```shell +kubectl get grpcroutes --selector=example=grpc-routing -o yaml +``` + +GRPCRoute 的状态应显示 `Accepted=True` 和引用示例 Gateway 的 `parentRef`。 +`example-route` 匹配 `grpc-example.com` 的任何流量并将其转发到 `yages` 服务。 + +## 测试配置 {#testing-the-configuration} + +在测试到 `yages` 后端的 GRPC 路由之前,请获取 Gateway 的地址。 + +```shell +export GATEWAY_HOST=$(kubectl get gateway/example-gateway -o jsonpath='{.status.addresses[0].value}') +``` + +使用 [grpcurl][] 命令测试到 `yages` 后端的 GRPC 路由。 + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +您应该看到以下响应: + +```shell +{ + "text": "pong" +} +``` + +Envoy Gateway 还支持此配置的 [gRPC-Web][] 请求。下面的 `curl` 命令可用于通过 HTTP/2 发送 grpc-Web 请求。 +您应该收到与上一个命令相同的响应。 + +正文 `AAAAAAA=` 中的数据是 Ping RPC 接受的空消息(数据长度为 0)的 Base64 编码表示。 + +```shell +curl --http2-prior-knowledge -s ${GATEWAY_HOST}:80/yages.Echo/Ping -H 'Host: grpc-example.com' -H 'Content-Type: application/grpc-web-text' -H 'Accept: application/grpc-web-text' -XPOST -d'AAAAAAA=' | base64 -d +``` + +## GRPCRoute 匹配 {#grpcroute-match} + +`matches` 字段可用于根据 GRPC 的服务和/或方法名称将路由限制到一组特定的请求。 +它支持两种匹配类型:`Exact`(精准)和 `RegularExpression`(正则)。 + +### 精准 {#exact} + +`Exact`(精准)匹配是默认匹配类型。 + +以下示例显示如何根据 `grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo` 的服务和方法名称来匹配请求, +以及如何在我们的部署中匹配方法名称为 `Ping` 且与 `yages.Echo/Ping` 匹配的所有服务。 + +{{< tabpane text=true >}} +{{% tab header="通过标准输入应用" %}} + +```shell +cat <}} + +验证 GRPCRoute 状态: + +```shell +kubectl get grpcroutes --selector=example=grpc-routing -o yaml +``` + +使用 [grpcurl][] 命令测试到 `yages` 后端的 GRPC 路由。 + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +### 正则 {#regularexpression} + +以下示例演示如何根据服务和方法名称将请求与匹配类型 `RegularExpression` 进行匹配。 +它与模式 `/.*.Echo/Pin.+` 匹配所有服务和方法,该模式与我们部署中的 `yages.Echo/Ping` 匹配。 + +{{< tabpane text=true >}} +{{% tab header="通过标准输入应用" %}} + +```shell +cat <}} + +检查 GRPCRoute 状态: + +```shell +kubectl get grpcroutes --selector=example=grpc-routing -o yaml +``` + +使用 [grpcurl][] 命令测试到 `yages` 后端的 GRPC 路由。 + +```shell +grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping +``` + +[GRPCRoute]: https://gateway-api.sigs.k8s.io/api-types/grpcroute/ +[Gateway API 文档]: https://gateway-api.sigs.k8s.io/ +[GatewayClass]: https://gateway-api.sigs.k8s.io/api-types/gatewayclass/ +[Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway/ +[Envoy 代理]: https://www.envoyproxy.io/ +[grpcurl]: https://github.com/fullstorydev/grpcurl +[gRPC-Web]: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md#protocol-differences-vs-grpc-over-http2 From 32c6876f0bc825a9a1b46c499d4d898b2f65a0c4 Mon Sep 17 00:00:00 2001 From: Dingkang Li Date: Fri, 17 May 2024 07:11:44 +0800 Subject: [PATCH 08/25] fix: duplicated xroutes are added to gatewayapi.Resources (#3282) fix duplicated xroutes Signed-off-by: Dingkang Li --- internal/provider/kubernetes/controller.go | 15 ++++++++++ internal/provider/kubernetes/routes.go | 35 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index e7329d49a663..1852384de4da 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -116,6 +116,16 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su Updater type resourceMappings struct { // Map for storing namespaces for Route, Service and Gateway objects. allAssociatedNamespaces map[string]struct{} + // Map for storing TLSRoutes' NamespacedNames attaching to various Gateway objects. + allAssociatedTLSRoutes map[string]struct{} + // Map for storing HTTPRoutes' NamespacedNames attaching to various Gateway objects. + allAssociatedHTTPRoutes map[string]struct{} + // Map for storing GRPCRoutes' NamespacedNames attaching to various Gateway objects. + allAssociatedGRPCRoutes map[string]struct{} + // Map for storing TCPRoutes' NamespacedNames attaching to various Gateway objects. + allAssociatedTCPRoutes map[string]struct{} + // Map for storing UDPRoutes' NamespacedNames attaching to various Gateway objects. + allAssociatedUDPRoutes map[string]struct{} // Map for storing backendRefs' NamespaceNames referred by various Route objects. allAssociatedBackendRefs map[gwapiv1.BackendObjectReference]struct{} // extensionRefFilters is a map of filters managed by an extension. @@ -127,6 +137,11 @@ type resourceMappings struct { func newResourceMapping() *resourceMappings { return &resourceMappings{ allAssociatedNamespaces: map[string]struct{}{}, + allAssociatedTLSRoutes: map[string]struct{}{}, + allAssociatedHTTPRoutes: map[string]struct{}{}, + allAssociatedGRPCRoutes: map[string]struct{}{}, + allAssociatedTCPRoutes: map[string]struct{}{}, + allAssociatedUDPRoutes: map[string]struct{}{}, allAssociatedBackendRefs: map[gwapiv1.BackendObjectReference]struct{}{}, extensionRefFilters: map[types.NamespacedName]unstructured.Unstructured{}, } diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index 1608f5147a31..f72d1b2cfa2c 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -43,6 +43,12 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName continue } } + + if _, ok := resourceMap.allAssociatedTLSRoutes[utils.NamespacedName(&tlsRoute).String()]; ok { + r.log.Info("current TLSRoute has been processed already", "namespace", tlsRoute.Namespace, "name", tlsRoute.Name) + continue + } + r.log.Info("processing TLSRoute", "namespace", tlsRoute.Namespace, "name", tlsRoute.Name) for _, rule := range tlsRoute.Spec.Rules { @@ -82,6 +88,7 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName } resourceMap.allAssociatedNamespaces[tlsRoute.Namespace] = struct{}{} + resourceMap.allAssociatedTLSRoutes[utils.NamespacedName(&tlsRoute).String()] = struct{}{} // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer tlsRoute.Status = gwapiv1a2.TLSRouteStatus{} @@ -115,6 +122,12 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam continue } } + + if _, ok := resourceMap.allAssociatedGRPCRoutes[utils.NamespacedName(&grpcRoute).String()]; ok { + r.log.Info("current GRPCRoute has been processed already", "namespace", grpcRoute.Namespace, "name", grpcRoute.Name) + continue + } + r.log.Info("processing GRPCRoute", "namespace", grpcRoute.Namespace, "name", grpcRoute.Name) for _, rule := range grpcRoute.Spec.Rules { @@ -193,6 +206,7 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam } resourceMap.allAssociatedNamespaces[grpcRoute.Namespace] = struct{}{} + resourceMap.allAssociatedGRPCRoutes[utils.NamespacedName(&grpcRoute).String()] = struct{}{} // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer grpcRoute.Status = gwapiv1.GRPCRouteStatus{} @@ -235,6 +249,12 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam continue } } + + if _, ok := resourceMap.allAssociatedHTTPRoutes[utils.NamespacedName(&httpRoute).String()]; ok { + r.log.Info("current HTTPRoute has been processed already", "namespace", httpRoute.Namespace, "name", httpRoute.Name) + continue + } + r.log.Info("processing HTTPRoute", "namespace", httpRoute.Namespace, "name", httpRoute.Name) for _, rule := range httpRoute.Spec.Rules { @@ -367,6 +387,7 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam } resourceMap.allAssociatedNamespaces[httpRoute.Namespace] = struct{}{} + resourceMap.allAssociatedHTTPRoutes[utils.NamespacedName(&httpRoute).String()] = struct{}{} // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer httpRoute.Status = gwapiv1.HTTPRouteStatus{} @@ -399,6 +420,12 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName continue } } + + if _, ok := resourceMap.allAssociatedTCPRoutes[utils.NamespacedName(&tcpRoute).String()]; ok { + r.log.Info("current TCPRoute has been processed already", "namespace", tcpRoute.Namespace, "name", tcpRoute.Name) + continue + } + r.log.Info("processing TCPRoute", "namespace", tcpRoute.Namespace, "name", tcpRoute.Name) for _, rule := range tcpRoute.Spec.Rules { @@ -438,6 +465,7 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName } resourceMap.allAssociatedNamespaces[tcpRoute.Namespace] = struct{}{} + resourceMap.allAssociatedTCPRoutes[utils.NamespacedName(&tcpRoute).String()] = struct{}{} // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer tcpRoute.Status = gwapiv1a2.TCPRouteStatus{} @@ -470,6 +498,12 @@ func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayName continue } } + + if _, ok := resourceMap.allAssociatedUDPRoutes[utils.NamespacedName(&udpRoute).String()]; ok { + r.log.Info("current UDPRoute has been processed already", "namespace", udpRoute.Namespace, "name", udpRoute.Name) + continue + } + r.log.Info("processing UDPRoute", "namespace", udpRoute.Namespace, "name", udpRoute.Name) for _, rule := range udpRoute.Spec.Rules { @@ -509,6 +543,7 @@ func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayName } resourceMap.allAssociatedNamespaces[udpRoute.Namespace] = struct{}{} + resourceMap.allAssociatedUDPRoutes[utils.NamespacedName(&udpRoute).String()] = struct{}{} // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer udpRoute.Status = gwapiv1a2.UDPRouteStatus{} From e5f86303d83d732f8c3890a6868c62e29a3e3029 Mon Sep 17 00:00:00 2001 From: shahar-h Date: Fri, 17 May 2024 02:14:35 +0300 Subject: [PATCH 09/25] ci: add license scan workflow (#3407) * ci: add license scan workflow Signed-off-by: Shahar Harari * fix lint issues Signed-off-by: Shahar Harari --------- Signed-off-by: Shahar Harari --- .github/workflows/license-scan.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/license-scan.yml diff --git a/.github/workflows/license-scan.yml b/.github/workflows/license-scan.yml new file mode 100644 index 000000000000..cf1743f02292 --- /dev/null +++ b/.github/workflows/license-scan.yml @@ -0,0 +1,27 @@ +name: License Scan + +on: + pull_request: + branches: + - "main" + push: + branches: + - "main" + +permissions: + contents: read + +jobs: + scan: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - name: Run scanner + uses: google/osv-scanner-action/osv-scanner-action@75532bf0bf75464b047d80414dbce04449498365 # v1.7.3 + with: + scan-args: |- + --skip-git + --experimental-licenses=Apache-2.0,BSD-2-Clause,BSD-2-Clause-FreeBSD,BSD-3-Clause,MIT,ISC,Python-2.0,PostgreSQL,X11,Zlib + ./ + continue-on-error: true # TODO remove once all issues are resolved From e76deb8e7b91afea507b9bd54bd0e5695729d2b3 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Thu, 16 May 2024 16:44:28 -0700 Subject: [PATCH 10/25] feat: add global image settings for all images in the EG chart (#3389) * add global image settings for all images in the EG chart Signed-off-by: huabing zhao * use envoy gateway image for shutdown manager Signed-off-by: huabing zhao * minor wording Signed-off-by: huabing zhao * add a global hub value Signed-off-by: huabing zhao * change pullPolicy form global setting to image specific setting Signed-off-by: huabing zhao * fix gen Signed-off-by: huabing zhao * add test for helm file Signed-off-by: huabing zhao * add test for helm file Signed-off-by: huabing zhao * add test for helm file Signed-off-by: huabing zhao * add test for helm file Signed-off-by: huabing zhao * add image secrets Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * fix namespace Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * fix lint Signed-off-by: huabing zhao * fix lint Signed-off-by: huabing zhao * fix lint Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * add helm test Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao * minor change Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao --- charts/gateway-helm/templates/_helpers.tpl | 53 ++ charts/gateway-helm/templates/certgen.yaml | 9 +- .../templates/envoy-gateway-config.yaml | 5 +- .../templates/envoy-gateway-deployment.yaml | 9 +- charts/gateway-helm/values.tmpl.yaml | 32 +- site/content/en/latest/install/api.md | 11 +- test/helm/default-config.in.yaml | 5 + .../{default.yaml => default-config.out.yaml} | 9 +- test/helm/deployment-images-config.in.yaml | 11 + test/helm/deployment-images-config.out.yaml | 540 ++++++++++++++++++ test/helm/envoy-gateway-config.in.yaml | 20 + test/helm/envoy-gateway-config.out.yaml | 538 +++++++++++++++++ test/helm/global-images-config.in.yaml | 10 + test/helm/global-images-config.out.yaml | 540 ++++++++++++++++++ tools/make/helm.mk | 12 +- 15 files changed, 1776 insertions(+), 28 deletions(-) create mode 100644 test/helm/default-config.in.yaml rename test/helm/{default.yaml => default-config.out.yaml} (98%) create mode 100644 test/helm/deployment-images-config.in.yaml create mode 100644 test/helm/deployment-images-config.out.yaml create mode 100644 test/helm/envoy-gateway-config.in.yaml create mode 100644 test/helm/envoy-gateway-config.out.yaml create mode 100644 test/helm/global-images-config.in.yaml create mode 100644 test/helm/global-images-config.out.yaml diff --git a/charts/gateway-helm/templates/_helpers.tpl b/charts/gateway-helm/templates/_helpers.tpl index 24e5cbd8fde7..0802657f85b3 100755 --- a/charts/gateway-helm/templates/_helpers.tpl +++ b/charts/gateway-helm/templates/_helpers.tpl @@ -60,3 +60,56 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +The name of the Envoy Gateway image. +*/}} +{{- define "eg.image" -}} +{{- if .Values.deployment.envoyGateway.image.repository }} +{{- .Values.deployment.envoyGateway.image.repository }}:{{ .Values.deployment.envoyGateway.image.tag | default .Values.global.images.envoyGateway.tag | default .Chart.AppVersion }} +{{- else if .Values.global.images.envoyGateway.image }} +{{- .Values.global.images.envoyGateway.image }} +{{- else }} +docker.io/envoyproxy/gateway:{{ .Chart.Version }} +{{- end }} +{{- end }} + +{{/* +Pull policy for the Envoy Gateway image. +*/}} +{{- define "eg.image.pullPolicy" -}} +{{ .Values.deployment.envoyGateway.imagePullPolicy | default .Values.global.images.envoyGateway.pullPolicy | default "IfNotPresent" }} +{{- end }} + +{{/* +Pull secrets for the Envoy Gateway image. +*/}} +{{- define "eg.image.pullSecrets" -}} +{{- if .Values.deployment.envoyGateway.imagePullSecrets -}} +imagePullSecrets: +{{ toYaml .Values.deployment.envoyGateway.imagePullSecrets }} +{{- else if .Values.global.images.envoyGateway.imagePullSecrets -}} +imagePullSecrets: +{{ toYaml .Values.global.images.envoyGateway.imagePullSecrets }} +{{- else -}} +imagePullSecrets: [] +{{- end }} +{{- end }} + +{{/* +The default Envoy Gateway configuration. +*/}} +{{- define "eg.default-envoy-gateway-config" -}} +provider: + type: Kubernetes + kubernetes: + rateLimitDeployment: + container: + {{- if .Values.global.images.ratelimit.image }} + image: {{ .Values.global.images.ratelimit.image }} + {{- else }} + image: "docker.io/envoyproxy/ratelimit:master" + {{- end }} + shutdownManager: + image: {{ include "eg.image" . }} +{{- end }} diff --git a/charts/gateway-helm/templates/certgen.yaml b/charts/gateway-helm/templates/certgen.yaml index 78d5ec2a28d1..f122f0a8e495 100644 --- a/charts/gateway-helm/templates/certgen.yaml +++ b/charts/gateway-helm/templates/certgen.yaml @@ -31,17 +31,14 @@ spec: fieldPath: metadata.namespace - name: KUBERNETES_CLUSTER_DOMAIN value: {{ .Values.kubernetesClusterDomain }} - image: {{ .Values.deployment.envoyGateway.image.repository }}:{{ .Values.deployment.envoyGateway.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.deployment.envoyGateway.imagePullPolicy }} + image: {{ include "eg.image" . }} + imagePullPolicy: {{ include "eg.image.pullPolicy" . }} name: envoy-gateway-certgen {{- with .Values.certgen.job.resources }} resources: {{- toYaml . | nindent 10 }} {{- end }} - {{- with .Values.deployment.envoyGateway.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} + {{- include "eg.image.pullSecrets" . | nindent 6 }} restartPolicy: Never securityContext: runAsGroup: 65534 diff --git a/charts/gateway-helm/templates/envoy-gateway-config.yaml b/charts/gateway-helm/templates/envoy-gateway-config.yaml index b57b6729c2e8..8fc1d2dfb63e 100644 --- a/charts/gateway-helm/templates/envoy-gateway-config.yaml +++ b/charts/gateway-helm/templates/envoy-gateway-config.yaml @@ -9,4 +9,7 @@ data: envoy-gateway.yaml: | apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyGateway - {{- toYaml .Values.config.envoyGateway | nindent 4 }} + {{- $baseEnvoyGatewayConfig := include "eg.default-envoy-gateway-config" . | fromYaml }} + {{- $userEnvoyGatewayConfig := .Values.config.envoyGateway }} + {{- $mergedEnvoyGatewayConfig := merge $userEnvoyGatewayConfig $baseEnvoyGatewayConfig }} + {{- toYaml $mergedEnvoyGatewayConfig | nindent 4 }} diff --git a/charts/gateway-helm/templates/envoy-gateway-deployment.yaml b/charts/gateway-helm/templates/envoy-gateway-deployment.yaml index 7ca6f2b64d14..5d0eb8183083 100644 --- a/charts/gateway-helm/templates/envoy-gateway-deployment.yaml +++ b/charts/gateway-helm/templates/envoy-gateway-deployment.yaml @@ -49,8 +49,8 @@ spec: fieldPath: metadata.namespace - name: KUBERNETES_CLUSTER_DOMAIN value: {{ .Values.kubernetesClusterDomain }} - image: {{ .Values.deployment.envoyGateway.image.repository }}:{{ .Values.deployment.envoyGateway.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.deployment.envoyGateway.imagePullPolicy }} + image: {{ include "eg.image" . }} + imagePullPolicy: {{ include "eg.image.pullPolicy" . }} livenessProbe: httpGet: path: /healthz @@ -80,10 +80,7 @@ spec: - mountPath: /certs name: certs readOnly: true - {{- with .Values.deployment.envoyGateway.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} + {{- include "eg.image.pullSecrets" . | nindent 6 }} securityContext: runAsNonRoot: true serviceAccountName: envoy-gateway diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml index 4760f2bb3ee0..0513ff811437 100644 --- a/charts/gateway-helm/values.tmpl.yaml +++ b/charts/gateway-helm/values.tmpl.yaml @@ -1,9 +1,32 @@ +# The global settings for the Envoy Gateway Helm chart. +# These values will be used if the values are not overridden in the other sections. +global: + images: + envoyGateway: + # This is the full image name including the hub, repo, and tag. + image: ${GatewayImage} + # Specify image pull policy if default behavior isn't desired. + # Default behavior: latest images will be Always else IfNotPresent. + pullPolicy: ${GatewayImagePullPolicy} + # List of secrets in the same namespace of the component that can be used to pull images from private repositories. + imagePullSecrets: [] + ratelimit: + # This is the full image name including the hub, repo, and tag. + image: "docker.io/envoyproxy/ratelimit:master" + # TODO: zhaohuabing add support for imagePullSecrets for ratelimit + # Specify image pull policy if default behavior isn't desired. + # Default behavior: latest images will be Always else IfNotPresent. + # pullPolicy: IfNotPresent + # List of secrets in the same namespace of the component that can be used to pull images from private repositories. + # imagePullSecrets: [] + # statsd: TODO: zhaohuabing add custom image support for statsd image + deployment: envoyGateway: image: - repository: ${ImageRepository} - tag: '${ImageTag}' - imagePullPolicy: ${ImagePullPolicy} + repository: "" + tag: "" + imagePullPolicy: "" imagePullSecrets: [] resources: limits: @@ -36,9 +59,6 @@ config: controllerName: gateway.envoyproxy.io/gatewayclass-controller provider: type: Kubernetes - kubernetes: - shutdownManager: - image: ${ImageRepository}:${ImageTag} logging: level: default: info diff --git a/site/content/en/latest/install/api.md b/site/content/en/latest/install/api.md index f9c3b35b5317..b5d318e22893 100644 --- a/site/content/en/latest/install/api.md +++ b/site/content/en/latest/install/api.md @@ -31,12 +31,11 @@ The Helm chart for Envoy Gateway | certgen.rbac.labels | object | `{}` | | | config.envoyGateway.gateway.controllerName | string | `"gateway.envoyproxy.io/gatewayclass-controller"` | | | config.envoyGateway.logging.level.default | string | `"info"` | | -| config.envoyGateway.provider.kubernetes.shutdownManager.image | string | `"docker.io/envoyproxy/gateway:latest"` | | | config.envoyGateway.provider.type | string | `"Kubernetes"` | | | createNamespace | bool | `false` | | -| deployment.envoyGateway.image.repository | string | `"docker.io/envoyproxy/gateway"` | | -| deployment.envoyGateway.image.tag | string | `"latest"` | | -| deployment.envoyGateway.imagePullPolicy | string | `"IfNotPresent"` | | +| deployment.envoyGateway.image.repository | string | `""` | | +| deployment.envoyGateway.image.tag | string | `""` | | +| deployment.envoyGateway.imagePullPolicy | string | `""` | | | deployment.envoyGateway.imagePullSecrets | list | `[]` | | | deployment.envoyGateway.resources.limits.cpu | string | `"500m"` | | | deployment.envoyGateway.resources.limits.memory | string | `"1024Mi"` | | @@ -56,5 +55,9 @@ The Helm chart for Envoy Gateway | deployment.ports[2].port | int | `19001` | | | deployment.ports[2].targetPort | int | `19001` | | | deployment.replicas | int | `1` | | +| global.images.envoyGateway.image | string | `nil` | | +| global.images.envoyGateway.imagePullSecrets | list | `[]` | | +| global.images.envoyGateway.pullPolicy | string | `nil` | | +| global.images.ratelimit.image | string | `"docker.io/envoyproxy/ratelimit:master"` | | | kubernetesClusterDomain | string | `"cluster.local"` | | diff --git a/test/helm/default-config.in.yaml b/test/helm/default-config.in.yaml new file mode 100644 index 000000000000..352f3f9b97ec --- /dev/null +++ b/test/helm/default-config.in.yaml @@ -0,0 +1,5 @@ +global: + images: + envoyGateway: + image: "docker.io/envoyproxy/gateway-dev:latest" + pullPolicy: Always diff --git a/test/helm/default.yaml b/test/helm/default-config.out.yaml similarity index 98% rename from test/helm/default.yaml rename to test/helm/default-config.out.yaml index b4a1b5426afb..ba4840ee0172 100644 --- a/test/helm/default.yaml +++ b/test/helm/default-config.out.yaml @@ -35,6 +35,9 @@ data: default: info provider: kubernetes: + rateLimitDeployment: + container: + image: docker.io/envoyproxy/ratelimit:master shutdownManager: image: docker.io/envoyproxy/gateway-dev:latest type: Kubernetes @@ -372,7 +375,7 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: cluster.local image: docker.io/envoyproxy/gateway-dev:latest - imagePullPolicy: IfNotPresent + imagePullPolicy: Always livenessProbe: httpGet: path: /healthz @@ -409,6 +412,7 @@ spec: - mountPath: /certs name: certs readOnly: true + imagePullSecrets: [] securityContext: runAsNonRoot: true serviceAccountName: envoy-gateway @@ -520,8 +524,9 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: cluster.local image: docker.io/envoyproxy/gateway-dev:latest - imagePullPolicy: IfNotPresent + imagePullPolicy: Always name: envoy-gateway-certgen + imagePullSecrets: [] restartPolicy: Never securityContext: runAsGroup: 65534 diff --git a/test/helm/deployment-images-config.in.yaml b/test/helm/deployment-images-config.in.yaml new file mode 100644 index 000000000000..f5f4425f7463 --- /dev/null +++ b/test/helm/deployment-images-config.in.yaml @@ -0,0 +1,11 @@ +# The image in the deployment is replaced with the image from the global configuration. +# It's retained for backwards compatibility. +deployment: + envoyGateway: + image: + repository: private-hub/envoyproxy/gateway + tag: abcdef12 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: "secret1" + - name: "secret2" diff --git a/test/helm/deployment-images-config.out.yaml b/test/helm/deployment-images-config.out.yaml new file mode 100644 index 000000000000..78256bf94df6 --- /dev/null +++ b/test/helm/deployment-images-config.out.yaml @@ -0,0 +1,540 @@ +--- +# Source: gateway-helm/templates/envoy-gateway-deployment.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +--- +# Source: gateway-helm/templates/envoy-gateway-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: envoy-gateway-config + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +data: + envoy-gateway.yaml: | + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyGateway + gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller + logging: + level: + default: info + provider: + kubernetes: + rateLimitDeployment: + container: + image: docker.io/envoyproxy/ratelimit:master + shutdownManager: + image: private-hub/envoyproxy/gateway:abcdef12 + type: Kubernetes +--- +# Source: gateway-helm/templates/envoy-gateway-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: eg-gateway-helm-envoy-gateway-role +rules: +- apiGroups: + - "" + resources: + - nodes + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses/status + verbs: + - update +- apiGroups: + - multicluster.x-k8s.io + resources: + - serviceimports + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + - secrets + - services + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - gateway.envoyproxy.io + resources: + - envoyproxies + - envoypatchpolicies + - clienttrafficpolicies + - backendtrafficpolicies + - securitypolicies + - envoyextensionpolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.envoyproxy.io + resources: + - envoypatchpolicies/status + - clienttrafficpolicies/status + - backendtrafficpolicies/status + - securitypolicies/status + - envoyextensionpolicies/status + verbs: + - update +- apiGroups: + - gateway.networking.k8s.io + resources: + - gateways + - grpcroutes + - httproutes + - referencegrants + - tcproutes + - tlsroutes + - udproutes + - backendtlspolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gateways/status + - grpcroutes/status + - httproutes/status + - tcproutes/status + - tlsroutes/status + - udproutes/status + - backendtlspolicies/status + verbs: + - update +--- +# Source: gateway-helm/templates/envoy-gateway-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: eg-gateway-helm-envoy-gateway-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: eg-gateway-helm-envoy-gateway-role +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/infra-manager-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-infra-manager + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +rules: +- apiGroups: + - "" + resources: + - serviceaccounts + - services + verbs: + - create + - get + - delete + - patch +- apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - create + - get + - delete + - patch +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - get + - delete + - patch +--- +# Source: gateway-helm/templates/leader-election-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-leader-election-role + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +# Source: gateway-helm/templates/infra-manager-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-infra-manager + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-infra-manager' +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/leader-election-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-leader-election-rolebinding + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-leader-election-role' +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/envoy-gateway-service.yaml +apiVersion: v1 +kind: Service +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + control-plane: envoy-gateway + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +spec: + selector: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + ports: + - name: grpc + port: 18000 + targetPort: 18000 + - name: ratelimit + port: 18001 + targetPort: 18001 + - name: metrics + port: 19001 + targetPort: 19001 +--- +# Source: gateway-helm/templates/envoy-gateway-deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + control-plane: envoy-gateway + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + template: + metadata: + annotations: + prometheus.io/port: "19001" + prometheus.io/scrape: "true" + labels: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + spec: + containers: + - args: + - server + - --config-path=/config/envoy-gateway.yaml + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBERNETES_CLUSTER_DOMAIN + value: cluster.local + image: private-hub/envoyproxy/gateway:abcdef12 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: envoy-gateway + ports: + - containerPort: 18000 + name: grpc + - containerPort: 18001 + name: ratelimit + - containerPort: 19001 + name: metrics + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 500m + memory: 1024Mi + requests: + cpu: 100m + memory: 256Mi + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + - mountPath: /config + name: envoy-gateway-config + readOnly: true + - mountPath: /certs + name: certs + readOnly: true + imagePullSecrets: + - name: secret1 + - name: secret2 + securityContext: + runAsNonRoot: true + serviceAccountName: envoy-gateway + terminationGracePeriodSeconds: 10 + volumes: + - configMap: + defaultMode: 420 + name: envoy-gateway-config + name: envoy-gateway-config + - name: certs + secret: + secretName: envoy-gateway +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create + - update +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-certgen' +subjects: +- kind: ServiceAccount + name: 'eg-gateway-helm-certgen' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/certgen.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install, pre-upgrade +spec: + backoffLimit: 1 + completions: 1 + parallelism: 1 + template: + metadata: + labels: + app: certgen + spec: + containers: + - command: + - envoy-gateway + - certgen + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBERNETES_CLUSTER_DOMAIN + value: cluster.local + image: private-hub/envoyproxy/gateway:abcdef12 + imagePullPolicy: IfNotPresent + name: envoy-gateway-certgen + imagePullSecrets: + - name: secret1 + - name: secret2 + restartPolicy: Never + securityContext: + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: eg-gateway-helm-certgen + ttlSecondsAfterFinished: 30 diff --git a/test/helm/envoy-gateway-config.in.yaml b/test/helm/envoy-gateway-config.in.yaml new file mode 100644 index 000000000000..936d3ddf87d9 --- /dev/null +++ b/test/helm/envoy-gateway-config.in.yaml @@ -0,0 +1,20 @@ +global: + images: + envoyGateway: + image: "docker.io/envoyproxy/gateway-dev:latest" + pullPolicy: Always +config: + envoyGateway: + gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller + provider: + type: Kubernetes + kubernetes: + leaderElection: + enabled: false + rateLimitDeployment: + container: + image: private-hub/envoyproxy/ratelimit:master + logging: + level: + default: debug diff --git a/test/helm/envoy-gateway-config.out.yaml b/test/helm/envoy-gateway-config.out.yaml new file mode 100644 index 000000000000..a2b051ea23c4 --- /dev/null +++ b/test/helm/envoy-gateway-config.out.yaml @@ -0,0 +1,538 @@ +--- +# Source: gateway-helm/templates/envoy-gateway-deployment.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +--- +# Source: gateway-helm/templates/envoy-gateway-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: envoy-gateway-config + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +data: + envoy-gateway.yaml: | + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyGateway + gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller + logging: + level: + default: debug + provider: + kubernetes: + leaderElection: + enabled: false + rateLimitDeployment: + container: + image: private-hub/envoyproxy/ratelimit:master + shutdownManager: + image: docker.io/envoyproxy/gateway-dev:latest + type: Kubernetes +--- +# Source: gateway-helm/templates/envoy-gateway-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: eg-gateway-helm-envoy-gateway-role +rules: +- apiGroups: + - "" + resources: + - nodes + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses/status + verbs: + - update +- apiGroups: + - multicluster.x-k8s.io + resources: + - serviceimports + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + - secrets + - services + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - gateway.envoyproxy.io + resources: + - envoyproxies + - envoypatchpolicies + - clienttrafficpolicies + - backendtrafficpolicies + - securitypolicies + - envoyextensionpolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.envoyproxy.io + resources: + - envoypatchpolicies/status + - clienttrafficpolicies/status + - backendtrafficpolicies/status + - securitypolicies/status + - envoyextensionpolicies/status + verbs: + - update +- apiGroups: + - gateway.networking.k8s.io + resources: + - gateways + - grpcroutes + - httproutes + - referencegrants + - tcproutes + - tlsroutes + - udproutes + - backendtlspolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gateways/status + - grpcroutes/status + - httproutes/status + - tcproutes/status + - tlsroutes/status + - udproutes/status + - backendtlspolicies/status + verbs: + - update +--- +# Source: gateway-helm/templates/envoy-gateway-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: eg-gateway-helm-envoy-gateway-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: eg-gateway-helm-envoy-gateway-role +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/infra-manager-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-infra-manager + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +rules: +- apiGroups: + - "" + resources: + - serviceaccounts + - services + verbs: + - create + - get + - delete + - patch +- apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - create + - get + - delete + - patch +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - get + - delete + - patch +--- +# Source: gateway-helm/templates/leader-election-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-leader-election-role + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +# Source: gateway-helm/templates/infra-manager-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-infra-manager + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-infra-manager' +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/leader-election-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-leader-election-rolebinding + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-leader-election-role' +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/envoy-gateway-service.yaml +apiVersion: v1 +kind: Service +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + control-plane: envoy-gateway + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +spec: + selector: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + ports: + - name: grpc + port: 18000 + targetPort: 18000 + - name: ratelimit + port: 18001 + targetPort: 18001 + - name: metrics + port: 19001 + targetPort: 19001 +--- +# Source: gateway-helm/templates/envoy-gateway-deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + control-plane: envoy-gateway + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + template: + metadata: + annotations: + prometheus.io/port: "19001" + prometheus.io/scrape: "true" + labels: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + spec: + containers: + - args: + - server + - --config-path=/config/envoy-gateway.yaml + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBERNETES_CLUSTER_DOMAIN + value: cluster.local + image: docker.io/envoyproxy/gateway-dev:latest + imagePullPolicy: Always + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: envoy-gateway + ports: + - containerPort: 18000 + name: grpc + - containerPort: 18001 + name: ratelimit + - containerPort: 19001 + name: metrics + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 500m + memory: 1024Mi + requests: + cpu: 100m + memory: 256Mi + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + - mountPath: /config + name: envoy-gateway-config + readOnly: true + - mountPath: /certs + name: certs + readOnly: true + imagePullSecrets: [] + securityContext: + runAsNonRoot: true + serviceAccountName: envoy-gateway + terminationGracePeriodSeconds: 10 + volumes: + - configMap: + defaultMode: 420 + name: envoy-gateway-config + name: envoy-gateway-config + - name: certs + secret: + secretName: envoy-gateway +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create + - update +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-certgen' +subjects: +- kind: ServiceAccount + name: 'eg-gateway-helm-certgen' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/certgen.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install, pre-upgrade +spec: + backoffLimit: 1 + completions: 1 + parallelism: 1 + template: + metadata: + labels: + app: certgen + spec: + containers: + - command: + - envoy-gateway + - certgen + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBERNETES_CLUSTER_DOMAIN + value: cluster.local + image: docker.io/envoyproxy/gateway-dev:latest + imagePullPolicy: Always + name: envoy-gateway-certgen + imagePullSecrets: [] + restartPolicy: Never + securityContext: + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: eg-gateway-helm-certgen + ttlSecondsAfterFinished: 30 diff --git a/test/helm/global-images-config.in.yaml b/test/helm/global-images-config.in.yaml new file mode 100644 index 000000000000..bbcb3a2028a0 --- /dev/null +++ b/test/helm/global-images-config.in.yaml @@ -0,0 +1,10 @@ +global: + images: + envoyGateway: + image: "private-hub/envoyproxy/gateway:abcdef12" + pullPolicy: Always + imagePullSecrets: + - name: "secret1" + - name: "secret2" + ratelimit: + image: "private-hub/envoyproxy/ratelimit:test" diff --git a/test/helm/global-images-config.out.yaml b/test/helm/global-images-config.out.yaml new file mode 100644 index 000000000000..0d417c210356 --- /dev/null +++ b/test/helm/global-images-config.out.yaml @@ -0,0 +1,540 @@ +--- +# Source: gateway-helm/templates/envoy-gateway-deployment.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +--- +# Source: gateway-helm/templates/envoy-gateway-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: envoy-gateway-config + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +data: + envoy-gateway.yaml: | + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyGateway + gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller + logging: + level: + default: info + provider: + kubernetes: + rateLimitDeployment: + container: + image: private-hub/envoyproxy/ratelimit:test + shutdownManager: + image: private-hub/envoyproxy/gateway:abcdef12 + type: Kubernetes +--- +# Source: gateway-helm/templates/envoy-gateway-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: eg-gateway-helm-envoy-gateway-role +rules: +- apiGroups: + - "" + resources: + - nodes + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses/status + verbs: + - update +- apiGroups: + - multicluster.x-k8s.io + resources: + - serviceimports + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + - secrets + - services + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch +- apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - gateway.envoyproxy.io + resources: + - envoyproxies + - envoypatchpolicies + - clienttrafficpolicies + - backendtrafficpolicies + - securitypolicies + - envoyextensionpolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.envoyproxy.io + resources: + - envoypatchpolicies/status + - clienttrafficpolicies/status + - backendtrafficpolicies/status + - securitypolicies/status + - envoyextensionpolicies/status + verbs: + - update +- apiGroups: + - gateway.networking.k8s.io + resources: + - gateways + - grpcroutes + - httproutes + - referencegrants + - tcproutes + - tlsroutes + - udproutes + - backendtlspolicies + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gateways/status + - grpcroutes/status + - httproutes/status + - tcproutes/status + - tlsroutes/status + - udproutes/status + - backendtlspolicies/status + verbs: + - update +--- +# Source: gateway-helm/templates/envoy-gateway-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: eg-gateway-helm-envoy-gateway-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: eg-gateway-helm-envoy-gateway-role +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/infra-manager-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-infra-manager + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +rules: +- apiGroups: + - "" + resources: + - serviceaccounts + - services + verbs: + - create + - get + - delete + - patch +- apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - create + - get + - delete + - patch +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - get + - delete + - patch +--- +# Source: gateway-helm/templates/leader-election-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-leader-election-role + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +# Source: gateway-helm/templates/infra-manager-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-infra-manager + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-infra-manager' +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/leader-election-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-leader-election-rolebinding + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-leader-election-role' +subjects: +- kind: ServiceAccount + name: 'envoy-gateway' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/envoy-gateway-service.yaml +apiVersion: v1 +kind: Service +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + control-plane: envoy-gateway + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +spec: + selector: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + ports: + - name: grpc + port: 18000 + targetPort: 18000 + - name: ratelimit + port: 18001 + targetPort: 18001 + - name: metrics + port: 19001 + targetPort: 19001 +--- +# Source: gateway-helm/templates/envoy-gateway-deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: envoy-gateway + namespace: 'envoy-gateway-system' + labels: + control-plane: envoy-gateway + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + template: + metadata: + annotations: + prometheus.io/port: "19001" + prometheus.io/scrape: "true" + labels: + control-plane: envoy-gateway + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + spec: + containers: + - args: + - server + - --config-path=/config/envoy-gateway.yaml + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBERNETES_CLUSTER_DOMAIN + value: cluster.local + image: private-hub/envoyproxy/gateway:abcdef12 + imagePullPolicy: Always + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: envoy-gateway + ports: + - containerPort: 18000 + name: grpc + - containerPort: 18001 + name: ratelimit + - containerPort: 19001 + name: metrics + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 500m + memory: 1024Mi + requests: + cpu: 100m + memory: 256Mi + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + - mountPath: /config + name: envoy-gateway-config + readOnly: true + - mountPath: /certs + name: certs + readOnly: true + imagePullSecrets: + - name: secret1 + - name: secret2 + securityContext: + runAsNonRoot: true + serviceAccountName: envoy-gateway + terminationGracePeriodSeconds: 10 + volumes: + - configMap: + defaultMode: 420 + name: envoy-gateway-config + name: envoy-gateway-config + - name: certs + secret: + secretName: envoy-gateway +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - create + - update +--- +# Source: gateway-helm/templates/certgen-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: 'eg-gateway-helm-certgen' +subjects: +- kind: ServiceAccount + name: 'eg-gateway-helm-certgen' + namespace: 'envoy-gateway-system' +--- +# Source: gateway-helm/templates/certgen.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: eg-gateway-helm-certgen + namespace: 'envoy-gateway-system' + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: eg + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + annotations: + "helm.sh/hook": pre-install, pre-upgrade +spec: + backoffLimit: 1 + completions: 1 + parallelism: 1 + template: + metadata: + labels: + app: certgen + spec: + containers: + - command: + - envoy-gateway + - certgen + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBERNETES_CLUSTER_DOMAIN + value: cluster.local + image: private-hub/envoyproxy/gateway:abcdef12 + imagePullPolicy: Always + name: envoy-gateway-certgen + imagePullSecrets: + - name: secret1 + - name: secret2 + restartPolicy: Never + securityContext: + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + serviceAccountName: eg-gateway-helm-certgen + ttlSecondsAfterFinished: 30 diff --git a/tools/make/helm.mk b/tools/make/helm.mk index c664974d133b..4d336d359b15 100644 --- a/tools/make/helm.mk +++ b/tools/make/helm.mk @@ -28,9 +28,15 @@ helm-install: helm-generate ## Install envoy gateway helm chart from OCI registr .PHONY: helm-generate helm-generate: - ImageRepository=${IMAGE} ImageTag=${TAG} ImagePullPolicy=${IMAGE_PULL_POLICY} envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml + GatewayImage=${IMAGE}:${TAG} GatewayImagePullPolicy=${IMAGE_PULL_POLICY} envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml helm lint charts/gateway-helm -helm-template: ## Template envoy gateway helm chart. +HELM_VALUES := $(wildcard test/helm/*.in.yaml) + +helm-template: ## Template envoy gateway helm chart.z @$(LOG_TARGET) - helm template eg charts/gateway-helm --set deployment.envoyGateway.image.tag=latest --set config.envoyGateway.provider.kubernetes.shutdownManager.image="docker.io/envoyproxy/gateway-dev:latest" > ./test/helm/default.yaml --namespace=envoy-gateway-system + @for file in $(HELM_VALUES); do \ + filename=$$(basename $${file}); \ + output="$${filename%.in.*}.out.yaml"; \ + helm template eg charts/gateway-helm -f $${file} > test/helm/$$output --namespace=envoy-gateway-system; \ + done From 02ff9eb749ba7eda1a53dfcbd80fb2b6f46b23fe Mon Sep 17 00:00:00 2001 From: Wilson Wu Date: Fri, 17 May 2024 11:12:36 +0800 Subject: [PATCH 11/25] docs(zh): translate Install docs into Chinese (#3403) * translate Install docs into Chinese Signed-off-by: Wilson Wu * Apply suggestions from code review Co-authored-by: sh2 Signed-off-by: Wilson Wu * Fix the en link Signed-off-by: Wilson Wu * Apply suggestions Signed-off-by: Wilson Wu --------- Signed-off-by: Wilson Wu Co-authored-by: sh2 --- .../content/en/latest/install/install-helm.md | 2 +- site/content/zh/latest/install/api.md | 59 +++++++ site/content/zh/latest/install/custom-cert.md | 149 ++++++++++++++++++ .../content/zh/latest/install/install-helm.md | 143 +++++++++++++++++ .../content/zh/latest/install/install-yaml.md | 38 +++++ 5 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 site/content/zh/latest/install/api.md create mode 100644 site/content/zh/latest/install/custom-cert.md create mode 100644 site/content/zh/latest/install/install-helm.md create mode 100644 site/content/zh/latest/install/install-yaml.md diff --git a/site/content/en/latest/install/install-helm.md b/site/content/en/latest/install/install-helm.md index 903abe509645..4c3351e62384 100644 --- a/site/content/en/latest/install/install-helm.md +++ b/site/content/en/latest/install/install-helm.md @@ -64,7 +64,7 @@ consideration when debugging. Some of the quick ways of using the helm install command for envoy gateway installation are below. {{% alert title="Helm Chart Values" color="primary" %}} -If you want to know all the available fields inside the values.yaml file, please see the [Helm Chart Values](../api). +If you want to know all the available fields inside the values.yaml file, please see the [Helm Chart Values](./api). {{% /alert %}} ### Increase the replicas diff --git a/site/content/zh/latest/install/api.md b/site/content/zh/latest/install/api.md new file mode 100644 index 000000000000..36fe24f6e5be --- /dev/null +++ b/site/content/zh/latest/install/api.md @@ -0,0 +1,59 @@ ++++ +title = "gateway-helm" ++++ + + +![Version: v0.0.0-latest](https://img.shields.io/badge/Version-v0.0.0--latest-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square) + +The Helm chart for Envoy Gateway + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| envoy-gateway-steering-committee | | | +| envoy-gateway-maintainers | | | + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| certgen.job.annotations | object | `{}` | | +| certgen.job.resources | object | `{}` | | +| certgen.job.ttlSecondsAfterFinished | int | `30` | | +| certgen.rbac.annotations | object | `{}` | | +| certgen.rbac.labels | object | `{}` | | +| config.envoyGateway.gateway.controllerName | string | `"gateway.envoyproxy.io/gatewayclass-controller"` | | +| config.envoyGateway.logging.level.default | string | `"info"` | | +| config.envoyGateway.provider.type | string | `"Kubernetes"` | | +| createNamespace | bool | `false` | | +| deployment.envoyGateway.image.repository | string | `"docker.io/envoyproxy/gateway"` | | +| deployment.envoyGateway.image.tag | string | `"latest"` | | +| deployment.envoyGateway.imagePullPolicy | string | `"IfNotPresent"` | | +| deployment.envoyGateway.imagePullSecrets | list | `[]` | | +| deployment.envoyGateway.resources.limits.cpu | string | `"500m"` | | +| deployment.envoyGateway.resources.limits.memory | string | `"1024Mi"` | | +| deployment.envoyGateway.resources.requests.cpu | string | `"100m"` | | +| deployment.envoyGateway.resources.requests.memory | string | `"256Mi"` | | +| deployment.pod.affinity | object | `{}` | | +| deployment.pod.annotations."prometheus.io/port" | string | `"19001"` | | +| deployment.pod.annotations."prometheus.io/scrape" | string | `"true"` | | +| deployment.pod.labels | object | `{}` | | +| deployment.ports[0].name | string | `"grpc"` | | +| deployment.ports[0].port | int | `18000` | | +| deployment.ports[0].targetPort | int | `18000` | | +| deployment.ports[1].name | string | `"ratelimit"` | | +| deployment.ports[1].port | int | `18001` | | +| deployment.ports[1].targetPort | int | `18001` | | +| deployment.ports[2].name | string | `"metrics"` | | +| deployment.ports[2].port | int | `19001` | | +| deployment.ports[2].targetPort | int | `19001` | | +| deployment.replicas | int | `1` | | +| kubernetesClusterDomain | string | `"cluster.local"` | | + diff --git a/site/content/zh/latest/install/custom-cert.md b/site/content/zh/latest/install/custom-cert.md new file mode 100644 index 000000000000..9265fe9122dc --- /dev/null +++ b/site/content/zh/latest/install/custom-cert.md @@ -0,0 +1,149 @@ +--- +title: 使用自定义证书的控制平面身份验证 +weight: -70 +--- + +Envoy Gateway 为 Envoy Gateway Pod 和 Envoy 代理队列之间的控制平面通信建立了安全的 TLS 连接。 +此处使用的 TLS 证书是自签名的,并使用在创建 Envoy Gateway 之前运行的 Job 生成, +并且这些证书被安装到 Envoy Gateway 和 Envoy 代理 Pod 上。 + +此任务将引导您完成为控制平面身份验证配置自定义证书。 + +## 开始之前 {#before-you-begin} + +我们使用 Cert-Manager 来管理证书。 +您可以按照[官方指南](https://cert-manager.io/docs/installation/kubernetes/)安装它。 + +## 为控制平面配置自定义证书 {#configure-custom-certs-for-control-plane} + +1. 首先您需要设置 CA 颁发者,在此任务中,我们以 `selfsigned-issuer` 为例。 + + **您不应在生产中使用自签名颁发者,您应该使用真实的 CA 颁发者。** + + ```shell + cat < +``` + +**注意**:以上是我们可以直接用于自定义安装的一些方法。但如果您正在寻找更复杂的更改, +[values.yaml](https://helm.sh/docs/chart_template_guide/values_files/) 可以帮助您。 + +### 使用 values.yaml 文件进行复杂安装 {#using-values-yaml-file-for-complex-installation} + +```yaml +deployment: + envoyGateway: + resources: + limits: + cpu: 700m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + ports: + - name: grpc + port: 18005 + targetPort: 18000 + - name: ratelimit + port: 18006 + targetPort: 18001 + +config: + envoyGateway: + logging: + level: + default: debug +``` + +在这里,我们对 value.yaml 文件进行了三处更改。将 CPU 的资源限制增加到 `700m`, +将 gRPC 的端口更改为 `18005`,将限流端口更改为 `18006`,并将日志记录级别更新为 `debug`。 + +您可以通过以下命令使用 value.yaml 文件安装 Envoy Gateway。 + +```shell +helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace -f values.yaml +``` + +{{% alert title="Helm Chart Values" color="primary" %}} +如果您想了解 values.yaml 文件中的所有可用字段,请参阅 [Helm Chart Values](./api)。 +{{% /alert %}} + +## 开放端口 {#open-ports} + +这些是 Envoy Gateway 和托管 Envoy 代理使用的端口。 + +### Envoy Gateway {#envoy-gateway} + +| Envoy Gateway | 地址 | 端口 | 是否可配置 | +|:----------------------:|:---------:|:------:| :------: | +| Xds EnvoyProxy Server | 0.0.0.0 | 18000 | No | +| Xds RateLimit Server | 0.0.0.0 | 18001 | No | +| Admin Server | 127.0.0.1 | 19000 | Yes | +| Metrics Server | 0.0.0.0 | 19001 | No | +| Health Check | 127.0.0.1 | 8081 | No | + +### EnvoyProxy {#envoyproxy} + +| Envoy Proxy | 地址 | 端口 | +|:---------------------------------:|:-----------:| :-----: | +| Admin Server | 127.0.0.1 | 19000 | +| Heath Check | 0.0.0.0 | 19001 | + +{{% alert title="后续步骤" color="warning" %}} +Envoy Gateway 现在应该已成功安装并运行。要体验 Envoy Gateway 的更多功能,请参阅[任务](../tasks)。 +{{% /alert %}} diff --git a/site/content/zh/latest/install/install-yaml.md b/site/content/zh/latest/install/install-yaml.md new file mode 100644 index 000000000000..cc94bb353b34 --- /dev/null +++ b/site/content/zh/latest/install/install-yaml.md @@ -0,0 +1,38 @@ ++++ +title = "使用 Kubernetes YAML 安装" +weight = -99 ++++ + +此任务将引导您完成在 Kubernetes 集群中安装 Envoy Gateway。 + +手动安装过程不允许像 [Helm 安装方法](./install-helm)那样对配置进行更多控制, +因此如果您需要对 Envoy Gateway 安装进行更多控制,建议您使用 Helm。 + +## 开始之前 {#before-you-begin} + +Envoy Gateway 设计为在 Kubernetes 中运行以进行生产。最重要的要求是: + +* Kubernetest 1.25+ 版本 +* `kubectl` 命令行工具 + +{{% alert title="兼容性矩阵" color="warning" %}} +请参阅[版本兼容性矩阵](./matrix)了解更多信息。 +{{% /alert %}} + +## 使用 YAML 安装 {#install-with-yaml} + +Envoy Gateway 通常从命令行部署到 Kubernetes。如果您没有 Kubernetes,则应该使用 `kind` 来创建一个。 + +{{% alert title="开发者指南" color="primary" %}} +请参阅[开发者指南](../../contributions/develop)了解更多信息。 +{{% /alert %}} + +1. 在终端中,运行以下命令: + + ```shell + kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/install.yaml + ``` + +2. 后续步骤 + + Envoy Gateway 现在应该已成功安装并运行,但是为了体验 Envoy Gateway 的更多功能,您可以参考[任务](/latest/tasks)。 From fe862e81d9d6f8be77c24680bf4c05df5ba39667 Mon Sep 17 00:00:00 2001 From: sh2 Date: Sat, 18 May 2024 00:20:10 +0800 Subject: [PATCH 12/25] doc: merge announcements and blogs into news (#3417) * merge announcements and blogs into news Signed-off-by: shawnh2 * fix doc-lint Signed-off-by: shawnh2 --------- Signed-off-by: shawnh2 --- site/content/en/blog/_index.md | 7 ------- site/content/en/blog/news/_index.md | 4 ---- site/content/en/blog/presentations/_index.md | 4 ---- site/content/en/contributions/DOCS.md | 2 +- site/content/en/news/_index.md | 12 ++++++++++++ .../news => news/blogs}/1.0-release/1.0-release.md | 2 +- site/content/en/news/blogs/_index.md | 8 ++++++++ .../news => news/blogs}/new-website/new-website.md | 0 site/content/en/news/presentations/_index.md | 8 ++++++++ .../presentations/kubecon-cn-2023/kubecon-cn-2023.md | 1 + .../presentations/kubecon-eu-2023/kubecon-eu-2023.md | 1 + .../presentations/kubecon-na-2022/kubecon-na-2022.md | 1 + .../en/{announcements => news/releases}/_index.md | 8 ++++---- .../en/{announcements => news/releases}/v0.2.md | 0 .../en/{announcements => news/releases}/v0.3.md | 0 .../en/{announcements => news/releases}/v0.4.md | 0 .../en/{announcements => news/releases}/v0.5.md | 0 .../en/{announcements => news/releases}/v0.6.md | 0 .../en/{announcements => news/releases}/v1.0.md | 0 site/content/en/v0.5.0/contributions/DOCS.md | 2 +- site/content/en/v0.6.0/contributions/DOCS.md | 2 +- site/content/zh/contributions/DOCS.md | 2 -- site/hugo.toml | 8 ++------ 23 files changed, 41 insertions(+), 31 deletions(-) delete mode 100644 site/content/en/blog/_index.md delete mode 100644 site/content/en/blog/news/_index.md delete mode 100644 site/content/en/blog/presentations/_index.md create mode 100644 site/content/en/news/_index.md rename site/content/en/{blog/news => news/blogs}/1.0-release/1.0-release.md (98%) create mode 100644 site/content/en/news/blogs/_index.md rename site/content/en/{blog/news => news/blogs}/new-website/new-website.md (100%) create mode 100644 site/content/en/news/presentations/_index.md rename site/content/en/{blog => news}/presentations/kubecon-cn-2023/kubecon-cn-2023.md (91%) rename site/content/en/{blog => news}/presentations/kubecon-eu-2023/kubecon-eu-2023.md (93%) rename site/content/en/{blog => news}/presentations/kubecon-na-2022/kubecon-na-2022.md (94%) rename site/content/en/{announcements => news/releases}/_index.md (94%) rename site/content/en/{announcements => news/releases}/v0.2.md (100%) rename site/content/en/{announcements => news/releases}/v0.3.md (100%) rename site/content/en/{announcements => news/releases}/v0.4.md (100%) rename site/content/en/{announcements => news/releases}/v0.5.md (100%) rename site/content/en/{announcements => news/releases}/v0.6.md (100%) rename site/content/en/{announcements => news/releases}/v1.0.md (100%) diff --git a/site/content/en/blog/_index.md b/site/content/en/blog/_index.md deleted file mode 100644 index 45f940a58238..000000000000 --- a/site/content/en/blog/_index.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Blog ---- - -This is the **blog** section. It has two categories: News and Releases. - -Files in these directories will be listed in reverse chronological order. diff --git a/site/content/en/blog/news/_index.md b/site/content/en/blog/news/_index.md deleted file mode 100644 index c609aa254312..000000000000 --- a/site/content/en/blog/news/_index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: News -weight: 20 ---- diff --git a/site/content/en/blog/presentations/_index.md b/site/content/en/blog/presentations/_index.md deleted file mode 100644 index c7e0ad1a052f..000000000000 --- a/site/content/en/blog/presentations/_index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Presentations -weight: 20 ---- diff --git a/site/content/en/contributions/DOCS.md b/site/content/en/contributions/DOCS.md index a2bc120101db..6c875a056694 100644 --- a/site/content/en/contributions/DOCS.md +++ b/site/content/en/contributions/DOCS.md @@ -7,7 +7,7 @@ description: "This section tells the development of {{% alert title="Note" color="warning" %}} We migrated from ***Sphinx*** to ***Hugo*** for Envoy Gateway Documents. -Read blog: [Welcome to new website!](/blog/2023/10/08/welcome-to-new-website/) +Read blog: [Welcome to new website!](/news/blogs/new-website/new-website) {{% /alert %}} The documentation for the Envoy Gateway lives in the `site/content/en` directory (the Chinese content in the `site/content/zh` directory). diff --git a/site/content/en/news/_index.md b/site/content/en/news/_index.md new file mode 100644 index 000000000000..34cabe89849c --- /dev/null +++ b/site/content/en/news/_index.md @@ -0,0 +1,12 @@ ++++ +title = "News" +linktitle = "News" +description = "News about Envoy Gateway" + +[[cascade]] +type = "docs" ++++ + +This is the **news** section. It has three categories: Blogs, Presentations and Releases. + +Files in these directories will be listed in reverse chronological order. diff --git a/site/content/en/blog/news/1.0-release/1.0-release.md b/site/content/en/news/blogs/1.0-release/1.0-release.md similarity index 98% rename from site/content/en/blog/news/1.0-release/1.0-release.md rename to site/content/en/news/blogs/1.0-release/1.0-release.md index 5711ee83b91f..44f5c4177719 100644 --- a/site/content/en/blog/news/1.0-release/1.0-release.md +++ b/site/content/en/news/blogs/1.0-release/1.0-release.md @@ -1,7 +1,7 @@ --- date: 2024-03-14 title: Announcing Envoy Gateway’s 1.0 Release! -linkTitle: 1.0 Release +linkTitle: Announcing Envoy Gateway’s 1.0 Release description: > v1.0.0 is here ! author: Alice Wasko (Ambassador Labs), Arko Dasgupta (Tetrate), Congqi Zhu (CECloud), Guy Daich (SAP), Huabing Zhao (Tetrate), Jianpeng He (Tetrate), Xunzhuo Liu (Tencent) diff --git a/site/content/en/news/blogs/_index.md b/site/content/en/news/blogs/_index.md new file mode 100644 index 000000000000..a3f4f23b1c4f --- /dev/null +++ b/site/content/en/news/blogs/_index.md @@ -0,0 +1,8 @@ ++++ +title = "Blogs" +description = "Blogs about Envoy Gateway" +linktitle = "Blogs" + +[[cascade]] +type = "docs" ++++ diff --git a/site/content/en/blog/news/new-website/new-website.md b/site/content/en/news/blogs/new-website/new-website.md similarity index 100% rename from site/content/en/blog/news/new-website/new-website.md rename to site/content/en/news/blogs/new-website/new-website.md diff --git a/site/content/en/news/presentations/_index.md b/site/content/en/news/presentations/_index.md new file mode 100644 index 000000000000..38367f5a8abc --- /dev/null +++ b/site/content/en/news/presentations/_index.md @@ -0,0 +1,8 @@ ++++ +title = "Presentations" +description = "Presentations, Talks and Events about Envoy Gateway" +linktitle = "Presentations" + +[[cascade]] +type = "docs" ++++ diff --git a/site/content/en/blog/presentations/kubecon-cn-2023/kubecon-cn-2023.md b/site/content/en/news/presentations/kubecon-cn-2023/kubecon-cn-2023.md similarity index 91% rename from site/content/en/blog/presentations/kubecon-cn-2023/kubecon-cn-2023.md rename to site/content/en/news/presentations/kubecon-cn-2023/kubecon-cn-2023.md index 433773033b8d..cc25487c6665 100644 --- a/site/content/en/blog/presentations/kubecon-cn-2023/kubecon-cn-2023.md +++ b/site/content/en/news/presentations/kubecon-cn-2023/kubecon-cn-2023.md @@ -1,5 +1,6 @@ --- title: "KubeCon China 2023" +description: "Envoy Gateway: The API Gateway in the Cloud Native Era" date: 2023-09-28 --- diff --git a/site/content/en/blog/presentations/kubecon-eu-2023/kubecon-eu-2023.md b/site/content/en/news/presentations/kubecon-eu-2023/kubecon-eu-2023.md similarity index 93% rename from site/content/en/blog/presentations/kubecon-eu-2023/kubecon-eu-2023.md rename to site/content/en/news/presentations/kubecon-eu-2023/kubecon-eu-2023.md index 13a0ccb8c511..d1865ecac879 100644 --- a/site/content/en/blog/presentations/kubecon-eu-2023/kubecon-eu-2023.md +++ b/site/content/en/news/presentations/kubecon-eu-2023/kubecon-eu-2023.md @@ -1,5 +1,6 @@ --- title: "KubeCon Europe 2023" +description: "Envoy Gateway Update" date: 2023-05-01 --- diff --git a/site/content/en/blog/presentations/kubecon-na-2022/kubecon-na-2022.md b/site/content/en/news/presentations/kubecon-na-2022/kubecon-na-2022.md similarity index 94% rename from site/content/en/blog/presentations/kubecon-na-2022/kubecon-na-2022.md rename to site/content/en/news/presentations/kubecon-na-2022/kubecon-na-2022.md index 4714c0f3d370..dddefdd3122a 100644 --- a/site/content/en/blog/presentations/kubecon-na-2022/kubecon-na-2022.md +++ b/site/content/en/news/presentations/kubecon-na-2022/kubecon-na-2022.md @@ -1,5 +1,6 @@ --- title: "KubeCon North America 2022" +description: "Envoy Gateway Update" date: 2022-10-28 --- diff --git a/site/content/en/announcements/_index.md b/site/content/en/news/releases/_index.md similarity index 94% rename from site/content/en/announcements/_index.md rename to site/content/en/news/releases/_index.md index 3c4fe9a2f7d4..cff55283750d 100644 --- a/site/content/en/announcements/_index.md +++ b/site/content/en/news/releases/_index.md @@ -1,7 +1,7 @@ +++ -title = "Release Announcement" -description = "Envoy Gateway Release Announcement" -linktitle = "Announcement" +title = "Release Announcements" +description = "Envoy Gateway Release Announcements" +linktitle = "Releases" [[cascade]] type = "docs" @@ -51,5 +51,5 @@ In order to align with the Envoy Proxy [release schedule][], Envoy Gateway relea | 0.6.0 | 2023/10/22 | 2023/11/02 | +10 days | 2024/05/02 | [v2.0.0 spec]: https://semver.org/spec/v2.0.0.html -[release guide]: ../contributions/releasing +[release guide]: ../../contributions/releasing [release schedule]: https://github.com/envoyproxy/envoy/blob/main/RELEASES.md#major-release-schedule diff --git a/site/content/en/announcements/v0.2.md b/site/content/en/news/releases/v0.2.md similarity index 100% rename from site/content/en/announcements/v0.2.md rename to site/content/en/news/releases/v0.2.md diff --git a/site/content/en/announcements/v0.3.md b/site/content/en/news/releases/v0.3.md similarity index 100% rename from site/content/en/announcements/v0.3.md rename to site/content/en/news/releases/v0.3.md diff --git a/site/content/en/announcements/v0.4.md b/site/content/en/news/releases/v0.4.md similarity index 100% rename from site/content/en/announcements/v0.4.md rename to site/content/en/news/releases/v0.4.md diff --git a/site/content/en/announcements/v0.5.md b/site/content/en/news/releases/v0.5.md similarity index 100% rename from site/content/en/announcements/v0.5.md rename to site/content/en/news/releases/v0.5.md diff --git a/site/content/en/announcements/v0.6.md b/site/content/en/news/releases/v0.6.md similarity index 100% rename from site/content/en/announcements/v0.6.md rename to site/content/en/news/releases/v0.6.md diff --git a/site/content/en/announcements/v1.0.md b/site/content/en/news/releases/v1.0.md similarity index 100% rename from site/content/en/announcements/v1.0.md rename to site/content/en/news/releases/v1.0.md diff --git a/site/content/en/v0.5.0/contributions/DOCS.md b/site/content/en/v0.5.0/contributions/DOCS.md index ae19953a8b5c..eb73584ce5a7 100644 --- a/site/content/en/v0.5.0/contributions/DOCS.md +++ b/site/content/en/v0.5.0/contributions/DOCS.md @@ -7,7 +7,7 @@ description: "This section tells the development of {{% alert title="Note" color="warning" %}} We migrated from ***Sphinx*** to ***Hugo*** for Envoy Gateway Documents. -Read blog: [Welcome to new website!](/blog/2023/10/08/welcome-to-new-website/) +Read blog: [Welcome to new website!](/news/blogs/new-website/new-website) {{% /alert %}} The documentation for the Envoy Gateway lives in the `site/content/en` directory. Any diff --git a/site/content/en/v0.6.0/contributions/DOCS.md b/site/content/en/v0.6.0/contributions/DOCS.md index ae19953a8b5c..eb73584ce5a7 100644 --- a/site/content/en/v0.6.0/contributions/DOCS.md +++ b/site/content/en/v0.6.0/contributions/DOCS.md @@ -7,7 +7,7 @@ description: "This section tells the development of {{% alert title="Note" color="warning" %}} We migrated from ***Sphinx*** to ***Hugo*** for Envoy Gateway Documents. -Read blog: [Welcome to new website!](/blog/2023/10/08/welcome-to-new-website/) +Read blog: [Welcome to new website!](/news/blogs/new-website/new-website) {{% /alert %}} The documentation for the Envoy Gateway lives in the `site/content/en` directory. Any diff --git a/site/content/zh/contributions/DOCS.md b/site/content/zh/contributions/DOCS.md index f05920705e83..096db7998cd7 100644 --- a/site/content/zh/contributions/DOCS.md +++ b/site/content/zh/contributions/DOCS.md @@ -5,8 +5,6 @@ description: "本节讲述 Envoy Gateway 文档的开发工作。" {{% alert title="注意" color="warning" %}} 我们已将 Envoy Gateway 文档从 **Sphinx** 迁移到 **Hugo**。 - -阅读博客:[Welcome to new website!](/blog/2023/10/08/welcome-to-new-website/) {{% /alert %}} Envoy Gateway 的文档位于 `site/content/en` 目录中(中文内容位于 `site/content/zh` 目录中)。 diff --git a/site/hugo.toml b/site/hugo.toml index b5a93a661688..3123251d9716 100644 --- a/site/hugo.toml +++ b/site/hugo.toml @@ -242,18 +242,14 @@ enable = true name = "Contributions" weight = -98 url = "/contributions" - [[menu.main]] - name = "Blog" - weight = -99 - url = "/blog" [[menu.main]] name = "About" weight = -100 url = "/about" [[menu.main]] - name = "Announcements" + name = "News" weight = -101 - url = "/announcements" + url = "/news" [[menu.main]] name = "Documentation" weight = -102 From aa854c106caf6ecaa99ae1f4fc0ec501b1646019 Mon Sep 17 00:00:00 2001 From: zirain Date: Sat, 18 May 2024 07:56:58 +0800 Subject: [PATCH 13/25] chore: support multi nodes cluster (#3422) * chore: support multi nodes cluster Signed-off-by: zirain * nit Signed-off-by: zirain --------- Signed-off-by: zirain --- tools/hack/create-cluster.sh | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/hack/create-cluster.sh b/tools/hack/create-cluster.sh index a78adaffd574..992ee5def929 100755 --- a/tools/hack/create-cluster.sh +++ b/tools/hack/create-cluster.sh @@ -6,12 +6,33 @@ set -euo pipefail CLUSTER_NAME=${CLUSTER_NAME:-"envoy-gateway"} METALLB_VERSION=${METALLB_VERSION:-"v0.13.10"} KIND_NODE_TAG=${KIND_NODE_TAG:-"v1.28.0"} +NUM_WORKERS=${NUM_WORKERS:-""} + + +KIND_CFG=$(cat <<-EOM +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane +EOM +) + +# https://kind.sigs.k8s.io/docs/user/quick-start/#multi-node-clusters +if [[ -n "${NUM_WORKERS}" ]]; then +for _ in $(seq 1 "${NUM_WORKERS}"); do + KIND_CFG+=$(printf "\n%s" "- role: worker") +done +fi ## Create kind cluster. if [[ -z "${KIND_NODE_TAG}" ]]; then - tools/bin/kind create cluster --name "${CLUSTER_NAME}" + cat << EOF | tools/bin/kind create cluster --name "${CLUSTER_NAME}" --config - +${KIND_CFG} +EOF else - tools/bin/kind create cluster --image "kindest/node:${KIND_NODE_TAG}" --name "${CLUSTER_NAME}" + cat << EOF | tools/bin/kind create cluster --image "kindest/node:${KIND_NODE_TAG}" --name "${CLUSTER_NAME}" --config - +${KIND_CFG} +EOF fi ## Install MetalLB. From 6dcf78aee3aa88fd7feae6fb7449ba6f3b9c57ff Mon Sep 17 00:00:00 2001 From: Wilson Wu Date: Sun, 19 May 2024 15:23:14 +0800 Subject: [PATCH 14/25] docs(zh): translate releases docs (1.0.0 and 1.0.1 only) into Chinese (#3413) * translate releases docs (1.0.0 and 1.0.1 only) into Chinese Signed-off-by: Wilson Wu * Fix typo Signed-off-by: Wilson Wu --------- Signed-off-by: Wilson Wu --- site/content/zh/latest/releases/_index.md | 5 + site/content/zh/latest/releases/v1.0.0.md | 179 ++++++++++++++++++++++ site/content/zh/latest/releases/v1.0.1.md | 29 ++++ 3 files changed, 213 insertions(+) create mode 100644 site/content/zh/latest/releases/_index.md create mode 100644 site/content/zh/latest/releases/v1.0.0.md create mode 100644 site/content/zh/latest/releases/v1.0.1.md diff --git a/site/content/zh/latest/releases/_index.md b/site/content/zh/latest/releases/_index.md new file mode 100644 index 000000000000..6a684ff59239 --- /dev/null +++ b/site/content/zh/latest/releases/_index.md @@ -0,0 +1,5 @@ +--- +title: "版本" +weight: 90 +description: 本节内容包含 Envoy Gateway 的版本。 +--- diff --git a/site/content/zh/latest/releases/v1.0.0.md b/site/content/zh/latest/releases/v1.0.0.md new file mode 100644 index 000000000000..f09638f64dd4 --- /dev/null +++ b/site/content/zh/latest/releases/v1.0.0.md @@ -0,0 +1,179 @@ +--- +title: "v1.0.0" +publishdate: 2024-03-13 +--- + +日期:2024 年 3 月 13 日 + +## 文档 {#documentation} + +- 新增了本地限流(Local Ratelimit)的用户指南 +- 新增了熔断(Circuit Breaker)的用户指南 +- 新增了故障注入(Fault Injection)的用户指南 +- 新增了 EnvoyProxy extraArgs 的用户指南 +- 新增了在 ClientTrafficPolicy 中超时的用户指南 +- 新增了基础路由的 JWT Claim 用户指南 +- 新增了 HTTP 超时的用户指南 +- 新增了在 BackendTrafficPolicy 中重试的用户指南 +- 新增了基础身份验证(Basic Auth)的用户指南 +- 新增了 OIDC 的用户指南 +- 新增了 ClientTrafficPolicy 的用户指南 +- 新增了 BackendTrafficPolicy 的用户指南 +- 新增了使用 HTTPS 的基础身份验证(Basic Auth)的用户指南 +- 新增外部鉴权(External Authorization)的用户指南 +- 新增了 Kubernetes 外部路由的用户指南 +- 新增了 BackendTLSPolicy 的用户指南 +- 新增了从外部客户端到网关的双向 TLS 的用户指南 +- 新增了使用自定义证书进行控制平面身份验证的用户指南 +- 新增了多 GatewayClass 和合并 Gateway 部署模式的用户指南 +- 为 CRD API 添加了 `Type` 和 `required` 的文档 +- 重构了用户指南文档的结构 +- 将设计文档移动到“参与”下并重构 +- 将 crd-ref-docs 更新至 0.0.10 +- 将 Envoy Proxy 镜像更新为 main 中的 envoy:distroless-dev + +## 安装 {#installation} + +- 新增了对从私有仓库中提取 envoyGateway 镜像的支持 +- 新增了为 certgen Job 配置资源的支持 +- 新增了为 EnvoyGateway Pod 配置亲和力的支持 + +## API {#api} + +- 在 ClientTrafficPolicy CRD 中添加了对下游 QUIC/HTTP3 的支持 +- 在 ClientTrafficPolicy CRD 中添加了对下游 MTLS 的支持 +- 在 ClientTrafficPolicy CRD 中添加了对 EnvoyHeaders 的启用支持 +- 在 ClientTrafficPolicy CRD 中添加了对 DisableMergeSlash 和 escapedSlashesAction 的支持 +- 在 ClientTrafficPolicy CRD 中添加了对 HTTP/1.1 中的 EnableTrailers 的支持 +- 在 ClientTrafficPolicy CRD 中添加了对 HTTP/1 上保留标头字母大小写的支持 +- 在 ClientTrafficPolicy CRD 中添加了对 HTTP/1.0 和 HTTP/0.9 启用的支持 +- 在 ClientTrafficPolicy CRD 中添加了对使用 XFF 进行客户端 IP 检测的支持 +- 在 ClientTrafficPolicy CRD 中添加了对使用自定义标头进行客户端 IP 检测的支持 +- 在 ClientTrafficPolicy CRD 中添加了对连接超时的支持 +- 在 ClientTrafficPolicy CRD 中添加了对常见 TLS 配置属性的支持 +- 在 ClientTrafficPolicy CRD 中添加了对代理协议的支持 +- 在 ClientTrafficPolicy CRD 中添加了对 TCPKeepAlive 的支持 +- 在 BackendTrafficPolicy CRD 中添加了对本地限流(Local Ratelimit)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对熔断(Circuit Breaker)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对故障注入(Fault Injection)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对被动健康检查(Passive Health Check)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对主动健康检查(Active Health Check)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对连接超时(Connection Timeout)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对压缩器/解压缩器(Compressor/Decompressor)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对重试(Retry)的支持 +- 在 BackendTrafficPolicy CRD 中添加了对慢启动模式的支持 +- 在 BackendTrafficPolicy CRD 中添加了对代理协议的支持 +- 在 BackendTrafficPolicy CRD 中添加了对 TCPKeepAlive 的支持 +- 在 BackendTrafficPolicy CRD 中添加了对 PolicyStatus 的支持 +- 在 ClientTrafficPolicy CRD 中添加了对 PolicyStatus 的支持 +- 在 SecurityPolicy CRD 中添加了对 PolicyStatus 的支持 +- 在 SecurityPolicy CRD 中添加了对 OIDC 的支持 +- 在 SecurityPolicy CRD 中添加了对基础身份验证(Basic Auth)的支持 +- 在 SecurityPolicy CRD 中添加了对 OIDC 的 RedirectURL 和 signoutPath 的支持 +- 在 SecurityPolicy CRD 中添加了对 ExtractFrom 标头和参数到 JWT 的支持 +- 在 SecurityPolicy CRD 中添加了对外部鉴权(External Authorization)的支持 +- 在 SecurityPolicy CRD 中添加了对 JWT 的 RecomputeRoute 字段的支持 +- 在 SecurityPolicy CRD 中添加了对 CORS 设置的 AllowCredentials 旋钮的支持 +- 在 SecurityPolicy CRD 中添加了对从不同标识符提取到 JWT 的支持 +- 在 EnvoyPatchPolicy CRD 中添加了对 Secret 资源的支持 +- 在 EnvoyPatchPolicy CRD 中添加了对 JSONPatchOperation 的值可选的支持 +- 在 EnvoyPatchPolicy CRD 中添加了对 JSONPatchOperation 中 `From` 字段的支持 +- 在 EnvoyPatchPolicy CRD 中添加了对 MergeGateways 的支持 +- 通过实施 BackendTLSPolicy CRD 添加了对上游 TLS 的支持 +- 在 EnvoyGateway 配置中添加了对 NamespaceSelectors 的 LabelSelector 类型的支持 +- 在 EnvoyGateway 配置中添加了对 Ratelimit Prometheus 的支持 +- 在 EnvoyProxy CRD 中添加了对 Pod 终止时 Envoy 关闭之前优雅地耗尽侦听器的支持 +- 在 EnvoyProxy CRD 中添加了对 Envoy 服务配置 externalTrafficPolicy 的支持 +- 在 EnvoyProxy CRD 中添加了对 Envoy 额外参数的支持 +- 在 EnvoyProxy CRD 中添加了对 Mergepatch 到 envoyproxy/ratelimit 部署的支持 +- 在 EnvoyProxy CRD 中添加了对 Mergepatch 到 envoyproxy 服务的支持 +- 在 EnvoyProxy CRD 中添加了对 NodeSelector 到 PodSpec 的支持 +- 在 EnvoyProxy CRD 中添加了对 HorizontalPodAutoscaler 的支持 +- 在 EnvoyProxy CRD 中添加了对 PodSpec 的 TopologySpreadConstraints 支持 +- 在 EnvoyProxy CRD 中添加了对 PodSpec 的 ImagePullSecrets 的支持 + +### 重大变化 {#breaking-changes} + +- 使用通配符将 AllowOrigins 与 SecurityPolicy CRD 中的 CORS 进行匹配 +- 删除 EnvoyProxy CRD 中的主机网络支持 + +## 一致性 {#conformance} + +- 将后端镜像从 gcr.io/k8s-staging-ingressconformance/echoserver 替换为 gcr.io/k8s-staging-gateway-api/echo-basic + +## 测试 {#testing} + +- 添加了标头中大小写保留的 e2e 测试 +- 添加了在 ClientTrafficPolicy 中超时的 e2e 测试 +- 添加了 JWT Claim 基础路由的 e2e 测试 +- 添加了 OIDC 的 e2e 测试 +- 添加了 BackendTrafficPolicy 重试(Retry)的 e2e 测试 +- 添加了后端升级的 e2e 测试 +- 添加了外部鉴权(External Authorization)的 e2e 测试 +- 添加了后端 TLS 策略的 e2e 测试 +- 添加了 Envoy Gateway 版本升级的 e2e 测试 +- 添加了加权后端的 e2e 测试 +- 添加了对 LoadBalancerIP 的验证以防止拖尾周期 + +## 转换器 {#translator} + +- 修复了前缀匹配,以防止具有相同前缀的路由匹配错误的问题 +- 通过为 ir.Infra 实现类似接口来修复多重调谐的问题 +- 修复了具有空条件 {} 的 EndpointSlice 问题 +- 修复了解析 http 请求超时时的错误处理 +- 修复了 EnvoyPatchPolicy 被禁用时无状态的问题 +- 修复了 xDS 和 infra IR 的可打印问题 +- 修复了跳过 backendRef 并将权重设置为 0 的问题 +- 修复了限流中的 AND 标头匹配不起作用的问题 +- 修复了不存在 GatewayClass 时的删除逻辑 +- 修复了 ClientTrafficPolicy 的 mergedGateway irKey 匹配问题 +- 修复了策略应仅被应用到 mergeGateway 为 true 的 Gateway 的问题 +- 修复了启用 mergeGateway 时不会显示网关侦听器状态的问题 +- 通过将 Web 套接字升级配置从 hcm 移动到路由,修复了 GRPCroute websocket 无法工作的问题 +- 修复了在 HTTPRoute 上设置超时时配置空闲超时的问题 +- 修复了 OIDC 令牌端点的放宽 HTTPS 限制 +- 修复了将路由转换到空的后端时出现的 Panic 问题 +- 修复了 xDS 转换应以最高效的方式完成 +- 修复了从监测中删除未被使用的状态键的问题 +- 修复了比较 Envoy Proxy 服务时忽略终结器的问题 +- 修复了如果 HTTP/3 被启用后不会覆盖 ALPN 数组的问题 +- 修复了启用 HTTP/3 时默认添加 h3 ALPN 的问题 +- 修复了 SecurityPolicy/BackendTrafficPolicy 的 Merge 行为,改为 Replace +- 修复了启用 HTTP/3 时在 alt-svc 标头中使用服务端口的问题 +- 修复了防止针对同一端口上的非 TLS 侦听器的策略发生冲突 +- 修复了跳过所有策略的 ReasonTargetNotFound +- 修复了跳过所有策略的空发布状态 +- 添加了在发送到 Envoy 之前正则表达式验证支持 +- 添加了当服务类型为 ClusterIP 时将 spec.addresses.value 设置为 ClusterIP 的支持 +- 为 BackendRef 中的过滤器添加了不支持的状态条件 +- 为 Provider 资源添加了 List 替代 Map,以保证稳定性 +- 添加了 OAuth Cookie 的后缀,以防止多个 OAuth 过滤器覆盖彼此的 Cookie +- 添加了对 BackendTrafficPolicy 和 SecurityPolicy 覆盖条件的支持 +- 添加了对默认重试预计量和重试主机判断的支持 +- 添加了对 gateway.spec.infrastructural 实现的支持 +- 添加了对多个后端的上游 TLS 的支持 +- 添加了在 ClientTrafficPolicy 中对 CA 证书验证的支持 + +## Provider {#providers} + +- 添加了对每个控制器多个 GatewayClass 的支持 +- 在 Kubernetes Provider 中添加了 SecurityPolicyIndexers +- 添加了对在 CertGen Job 中生成 HMAC 密钥的支持 +- 修复了删除 GatewayClass 时的 Finalizer 逻辑 +- 修复了重新启动控制平面时 MergeGateway 出现 Panic 的问题 + +## xDS {#xds} + +- 添加了对 EDS 缓存的支持 +- 添加了对 ADS 缓存的支持,以保证规则顺序 +- 修复了使用 RequestHeaderModifier 过滤器时出现的已弃用字段错误 +- 修复了 Envoy 在运行时拒绝 XDS 并在重新启动时丢失所有路由的问题 +- 修复了与定义的路由不匹配的请求触发每个路由过滤器的问题 +- 将 go-control-plane 升级至 v0.12.0 + +## Cli {#cli} + +- 添加了对 egctl x status 命令的支持 +- 添加了对 egctl experimental dashboard envoy-proxy 命令的支持 +- 添加了对 egctl config ratelimit 命令的支持 +- 添加了对从 gateway-api 资源到 IR 的 gctl translate from gateway-api 命令的支持 diff --git a/site/content/zh/latest/releases/v1.0.1.md b/site/content/zh/latest/releases/v1.0.1.md new file mode 100644 index 000000000000..d164d23d3022 --- /dev/null +++ b/site/content/zh/latest/releases/v1.0.1.md @@ -0,0 +1,29 @@ +--- +title: "v1.0.1" +publishdate: 2024-04-09 +--- + +日期:2024 年 4 月 9 日 + +## 安装 {#installation} + +- 将 EnvoyProxy 版本更新至 v1.29.3 +- 修复了 Certgen 以支持在升级期间创建 hmac 密钥 + +## 转换器 {#translator} + +- 修复了 ResourceVersionTable 中的 nil Secret 问题 +- 当启用 ClientTrafficPolicy 和 MergeGateway 时,将缺少的 HTTP 过滤器添加到 HTTP 过滤器链 +- 启用 URL 重写时允许 WebSocket +- 设置 HTTP 健康检查器的 Host 标头 +- 修复了重定向 URL 中的双斜杠 +- 允许 ClientTrafficPolicy 附加到同一网关内的多个 HTTP(非 HTTPS)侦听器 +- 为 HTTP Ext Auth 服务的路径设置前缀 +- 设置路由匹配优先顺序为 Exact > RegularExpression > PathPrefix +- 修复了被合并网关的 infraIR 重复端口转换 +- 将 SpawnUpstreamSpan 设置为 true +- 允许限流与多个监听器一起使用 + +## Infra-manager + +- 当 InfraIR 具有空侦听器时跳过创建基础设施资源 From e847d68c2665d471912d66250990937b73787dc6 Mon Sep 17 00:00:00 2001 From: shahar-h Date: Mon, 20 May 2024 05:49:19 +0300 Subject: [PATCH 15/25] ci: fix codecov upload issue (#3421) * ci: fix codecov upload issue Signed-off-by: Shahar Harari * remove trailing space Signed-off-by: Shahar Harari * simplify condition Signed-off-by: Shahar Harari --------- Signed-off-by: Shahar Harari --- .github/dependabot.yml | 2 -- .github/workflows/build_and_test.yaml | 11 +++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2f37284cf4a6..c7a5bee84ffd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -20,8 +20,6 @@ updates: ignore: # skip to update retest, because it won't work with the latest version - dependency-name: "envoyproxy/toolshed/gh-actions/retest" - # skip until https://github.com/codecov/feedback/issues/112 is resolved - - dependency-name: "codecov/codecov-action" - package-ecosystem: github-actions directory: /tools/github-actions/setup-deps schedule: diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index e812062f3298..4f53f7f30a8f 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -44,6 +44,9 @@ jobs: coverage-test: runs-on: ubuntu-latest + permissions: + contents: read # for actions/checkout + id-token: write # for fetching OIDC token steps: - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: ./tools/github-actions/setup-deps @@ -52,12 +55,16 @@ jobs: - name: Run Coverage Tests run: make go.test.coverage - name: Upload coverage to Codecov - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # v3.1.5 + uses: codecov/codecov-action@6d798873df2b1b8e5846dba6fb86631229fbcb17 # v4.4.0 with: - fail_ci_if_error: false + fail_ci_if_error: true files: ./coverage.xml name: codecov-envoy-gateway verbose: true + # only use oidc for push events or PRs from the same repo, since PRs from forks cannot fetch an OIDC token + # Codecov supports Token-less Uploads for PRs from forks: + # https://docs.codecov.com/docs/codecov-uploader#supporting-token-less-uploads-for-forks-of-open-source-repos-using-codecov + use_oidc: ${{ github.event_name == 'push' }} build: runs-on: ubuntu-latest From dedc4464e9041a4610bcc8fe189496a637c50714 Mon Sep 17 00:00:00 2001 From: shahar-h Date: Mon, 20 May 2024 09:40:44 +0300 Subject: [PATCH 16/25] ci: fix codecov upload on dependabot PRs (#3439) Signed-off-by: Shahar Harari --- .github/workflows/build_and_test.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index 4f53f7f30a8f..d5714c531ffd 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -61,10 +61,8 @@ jobs: files: ./coverage.xml name: codecov-envoy-gateway verbose: true - # only use oidc for push events or PRs from the same repo, since PRs from forks cannot fetch an OIDC token - # Codecov supports Token-less Uploads for PRs from forks: - # https://docs.codecov.com/docs/codecov-uploader#supporting-token-less-uploads-for-forks-of-open-source-repos-using-codecov - use_oidc: ${{ github.event_name == 'push' }} + # TODO change to `use_oidc: true` once https://github.com/codecov/codecov-action/issues/1435 is resolved. + use_oidc: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }} build: runs-on: ubuntu-latest From 8206e11d7ed3a04722b847f936437af66552cdef Mon Sep 17 00:00:00 2001 From: xu0o0 Date: Mon, 20 May 2024 14:46:50 +0800 Subject: [PATCH 17/25] fix(translator): set ignoreCase for header matchers in extAuth (#3420) fix: set ignoreCase for header matchers in extAuth Signed-off-by: haoqixu --- internal/xds/translator/extauth.go | 2 ++ .../translator/testdata/out/xds-ir/ext-auth.listeners.yaml | 4 ++++ ...-listeners-same-port-with-different-filters.listeners.yaml | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go index 0d8edfce2420..46ce5df80e46 100644 --- a/internal/xds/translator/extauth.go +++ b/internal/xds/translator/extauth.go @@ -113,6 +113,7 @@ func extAuthConfig(extAuth *ir.ExtAuth) *extauthv3.ExtAuthz { MatchPattern: &matcherv3.StringMatcher_Exact{ Exact: header, }, + IgnoreCase: true, }) } @@ -178,6 +179,7 @@ func httpService(http *ir.HTTPExtAuthService) *extauthv3.HttpService { MatchPattern: &matcherv3.StringMatcher_Exact{ Exact: header, }, + IgnoreCase: true, }) } diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml index 083a4a6f3f1d..1c2ed9d00136 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml @@ -21,7 +21,9 @@ allowedHeaders: patterns: - exact: header1 + ignoreCase: true - exact: header2 + ignoreCase: true grpcService: envoyGrpc: authority: grpc-backend.default:9000 @@ -38,7 +40,9 @@ allowedUpstreamHeaders: patterns: - exact: header1 + ignoreCase: true - exact: header2 + ignoreCase: true pathPrefix: /auth serverUri: cluster: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml index cec7fd427dbf..1365c290cb7e 100755 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.listeners.yaml @@ -27,7 +27,9 @@ allowedUpstreamHeaders: patterns: - exact: header1 + ignoreCase: true - exact: header2 + ignoreCase: true pathPrefix: /auth serverUri: cluster: securitypolicy/default/policy-for-http-route-2/envoy-gateway/http-backend @@ -86,7 +88,9 @@ allowedUpstreamHeaders: patterns: - exact: header1 + ignoreCase: true - exact: header2 + ignoreCase: true pathPrefix: /auth serverUri: cluster: securitypolicy/default/policy-for-http-route-2/envoy-gateway/http-backend From 8ca2675227ea50bb95314df855ead4c7c700de5d Mon Sep 17 00:00:00 2001 From: sh2 Date: Mon, 20 May 2024 17:28:21 +0800 Subject: [PATCH 18/25] feat: add metrics instrumentation for xds server (#3393) * add metrics instrumentation for xds server Signed-off-by: shawnh2 * add histogram metrics type for xds stream duration Signed-off-by: shawnh2 --------- Signed-off-by: shawnh2 --- internal/xds/cache/metrics.go | 23 +++++++++++ internal/xds/cache/snapshotcache.go | 62 ++++++++++++++++++++++------ internal/xds/server/runner/runner.go | 3 +- 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 internal/xds/cache/metrics.go diff --git a/internal/xds/cache/metrics.go b/internal/xds/cache/metrics.go new file mode 100644 index 000000000000..3480b9c4088f --- /dev/null +++ b/internal/xds/cache/metrics.go @@ -0,0 +1,23 @@ +// 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 cache + +import "github.com/envoyproxy/gateway/internal/metrics" + +var ( + xdsSnapshotCreationTotal = metrics.NewCounter("xds_snapshot_creation_total", "Total number of xds snapshot cache creation.") + xdsSnapshotCreationFailed = metrics.NewCounter("xds_snapshot_creation_failed", "Number of xds snapshot cache creation that failed.") + xdsSnapshotCreationSuccess = metrics.NewCounter("xds_snapshot_creation_success", "Number of xds snapshot cache creation that succeeded.") + + xdsSnapshotUpdateTotal = metrics.NewCounter("xds_snapshot_update_total", "Total number of xds snapshot cache updates by node id.") + xdsSnapshotUpdateFailed = metrics.NewCounter("xds_snapshot_update_failed", "Number of xds snapshot cache updates that failed by node id.") + xdsSnapshotUpdateSuccess = metrics.NewCounter("xds_snapshot_update_success", "Number of xds snapshot cache updates that succeeded by node id.") + nodeIDLabel = metrics.NewLabel("nodeID") + + xdsStreamDurationSeconds = metrics.NewHistogram("xds_stream_duration_seconds", "How long a xds stream takes to finish.", []float64{0.1, 10, 50, 100, 1000, 10000}) + xdsDeltaStreamDurationSeconds = metrics.NewHistogram("xds_delta_stream_duration_seconds", "How long a xds delta stream takes to finish.", []float64{0.1, 10, 50, 100, 1000, 10000}) + streamIDLabel = metrics.NewLabel("streamID") +) diff --git a/internal/xds/cache/snapshotcache.go b/internal/xds/cache/snapshotcache.go index bd3b22fb2849..383aad836f70 100644 --- a/internal/xds/cache/snapshotcache.go +++ b/internal/xds/cache/snapshotcache.go @@ -19,6 +19,7 @@ import ( "math" "strconv" "sync" + "time" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" discoveryv3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" @@ -51,13 +52,17 @@ type snapshotMap map[string]*cachev3.Snapshot type nodeInfoMap map[int64]*corev3.Node +type streamDurationMap map[int64]time.Time + type snapshotCache struct { cachev3.SnapshotCache - streamIDNodeInfo nodeInfoMap - snapshotVersion int64 - lastSnapshot snapshotMap - log *zap.SugaredLogger - mu sync.Mutex + streamIDNodeInfo nodeInfoMap + streamDuration streamDurationMap + deltaStreamDuration streamDurationMap + snapshotVersion int64 + lastSnapshot snapshotMap + log *zap.SugaredLogger + mu sync.Mutex } // GenerateNewSnapshot takes a table of resources (the output from the IR->xDS @@ -73,17 +78,26 @@ func (s *snapshotCache) GenerateNewSnapshot(irKey string, resources types.XdsRes version, resources, ) + + xdsSnapshotCreationTotal.Increment() if err != nil { + xdsSnapshotCreationFailed.Increment() return err + } else { + xdsSnapshotCreationSuccess.Increment() } s.lastSnapshot[irKey] = snapshot for _, node := range s.getNodeIDs(irKey) { s.log.Debugf("Generating a snapshot with Node %s", node) - err := s.SetSnapshot(context.TODO(), node, snapshot) - if err != nil { + xdsSnapshotUpdateTotal.With(nodeIDLabel.Value(node)).Increment() + + if err = s.SetSnapshot(context.TODO(), node, snapshot); err != nil { + xdsSnapshotUpdateFailed.With(nodeIDLabel.Value(node)).Increment() return err + } else { + xdsSnapshotUpdateSuccess.With(nodeIDLabel.Value(node)).Increment() } } @@ -110,10 +124,12 @@ func NewSnapshotCache(ads bool, logger logging.Logger) SnapshotCacheWithCallback // Set up the nasty wrapper hack. wrappedLogger := logger.Sugar() return &snapshotCache{ - SnapshotCache: cachev3.NewSnapshotCache(ads, &Hash, wrappedLogger), - log: wrappedLogger, - lastSnapshot: make(snapshotMap), - streamIDNodeInfo: make(nodeInfoMap), + SnapshotCache: cachev3.NewSnapshotCache(ads, &Hash, wrappedLogger), + log: wrappedLogger, + lastSnapshot: make(snapshotMap), + streamIDNodeInfo: make(nodeInfoMap), + streamDuration: make(streamDurationMap), + deltaStreamDuration: make(streamDurationMap), } } @@ -137,16 +153,26 @@ func (s *snapshotCache) OnStreamOpen(_ context.Context, streamID int64, _ string defer s.mu.Unlock() s.streamIDNodeInfo[streamID] = nil + s.streamDuration[streamID] = time.Now() return nil } -func (s *snapshotCache) OnStreamClosed(streamID int64, _ *corev3.Node) { +func (s *snapshotCache) OnStreamClosed(streamID int64, node *corev3.Node) { // TODO: something with the node? s.mu.Lock() defer s.mu.Unlock() + if startTime, ok := s.streamDuration[streamID]; ok { + streamDuration := time.Since(startTime) + xdsStreamDurationSeconds.With( + streamIDLabel.Value(strconv.FormatInt(streamID, 10)), + nodeIDLabel.Value(node.Id), + ).Record(streamDuration.Seconds()) + } + delete(s.streamIDNodeInfo, streamID) + delete(s.streamDuration, streamID) } func (s *snapshotCache) OnStreamRequest(streamID int64, req *discoveryv3.DiscoveryRequest) error { @@ -229,16 +255,26 @@ func (s *snapshotCache) OnDeltaStreamOpen(_ context.Context, streamID int64, _ s // Ensure that we're adding the streamID to the Node ID list. s.streamIDNodeInfo[streamID] = nil + s.deltaStreamDuration[streamID] = time.Now() return nil } -func (s *snapshotCache) OnDeltaStreamClosed(streamID int64, _ *corev3.Node) { +func (s *snapshotCache) OnDeltaStreamClosed(streamID int64, node *corev3.Node) { // TODO: something with the node? s.mu.Lock() defer s.mu.Unlock() + if startTime, ok := s.deltaStreamDuration[streamID]; ok { + deltaStreamDuration := time.Since(startTime) + xdsDeltaStreamDurationSeconds.With( + streamIDLabel.Value(strconv.FormatInt(streamID, 10)), + nodeIDLabel.Value(node.Id), + ).Record(deltaStreamDuration.Seconds()) + } + delete(s.streamIDNodeInfo, streamID) + delete(s.deltaStreamDuration, streamID) } func (s *snapshotCache) OnStreamDeltaRequest(streamID int64, req *discoveryv3.DeltaDiscoveryRequest) error { diff --git a/internal/xds/server/runner/runner.go b/internal/xds/server/runner/runner.go index 28c203a86341..f0812752524c 100644 --- a/internal/xds/server/runner/runner.go +++ b/internal/xds/server/runner/runner.go @@ -16,8 +16,6 @@ import ( "strconv" "time" - "google.golang.org/grpc/keepalive" - clusterv3 "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3" discoveryv3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" endpointv3 "github.com/envoyproxy/go-control-plane/envoy/service/endpoint/v3" @@ -28,6 +26,7 @@ import ( serverv3 "github.com/envoyproxy/go-control-plane/pkg/server/v3" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/keepalive" "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway/config" From 711d54521ab3e23d92081fe6270d6003bc52ce77 Mon Sep 17 00:00:00 2001 From: Ardika Date: Mon, 20 May 2024 22:21:33 +0700 Subject: [PATCH 19/25] feat: PreserveExternalRequestID on ClientTrafficPolicy (#3225) * feat: PreserveExternalRequestID on ClientTrafficPolicy Signed-off-by: Ardika Bagus * chore: rename it to PreserveXRequestID Signed-off-by: Ardika Bagus --------- Signed-off-by: Ardika Bagus --- api/v1alpha1/clienttrafficpolicy_types.go | 7 ++ api/v1alpha1/zz_generated.deepcopy.go | 5 ++ ...y.envoyproxy.io_clienttrafficpolicies.yaml | 6 ++ internal/gatewayapi/clienttrafficpolicy.go | 1 + .../clienttrafficpolicy-headers.in.yaml | 1 + .../clienttrafficpolicy-headers.out.yaml | 3 + internal/ir/xds.go | 5 ++ internal/xds/translator/listener.go | 3 +- .../headers-with-preserve-x-request-id.yaml | 32 +++++++++ ...s-with-preserve-x-request-id.clusters.yaml | 34 ++++++++++ ...-with-preserve-x-request-id.endpoints.yaml | 24 +++++++ ...-with-preserve-x-request-id.listeners.yaml | 65 +++++++++++++++++++ ...ers-with-preserve-x-request-id.routes.yaml | 28 ++++++++ site/content/en/latest/api/extension_types.md | 1 + 14 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml create mode 100755 internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 440c01c6c988..ea9d79018983 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -108,6 +108,13 @@ type HeaderSettings struct { // is encountered. The default action is to reject the request. // +optional WithUnderscoresAction *WithUnderscoresAction `json:"withUnderscoresAction,omitempty"` + + // PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge + // (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. + // It defaults to false. + // + // +optional + PreserveXRequestID *bool `json:"preserveXRequestID,omitempty"` } // WithUnderscoresAction configures the action to take when an HTTP header with underscores diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index fd607c16af7e..7aa98ab9f57d 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -2473,6 +2473,11 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = new(WithUnderscoresAction) **out = **in } + if in.PreserveXRequestID != nil { + in, out := &in.PreserveXRequestID, &out.PreserveXRequestID + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index a9d3fb95fcf1..6d4805ca0b80 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -147,6 +147,12 @@ spec: EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests and responses. type: boolean + preserveXRequestID: + description: |- + PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge + (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. + It defaults to false. + type: boolean withUnderscoresAction: description: |- WithUnderscoresAction configures the action to take when an HTTP header with underscores diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 8cc054dee71b..f5465fcd798d 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -547,6 +547,7 @@ func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, http httpIR.Headers = &ir.HeaderSettings{ EnableEnvoyHeaders: ptr.Deref(headerSettings.EnableEnvoyHeaders, false), WithUnderscoresAction: ir.WithUnderscoresAction(ptr.Deref(headerSettings.WithUnderscoresAction, egv1a1.WithUnderscoresActionRejectRequest)), + PreserveXRequestID: ptr.Deref(headerSettings.PreserveXRequestID, false), } } diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml index c21285612d99..6d73bee1a160 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml @@ -8,6 +8,7 @@ clientTrafficPolicies: headers: enableEnvoyHeaders: true withUnderscoresAction: Allow + preserveXRequestID: true targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml index 8fa939ac327c..8b184cbbabc9 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml @@ -8,6 +8,7 @@ clientTrafficPolicies: spec: headers: enableEnvoyHeaders: true + preserveXRequestID: true withUnderscoresAction: Allow targetRef: group: gateway.networking.k8s.io @@ -129,6 +130,7 @@ xdsIR: - address: 0.0.0.0 headers: enableEnvoyHeaders: true + preserveXRequestID: true withUnderscoresAction: Allow hostnames: - '*' @@ -141,6 +143,7 @@ xdsIR: - address: 0.0.0.0 headers: enableEnvoyHeaders: true + preserveXRequestID: true withUnderscoresAction: Allow hostnames: - '*' diff --git a/internal/ir/xds.go b/internal/ir/xds.go index b77d26cf7590..5b8af16c93c8 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -423,6 +423,11 @@ type HeaderSettings struct { // is encountered. The default action is to reject the request. // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-enum-config-core-v3-httpprotocoloptions-headerswithunderscoresaction WithUnderscoresAction WithUnderscoresAction `json:"withUnderscoresAction,omitempty" yaml:"withUnderscoresAction,omitempty"` + + // PreserveXRequestID configures whether Envoy will keep the x-request-id header if passed for a request that is edge + // (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. + // It defaults to false. + PreserveXRequestID bool `json:"preserveXRequestID,omitempty" yaml:"preserveXRequestID,omitempty"` } // ClientTimeout sets the timeout configuration for downstream connections diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index a86bff57fd96..ada6ee454d7c 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -260,7 +260,8 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis CommonHttpProtocolOptions: &corev3.HttpProtocolOptions{ HeadersWithUnderscoresAction: buildHeadersWithUnderscoresAction(irListener.Headers), }, - Tracing: hcmTracing, + Tracing: hcmTracing, + PreserveExternalRequestId: ptr.Deref(irListener.Headers, ir.HeaderSettings{}).PreserveXRequestID, } if irListener.Timeout != nil && irListener.Timeout.HTTP != nil { diff --git a/internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml b/internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml new file mode 100644 index 000000000000..1376be42e146 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/headers-with-preserve-x-request-id.yaml @@ -0,0 +1,32 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 8081 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 8081 + headers: + preserveXRequestID: true +- name: "second-listener" + address: "0.0.0.0" + port: 8082 + hostnames: + - "*" + routes: + - name: "second-route" + hostname: "*" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "2.2.2.2" + port: 8082 + diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml new file mode 100755 index 000000000000..d65e267ad7de --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.clusters.yaml @@ -0,0 +1,34 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml new file mode 100755 index 000000000000..9ad09dd91b0d --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.endpoints.yaml @@ -0,0 +1,24 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 8081 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 8082 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml new file mode 100644 index 000000000000..880644d46776 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.listeners.yaml @@ -0,0 +1,65 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8081 + 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: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + normalizePath: true + preserveExternalRequestId: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: first-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8082 + 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: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + normalizePath: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: second-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml new file mode 100755 index 000000000000..ff93cfff360b --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/headers-with-preserve-x-request-id.routes.yaml @@ -0,0 +1,28 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 6ac4fe6b123b..fdbd7bc827d3 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1797,6 +1797,7 @@ _Appears in:_ | --- | --- | --- | --- | | `enableEnvoyHeaders` | _boolean_ | false | EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests
and responses. | | `withUnderscoresAction` | _[WithUnderscoresAction](#withunderscoresaction)_ | false | WithUnderscoresAction configures the action to take when an HTTP header with underscores
is encountered. The default action is to reject the request. | +| `preserveXRequestID` | _boolean_ | false | PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge
(Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour.
It defaults to false. | #### HealthCheck From d49f984d990eb6045117066b7fe19ca7cd61a92e Mon Sep 17 00:00:00 2001 From: Vladimir <31961982+zvlb@users.noreply.github.com> Date: Mon, 20 May 2024 19:47:08 +0300 Subject: [PATCH 20/25] feat: add knob for switching container port (#3333) add feature disablePortShift Signed-off-by: zvlb --- api/v1alpha1/envoyproxy_helpers.go | 17 +++++++ api/v1alpha1/envoyproxy_types.go | 7 +++ api/v1alpha1/zz_generated.deepcopy.go | 5 ++ .../gateway.envoyproxy.io_envoyproxies.yaml | 6 +++ internal/gatewayapi/helpers.go | 9 +++- internal/gatewayapi/listener.go | 8 ++-- internal/gatewayapi/translator_test.go | 46 ++++++++++++++++++- internal/ir/infra.go | 4 +- site/content/en/latest/api/extension_types.md | 1 + 9 files changed, 95 insertions(+), 8 deletions(-) diff --git a/api/v1alpha1/envoyproxy_helpers.go b/api/v1alpha1/envoyproxy_helpers.go index 2bcc086cbba9..03f50d9c9e36 100644 --- a/api/v1alpha1/envoyproxy_helpers.go +++ b/api/v1alpha1/envoyproxy_helpers.go @@ -57,6 +57,23 @@ func DefaultEnvoyProxyHpaMetrics() []autoscalingv2.MetricSpec { } } +// NeedToSwitchPorts returns true if the EnvoyProxy needs to switch ports. +func (e *EnvoyProxy) NeedToSwitchPorts() bool { + if e.Spec.Provider == nil { + return true + } + + if e.Spec.Provider.Kubernetes == nil { + return true + } + + if e.Spec.Provider.Kubernetes.UseListenerPortAsContainerPort == nil { + return true + } + + return !*e.Spec.Provider.Kubernetes.UseListenerPortAsContainerPort +} + // GetEnvoyProxyKubeProvider returns the EnvoyProxyKubernetesProvider of EnvoyProxyProvider or // a default EnvoyProxyKubernetesProvider if unspecified. If EnvoyProxyProvider is not of // type "Kubernetes", a nil EnvoyProxyKubernetesProvider is returned. diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index d8afe76ca788..8ccf37460e4d 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -264,6 +264,13 @@ type EnvoyProxyKubernetesProvider struct { // // +optional EnvoyHpa *KubernetesHorizontalPodAutoscalerSpec `json:"envoyHpa,omitempty"` + + // UseListenerPortAsContainerPort disables the port shifting feature in the Envoy Proxy. + // When set to false (default value), if the service port is a privileged port (1-1023), add a constant to the value converting it into an ephemeral port. + // This allows the container to bind to the port without needing a CAP_NET_BIND_SERVICE capability. + // + // +optional + UseListenerPortAsContainerPort *bool `json:"useListenerPortAsContainerPort,omitempty"` } // ProxyLogging defines logging parameters for managed proxies. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 7aa98ab9f57d..1456fde63eb8 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1646,6 +1646,11 @@ func (in *EnvoyProxyKubernetesProvider) DeepCopyInto(out *EnvoyProxyKubernetesPr *out = new(KubernetesHorizontalPodAutoscalerSpec) (*in).DeepCopyInto(*out) } + if in.UseListenerPortAsContainerPort != nil { + in, out := &in.UseListenerPortAsContainerPort, &out.UseListenerPortAsContainerPort + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxyKubernetesProvider. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index 0282aed70d0d..08042e02d71c 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -9980,6 +9980,12 @@ spec: - message: loadBalancerIP can only be set for LoadBalancer type rule: '!has(self.loadBalancerIP) || self.type == ''LoadBalancer''' + useListenerPortAsContainerPort: + description: |- + UseListenerPortAsContainerPort disables the port shifting feature in the Envoy Proxy. + When set to false (default value), if the service port is a privileged port (1-1023), add a constant to the value converting it into an ephemeral port. + This allows the container to bind to the port without needing a CAP_NET_BIND_SERVICE capability. + type: boolean type: object x-kubernetes-validations: - message: only one of envoyDeployment or envoyDaemonSet can be diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index 2dfc04a18428..0e2b6b45afd3 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -17,6 +17,7 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/utils" ) @@ -228,7 +229,13 @@ func GatewayClassOwnerLabel(name string) map[string]string { // servicePortToContainerPort translates a service port into an ephemeral // container port. -func servicePortToContainerPort(servicePort int32) int32 { +func servicePortToContainerPort(servicePort int32, envoyProxy *egv1a1.EnvoyProxy) int32 { + if envoyProxy != nil { + if !envoyProxy.NeedToSwitchPorts() { + return servicePort + } + } + // If the service port is a privileged port (1-1023) // add a constant to the value converting it into an ephemeral port. // This allows the container to bind to the port without needing a diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index 62d60b75f1f5..0eb383c90cd4 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -95,7 +95,7 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR XdsIRMap } // Add the listener to the Xds IR servicePort := &protocolPort{protocol: listener.Protocol, port: int32(listener.Port)} - containerPort := servicePortToContainerPort(servicePort.port) + containerPort := servicePortToContainerPort(int32(listener.Port), resources.EnvoyProxy) switch listener.Protocol { case gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType: irListener := &ir.HTTPListener{ @@ -136,7 +136,7 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR XdsIRMap // Add the listener to the Infra IR. Infra IR ports must have a unique port number per layer-4 protocol // (TCP or UDP). if !containsPort(foundPorts[irKey], servicePort) { - t.processInfraIRListener(listener, infraIR, irKey, servicePort) + t.processInfraIRListener(listener, infraIR, irKey, servicePort, containerPort) foundPorts[irKey] = append(foundPorts[irKey], servicePort) } } @@ -149,7 +149,7 @@ func (t *Translator) processProxyObservability(gw *gwapiv1.Gateway, xdsIR *ir.Xd xdsIR.Metrics = processMetrics(envoyProxy) } -func (t *Translator) processInfraIRListener(listener *ListenerContext, infraIR InfraIRMap, irKey string, servicePort *protocolPort) { +func (t *Translator) processInfraIRListener(listener *ListenerContext, infraIR InfraIRMap, irKey string, servicePort *protocolPort, containerPort int32) { var proto ir.ProtocolType switch listener.Protocol { case gwapiv1.HTTPProtocolType: @@ -168,7 +168,7 @@ func (t *Translator) processInfraIRListener(listener *ListenerContext, infraIR I Name: irListenerPortName(proto, servicePort.port), Protocol: proto, ServicePort: servicePort.port, - ContainerPort: servicePortToContainerPort(servicePort.port), + ContainerPort: containerPort, } proxyListener := &ir.ProxyListener{ diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index 23ade13da9be..1a200555ba25 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -679,27 +679,71 @@ func TestServicePortToContainerPort(t *testing.T) { testCases := []struct { servicePort int32 containerPort int32 + envoyProxy *egv1a1.EnvoyProxy }{ { servicePort: 99, containerPort: 10099, + envoyProxy: nil, }, { servicePort: 1023, containerPort: 11023, + envoyProxy: nil, }, { servicePort: 1024, containerPort: 1024, + envoyProxy: nil, }, { servicePort: 8080, containerPort: 8080, + envoyProxy: nil, + }, + { + servicePort: 99, + containerPort: 10099, + envoyProxy: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + }, + }, + }, + }, + { + servicePort: 99, + containerPort: 10099, + envoyProxy: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + UseListenerPortAsContainerPort: ptr.To(false), + }, + }, + }, + }, + }, + { + servicePort: 99, + containerPort: 99, + envoyProxy: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + UseListenerPortAsContainerPort: ptr.To(true), + }, + }, + }, + }, }, } for _, tc := range testCases { - got := servicePortToContainerPort(tc.servicePort) + got := servicePortToContainerPort(tc.servicePort, tc.envoyProxy) assert.Equal(t, tc.containerPort, got) } } diff --git a/internal/ir/infra.go b/internal/ir/infra.go index 60a26bddcc2a..52672be64b12 100644 --- a/internal/ir/infra.go +++ b/internal/ir/infra.go @@ -222,8 +222,8 @@ func (p *ProxyInfra) Validate() error { if listener.Ports[j].ServicePort < 1 || listener.Ports[j].ServicePort > 65353 { errs = append(errs, errors.New("listener service port must be a valid port number")) } - if listener.Ports[j].ContainerPort < 1024 || listener.Ports[j].ContainerPort > 65353 { - errs = append(errs, errors.New("listener container port must be a valid ephemeral port number")) + if listener.Ports[j].ContainerPort < 1 || listener.Ports[j].ContainerPort > 65353 { + errs = append(errs, errors.New("listener container port must be a valid port number")) } } } diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index fdbd7bc827d3..1e3391760b7b 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1233,6 +1233,7 @@ _Appears in:_ | `envoyDaemonSet` | _[KubernetesDaemonSetSpec](#kubernetesdaemonsetspec)_ | false | EnvoyDaemonSet defines the desired state of the Envoy daemonset resource.
Disabled by default, a deployment resource is used instead to provision the Envoy Proxy fleet | | `envoyService` | _[KubernetesServiceSpec](#kubernetesservicespec)_ | false | EnvoyService defines the desired state of the Envoy service resource.
If unspecified, default settings for the managed Envoy service resource
are applied. | | `envoyHpa` | _[KubernetesHorizontalPodAutoscalerSpec](#kuberneteshorizontalpodautoscalerspec)_ | false | EnvoyHpa defines the Horizontal Pod Autoscaler settings for Envoy Proxy Deployment.
Once the HPA is being set, Replicas field from EnvoyDeployment will be ignored. | +| `useListenerPortAsContainerPort` | _boolean_ | false | UseListenerPortAsContainerPort disables the port shifting feature in the Envoy Proxy.
When set to false (default value), if the service port is a privileged port (1-1023), add a constant to the value converting it into an ephemeral port.
This allows the container to bind to the port without needing a CAP_NET_BIND_SERVICE capability. | #### EnvoyProxyProvider From 95e2e3569953f5f4be74f55d9b1e6777d6e9d241 Mon Sep 17 00:00:00 2001 From: Lior Okman Date: Mon, 20 May 2024 19:51:02 +0300 Subject: [PATCH 21/25] bug: Route extension filters with different types but the same name and namespace aren't correctly cached (#3388) * Route extension filters are unstructured.Unstructured instances, so caching them should be done with both the name and type as a key. Signed-off-by: Lior Okman * Moved NamespacedNameAndType to the Kubernetes helpers, and renamed it to be clearer about what it has. Signed-off-by: Lior Okman * Also renamed the helper function. Signed-off-by: Lior Okman * Moved to the 'utils' package to be beside NamespacedName. Signed-off-by: Lior Okman * Renamed structure according to review, and updated the comments Signed-off-by: Lior Okman --------- Signed-off-by: Lior Okman --- internal/provider/kubernetes/controller.go | 6 +- internal/provider/kubernetes/routes.go | 27 +++-- internal/provider/kubernetes/routes_test.go | 110 +++++++++++++++++++- internal/utils/misc.go | 20 ++++ 4 files changed, 149 insertions(+), 14 deletions(-) diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 1852384de4da..0c33873c1df6 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -129,9 +129,9 @@ type resourceMappings struct { // Map for storing backendRefs' NamespaceNames referred by various Route objects. allAssociatedBackendRefs map[gwapiv1.BackendObjectReference]struct{} // extensionRefFilters is a map of filters managed by an extension. - // The key is the namespaced name of the filter and the value is the + // The key is the namespaced name, group and kind of the filter and the value is the // unstructured form of the resource. - extensionRefFilters map[types.NamespacedName]unstructured.Unstructured + extensionRefFilters map[utils.NamespacedNameWithGroupKind]unstructured.Unstructured } func newResourceMapping() *resourceMappings { @@ -143,7 +143,7 @@ func newResourceMapping() *resourceMappings { allAssociatedTCPRoutes: map[string]struct{}{}, allAssociatedUDPRoutes: map[string]struct{}{}, allAssociatedBackendRefs: map[gwapiv1.BackendObjectReference]struct{}{}, - extensionRefFilters: map[types.NamespacedName]unstructured.Unstructured{}, + extensionRefFilters: map[utils.NamespacedNameWithGroupKind]unstructured.Unstructured{}, } } diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index f72d1b2cfa2c..76991be9947d 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -185,10 +185,17 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam if filter.Type == gwapiv1.GRPCRouteFilterExtensionRef { // NOTE: filters must be in the same namespace as the GRPCRoute // Check if it's a Kind managed by an extension and add to resourceTree - key := types.NamespacedName{ - Namespace: grpcRoute.Namespace, - Name: string(filter.ExtensionRef.Name), + key := utils.NamespacedNameWithGroupKind{ + NamespacedName: types.NamespacedName{ + Namespace: grpcRoute.Namespace, + Name: string(filter.ExtensionRef.Name), + }, + GroupKind: schema.GroupKind{ + Group: string(filter.ExtensionRef.Group), + Kind: string(filter.ExtensionRef.Kind), + }, } + extRefFilter, ok := resourceMap.extensionRefFilters[key] if !ok { r.log.Error( @@ -229,7 +236,7 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam } for i := range extensionRefFilters { filter := extensionRefFilters[i] - resourceMap.extensionRefFilters[utils.NamespacedName(&filter)] = filter + resourceMap.extensionRefFilters[utils.GetNamespacedNameWithGroupKind(&filter)] = filter } if err := r.client.List(ctx, httpRouteList, &client.ListOptions{ @@ -367,9 +374,15 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam } else if filter.Type == gwapiv1.HTTPRouteFilterExtensionRef { // NOTE: filters must be in the same namespace as the HTTPRoute // Check if it's a Kind managed by an extension and add to resourceTree - key := types.NamespacedName{ - Namespace: httpRoute.Namespace, - Name: string(filter.ExtensionRef.Name), + key := utils.NamespacedNameWithGroupKind{ + NamespacedName: types.NamespacedName{ + Namespace: httpRoute.Namespace, + Name: string(filter.ExtensionRef.Name), + }, + GroupKind: schema.GroupKind{ + Group: string(filter.ExtensionRef.Group), + Kind: string(filter.ExtensionRef.Kind), + }, } extRefFilter, ok := resourceMap.extensionRefFilters[key] if !ok { diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go index 9a230e6824b2..be6769589a15 100644 --- a/internal/provider/kubernetes/routes_test.go +++ b/internal/provider/kubernetes/routes_test.go @@ -120,6 +120,102 @@ func TestProcessHTTPRoutes(t *testing.T) { }, expected: true, }, + { + name: "httproute with extension filter multiple types same name", + routes: []*gwapiv1.HTTPRoute{ + { + ObjectMeta: metav1.ObjectMeta{ + Namespace: httpRouteNS, + Name: "test", + }, + Spec: gwapiv1.HTTPRouteSpec{ + CommonRouteSpec: gwapiv1.CommonRouteSpec{ + ParentRefs: []gwapiv1.ParentReference{ + { + Name: "test", + }, + }, + }, + Rules: []gwapiv1.HTTPRouteRule{ + { + Matches: []gwapiv1.HTTPRouteMatch{ + { + Path: &gwapiv1.HTTPPathMatch{ + Type: ptr.To(gwapiv1.PathMatchPathPrefix), + Value: ptr.To("/"), + }, + }, + }, + Filters: []gwapiv1.HTTPRouteFilter{ + { + Type: gwapiv1.HTTPRouteFilterExtensionRef, + ExtensionRef: &gwapiv1.LocalObjectReference{ + Group: gwapiv1.Group("gateway.example.io"), + Kind: gwapiv1.Kind("Bar"), + Name: gwapiv1.ObjectName("test"), + }, + }, + { + Type: gwapiv1.HTTPRouteFilterExtensionRef, + ExtensionRef: &gwapiv1.LocalObjectReference{ + Group: gwapiv1.Group("gateway.example.io"), + Kind: gwapiv1.Kind("Foo"), + Name: gwapiv1.ObjectName("test"), + }, + }, + }, + BackendRefs: []gwapiv1.HTTPBackendRef{ + { + BackendRef: gwapiv1.BackendRef{ + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: gatewayapi.GroupPtr(corev1.GroupName), + Kind: gatewayapi.KindPtr(gatewayapi.KindService), + Name: "test", + }, + }, + }, + }, + }, + }, + }, + }, + }, + extensionFilters: []*unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "apiVersion": "gateway.example.io/v1alpha1", + "kind": "Bar", + "metadata": map[string]interface{}{ + "name": "test", + "namespace": httpRouteNS, + }, + }, + }, + { + Object: map[string]interface{}{ + "apiVersion": "gateway.example.io/v1alpha1", + "kind": "Foo", + "metadata": map[string]interface{}{ + "name": "test", + "namespace": httpRouteNS, + }, + }, + }, + }, + extensionAPIGroups: []schema.GroupVersionKind{ + { + Group: "gateway.example.io", + Version: "v1alpha1", + Kind: "Bar", + }, + { + Group: "gateway.example.io", + Version: "v1alpha1", + Kind: "Foo", + }, + }, + expected: true, + }, { name: "httproute with one filter_from_extension", routes: []*gwapiv1.HTTPRoute{ @@ -294,10 +390,16 @@ func TestProcessHTTPRoutes(t *testing.T) { // Ensure the resource tree and map are as expected. require.Equal(t, tc.routes, resourceTree.HTTPRoutes) if tc.extensionFilters != nil { - for i, filter := range tc.extensionFilters { - key := types.NamespacedName{ - Namespace: tc.routes[i].Namespace, - Name: filter.GetName(), + for _, filter := range tc.extensionFilters { + key := utils.NamespacedNameWithGroupKind{ + NamespacedName: types.NamespacedName{ + Namespace: tc.routes[0].Namespace, + Name: filter.GetName(), + }, + GroupKind: schema.GroupKind{ + Group: filter.GroupVersionKind().Group, + Kind: filter.GroupVersionKind().Kind, + }, } require.Equal(t, *filter, resourceMap.extensionRefFilters[key]) } diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 6e434660de64..84043ecdcd2b 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -11,10 +11,30 @@ import ( "hash/fnv" "strings" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) +type NamespacedNameWithGroupKind struct { + types.NamespacedName + schema.GroupKind +} + +// GetNamespacedNameWithGroupKind creates and returns object's NamespacedNameWithGroupKind. +func GetNamespacedNameWithGroupKind(obj client.Object) NamespacedNameWithGroupKind { + return NamespacedNameWithGroupKind{ + NamespacedName: types.NamespacedName{ + Namespace: obj.GetNamespace(), + Name: obj.GetName(), + }, + GroupKind: schema.GroupKind{ + Group: obj.GetObjectKind().GroupVersionKind().GroupKind().Group, + Kind: obj.GetObjectKind().GroupVersionKind().GroupKind().Kind, + }, + } +} + // NamespacedName creates and returns object's NamespacedName. func NamespacedName(obj client.Object) types.NamespacedName { return types.NamespacedName{ From 31d5e7c5267b29f8934c9792191bbbac886ecc7e Mon Sep 17 00:00:00 2001 From: sh2 Date: Tue, 21 May 2024 01:13:35 +0800 Subject: [PATCH 22/25] chore: enable gci in golangci-lint (#3437) enable gci Signed-off-by: shawnh2 --- internal/extension/registry/extension_manager.go | 1 - internal/gatewayapi/status/gatewayclass_test.go | 1 - internal/xds/translator/extproc.go | 5 ++--- internal/xds/translator/httpfilters.go | 3 +-- internal/xds/translator/runner/runner_test.go | 1 - test/cel-validation/envoyextensionpolicy_test.go | 7 +++---- test/cel-validation/securitypolicy_test.go | 1 - test/e2e/tests/backend_upgrade.go | 2 -- test/e2e/tests/tcp_route.go | 7 +++---- test/e2e/tests/utils.go | 3 --- tools/linter/golangci-lint/.golangci.yml | 1 + 11 files changed, 10 insertions(+), 22 deletions(-) diff --git a/internal/extension/registry/extension_manager.go b/internal/extension/registry/extension_manager.go index dd2170c5be6c..d00e51ce402b 100644 --- a/internal/extension/registry/extension_manager.go +++ b/internal/extension/registry/extension_manager.go @@ -14,7 +14,6 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" - corev1 "k8s.io/api/core/v1" k8scli "sigs.k8s.io/controller-runtime/pkg/client" k8sclicfg "sigs.k8s.io/controller-runtime/pkg/client/config" diff --git a/internal/gatewayapi/status/gatewayclass_test.go b/internal/gatewayapi/status/gatewayclass_test.go index 0ccce4263531..8e66d166f39a 100644 --- a/internal/gatewayapi/status/gatewayclass_test.go +++ b/internal/gatewayapi/status/gatewayclass_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" - gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/suite" "sigs.k8s.io/gateway-api/pkg/features" diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go index 9a397484ed94..9d4779b41c79 100644 --- a/internal/xds/translator/extproc.go +++ b/internal/xds/translator/extproc.go @@ -12,12 +12,11 @@ import ( routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" extprocv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" - - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/durationpb" ) const ( diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index 5738d621eb84..22c351f81e5d 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -18,10 +18,9 @@ import ( "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/filters" "github.com/envoyproxy/gateway/internal/xds/types" - - "github.com/envoyproxy/gateway/internal/ir" ) var httpFilters []httpFilter diff --git a/internal/xds/translator/runner/runner_test.go b/internal/xds/translator/runner/runner_test.go index a7be53236c83..43bd2164e4be 100644 --- a/internal/xds/translator/runner/runner_test.go +++ b/internal/xds/translator/runner/runner_test.go @@ -13,7 +13,6 @@ import ( listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "github.com/stretchr/testify/require" "github.com/envoyproxy/gateway/api/v1alpha1" diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go index 53d55412f234..773ce8640c22 100644 --- a/test/cel-validation/envoyextensionpolicy_test.go +++ b/test/cel-validation/envoyextensionpolicy_test.go @@ -15,13 +15,12 @@ import ( "testing" "time" - "k8s.io/utils/ptr" - - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) func TestEnvoyExtensionPolicyTarget(t *testing.T) { diff --git a/test/cel-validation/securitypolicy_test.go b/test/cel-validation/securitypolicy_test.go index 12511c6d4c08..984903cf72da 100644 --- a/test/cel-validation/securitypolicy_test.go +++ b/test/cel-validation/securitypolicy_test.go @@ -18,7 +18,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" - gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" diff --git a/test/e2e/tests/backend_upgrade.go b/test/e2e/tests/backend_upgrade.go index 04aa1cc8a562..261ee9acb630 100644 --- a/test/e2e/tests/backend_upgrade.go +++ b/test/e2e/tests/backend_upgrade.go @@ -15,13 +15,11 @@ import ( "time" "fortio.org/fortio/periodic" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/http" diff --git a/test/e2e/tests/tcp_route.go b/test/e2e/tests/tcp_route.go index f09521db0106..bb4d80ff6d62 100644 --- a/test/e2e/tests/tcp_route.go +++ b/test/e2e/tests/tcp_route.go @@ -19,17 +19,16 @@ import ( "time" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" ) func init() { diff --git a/test/e2e/tests/utils.go b/test/e2e/tests/utils.go index a07cf6cb4643..c33cc9e3fc8b 100644 --- a/test/e2e/tests/utils.go +++ b/test/e2e/tests/utils.go @@ -15,16 +15,13 @@ import ( "fortio.org/fortio/fhttp" "fortio.org/fortio/periodic" flog "fortio.org/log" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/client" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/utils/config" diff --git a/tools/linter/golangci-lint/.golangci.yml b/tools/linter/golangci-lint/.golangci.yml index 267fbc46c9ac..10c9da6ce548 100644 --- a/tools/linter/golangci-lint/.golangci.yml +++ b/tools/linter/golangci-lint/.golangci.yml @@ -7,6 +7,7 @@ linters: - depguard - errorlint - exportloopref + - gci - gofmt - gofumpt - goimports From 60888c00c73d4c40435da90b9cf16ce9d900c8af Mon Sep 17 00:00:00 2001 From: Karol Szwaj Date: Mon, 20 May 2024 20:48:05 +0200 Subject: [PATCH 23/25] feat: support BackendRef HTTP filters (#3246) * feat: support for BackendRef HTTP filters Signed-off-by: Karol Szwaj * add xds configuration Signed-off-by: Karol Szwaj * gofumpt Signed-off-by: Karol Szwaj * enable backendRef filters conformance tests Signed-off-by: Karol Szwaj * build multiple weighted clusters Signed-off-by: Karol Szwaj * fix lint Signed-off-by: Karol Szwaj * refactor translator Signed-off-by: Karol Szwaj * add weight from setting Signed-off-by: Karol Szwaj * restore backend weights to set only when invalid Signed-off-by: Karol Szwaj * fix filters func Signed-off-by: Karol Szwaj * validate other filters Signed-off-by: Karol Szwaj * refactor code Signed-off-by: Karol Szwaj --------- Signed-off-by: Karol Szwaj --- internal/gatewayapi/conformance/features.go | 2 +- internal/gatewayapi/contexts.go | 6 +- internal/gatewayapi/route.go | 56 +++++- ...th-backendref-add-multiple-filters.in.yaml | 57 ++++++ ...h-backendref-add-multiple-filters.out.yaml | 184 ++++++++++++++++++ ...lid-backend-ref-unsupported-filter.in.yaml | 10 +- ...id-backend-ref-unsupported-filter.out.yaml | 13 +- internal/gatewayapi/validate.go | 26 ++- internal/ir/xds.go | 16 +- internal/ir/zz_generated.deepcopy.go | 40 ++++ internal/xds/translator/route.go | 77 ++++++-- ...p-route-weighted-backend-with-filters.yaml | 56 ++++++ ...eighted-backend-with-filters.clusters.yaml | 34 ++++ ...ighted-backend-with-filters.endpoints.yaml | 34 ++++ ...ighted-backend-with-filters.listeners.yaml | 34 ++++ ...-weighted-backend-with-filters.routes.yaml | 43 ++++ ...route-weighted-invalid-backend.routes.yaml | 2 - 17 files changed, 645 insertions(+), 45 deletions(-) create mode 100644 internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.in.yaml create mode 100755 internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml mode change 100644 => 100755 internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.routes.yaml diff --git a/internal/gatewayapi/conformance/features.go b/internal/gatewayapi/conformance/features.go index 93b13751d7cc..33d8b61e9e48 100644 --- a/internal/gatewayapi/conformance/features.go +++ b/internal/gatewayapi/conformance/features.go @@ -15,7 +15,7 @@ import ( // SkipTests is a list of tests that are skipped in the conformance suite. var SkipTests = []suite.ConformanceTest{ tests.GatewayStaticAddresses, - tests.GatewayHTTPListenerIsolation, // https://github.com/kubernetes-sigs/gateway-api/issues/3049 + tests.GatewayHTTPListenerIsolation, // https://github.com/kubernetes-sigs/gateway-api/issues/3352 tests.HTTPRouteBackendRequestHeaderModifier, // https://github.com/envoyproxy/gateway/issues/3338 } diff --git a/internal/gatewayapi/contexts.go b/internal/gatewayapi/contexts.go index 28e0affa2174..1ba5e7e4473d 100644 --- a/internal/gatewayapi/contexts.go +++ b/internal/gatewayapi/contexts.go @@ -368,5 +368,9 @@ func GetBackendRef(b BackendRefContext) *gwapiv1.BackendRef { } func GetFilters(b BackendRefContext) any { - return reflect.ValueOf(b).FieldByName("Filters").Interface() + filters := reflect.ValueOf(b).FieldByName("Filters") + if !filters.IsValid() { + return nil + } + return filters.Interface() } diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index aa1d2091b63f..18056c29412e 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -1225,17 +1225,71 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext, gwapiv1a2.RouteReasonResolvedRefs, "Mixed endpointslice address type for the same backendRef is not supported") } - + destinationFilters := t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources) ds = &ir.DestinationSetting{ Weight: &weight, Protocol: protocol, Endpoints: endpoints, AddressType: addrType, TLS: backendTLS, + Filters: destinationFilters, } + return ds } +func getBackendFilters(routeType gwapiv1.Kind, backendRefContext BackendRefContext) (backendFilters any) { + filters := GetFilters(backendRefContext) + switch routeType { + case KindHTTPRoute: + if len(filters.([]gwapiv1.HTTPRouteFilter)) > 0 { + return filters.([]gwapiv1.HTTPRouteFilter) + } + case KindGRPCRoute: + if len(filters.([]gwapiv1.GRPCRouteFilter)) > 0 { + return filters.([]gwapiv1.GRPCRouteFilter) + } + } + + return nil +} + +func (t *Translator) processDestinationFilters(routeType gwapiv1.Kind, backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *Resources) *ir.DestinationFilters { + backendFilters := getBackendFilters(routeType, backendRefContext) + if backendFilters == nil { + return nil + } + + var httpFiltersContext *HTTPFiltersContext + var destFilters ir.DestinationFilters + + switch filters := backendFilters.(type) { + case []gwapiv1.HTTPRouteFilter: + httpFiltersContext = t.ProcessHTTPFilters(parentRef, route, filters, 0, resources) + + case []gwapiv1.GRPCRouteFilter: + httpFiltersContext = t.ProcessGRPCFilters(parentRef, route, filters, resources) + } + applyHTTPFiltersContextToDestinationFilters(httpFiltersContext, &destFilters) + + return &destFilters +} + +func applyHTTPFiltersContextToDestinationFilters(httpFiltersContext *HTTPFiltersContext, destFilters *ir.DestinationFilters) { + if len(httpFiltersContext.AddRequestHeaders) > 0 { + destFilters.AddRequestHeaders = httpFiltersContext.AddRequestHeaders + } + if len(httpFiltersContext.RemoveRequestHeaders) > 0 { + destFilters.RemoveRequestHeaders = httpFiltersContext.RemoveRequestHeaders + } + if len(httpFiltersContext.AddResponseHeaders) > 0 { + destFilters.AddResponseHeaders = httpFiltersContext.AddResponseHeaders + } + if len(httpFiltersContext.RemoveResponseHeaders) > 0 { + destFilters.RemoveResponseHeaders = httpFiltersContext.RemoveResponseHeaders + } +} + func inspectAppProtocolByRouteKind(kind gwapiv1.Kind) ir.AppProtocol { switch kind { case KindUDPRoute: diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.in.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.in.yaml new file mode 100644 index 000000000000..3e5cc4db8c04 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.in.yaml @@ -0,0 +1,57 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + 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: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 + weight: 8 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + add: + - name: "add-header-1" + value: "some-value" + - name: "add-header-2" + value: "some-value" + - name: service-2 + port: 8080 + weight: 2 + - matches: + - path: + value: "/foo" + backendRefs: + - name: service-3 + port: 8080 + weight: 1 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: "add-header-3" + value: "some-value" diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml new file mode 100755 index 000000000000..2496f90f7a84 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml @@ -0,0 +1,184 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + 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: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - filters: + - requestHeaderModifier: + add: + - name: add-header-1 + value: some-value + - name: add-header-2 + value: some-value + type: RequestHeaderModifier + name: service-1 + port: 8080 + weight: 8 + - name: service-2 + port: 8080 + weight: 2 + matches: + - path: + value: / + - backendRefs: + - filters: + - requestHeaderModifier: + set: + - name: add-header-3 + value: some-value + type: RequestHeaderModifier + name: service-3 + port: 8080 + weight: 1 + matches: + - path: + value: /foo + 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: envoy-gateway +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/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: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + filters: + addRequestHeaders: + - append: false + name: add-header-3 + value: some-value + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/1/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /foo + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + filters: + addRequestHeaders: + - append: true + name: add-header-1 + value: some-value + - append: true + name: add-header-2 + value: some-value + protocol: HTTP + weight: 8 + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 2 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml index 236a10736d20..7f18d6119266 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml @@ -32,8 +32,8 @@ httpRoutes: - name: service-1 port: 8080 filters: - - type: ResponseHeaderModifier - responseHeaderModifier: - set: - - name: "set-header-1" - value: "some-value" + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 + hostname: "redirected.com" diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml old mode 100644 new mode 100755 index 5aaa08d2f417..9eafb47b5677 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml @@ -53,11 +53,11 @@ httpRoutes: rules: - backendRefs: - filters: - - responseHeaderModifier: - set: - - name: set-header-1 - value: some-value - type: ResponseHeaderModifier + - requestRedirect: + hostname: redirected.com + scheme: https + statusCode: 301 + type: RequestRedirect name: service-1 port: 8080 matches: @@ -73,7 +73,8 @@ httpRoutes: status: "True" type: Accepted - lastTransitionTime: null - message: The filters field within BackendRef is not supported + message: Specific filter is not supported within BackendRef, only RequestHeaderModifier + and ResponseHeaderModifier are supported reason: UnsupportedRefValue status: "False" type: ResolvedRefs diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index c3407135c966..344b886a6f9e 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -26,11 +26,11 @@ import ( func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *Resources, backendNamespace string, routeKind gwapiv1.Kind, ) bool { + backendRef := GetBackendRef(backendRefContext) + if !t.validateBackendRefFilters(backendRefContext, parentRef, route, routeKind) { return false } - backendRef := GetBackendRef(backendRefContext) - if !t.validateBackendRefGroup(backendRef, parentRef, route) { return false } @@ -94,19 +94,27 @@ func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, pa } func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, parentRef *RouteParentContext, route RouteContext, routeKind gwapiv1.Kind) bool { - var filtersLen int + filters := GetFilters(backendRef) + var unsupportedFilters bool + switch routeKind { case KindHTTPRoute: - filters := GetFilters(backendRef).([]gwapiv1.HTTPRouteFilter) - filtersLen = len(filters) + for _, filter := range filters.([]gwapiv1.HTTPRouteFilter) { + if filter.Type != gwapiv1.HTTPRouteFilterRequestHeaderModifier && filter.Type != gwapiv1.HTTPRouteFilterResponseHeaderModifier { + unsupportedFilters = true + } + } case KindGRPCRoute: - filters := GetFilters(backendRef).([]gwapiv1.GRPCRouteFilter) - filtersLen = len(filters) + for _, filter := range filters.([]gwapiv1.GRPCRouteFilter) { + if filter.Type != gwapiv1.GRPCRouteFilterRequestHeaderModifier && filter.Type != gwapiv1.GRPCRouteFilterResponseHeaderModifier { + unsupportedFilters = true + } + } default: return true } - if filtersLen > 0 { + if unsupportedFilters { routeStatus := GetRouteStatus(route) status.SetRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, @@ -114,7 +122,7 @@ func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, par gwapiv1.RouteConditionResolvedRefs, metav1.ConditionFalse, "UnsupportedRefValue", - "The filters field within BackendRef is not supported", + "Specific filter is not supported within BackendRef, only RequestHeaderModifier and ResponseHeaderModifier are supported", ) return false } diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 5b8af16c93c8..bc6037566b70 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -969,7 +969,8 @@ type DestinationSetting struct { // AddressTypeState specifies the state of DestinationEndpoint address type. AddressType *DestinationAddressType `json:"addressType,omitempty" yaml:"addressType,omitempty"` - TLS *TLSUpstreamConfig `json:"tls,omitempty" yaml:"tls,omitempty"` + TLS *TLSUpstreamConfig `json:"tls,omitempty" yaml:"tls,omitempty"` + Filters *DestinationFilters `json:"filters,omitempty" yaml:"filters,omitempty"` } // Validate the fields within the RouteDestination structure @@ -2092,3 +2093,16 @@ type HTTPWasmCode struct { // SHA256 checksum that will be used to verify the wasm code. SHA256 string `json:"sha256"` } + +// DestinationFilters contains HTTP filters that will be used with the DestinationSetting. +// +k8s:deepcopy-gen=true +type DestinationFilters struct { + // AddRequestHeaders defines header/value sets to be added to the headers of requests. + AddRequestHeaders []AddHeader `json:"addRequestHeaders,omitempty" yaml:"addRequestHeaders,omitempty"` + // RemoveRequestHeaders defines a list of headers to be removed from requests. + RemoveRequestHeaders []string `json:"removeRequestHeaders,omitempty" yaml:"removeRequestHeaders,omitempty"` + // AddResponseHeaders defines header/value sets to be added to the headers of response. + AddResponseHeaders []AddHeader `json:"addResponseHeaders,omitempty" yaml:"addResponseHeaders,omitempty"` + // RemoveResponseHeaders defines a list of headers to be removed from response. + RemoveResponseHeaders []string `json:"removeResponseHeaders,omitempty" yaml:"removeResponseHeaders,omitempty"` +} diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 0024414525f7..b24b46aeacad 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -390,6 +390,41 @@ func (in *DestinationEndpoint) DeepCopy() *DestinationEndpoint { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DestinationFilters) DeepCopyInto(out *DestinationFilters) { + *out = *in + if in.AddRequestHeaders != nil { + in, out := &in.AddRequestHeaders, &out.AddRequestHeaders + *out = make([]AddHeader, len(*in)) + copy(*out, *in) + } + if in.RemoveRequestHeaders != nil { + in, out := &in.RemoveRequestHeaders, &out.RemoveRequestHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AddResponseHeaders != nil { + in, out := &in.AddResponseHeaders, &out.AddResponseHeaders + *out = make([]AddHeader, len(*in)) + copy(*out, *in) + } + if in.RemoveResponseHeaders != nil { + in, out := &in.RemoveResponseHeaders, &out.RemoveResponseHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationFilters. +func (in *DestinationFilters) DeepCopy() *DestinationFilters { + if in == nil { + return nil + } + out := new(DestinationFilters) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DestinationSetting) DeepCopyInto(out *DestinationSetting) { *out = *in @@ -419,6 +454,11 @@ func (in *DestinationSetting) DeepCopyInto(out *DestinationSetting) { *out = new(TLSUpstreamConfig) (*in).DeepCopyInto(*out) } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = new(DestinationFilters) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DestinationSetting. diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index c8205fa9509c..55e6c258e65f 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -71,7 +71,7 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute) (*routev3.Route, error) { router.Action = &routev3.Route_Route{Route: routeAction} default: backendWeights := httpRoute.Destination.ToBackendWeights() - routeAction := buildXdsRouteAction(backendWeights) + routeAction := buildXdsRouteAction(backendWeights, httpRoute.Destination.Settings) routeAction.IdleTimeout = idleTimeout(httpRoute) if httpRoute.Mirrors != nil { @@ -222,33 +222,62 @@ func buildXdsStringMatcher(irMatch *ir.StringMatch) *matcherv3.StringMatcher { return stringMatcher } -func buildXdsRouteAction(backendWeights *ir.BackendWeights) *routev3.RouteAction { +func buildXdsRouteAction(backendWeights *ir.BackendWeights, settings []*ir.DestinationSetting) *routev3.RouteAction { // only use weighted cluster when there are invalid weights - if backendWeights.Invalid == 0 { - return &routev3.RouteAction{ - ClusterSpecifier: &routev3.RouteAction_Cluster{ - Cluster: backendWeights.Name, - }, - } + if hasFiltersInSettings(settings) || backendWeights.Invalid != 0 { + return buildXdsWeightedRouteAction(backendWeights, settings) } - return buildXdsWeightedRouteAction(backendWeights) + return &routev3.RouteAction{ + ClusterSpecifier: &routev3.RouteAction_Cluster{ + Cluster: backendWeights.Name, + }, + } } -func buildXdsWeightedRouteAction(backendWeights *ir.BackendWeights) *routev3.RouteAction { - clusters := []*routev3.WeightedCluster_ClusterWeight{ - { +func buildXdsWeightedRouteAction(backendWeights *ir.BackendWeights, settings []*ir.DestinationSetting) *routev3.RouteAction { + weightedClusters := []*routev3.WeightedCluster_ClusterWeight{} + if backendWeights.Invalid > 0 { + invalidCluster := &routev3.WeightedCluster_ClusterWeight{ Name: "invalid-backend-cluster", Weight: &wrapperspb.UInt32Value{Value: backendWeights.Invalid}, - }, + } + weightedClusters = append(weightedClusters, invalidCluster) + return &routev3.RouteAction{ + // Intentionally route to a non-existent cluster and return a 500 error when it is not found + ClusterNotFoundResponseCode: routev3.RouteAction_INTERNAL_SERVER_ERROR, + ClusterSpecifier: &routev3.RouteAction_WeightedClusters{ + WeightedClusters: &routev3.WeightedCluster{ + Clusters: weightedClusters, + }, + }, + } } - if backendWeights.Valid > 0 { - validCluster := &routev3.WeightedCluster_ClusterWeight{ - Name: backendWeights.Name, - Weight: &wrapperspb.UInt32Value{Value: backendWeights.Valid}, + for _, destinationSetting := range settings { + if destinationSetting.Filters != nil { + validCluster := &routev3.WeightedCluster_ClusterWeight{ + Name: backendWeights.Name, + Weight: &wrapperspb.UInt32Value{Value: *destinationSetting.Weight}, + } + + if len(destinationSetting.Filters.AddRequestHeaders) > 0 { + validCluster.RequestHeadersToAdd = append(validCluster.RequestHeadersToAdd, buildXdsAddedHeaders(destinationSetting.Filters.AddRequestHeaders)...) + } + + if len(destinationSetting.Filters.RemoveRequestHeaders) > 0 { + validCluster.RequestHeadersToRemove = append(validCluster.RequestHeadersToRemove, destinationSetting.Filters.RemoveRequestHeaders...) + } + + if len(destinationSetting.Filters.AddResponseHeaders) > 0 { + validCluster.ResponseHeadersToAdd = append(validCluster.ResponseHeadersToAdd, buildXdsAddedHeaders(destinationSetting.Filters.AddResponseHeaders)...) + } + + if len(destinationSetting.Filters.RemoveResponseHeaders) > 0 { + validCluster.ResponseHeadersToRemove = append(validCluster.ResponseHeadersToRemove, destinationSetting.Filters.RemoveResponseHeaders...) + } + weightedClusters = append(weightedClusters, validCluster) } - clusters = append(clusters, validCluster) } return &routev3.RouteAction{ @@ -256,7 +285,7 @@ func buildXdsWeightedRouteAction(backendWeights *ir.BackendWeights) *routev3.Rou ClusterNotFoundResponseCode: routev3.RouteAction_INTERNAL_SERVER_ERROR, ClusterSpecifier: &routev3.RouteAction_WeightedClusters{ WeightedClusters: &routev3.WeightedCluster{ - Clusters: clusters, + Clusters: weightedClusters, }, }, } @@ -588,3 +617,13 @@ func buildRetryOn(triggers []ir.TriggerEnum) (string, error) { return b.String(), nil } + +func hasFiltersInSettings(settings []*ir.DestinationSetting) bool { + for _, setting := range settings { + filters := setting.Filters + if filters != nil { + return true + } + } + return false +} diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml new file mode 100644 index 000000000000..f8943d07f015 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml @@ -0,0 +1,56 @@ +http: + - name: "first-listener" + address: "0.0.0.0" + hostnames: + - '*' + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: "first-route-dest" + settings: + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 8080 + filters: + addRequestHeaders: + - append: false + name: add-header-3 + value: some-value + protocol: HTTP + weight: 1 + hostname: '*' + name: "first-route" + pathMatch: + prefix: /foo + - destination: + name: "second-route-dest" + settings: + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 8080 + filters: + addRequestHeaders: + - append: true + name: add-header-1 + value: some-value + - append: true + name: add-header-2 + value: some-value + protocol: HTTP + weight: 8 + - addressType: IP + endpoints: + - host: 3.3.3.3 + port: 8080 + filters: {} + protocol: HTTP + weight: 2 + hostname: '*' + name: "second-route" + pathMatch: + prefix: / diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.clusters.yaml new file mode 100644 index 000000000000..d65e267ad7de --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.clusters.yaml @@ -0,0 +1,34 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.endpoints.yaml new file mode 100644 index 000000000000..261bcf04f941 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.endpoints.yaml @@ -0,0 +1,34 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 8 + locality: + region: second-route-dest/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 3.3.3.3 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 2 + locality: + region: second-route-dest/backend/1 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.listeners.yaml new file mode 100644 index 000000000000..17a4871056a6 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.listeners.yaml @@ -0,0 +1,34 @@ +- 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: + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.routes.yaml new file mode 100644 index 000000000000..784ab102ad0f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend-with-filters.routes.yaml @@ -0,0 +1,43 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + pathSeparatedPrefix: /foo + name: first-route + route: + clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + upgradeConfigs: + - upgradeType: websocket + weightedClusters: + clusters: + - name: first-route-dest + requestHeadersToAdd: + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: add-header-3 + value: some-value + weight: 1 + - match: + prefix: / + name: second-route + route: + clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + upgradeConfigs: + - upgradeType: websocket + weightedClusters: + clusters: + - name: second-route-dest + requestHeadersToAdd: + - header: + key: add-header-1 + value: some-value + - header: + key: add-header-2 + value: some-value + weight: 8 + - name: second-route-dest + weight: 2 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml index 235dea427290..6b53d359a22c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml @@ -16,5 +16,3 @@ clusters: - name: invalid-backend-cluster weight: 1 - - name: first-route-dest - weight: 1 From b99888af4c6527b016e36e6102b6f263626bea54 Mon Sep 17 00:00:00 2001 From: Zufar Dhiyaulhaq Date: Tue, 21 May 2024 01:50:25 +0700 Subject: [PATCH 24/25] feat: support forward client cert config XFCC header (#3202) * feat: support forward client cert config XFCC headers Signed-off-by: zufardhiyaulhaq * feat: add clientCertDetailsConfiguration to configure xfcc header Signed-off-by: zufardhiyaulhaq * feat: fix sites Signed-off-by: zufardhiyaulhaq * feat: fix unit tests Signed-off-by: zufardhiyaulhaq * feat: move xfcc configuration to tls.clientvalidation & group into 1 struct Signed-off-by: zufardhiyaulhaq * feat: fix gen-check Signed-off-by: zufardhiyaulhaq * feat: fix API removing uniqueItems & trailing space on test data Signed-off-by: zufardhiyaulhaq * fix: API & implementation moving ForwardClientSet to Headers Signed-off-by: zufardhiyaulhaq * feat: move unit tests to headers & fix logic on headers Signed-off-by: zufardhiyaulhaq * feat: fix logic on xds listener & unit tests Signed-off-by: zufardhiyaulhaq * feat: fix gen-check Signed-off-by: zufardhiyaulhaq * feat: fix gen-check Signed-off-by: zufardhiyaulhaq * feat: fix lint Signed-off-by: zufardhiyaulhaq * feat: change forwardClientCert to xForwardedClientCert Signed-off-by: zufardhiyaulhaq * fix gen-check job Signed-off-by: zufardhiyaulhaq --------- Signed-off-by: zufardhiyaulhaq --- api/v1alpha1/clienttrafficpolicy_types.go | 58 ++ api/v1alpha1/zz_generated.deepcopy.go | 30 + ...y.envoyproxy.io_clienttrafficpolicies.yaml | 33 + internal/gatewayapi/clienttrafficpolicy.go | 15 + ...ls-forward-client-cert-custom-data.in.yaml | 252 +++++++ ...s-forward-client-cert-custom-data.out.yaml | 711 ++++++++++++++++++ ...ficpolicy-mtls-forward-client-cert.in.yaml | 236 ++++++ ...icpolicy-mtls-forward-client-cert.out.yaml | 683 +++++++++++++++++ internal/ir/xds.go | 37 + internal/ir/zz_generated.deepcopy.go | 27 +- internal/xds/translator/listener.go | 57 ++ ...d-client-certificate-with-custom-data.yaml | 196 +++++ ...mutual-tls-forward-client-certificate.yaml | 181 +++++ ...certificate-with-custom-data.clusters.yaml | 85 +++ ...ertificate-with-custom-data.endpoints.yaml | 60 ++ ...ertificate-with-custom-data.listeners.yaml | 301 ++++++++ ...t-certificate-with-custom-data.routes.yaml | 70 ++ ...-certificate-with-custom-data.secrets.yaml | 80 ++ ...s-forward-client-certificate.clusters.yaml | 85 +++ ...-forward-client-certificate.endpoints.yaml | 60 ++ ...-forward-client-certificate.listeners.yaml | 289 +++++++ ...tls-forward-client-certificate.routes.yaml | 70 ++ ...ls-forward-client-certificate.secrets.yaml | 80 ++ site/content/en/latest/api/extension_types.md | 53 ++ 24 files changed, 3748 insertions(+), 1 deletion(-) create mode 100644 internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.in.yaml create mode 100644 internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.out.yaml create mode 100644 internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.in.yaml create mode 100644 internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.out.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.routes.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.secrets.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.routes.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.secrets.yaml diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index ea9d79018983..0b967a71bb31 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -104,6 +104,11 @@ type HeaderSettings struct { // +optional EnableEnvoyHeaders *bool `json:"enableEnvoyHeaders,omitempty"` + // Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header. + // When enabled, Hash and By is always set + // +optional + XForwardedClientCert *XForwardedClientCert `json:"xForwardedClientCert,omitempty"` + // WithUnderscoresAction configures the action to take when an HTTP header with underscores // is encountered. The default action is to reject the request. // +optional @@ -134,6 +139,59 @@ const ( WithUnderscoresActionDropHeader WithUnderscoresAction = "DropHeader" ) +// Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header. +type XForwardedClientCert struct { + // Envoy Proxy mode how to handle the x-forwarded-client-cert (XFCC) HTTP header. + // +optional + Mode *ForwardMode `json:"mode,omitempty"` + + // Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header + // +kubebuilder:validation:MaxItems=5 + // +optional + CertDetailsToAdd []ClientCertData `json:"certDetailsToAdd,omitempty"` +} + +// Envoy Proxy mode how to handle the x-forwarded-client-cert (XFCC) HTTP header. +// +kubebuilder:validation:Enum=Sanitize;ForwardOnly;AppendForward;SanitizeSet;AlwaysForwardOnly +type ForwardMode string + +const ( + // Do not send the XFCC header to the next hop. This is the default value. + ForwardModeSanitize ForwardMode = "Sanitize" + // When the client connection is mTLS (Mutual TLS), forward the XFCC header + // in the request. + ForwardModeForwardOnly ForwardMode = "ForwardOnly" + // When the client connection is mTLS, append the client certificate + // information to the request’s XFCC header and forward it. + ForwardModeAppendForward ForwardMode = "AppendForward" + // When the client connection is mTLS, reset the XFCC header with the client + // certificate information and send it to the next hop. + ForwardModeSanitizeSet ForwardMode = "SanitizeSet" + // Always forward the XFCC header in the request, regardless of whether the + // client connection is mTLS. + ForwardModeAlwaysForwardOnly ForwardMode = "AlwaysForwardOnly" +) + +// Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header +// By default, x-forwarded-client-cert (XFCC) will always include By and Hash data +// +kubebuilder:validation:Enum=Subject;Cert;Chain;Dns;Uri +type ClientCertData string + +const ( + // Whether to forward the subject of the client cert. + ClientCertDataSubject ClientCertData = "Subject" + // Whether to forward the entire client cert in URL encoded PEM format. + // This will appear in the XFCC header comma separated from other values with the value Cert=”PEM”. + ClientCertDataCert ClientCertData = "Cert" + // Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM format. + // This will appear in the XFCC header comma separated from other values with the value Chain=”PEM”. + ClientCertDataChain ClientCertData = "Chain" + // Whether to forward the DNS type Subject Alternative Names of the client cert. + ClientCertDataDNS ClientCertData = "Dns" + // Whether to forward the URI type Subject Alternative Name of the client cert. + ClientCertDataURI ClientCertData = "Uri" +) + // ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. // // +kubebuilder:validation:XValidation:rule="!(has(self.xForwardedFor) && has(self.customHeader))",message="customHeader cannot be used in conjunction with xForwardedFor" diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 1456fde63eb8..37ae123f6cd6 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -2473,6 +2473,11 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = new(bool) **out = **in } + if in.XForwardedClientCert != nil { + in, out := &in.XForwardedClientCert, &out.XForwardedClientCert + *out = new(XForwardedClientCert) + (*in).DeepCopyInto(*out) + } if in.WithUnderscoresAction != nil { in, out := &in.WithUnderscoresAction, &out.WithUnderscoresAction *out = new(WithUnderscoresAction) @@ -4580,6 +4585,31 @@ func (in *XDSTranslatorHooks) DeepCopy() *XDSTranslatorHooks { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XForwardedClientCert) DeepCopyInto(out *XForwardedClientCert) { + *out = *in + if in.Mode != nil { + in, out := &in.Mode, &out.Mode + *out = new(ForwardMode) + **out = **in + } + if in.CertDetailsToAdd != nil { + in, out := &in.CertDetailsToAdd, &out.CertDetailsToAdd + *out = make([]ClientCertData, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XForwardedClientCert. +func (in *XForwardedClientCert) DeepCopy() *XForwardedClientCert { + if in == nil { + return nil + } + out := new(XForwardedClientCert) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *XForwardedForSettings) DeepCopyInto(out *XForwardedForSettings) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 6d4805ca0b80..796f74c1569c 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -162,6 +162,39 @@ spec: - RejectRequest - DropHeader type: string + xForwardedClientCert: + description: |- + Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header. + When enabled, Hash and By is always set + properties: + certDetailsToAdd: + description: Specifies the fields in the client certificate + to be forwarded on the x-forwarded-client-cert (XFCC) HTTP + header + items: + description: |- + Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header + By default, x-forwarded-client-cert (XFCC) will always include By and Hash data + enum: + - Subject + - Cert + - Chain + - Dns + - Uri + type: string + maxItems: 5 + type: array + mode: + description: Envoy Proxy mode how to handle the x-forwarded-client-cert + (XFCC) HTTP header. + enum: + - Sanitize + - ForwardOnly + - AppendForward + - SanitizeSet + - AlwaysForwardOnly + type: string + type: object type: object http1: description: HTTP1 provides HTTP/1 configuration on the listener. diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index f5465fcd798d..6ce87fb17377 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -549,6 +549,21 @@ func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, http WithUnderscoresAction: ir.WithUnderscoresAction(ptr.Deref(headerSettings.WithUnderscoresAction, egv1a1.WithUnderscoresActionRejectRequest)), PreserveXRequestID: ptr.Deref(headerSettings.PreserveXRequestID, false), } + + if headerSettings.XForwardedClientCert != nil { + httpIR.Headers.XForwardedClientCert = &ir.XForwardedClientCert{ + Mode: ir.ForwardMode(ptr.Deref(headerSettings.XForwardedClientCert.Mode, egv1a1.ForwardModeSanitize)), + } + + var certDetailsToAdd []ir.ClientCertData + if httpIR.Headers.XForwardedClientCert.Mode == ir.ForwardModeAppendForward || httpIR.Headers.XForwardedClientCert.Mode == ir.ForwardModeSanitizeSet { + for _, data := range headerSettings.XForwardedClientCert.CertDetailsToAdd { + certDetailsToAdd = append(certDetailsToAdd, ir.ClientCertData(data)) + } + + httpIR.Headers.XForwardedClientCert.CertDetailsToAdd = certDetailsToAdd + } + } } func translateHTTP1Settings(http1Settings *egv1a1.HTTP1Settings, httpIR *ir.HTTPListener) error { diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.in.yaml new file mode 100644 index 000000000000..97f977440de7 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.in.yaml @@ -0,0 +1,252 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + headers: + xForwardedClientCert: + mode: Sanitize + certDetailsToAdd: + - Cert + tls: + clientValidation: + caCertificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-2 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + headers: + xForwardedClientCert: + mode: ForwardOnly + certDetailsToAdd: + - Cert + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-3 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-3 + headers: + xForwardedClientCert: + mode: AppendForward + certDetailsToAdd: + - Cert + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-4 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-4 + headers: + xForwardedClientCert: + mode: SanitizeSet + certDetailsToAdd: + - Cert + - Uri + - Chain + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-5 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-5 + headers: + xForwardedClientCert: + mode: SanitizeSet + certDetailsToAdd: + - Cert + - Uri + - Chain + - Subject + - Dns + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-3 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-4 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-5 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +configMaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-configmap + namespace: envoy-gateway + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDOzCCAiOgAwIBAgIUc41kpE9wK+NHgRGvBIgw8SCaz/8wDQYJKoZIhvcNAQEL + BQAwLTEVMBMGA1UECgwMZXhhbXBsZSBJbmMuMRQwEgYDVQQDDAtleGFtcGxlLmNv + bTAeFw0yNDAxMjYyMzE1MzFaFw0yNTAxMjUyMzE1MzFaMC0xFTATBgNVBAoMDGV4 + YW1wbGUgSW5jLjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB + AQUAA4IBDwAwggEKAoIBAQDCLhZ5DnCVE5JJ97yOocpRwclbl0UwX3cI+1ZZNltl + W6jRgy1GuN6Vr7CBmI/mPtgGs9T7DNRMl5gJJkNHSZomI6GjuP1KUhuvlfbZPWNo + p45T235Z82Gg8ORJHT5mn1QRK+bz9ruJfyldMMlicUJv/Yft6zNURxQ7BU9ciGe1 + tM+UMSxkop3dovVptELnkTDJSwt5dn+nj6j/Gr95z90/e2gjfVTtmArAG3xh/2B1 + /D6NXhwPMzYrplnM3lOpxzflOVgjMUloL1oI7sm6c+2A14NeBrW/ofB9RD7DWBHd + 76j+hcAWFsxYmsHo5Ox/tFeTk7GRdkHEELLWFBvYG0BTAgMBAAGjUzBRMB0GA1Ud + DgQWBBSrLbcQPpEx+Dt+hYE/yrjt6rOV6TAfBgNVHSMEGDAWgBSrLbcQPpEx+Dt+ + hYE/yrjt6rOV6TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCF + 4jltqxVaKZaVML7HNQSwegy+gZ1xalymMNo7Ipc8zOyUUI47weEf/p+nkq8oxi/m + mLZoeMSdXg+gebYMMcURgtl9QfuF0aYCB3AlCxlpdH4Lk3uXNTLQXJiLQRTNsBu/ + LJ6UYvLFKPwodvRKL8KWKEgLVJmrTe3g8iL3SSnw00hWieuCdSsxNl/47ThgYXrg + u1PRBUt5g+XoWpUSOCMOFWlBJqwJYKfRA3E6ff44IUJsb7qUHHAe1wa1YDfuD+T5 + At9/m+M7GyW9oEbSQsPTGfYqP59QE+1iei6qiG+7kn4iRxJqhgm5N5o86QSk0Maz + Cz4jTEKdNvXYVFfh6Zqr + -----END CERTIFICATE----- +secrets: +- apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-1 + type: kubernetes.io/tls + data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.out.yaml new file mode 100644 index 000000000000..134cc92b2e1c --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert-custom-data.out.yaml @@ -0,0 +1,711 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + certDetailsToAdd: + - Cert + mode: Sanitize + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-2 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + certDetailsToAdd: + - Cert + mode: ForwardOnly + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-3 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + certDetailsToAdd: + - Cert + mode: AppendForward + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-3 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-3 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-4 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + certDetailsToAdd: + - Cert + - Uri + - Chain + mode: SanitizeSet + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-4 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-4 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-5 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + certDetailsToAdd: + - Cert + - Uri + - Chain + - Subject + - Dns + mode: SanitizeSet + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-5 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-5 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 0 + 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-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-3 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-4 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-5 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-8080 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 + envoy-gateway/gateway-3: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-3/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-3 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-3 + envoy-gateway/gateway-4: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-4/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-4 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-4 + envoy-gateway/gateway-5: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-5/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-5 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-5 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: Sanitize + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-1/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: Sanitize + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: ForwardOnly + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-2/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + envoy-gateway/gateway-3: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + certDetailsToAdd: + - Cert + mode: AppendForward + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-3/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-3/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + envoy-gateway/gateway-4: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + certDetailsToAdd: + - Cert + - Uri + - Chain + mode: SanitizeSet + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-4/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-4/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + envoy-gateway/gateway-5: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + certDetailsToAdd: + - Cert + - Uri + - Chain + - Subject + - Dns + mode: SanitizeSet + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-5/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-5/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.in.yaml new file mode 100644 index 000000000000..ba8d1ff5b064 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.in.yaml @@ -0,0 +1,236 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + headers: + xForwardedClientCert: + mode: Sanitize + tls: + clientValidation: + caCertificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-2 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + headers: + xForwardedClientCert: + mode: ForwardOnly + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-3 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-3 + headers: + xForwardedClientCert: + mode: AppendForward + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-4 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-4 + headers: + xForwardedClientCert: + mode: SanitizeSet + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-5 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-5 + headers: + xForwardedClientCert: + mode: AlwaysForwardOnly + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-3 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-4 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-5 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +configMaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-configmap + namespace: envoy-gateway + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDOzCCAiOgAwIBAgIUc41kpE9wK+NHgRGvBIgw8SCaz/8wDQYJKoZIhvcNAQEL + BQAwLTEVMBMGA1UECgwMZXhhbXBsZSBJbmMuMRQwEgYDVQQDDAtleGFtcGxlLmNv + bTAeFw0yNDAxMjYyMzE1MzFaFw0yNTAxMjUyMzE1MzFaMC0xFTATBgNVBAoMDGV4 + YW1wbGUgSW5jLjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB + AQUAA4IBDwAwggEKAoIBAQDCLhZ5DnCVE5JJ97yOocpRwclbl0UwX3cI+1ZZNltl + W6jRgy1GuN6Vr7CBmI/mPtgGs9T7DNRMl5gJJkNHSZomI6GjuP1KUhuvlfbZPWNo + p45T235Z82Gg8ORJHT5mn1QRK+bz9ruJfyldMMlicUJv/Yft6zNURxQ7BU9ciGe1 + tM+UMSxkop3dovVptELnkTDJSwt5dn+nj6j/Gr95z90/e2gjfVTtmArAG3xh/2B1 + /D6NXhwPMzYrplnM3lOpxzflOVgjMUloL1oI7sm6c+2A14NeBrW/ofB9RD7DWBHd + 76j+hcAWFsxYmsHo5Ox/tFeTk7GRdkHEELLWFBvYG0BTAgMBAAGjUzBRMB0GA1Ud + DgQWBBSrLbcQPpEx+Dt+hYE/yrjt6rOV6TAfBgNVHSMEGDAWgBSrLbcQPpEx+Dt+ + hYE/yrjt6rOV6TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCF + 4jltqxVaKZaVML7HNQSwegy+gZ1xalymMNo7Ipc8zOyUUI47weEf/p+nkq8oxi/m + mLZoeMSdXg+gebYMMcURgtl9QfuF0aYCB3AlCxlpdH4Lk3uXNTLQXJiLQRTNsBu/ + LJ6UYvLFKPwodvRKL8KWKEgLVJmrTe3g8iL3SSnw00hWieuCdSsxNl/47ThgYXrg + u1PRBUt5g+XoWpUSOCMOFWlBJqwJYKfRA3E6ff44IUJsb7qUHHAe1wa1YDfuD+T5 + At9/m+M7GyW9oEbSQsPTGfYqP59QE+1iei6qiG+7kn4iRxJqhgm5N5o86QSk0Maz + Cz4jTEKdNvXYVFfh6Zqr + -----END CERTIFICATE----- +secrets: +- apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-1 + type: kubernetes.io/tls + data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.out.yaml new file mode 100644 index 000000000000..c60dca197fed --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls-forward-client-cert.out.yaml @@ -0,0 +1,683 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + mode: Sanitize + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-2 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + mode: ForwardOnly + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-3 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + mode: AppendForward + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-3 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-3 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-4 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + mode: SanitizeSet + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-4 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-4 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-5 + namespace: envoy-gateway + spec: + headers: + xForwardedClientCert: + mode: AlwaysForwardOnly + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-5 + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-5 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 0 + 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-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-3 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-4 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-5 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + 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-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-8080 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 + envoy-gateway/gateway-3: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-3/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-3 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-3 + envoy-gateway/gateway-4: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-4/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-4 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-4 + envoy-gateway/gateway-5: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-5/http-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-5 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-5 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: Sanitize + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-1/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: Sanitize + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: ForwardOnly + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-2/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + envoy-gateway/gateway-3: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: AppendForward + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-3/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-3/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + envoy-gateway/gateway-4: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: SanitizeSet + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-4/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-4/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true + envoy-gateway/gateway-5: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + withUnderscoresAction: RejectRequest + xForwardedClientCert: + mode: AlwaysForwardOnly + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-5/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-5/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + requireClientCertificate: true diff --git a/internal/ir/xds.go b/internal/ir/xds.go index bc6037566b70..3eb789f19d82 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -373,6 +373,39 @@ const ( WithUnderscoresActionDropHeader = WithUnderscoresAction(egv1a1.WithUnderscoresActionDropHeader) ) +// Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header. +// +k8s:deepcopy-gen=true +type XForwardedClientCert struct { + // Envoy Proxy mode how to handle the x-forwarded-client-cert (XFCC) HTTP header. + Mode ForwardMode `json:"mode,omitempty" yaml:"mode,omitempty"` + // Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header + CertDetailsToAdd []ClientCertData `json:"certDetailsToAdd,omitempty" yaml:"certDetailsToAdd,omitempty"` +} + +// Envoy Proxy mode how to handle the x-forwarded-client-cert (XFCC) HTTP header. +// +k8s:deepcopy-gen=true +type ForwardMode egv1a1.ForwardMode + +const ( + ForwardModeSanitize = ForwardMode(egv1a1.ForwardModeSanitize) + ForwardModeForwardOnly = ForwardMode(egv1a1.ForwardModeForwardOnly) + ForwardModeAppendForward = ForwardMode(egv1a1.ForwardModeAppendForward) + ForwardModeSanitizeSet = ForwardMode(egv1a1.ForwardModeSanitizeSet) + ForwardModeAlwaysForwardOnly = ForwardMode(egv1a1.ForwardModeAlwaysForwardOnly) +) + +// Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header +// +k8s:deepcopy-gen=true +type ClientCertData egv1a1.ClientCertData + +const ( + ClientCertDataSubject = ClientCertData(egv1a1.ClientCertDataSubject) + ClientCertDataCert = ClientCertData(egv1a1.ClientCertDataCert) + ClientCertDataChain = ClientCertData(egv1a1.ClientCertDataChain) + ClientCertDataDNS = ClientCertData(egv1a1.ClientCertDataDNS) + ClientCertDataURI = ClientCertData(egv1a1.ClientCertDataURI) +) + // ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. // +k8s:deepcopy-gen=true type ClientIPDetectionSettings egv1a1.ClientIPDetectionSettings @@ -419,6 +452,10 @@ type HeaderSettings struct { // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/router/v3/router.proto#extensions-filters-http-router-v3-router EnableEnvoyHeaders bool `json:"enableEnvoyHeaders,omitempty" yaml:"enableEnvoyHeaders,omitempty"` + // Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header. + // refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-enum-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-forwardclientcertdetails + XForwardedClientCert *XForwardedClientCert `json:"xForwardedClientCert,omitempty" yaml:"xForwardedClientCert,omitempty"` + // WithUnderscoresAction configures the action to take when an HTTP header with underscores // is encountered. The default action is to reject the request. // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/protocol.proto#envoy-v3-api-enum-config-core-v3-httpprotocoloptions-headerswithunderscoresaction diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index b24b46aeacad..0965e4013769 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -909,7 +909,7 @@ func (in *HTTPListener) DeepCopyInto(out *HTTPListener) { if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(HeaderSettings) - **out = **in + (*in).DeepCopyInto(*out) } if in.ClientIPDetection != nil { in, out := &in.ClientIPDetection, &out.ClientIPDetection @@ -1145,6 +1145,11 @@ func (in *HTTPTimeout) DeepCopy() *HTTPTimeout { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = *in + if in.XForwardedClientCert != nil { + in, out := &in.XForwardedClientCert, &out.XForwardedClientCert + *out = new(XForwardedClientCert) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. @@ -2607,6 +2612,26 @@ func (in *Wasm) DeepCopy() *Wasm { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XForwardedClientCert) DeepCopyInto(out *XForwardedClientCert) { + *out = *in + if in.CertDetailsToAdd != nil { + in, out := &in.CertDetailsToAdd, &out.CertDetailsToAdd + *out = make([]ClientCertData, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XForwardedClientCert. +func (in *XForwardedClientCert) DeepCopy() *XForwardedClientCert { + if in == nil { + return nil + } + out := new(XForwardedClientCert) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Xds) DeepCopyInto(out *Xds) { *out = *in diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index ada6ee454d7c..ef99f3ed3311 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -261,9 +261,14 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis HeadersWithUnderscoresAction: buildHeadersWithUnderscoresAction(irListener.Headers), }, Tracing: hcmTracing, + ForwardClientCertDetails: buildForwardClientCertDetailsAction(irListener.Headers), PreserveExternalRequestId: ptr.Deref(irListener.Headers, ir.HeaderSettings{}).PreserveXRequestID, } + if mgr.ForwardClientCertDetails == hcmv3.HttpConnectionManager_APPEND_FORWARD || mgr.ForwardClientCertDetails == hcmv3.HttpConnectionManager_SANITIZE_SET { + mgr.SetCurrentClientCertDetails = buildSetCurrentClientCertDetails(irListener.Headers) + } + if irListener.Timeout != nil && irListener.Timeout.HTTP != nil { if irListener.Timeout.HTTP.RequestReceivedTimeout != nil { mgr.RequestTimeout = durationpb.New(irListener.Timeout.HTTP.RequestReceivedTimeout.Duration) @@ -786,3 +791,55 @@ func buildHeadersWithUnderscoresAction(in *ir.HeaderSettings) corev3.HttpProtoco } return corev3.HttpProtocolOptions_REJECT_REQUEST } + +func buildForwardClientCertDetailsAction(in *ir.HeaderSettings) hcmv3.HttpConnectionManager_ForwardClientCertDetails { + if in != nil { + if in.XForwardedClientCert != nil { + switch in.XForwardedClientCert.Mode { + case ir.ForwardModeSanitize: + return hcmv3.HttpConnectionManager_SANITIZE + case ir.ForwardModeForwardOnly: + return hcmv3.HttpConnectionManager_FORWARD_ONLY + case ir.ForwardModeAppendForward: + return hcmv3.HttpConnectionManager_APPEND_FORWARD + case ir.ForwardModeSanitizeSet: + return hcmv3.HttpConnectionManager_SANITIZE_SET + case ir.ForwardModeAlwaysForwardOnly: + return hcmv3.HttpConnectionManager_ALWAYS_FORWARD_ONLY + } + } + } + return hcmv3.HttpConnectionManager_SANITIZE +} + +func buildSetCurrentClientCertDetails(in *ir.HeaderSettings) *hcmv3.HttpConnectionManager_SetCurrentClientCertDetails { + if in == nil { + return nil + } + + if in.XForwardedClientCert == nil { + return nil + } + + if len(in.XForwardedClientCert.CertDetailsToAdd) == 0 { + return nil + } + + clientCertDetails := &hcmv3.HttpConnectionManager_SetCurrentClientCertDetails{} + for _, data := range in.XForwardedClientCert.CertDetailsToAdd { + switch data { + case ir.ClientCertDataCert: + clientCertDetails.Cert = true + case ir.ClientCertDataChain: + clientCertDetails.Chain = true + case ir.ClientCertDataDNS: + clientCertDetails.Dns = true + case ir.ClientCertDataSubject: + clientCertDetails.Subject = &wrapperspb.BoolValue{Value: true} + case ir.ClientCertDataURI: + clientCertDetails.Uri = true + } + } + + return clientCertDetails +} diff --git a/internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.yaml b/internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.yaml new file mode 100644 index 000000000000..d2ea5948ad23 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.yaml @@ -0,0 +1,196 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10001 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: Sanitize + certDetailsToAdd: + - Subject + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10001 +- name: "second-listener" + address: "0.0.0.0" + port: 10002 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: AppendForward + certDetailsToAdd: [] + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "second-route" + hostname: "*" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10002 +- name: "third-listener" + address: "0.0.0.0" + port: 10003 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: AppendForward + certDetailsToAdd: + - Subject + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "third-route" + hostname: "*" + destination: + name: "third-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10003 +- name: "fourth-listener" + address: "0.0.0.0" + port: 10004 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: SanitizeSet + certDetailsToAdd: + - Subject + - Dns + - Uri + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "fourth-route" + hostname: "*" + destination: + name: "fourth-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10004 +- name: "fifth-listener" + address: "0.0.0.0" + port: 10005 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: SanitizeSet + certDetailsToAdd: + - Subject + - Dns + - Chain + - Cert + - Uri + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "fifth-route" + hostname: "*" + destination: + name: "fifth-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10005 diff --git a/internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate.yaml b/internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate.yaml new file mode 100644 index 000000000000..72eaea1f58e4 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/mutual-tls-forward-client-certificate.yaml @@ -0,0 +1,181 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10001 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: Sanitize + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10001 +- name: "second-listener" + address: "0.0.0.0" + port: 10002 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: ForwardOnly + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "second-route" + hostname: "*" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10002 +- name: "third-listener" + address: "0.0.0.0" + port: 10003 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: AppendForward + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "third-route" + hostname: "*" + destination: + name: "third-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10003 +- name: "fourth-listener" + address: "0.0.0.0" + port: 10004 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: SanitizeSet + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "fourth-route" + hostname: "*" + destination: + name: "fourth-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10004 +- name: "fifth-listener" + address: "0.0.0.0" + port: 10005 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + headers: + xForwardedClientCert: + mode: AlwaysForwardOnly + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "fifth-route" + hostname: "*" + destination: + name: "fifth-route-dest" + settings: + - endpoints: + - host: "10.0.0.1" + port: 10005 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.clusters.yaml new file mode 100644 index 000000000000..03e10ccd7fc2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.clusters.yaml @@ -0,0 +1,85 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: third-route-dest + lbPolicy: LEAST_REQUEST + name: third-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: fourth-route-dest + lbPolicy: LEAST_REQUEST + name: fourth-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: fifth-route-dest + lbPolicy: LEAST_REQUEST + name: fifth-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.endpoints.yaml new file mode 100644 index 000000000000..aca2f65d71ac --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.endpoints.yaml @@ -0,0 +1,60 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10002 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 +- clusterName: third-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10003 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: third-route-dest/backend/0 +- clusterName: fourth-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10004 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: fourth-route-dest/backend/0 +- clusterName: fifth-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10005 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: fifth-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.listeners.yaml new file mode 100644 index 000000000000..ea4d4d44a37c --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.listeners.yaml @@ -0,0 +1,301 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10001 + drainType: MODIFY_ONLY + filterChains: + - 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: + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: first-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10002 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: APPEND_FORWARD + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: second-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10003 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: APPEND_FORWARD + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: third-listener + serverHeaderTransformation: PASS_THROUGH + setCurrentClientCertDetails: + subject: true + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: third-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10004 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: SANITIZE_SET + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: fourth-listener + serverHeaderTransformation: PASS_THROUGH + setCurrentClientCertDetails: + dns: true + subject: true + uri: true + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: fourth-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10005 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: SANITIZE_SET + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: fifth-listener + serverHeaderTransformation: PASS_THROUGH + setCurrentClientCertDetails: + cert: true + chain: true + dns: true + subject: true + uri: true + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: fifth-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.routes.yaml new file mode 100644 index 000000000000..952278bf43d2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.routes.yaml @@ -0,0 +1,70 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: third-listener + virtualHosts: + - domains: + - '*' + name: third-listener/* + routes: + - match: + prefix: / + name: third-route + route: + cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: fourth-listener + virtualHosts: + - domains: + - '*' + name: fourth-listener/* + routes: + - match: + prefix: / + name: fourth-route + route: + cluster: fourth-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: fifth-listener + virtualHosts: + - domains: + - '*' + name: fifth-listener/* + routes: + - match: + prefix: / + name: fifth-route + route: + cluster: fifth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.secrets.yaml new file mode 100644 index 000000000000..b35ba555fa0e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate-with-custom-data.secrets.yaml @@ -0,0 +1,80 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.clusters.yaml new file mode 100644 index 000000000000..03e10ccd7fc2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.clusters.yaml @@ -0,0 +1,85 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: third-route-dest + lbPolicy: LEAST_REQUEST + name: third-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: fourth-route-dest + lbPolicy: LEAST_REQUEST + name: fourth-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: fifth-route-dest + lbPolicy: LEAST_REQUEST + name: fifth-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.endpoints.yaml new file mode 100644 index 000000000000..aca2f65d71ac --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.endpoints.yaml @@ -0,0 +1,60 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10002 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 +- clusterName: third-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10003 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: third-route-dest/backend/0 +- clusterName: fourth-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10004 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: fourth-route-dest/backend/0 +- clusterName: fifth-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 10005 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: fifth-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.listeners.yaml new file mode 100644 index 000000000000..b063af61619a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.listeners.yaml @@ -0,0 +1,289 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10001 + drainType: MODIFY_ONLY + filterChains: + - 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: + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: first-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10002 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: FORWARD_ONLY + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: second-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10003 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: APPEND_FORWARD + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: third-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: third-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10004 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: SANITIZE_SET + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: fourth-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: fourth-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10005 + drainType: MODIFY_ONLY + filterChains: + - 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 + forwardClientCertDetails: ALWAYS_FORWARD_ONLY + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - 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: fifth-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: false + name: fifth-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.routes.yaml new file mode 100644 index 000000000000..952278bf43d2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.routes.yaml @@ -0,0 +1,70 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: third-listener + virtualHosts: + - domains: + - '*' + name: third-listener/* + routes: + - match: + prefix: / + name: third-route + route: + cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: fourth-listener + virtualHosts: + - domains: + - '*' + name: fourth-listener/* + routes: + - match: + prefix: / + name: fourth-route + route: + cluster: fourth-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: fifth-listener + virtualHosts: + - domains: + - '*' + name: fifth-listener/* + routes: + - match: + prefix: / + name: fifth-route + route: + cluster: fifth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.secrets.yaml new file mode 100644 index 000000000000..b35ba555fa0e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls-forward-client-certificate.secrets.yaml @@ -0,0 +1,80 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 1e3391760b7b..40f6a28d2948 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -472,6 +472,25 @@ _Appears in:_ | `claim` | _string_ | true | Claim is the JWT Claim that should be saved into the header : it can be a nested claim of type
(eg. "claim.nested.key", "sub"). The nested claim name must use dot "."
to separate the JSON name path. | +#### ClientCertData + +_Underlying type:_ _string_ + +Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header +By default, x-forwarded-client-cert (XFCC) will always include By and Hash data + +_Appears in:_ +- [XForwardedClientCert](#xforwardedclientcert) + +| Value | Description | +| ----- | ----------- | +| `Subject` | Whether to forward the subject of the client cert.
| +| `Cert` | Whether to forward the entire client cert in URL encoded PEM format.
This will appear in the XFCC header comma separated from other values with the value Cert=”PEM”.
| +| `Chain` | Whether to forward the entire client cert chain (including the leaf cert) in URL encoded PEM format.
This will appear in the XFCC header comma separated from other values with the value Chain=”PEM”.
| +| `Dns` | Whether to forward the DNS type Subject Alternative Names of the client cert.
| +| `Uri` | Whether to forward the URI type Subject Alternative Name of the client cert.
| + + #### ClientIPDetectionSettings @@ -1530,6 +1549,24 @@ _Appears in:_ | `after` | _[EnvoyFilter](#envoyfilter)_ | true | After defines the filter that should come after the filter.
Only one of Before or After must be set. | +#### ForwardMode + +_Underlying type:_ _string_ + +Envoy Proxy mode how to handle the x-forwarded-client-cert (XFCC) HTTP header. + +_Appears in:_ +- [XForwardedClientCert](#xforwardedclientcert) + +| Value | Description | +| ----- | ----------- | +| `Sanitize` | Do not send the XFCC header to the next hop. This is the default value.
| +| `ForwardOnly` | When the client connection is mTLS (Mutual TLS), forward the XFCC header
in the request.
| +| `AppendForward` | When the client connection is mTLS, append the client certificate
information to the request’s XFCC header and forward it.
| +| `SanitizeSet` | When the client connection is mTLS, reset the XFCC header with the client
certificate information and send it to the next hop.
| +| `AlwaysForwardOnly` | Always forward the XFCC header in the request, regardless of whether the
client connection is mTLS.
| + + #### GRPCExtAuthService @@ -1797,6 +1834,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `enableEnvoyHeaders` | _boolean_ | false | EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests
and responses. | +| `xForwardedClientCert` | _[XForwardedClientCert](#xforwardedclientcert)_ | false | Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header.
When enabled, Hash and By is always set | | `withUnderscoresAction` | _[WithUnderscoresAction](#withunderscoresaction)_ | false | WithUnderscoresAction configures the action to take when an HTTP header with underscores
is encountered. The default action is to reject the request. | | `preserveXRequestID` | _boolean_ | false | PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge
(Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour.
It defaults to false. | @@ -3542,6 +3580,21 @@ _Appears in:_ | `post` | _[XDSTranslatorHook](#xdstranslatorhook) array_ | true | | +#### XForwardedClientCert + + + +Configure Envoy proxy how to handle the x-forwarded-client-cert (XFCC) HTTP header. + +_Appears in:_ +- [HeaderSettings](#headersettings) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `mode` | _[ForwardMode](#forwardmode)_ | false | Envoy Proxy mode how to handle the x-forwarded-client-cert (XFCC) HTTP header. | +| `certDetailsToAdd` | _[ClientCertData](#clientcertdata) array_ | false | Specifies the fields in the client certificate to be forwarded on the x-forwarded-client-cert (XFCC) HTTP header | + + #### XForwardedForSettings From 926d572ba25c6519a61286e20c6ed46b6bd0b661 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 07:57:19 +0800 Subject: [PATCH 25/25] build(deps): bump helm.sh/helm/v3 from 3.14.4 to 3.15.0 (#3436) Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.14.4 to 3.15.0. - [Release notes](https://github.com/helm/helm/releases) - [Commits](https://github.com/helm/helm/compare/v3.14.4...v3.15.0) --- updated-dependencies: - dependency-name: helm.sh/helm/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f32eaef58c13..f39bcd3994f1 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v3 v3.0.1 - helm.sh/helm/v3 v3.14.4 + helm.sh/helm/v3 v3.15.0 k8s.io/api v0.30.0 k8s.io/apiextensions-apiserver v0.30.0 k8s.io/apimachinery v0.30.0 diff --git a/go.sum b/go.sum index df1a517bd446..6fec7be6fc3d 100644 --- a/go.sum +++ b/go.sum @@ -922,8 +922,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -helm.sh/helm/v3 v3.14.4 h1:6FSpEfqyDalHq3kUr4gOMThhgY55kXUEjdQoyODYnrM= -helm.sh/helm/v3 v3.14.4/go.mod h1:Tje7LL4gprZpuBNTbG34d1Xn5NmRT3OWfBRwpOSer9I= +helm.sh/helm/v3 v3.15.0 h1:gcLxHeFp0Hfo7lYi6KIZ84ZyvlAnfFRSJ8lTL3zvG5U= +helm.sh/helm/v3 v3.15.0/go.mod h1:fvfoRcB8UKRUV5jrIfOTaN/pG1TPhuqSb56fjYdTKXg= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=