diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index 46f09ae79aa..399ec929bc0 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -7,6 +7,7 @@ package gatewayapi import ( "fmt" + "reflect" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -144,13 +145,12 @@ func backendTLSTargetMatched(policy gwapiv1a3.BackendTLSPolicy, target gwapiv1a2 target.Kind == currTarget.Kind && backendNamespace == policy.Namespace && target.Name == currTarget.Name { - if currTarget.SectionName != nil { - if target.SectionName != nil && *currTarget.SectionName == *target.SectionName { - return true - } - return false + // if section name is not set, then it targets the entire backend + if currTarget.SectionName == nil { + return true + } else if reflect.DeepEqual(currTarget.SectionName, target.SectionName) { + return true } - return true } } return false diff --git a/internal/gatewayapi/testdata/backendtlspolicy-multiple-targets.in.yaml b/internal/gatewayapi/testdata/backendtlspolicy-multiple-targets.in.yaml new file mode 100644 index 00000000000..d3458d06da8 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtlspolicy-multiple-targets.in.yaml @@ -0,0 +1,123 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-btls + namespace: envoy-gateway + 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: + name: httproute-btls-1 + namespace: envoy-gateway + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-btls + sectionName: http + rules: + - matches: + - path: + type: Exact + value: "/exact-1" + backendRefs: + - name: http-backend + namespace: envoy-gateway + port: 8080 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-btls-2 + namespace: envoy-gateway + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-btls + sectionName: http + rules: + - matches: + - path: + type: Exact + value: "/exact-2" + backendRefs: + - name: http-backend + namespace: envoy-gateway + port: 8081 + +services: + - apiVersion: v1 + kind: Service + metadata: + name: http-backend + namespace: envoy-gateway + spec: + clusterIP: 10.11.12.13 + ports: + - port: 8080 + name: http + protocol: TCP + targetPort: 8080 + - port: 8081 + name: http + protocol: TCP + targetPort: 8081 + +configMaps: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-cmap + namespace: envoy-gateway + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL + BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw + MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G + A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc + 1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM + yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b + kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU + Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq + ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR + bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48 + 6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/ + BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz + 2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J + i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE + A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg + d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1 + 3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q== + -----END CERTIFICATE----- +backendTLSPolicies: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls + namespace: envoy-gateway + spec: + targetRefs: + - group: "" + kind: Service + name: http-backend + sectionName: "8080" + - group: "" + kind: Service + name: http-backend + sectionName: "8081" + validation: + caCertificateRefs: + - name: ca-cmap + group: "" + kind: ConfigMap + hostname: example.com diff --git a/internal/gatewayapi/testdata/backendtlspolicy-multiple-targets.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-multiple-targets.out.yaml new file mode 100644 index 00000000000..d83f18e117a --- /dev/null +++ b/internal/gatewayapi/testdata/backendtlspolicy-multiple-targets.out.yaml @@ -0,0 +1,237 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls + namespace: envoy-gateway + spec: + targetRefs: + - group: "" + kind: Service + name: http-backend + sectionName: "8080" + - group: "" + kind: Service + name: http-backend + sectionName: "8081" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: example.com + status: + ancestors: + - ancestorRef: + name: gateway-btls + namespace: envoy-gateway + sectionName: http + 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-btls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-btls-1 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-btls + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: http-backend + namespace: envoy-gateway + port: 8080 + matches: + - path: + type: Exact + value: /exact-1 + 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-btls + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-btls-2 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-btls + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: http-backend + namespace: envoy-gateway + port: 8081 + matches: + - path: + type: Exact + value: /exact-2 + 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-btls + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-btls: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-btls/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-btls + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-btls +xdsIR: + envoy-gateway/gateway-btls: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-btls + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-btls/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/envoy-gateway/httproute-btls-1/rule/0 + settings: + - protocol: HTTP + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls/envoy-gateway-ca + sni: example.com + weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-btls-1 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-btls-1/rule/0/match/0/* + pathMatch: + distinct: false + exact: /exact-1 + name: "" + - destination: + name: httproute/envoy-gateway/httproute-btls-2/rule/0 + settings: + - protocol: HTTP + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls/envoy-gateway-ca + sni: example.com + weight: 1 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-btls-2 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-btls-2/rule/0/match/0/* + pathMatch: + distinct: false + exact: /exact-2 + name: "" diff --git a/internal/provider/kubernetes/status_updater.go b/internal/provider/kubernetes/status_updater.go index 48a32c617a0..6e6cef37b8a 100644 --- a/internal/provider/kubernetes/status_updater.go +++ b/internal/provider/kubernetes/status_updater.go @@ -7,6 +7,7 @@ package kubernetes import ( "context" + "errors" "time" "github.com/go-logr/logr" @@ -56,14 +57,25 @@ func (m MutatorFunc) Mutate(old client.Object) client.Object { type UpdateHandler struct { log logr.Logger client client.Client + sendUpdates chan struct{} updateChannel chan Update + writer *UpdateWriter } func NewUpdateHandler(log logr.Logger, client client.Client) *UpdateHandler { + sendUpdates := make(chan struct{}) + updateChannel := make(chan Update, 100) return &UpdateHandler{ log: log, client: client, - updateChannel: make(chan Update, 100), + sendUpdates: sendUpdates, + updateChannel: updateChannel, + writer: &UpdateWriter{ + log: log, + enabled: sendUpdates, + updateChannel: updateChannel, + eventsBeforeEnabled: make(chan Update, 1000), + }, } } @@ -127,6 +139,10 @@ func (u *UpdateHandler) Start(ctx context.Context) error { u.log.Info("started status update handler") defer u.log.Info("stopped status update handler") + // Enable Updaters to start sending updates to this handler. + close(u.sendUpdates) + u.writer.handleEventsReceivedBeforeEnabled() + for { select { case <-ctx.Done(): @@ -142,9 +158,7 @@ func (u *UpdateHandler) Start(ctx context.Context) error { // Writer retrieves the interface that should be used to write to the UpdateHandler. func (u *UpdateHandler) Writer() Updater { - return &UpdateWriter{ - updateChannel: u.updateChannel, - } + return u.writer } // Updater describes an interface to send status updates somewhere. @@ -154,13 +168,40 @@ type Updater interface { // UpdateWriter takes status updates and sends these to the UpdateHandler via a channel. type UpdateWriter struct { + log logr.Logger + enabled <-chan struct{} updateChannel chan<- Update + // a temporary buffer to store events received before the Updater is enabled. + // These events will be sent to the update channel once the Updater is enabled. + eventsBeforeEnabled chan Update } // Send sends the given Update off to the update channel for writing by the UpdateHandler. func (u *UpdateWriter) Send(update Update) { // Non-blocking receive to see if we should pass along update. - u.updateChannel <- update + select { + case <-u.enabled: + u.updateChannel <- update + default: + if len(u.eventsBeforeEnabled) < cap(u.eventsBeforeEnabled) { + u.log.Info("received a status update while disabled, storing for later", "event", update.NamespacedName) + u.eventsBeforeEnabled <- update + } else { + // If the buffer is full, drop the event to avoid blocking the sender. + u.log.Error(errors.New("dropping status update, buffer full"), "event", update.NamespacedName) + } + } +} + +// handleEventsReceivedBeforeEnabled sends the events received before the Updater was enabled to the update channel. +func (u *UpdateWriter) handleEventsReceivedBeforeEnabled() { + go func() { + for e := range u.eventsBeforeEnabled { + u.log.Info("sending stored status update", "event", e.NamespacedName) + u.updateChannel <- e + } + close(u.eventsBeforeEnabled) + }() } // isStatusEqual checks if two objects have equivalent status. diff --git a/internal/xds/translator/testdata/in/extension-xds-ir/extensionpolicy-tcp-udp-http.yaml b/internal/xds/translator/testdata/in/extension-xds-ir/extensionpolicy-tcp-udp-http.yaml index 77ced570f46..6a5d283ee44 100644 --- a/internal/xds/translator/testdata/in/extension-xds-ir/extensionpolicy-tcp-udp-http.yaml +++ b/internal/xds/translator/testdata/in/extension-xds-ir/extensionpolicy-tcp-udp-http.yaml @@ -35,6 +35,15 @@ http: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 + routes: + - name: "http-route" + hostname: "*" + destination: + name: "http-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 tcp: - address: 0.0.0.0 extensionRefs: @@ -66,6 +75,13 @@ tcp: controllerName: gateway.envoyproxy.io/gatewayclass-controller name: envoy-gateway/gateway-1/tcp1 port: 10080 + routes: + - destination: + name: "tcp-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 udp: - address: 0.0.0.0 route: diff --git a/internal/xds/translator/testdata/in/xds-ir/listener-connection-limit.yaml b/internal/xds/translator/testdata/in/xds-ir/listener-connection-limit.yaml index 049ec905b9a..b8022bc0357 100644 --- a/internal/xds/translator/testdata/in/xds-ir/listener-connection-limit.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/listener-connection-limit.yaml @@ -44,16 +44,17 @@ tcp: connection: limit: value: 3 - tls: - passthrough: - snis: - - bar.com - destination: - name: "tls-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 + routes: + - tls: + inspector: + snis: + - bar.com + destination: + name: "tls-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 - name: "fourth-listener" address: "0.0.0.0" connection: @@ -61,9 +62,10 @@ tcp: value: 10 closeDelay: 3s port: 10083 - destination: - name: "tcp-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 + routes: + - destination: + name: "tcp-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/listener-tcp-keepalive.yaml b/internal/xds/translator/testdata/in/xds-ir/listener-tcp-keepalive.yaml index 9bdaf244912..19d7d3335d5 100644 --- a/internal/xds/translator/testdata/in/xds-ir/listener-tcp-keepalive.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/listener-tcp-keepalive.yaml @@ -43,24 +43,26 @@ tcp: address: "0.0.0.0" port: 10082 tcpKeepalive: {} - tls: - inspector: - snis: - - bar.com - destination: - name: "tls-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 + routes: + - tls: + inspector: + snis: + - bar.com + destination: + name: "tls-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 - name: "fourth-listener" address: "0.0.0.0" tcpKeepalive: probes: 10 port: 10083 - destination: - name: "tcp-route-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 + routes: + - destination: + name: "tcp-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml b/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml new file mode 100644 index 00000000000..cc24bfbdf00 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/listener-tcp-without-route.yaml @@ -0,0 +1,17 @@ +tcp: +- address: 0.0.0.0 + connection: + bufferLimit: 50000000 + limit: + closeDelay: 10s + value: 3 + enableProxyProtocol: true + name: envoy-gateway/gateway-1/tls-1 + port: 10443 + tcpKeepalive: + idleTime: 1200 + interval: 60 + probes: 3 + timeout: + tcp: + idleTimeout: 20m0s diff --git a/internal/xds/translator/testdata/in/xds-ir/tcp-endpoint-stats.yaml b/internal/xds/translator/testdata/in/xds-ir/tcp-endpoint-stats.yaml index 60176773c96..1bbe5a43371 100644 --- a/internal/xds/translator/testdata/in/xds-ir/tcp-endpoint-stats.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/tcp-endpoint-stats.yaml @@ -5,11 +5,12 @@ tcp: - name: "tcp-route-enable-endpoint-stats" address: "0.0.0.0" port: 10080 - destination: - name: "tcp-route-simple-dest" - settings: - - endpoints: - - host: "1.2.3.4" - port: 50000 - - host: "5.6.7.8" - port: 50001 + routes: + - destination: + name: "tcp-route-simple-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - host: "5.6.7.8" + port: 50001 diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.clusters.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.clusters.yaml index 8012c6fa499..2d37826ef84 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.clusters.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.clusters.yaml @@ -1,3 +1,37 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: http-route-dest + lbPolicy: LEAST_REQUEST + name: http-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tcp-route-dest + lbPolicy: LEAST_REQUEST + name: tcp-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS - circuitBreakers: thresholds: - maxRetries: 1024 diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.endpoints.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.endpoints.yaml index 8869685de5e..9308c055cfe 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.endpoints.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.endpoints.yaml @@ -1,3 +1,27 @@ +- clusterName: http-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: http-route-dest/backend/0 +- clusterName: tcp-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tcp-route-dest/backend/0 - clusterName: udp-route-dest endpoints: - lbEndpoints: diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.listeners.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.listeners.yaml index e3831830bba..4f350093600 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.listeners.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.listeners.yaml @@ -30,6 +30,13 @@ statPrefix: http useRemoteAddress: true name: envoy-gateway/gateway-1/http1 + filterChains: + - filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tcp-route-dest + statPrefix: tcp name: envoy-gateway/gateway-1/http1 perConnectionBufferLimitBytes: 32768 statPrefix: envoy-gateway/gateway-1/http1 diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.routes.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.routes.yaml index b03ec37faa6..bfcb22e483f 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.routes.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/extensionpolicy-tcp-udp-http.routes.yaml @@ -1,2 +1,14 @@ - ignorePortInHostMatching: true name: envoy-gateway/gateway-1/http1 + virtualHosts: + - domains: + - '*' + name: envoy-gateway/gateway-1/http1/* + routes: + - match: + prefix: / + name: http-route + route: + cluster: http-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.clusters.yaml index d65e267ad7d..a52251e32bf 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.clusters.yaml @@ -32,3 +32,37 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tls-route-dest + lbPolicy: LEAST_REQUEST + name: tls-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tcp-route-dest + lbPolicy: LEAST_REQUEST + name: tcp-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.endpoints.yaml index de95bf555b9..5b4fe89e58c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.endpoints.yaml @@ -22,3 +22,27 @@ loadBalancingWeight: 1 locality: region: second-route-dest/backend/0 +- clusterName: tls-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tls-route-dest/backend/0 +- clusterName: tcp-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tcp-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.listeners.yaml index 99c8be1aa99..a7b0190d7cc 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-connection-limit.listeners.yaml @@ -75,11 +75,43 @@ socketAddress: address: 0.0.0.0 portValue: 10082 + filterChains: + - filterChainMatch: + serverNames: + - bar.com + filters: + - name: envoy.filters.network.connection_limit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit + maxConnections: "3" + statPrefix: passthrough + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tls-route-dest + statPrefix: passthrough + listenerFilters: + - name: envoy.filters.listener.tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector name: third-listener perConnectionBufferLimitBytes: 32768 - address: socketAddress: address: 0.0.0.0 portValue: 10083 + filterChains: + - filters: + - name: envoy.filters.network.connection_limit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit + delay: 3s + maxConnections: "10" + statPrefix: tcp + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tcp-route-dest + statPrefix: tcp name: fourth-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.clusters.yaml index d65e267ad7d..a52251e32bf 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.clusters.yaml @@ -32,3 +32,37 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tls-route-dest + lbPolicy: LEAST_REQUEST + name: tls-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tcp-route-dest + lbPolicy: LEAST_REQUEST + name: tcp-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.endpoints.yaml index de95bf555b9..5b4fe89e58c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.endpoints.yaml @@ -22,3 +22,27 @@ loadBalancingWeight: 1 locality: region: second-route-dest/backend/0 +- clusterName: tls-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tls-route-dest/backend/0 +- clusterName: tcp-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tcp-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml index 52cc2cbf8ce..1c8a9a096ac 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml @@ -92,6 +92,20 @@ socketAddress: address: 0.0.0.0 portValue: 10082 + filterChains: + - filterChainMatch: + serverNames: + - bar.com + filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tls-route-dest + statPrefix: passthrough + listenerFilters: + - name: envoy.filters.listener.tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector name: third-listener perConnectionBufferLimitBytes: 32768 socketOptions: @@ -103,6 +117,13 @@ socketAddress: address: 0.0.0.0 portValue: 10083 + filterChains: + - filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tcp-route-dest + statPrefix: tcp name: fourth-listener perConnectionBufferLimitBytes: 32768 socketOptions: diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.clusters.yaml new file mode 100644 index 00000000000..0764d46f0ed --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.clusters.yaml @@ -0,0 +1,2 @@ +- name: EmptyCluster + type: STATIC diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.endpoints.yaml new file mode 100644 index 00000000000..fe51488c706 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.endpoints.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.listeners.yaml new file mode 100644 index 00000000000..e29000d3ed3 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.listeners.yaml @@ -0,0 +1,42 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10443 + filterChains: + - filters: + - name: envoy.filters.network.connection_limit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit + delay: 10s + maxConnections: "3" + statPrefix: tcp + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: EmptyCluster + idleTimeout: 1200s + statPrefix: tcp + name: EmptyCluster + listenerFilters: + - name: envoy.filters.listener.proxy_protocol + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol + name: envoy-gateway/gateway-1/tls-1 + perConnectionBufferLimitBytes: 50000000 + socketOptions: + - description: socket option to enable tcp keep alive + intValue: "1" + level: "1" + name: "9" + - description: socket option for keep alive probes + intValue: "3" + level: "6" + name: "6" + - description: socket option for keep alive idle time + intValue: "1200" + level: "6" + name: "4" + - description: socket option for keep alive interval + intValue: "60" + level: "6" + name: "5" diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.routes.yaml new file mode 100644 index 00000000000..fe51488c706 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-without-route.routes.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.clusters.yaml index fe51488c706..4387d9b31e0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.clusters.yaml @@ -1 +1,19 @@ -[] +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: tcp-route-simple-dest + lbPolicy: LEAST_REQUEST + name: tcp-route-simple-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + trackClusterStats: + perEndpointStats: true + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.endpoints.yaml index fe51488c706..7eb06a08f40 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.endpoints.yaml @@ -1 +1,18 @@ -[] +- clusterName: tcp-route-simple-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + - endpoint: + address: + socketAddress: + address: 5.6.7.8 + portValue: 50001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: tcp-route-simple-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.listeners.yaml index 2e300bdfaad..a3437c437a9 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-endpoint-stats.listeners.yaml @@ -2,5 +2,12 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + filterChains: + - filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: tcp-route-simple-dest + statPrefix: tcp name: tcp-route-enable-endpoint-stats perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 11edb94bacb..74c0070c4ca 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -39,7 +39,11 @@ var ( ErrXdsSecretExists = errors.New("xds secret exists") ) -const AuthorityHeaderKey = ":authority" +const ( + AuthorityHeaderKey = ":authority" + // The dummy cluster for TCP listeners that have no routes + emptyClusterName = "EmptyCluster" +) // Translator translates the xDS IR into xDS resources. type Translator struct { @@ -627,6 +631,31 @@ func (t *Translator) processTCPListenerXdsTranslation( errs = errors.Join(errs, err) } } + + // If there are no routes, add a route without a destination to the listener to create a filter chain + // This is needed because Envoy requires a filter chain to be present in the listener, otherwise it will reject the listener and report a warning + if len(tcpListener.Routes) == 0 { + emptyRouteCluster := &clusterv3.Cluster{ + Name: emptyClusterName, + ClusterDiscoveryType: &clusterv3.Cluster_Type{Type: clusterv3.Cluster_STATIC}, + } + + if findXdsCluster(tCtx, emptyClusterName) == nil { + if err := tCtx.AddXdsResource(resourcev3.ClusterType, emptyRouteCluster); err != nil { + errs = errors.Join(errs, err) + } + } + + emptyRoute := &ir.TCPRoute{ + Name: emptyClusterName, + Destination: &ir.RouteDestination{ + Name: emptyClusterName, + }, + } + if err := addXdsTCPFilterChain(xdsListener, emptyRoute, emptyClusterName, accesslog, tcpListener.Timeout, tcpListener.Connection); err != nil { + errs = errors.Join(errs, err) + } + } } return errs }