From aec6c6f388a071066cd0c38af2f8635bd740fc38 Mon Sep 17 00:00:00 2001 From: Steven Jin Xuan Date: Mon, 2 Mar 2026 11:09:11 -0500 Subject: [PATCH] fix: deduplicate TLS CertificateRefs in gateway listeners --- pkg/i2gw/providers/common/converter.go | 6 +- pkg/i2gw/providers/common/converter_test.go | 102 ++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/pkg/i2gw/providers/common/converter.go b/pkg/i2gw/providers/common/converter.go index 0340fa2f1..797d1770c 100644 --- a/pkg/i2gw/providers/common/converter.go +++ b/pkg/i2gw/providers/common/converter.go @@ -228,12 +228,16 @@ func (a *ingressAggregator) toHTTPRoutesAndGateways(options i2gw.ProviderImpleme if len(rg.tls) > 0 { listener.TLS = &gatewayv1.ListenerTLSConfig{} } + certNames := map[string]struct{}{} for _, tls := range rg.tls { + certNames[tls.SecretName] = struct{}{} + } + for certName := range certNames { listener.TLS.CertificateRefs = append(listener.TLS.CertificateRefs, gatewayv1.SecretObjectReference{ Group: ptr.To(gatewayv1.Group("")), Kind: ptr.To(gatewayv1.Kind("Secret")), - Name: gatewayv1.ObjectName(tls.SecretName), + Name: gatewayv1.ObjectName(certName), }) } gwKey := fmt.Sprintf("%s/%s", rg.namespace, rg.ingressClass) diff --git a/pkg/i2gw/providers/common/converter_test.go b/pkg/i2gw/providers/common/converter_test.go index f71537327..1ed8c4d9a 100644 --- a/pkg/i2gw/providers/common/converter_test.go +++ b/pkg/i2gw/providers/common/converter_test.go @@ -229,6 +229,108 @@ func Test_ToIR(t *testing.T) { }, expectedErrors: field.ErrorList{}, }, + { + name: "ingress with duplicate TLS secret names deduplicates CertificateRefs", + ingresses: []networkingv1.Ingress{{ + ObjectMeta: metav1.ObjectMeta{Name: "dup-tls", Namespace: "test"}, + Spec: networkingv1.IngressSpec{ + TLS: []networkingv1.IngressTLS{ + { + Hosts: []string{"foo.example.com"}, + SecretName: "shared-cert", + }, + { + Hosts: []string{"bar.example.com"}, + SecretName: "shared-cert", + }, + }, + Rules: []networkingv1.IngressRule{{ + Host: "foo.example.com", + IngressRuleValue: networkingv1.IngressRuleValue{ + HTTP: &networkingv1.HTTPIngressRuleValue{ + Paths: []networkingv1.HTTPIngressPath{{ + Path: "/", + PathType: &iPrefix, + Backend: networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{ + Name: "foo-svc", + Port: networkingv1.ServiceBackendPort{ + Number: 80, + }, + }, + }, + }}, + }, + }, + }}, + IngressClassName: PtrTo("dup-tls"), + }, + }}, + servicePorts: map[types.NamespacedName]map[string]int32{}, + expectedIR: providerir.ProviderIR{ + Gateways: map[types.NamespacedName]providerir.GatewayContext{ + {Namespace: "test", Name: "dup-tls"}: { + Gateway: gatewayv1.Gateway{ + ObjectMeta: metav1.ObjectMeta{Name: "dup-tls", Namespace: "test"}, + Spec: gatewayv1.GatewaySpec{ + GatewayClassName: "dup-tls", + Listeners: []gatewayv1.Listener{{ + Name: "foo-example-com-http", + Port: 80, + Protocol: gatewayv1.HTTPProtocolType, + Hostname: PtrTo(gatewayv1.Hostname("foo.example.com")), + }, { + Name: "foo-example-com-https", + Port: 443, + Protocol: gatewayv1.HTTPSProtocolType, + Hostname: PtrTo(gatewayv1.Hostname("foo.example.com")), + TLS: &gatewayv1.ListenerTLSConfig{ + CertificateRefs: []gatewayv1.SecretObjectReference{{ + Group: ptr.To(gatewayv1.Group("")), + Kind: ptr.To(gatewayv1.Kind("Secret")), + Name: "shared-cert", + }}, + }, + }}, + }, + }, + }, + }, + HTTPRoutes: map[types.NamespacedName]providerir.HTTPRouteContext{ + {Namespace: "test", Name: "dup-tls-foo-example-com"}: { + HTTPRoute: gatewayv1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{Name: "dup-tls-foo-example-com", Namespace: "test"}, + Spec: gatewayv1.HTTPRouteSpec{ + CommonRouteSpec: gatewayv1.CommonRouteSpec{ + ParentRefs: []gatewayv1.ParentReference{{ + Name: "dup-tls", + }}, + }, + Hostnames: []gatewayv1.Hostname{"foo.example.com"}, + Rules: []gatewayv1.HTTPRouteRule{{ + Name: ptr.To(gatewayv1.SectionName("rule-0")), + Matches: []gatewayv1.HTTPRouteMatch{{ + Path: &gatewayv1.HTTPPathMatch{ + Type: &gPathPrefix, + Value: PtrTo("/"), + }, + }}, + BackendRefs: []gatewayv1.HTTPBackendRef{{ + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: "foo-svc", + Port: PtrTo(gatewayv1.PortNumber(80)), + }, + }, + }}, + }}, + }, + }, + }, + }, + }, + expectedErrors: field.ErrorList{}, + }, { name: "ingress with custom and default backend", ingresses: []networkingv1.Ingress{{