@@ -310,5 +310,111 @@ spec:
310310 assert .Equal (GinkgoT (), int64 (10 ), * tls [0 ].Client .Depth , "client depth should be 10" )
311311 assert .Contains (GinkgoT (), tls [0 ].Client .SkipMtlsURIRegex , skipMtlsUriRegex , "skip_mtls_uri_regex should be set" )
312312 })
313+
314+ It ("ApisixTls and Ingress with same certificate but different hosts" , func () {
315+ if framework .IngressVersion != "v1" {
316+ Skip ("skipping test in non-v1 ingress version" )
317+ }
318+ By ("create shared TLS secret" )
319+ err := s .NewKubeTlsSecret ("shared-tls-secret" , Cert , Key )
320+ Expect (err ).NotTo (HaveOccurred (), "creating shared TLS secret" )
321+
322+ const apisixTlsSpec = `
323+ apiVersion: apisix.apache.org/v2
324+ kind: ApisixTls
325+ metadata:
326+ name: test-apisixtls-shared
327+ spec:
328+ ingressClassName: %s
329+ hosts:
330+ - api6.com
331+ secret:
332+ name: shared-tls-secret
333+ namespace: %s
334+ `
335+
336+ By ("apply ApisixTls with api6.com" )
337+ var apisixTls apiv2.ApisixTls
338+ tlsSpec := fmt .Sprintf (apisixTlsSpec , s .Namespace (), s .Namespace ())
339+ applier .MustApplyAPIv2 (types.NamespacedName {Namespace : s .Namespace (), Name : "test-apisixtls-shared" }, & apisixTls , tlsSpec )
340+
341+ const ingressYamlWithTLS = `
342+ apiVersion: networking.k8s.io/v1
343+ kind: Ingress
344+ metadata:
345+ name: test-ingress-tls-shared
346+ spec:
347+ ingressClassName: %s
348+ tls:
349+ - hosts:
350+ - api7.com
351+ secretName: shared-tls-secret
352+ rules:
353+ - host: api7.com
354+ http:
355+ paths:
356+ - path: /
357+ pathType: Prefix
358+ backend:
359+ service:
360+ name: httpbin-service-e2e-test
361+ port:
362+ number: 80
363+ `
364+
365+ By ("apply Ingress with api7.com using same certificate" )
366+ err = s .CreateResourceFromString (fmt .Sprintf (ingressYamlWithTLS , s .Namespace ()))
367+ Expect (err ).NotTo (HaveOccurred (), "creating Ingress" )
368+
369+ By ("verify two SSL objects exist in control plane" )
370+ Eventually (func () bool {
371+ tls , err := s .DefaultDataplaneResource ().SSL ().List (context .Background ())
372+ if err != nil {
373+ return false
374+ }
375+ return len (tls ) == 2
376+ }).WithTimeout (30 * time .Second ).ProbeEvery (1 * time .Second ).Should (BeTrue ())
377+
378+ tls , err := s .DefaultDataplaneResource ().SSL ().List (context .Background ())
379+ assert .Nil (GinkgoT (), err , "list tls error" )
380+ assert .Len (GinkgoT (), tls , 2 , "should have exactly 2 SSL objects" )
381+
382+ By ("verify SSL objects have different IDs and SNIs" )
383+ sniFound := make (map [string ]bool )
384+
385+ for i := range tls {
386+ // Check certificate content is the same
387+ assert .Len (GinkgoT (), tls [i ].Certificates , 1 , "each SSL should have 1 certificate" )
388+ assert .Equal (GinkgoT (), Cert , tls [i ].Certificates [0 ].Certificate , "certificate should match" )
389+
390+ // Track SNIs
391+ for _ , sni := range tls [i ].Snis {
392+ sniFound [sni ] = true
393+ }
394+ }
395+
396+ By ("verify both hosts are covered" )
397+ assert .True (GinkgoT (), sniFound ["api6.com" ], "api6.com should be in SNIs" )
398+ assert .True (GinkgoT (), sniFound ["api7.com" ], "api7.com should be in SNIs" )
399+
400+ By ("test HTTPS request to api6.com" )
401+ Eventually (func () int {
402+ return s .NewAPISIXHttpsClient ("api6.com" ).
403+ GET ("/get" ).
404+ WithHost ("api6.com" ).
405+ Expect ().
406+ Raw ().StatusCode
407+ }).WithTimeout (30 * time .Second ).ProbeEvery (1 * time .Second ).Should (Equal (http .StatusOK ))
408+
409+ By ("test HTTPS request to api7.com" )
410+ Eventually (func () int {
411+ return s .NewAPISIXHttpsClient ("api7.com" ).
412+ GET ("/get" ).
413+ WithHost ("api7.com" ).
414+ Expect ().
415+ Raw ().StatusCode
416+ }).WithTimeout (30 * time .Second ).ProbeEvery (1 * time .Second ).Should (Equal (http .StatusOK ))
417+ })
418+
313419 })
314420})
0 commit comments