Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions test/e2e/features/listenerset/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,71 @@ func (s *testingSuite) TestPolicies() {
expectOKWithCustomHeader("policy", "gateway"))
}

func (s *testingSuite) TestHTTPSListenerSet() {
// Verify Gateway has attached listener sets
s.TestInstallation.AssertionsT(s.T()).EventuallyGatewayCondition(s.Ctx, proxyObjectMeta.Name, proxyObjectMeta.Namespace, listener.GatewayConditionAttachedListenerSets, metav1.ConditionTrue)

// Verify HTTPS XListenerSet is accepted and programmed
s.TestInstallation.AssertionsT(s.T()).EventuallyListenerSetStatus(s.Ctx, httpsListenerSet.GetName(), httpsListenerSet.GetNamespace(),
gwxv1a1.ListenerSetStatus{
Conditions: []metav1.Condition{
{
Type: string(gwxv1a1.ListenerSetConditionAccepted),
Status: metav1.ConditionTrue,
Reason: string(gwxv1a1.ListenerSetReasonAccepted),
},
{
Type: string(gwxv1a1.ListenerSetConditionProgrammed),
Status: metav1.ConditionTrue,
Reason: string(gwxv1a1.ListenerSetReasonProgrammed),
},
},
Listeners: []gwxv1a1.ListenerEntryStatus{
{
Name: "https",
Port: gwxv1a1.PortNumber(httpsListenerPort), //nolint:gosec // G115: test port constant is int, always in valid range
AttachedRoutes: 1,
Conditions: []metav1.Condition{
{
Type: string(gwxv1a1.ListenerEntryConditionAccepted),
Status: metav1.ConditionTrue,
Reason: string(gwxv1a1.ListenerEntryReasonAccepted),
},
{
Type: string(gwxv1a1.ListenerEntryConditionConflicted),
Status: metav1.ConditionFalse,
Reason: string(gwv1.ListenerReasonNoConflicts),
},
{
Type: string(gwxv1a1.ListenerEntryConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: string(gwxv1a1.ListenerEntryReasonResolvedRefs),
},
{
Type: string(gwxv1a1.ListenerEntryConditionProgrammed),
Status: metav1.ConditionTrue,
Reason: string(gwxv1a1.ListenerEntryReasonProgrammed),
},
},
},
},
})

// Test HTTPS connectivity on XListenerSet
// This verifies that TLS termination works correctly on HTTPS listeners
s.TestInstallation.AssertionsT(s.T()).AssertEventualCurlResponse(
s.Ctx,
defaults.CurlPodExecOpt,
[]curl.Option{
curl.WithHost(kubeutils.ServiceFQDN(proxyService.ObjectMeta)),
curl.WithPort(httpsListenerPort),
curl.WithScheme("https"),
curl.IgnoreServerCert(), // Self-signed certificate
curl.WithHostHeader("https-listenerset.com"),
},
expectOK)
}

func (s *testingSuite) expectValidListenerSetAccepted(obj client.Object) {
s.TestInstallation.AssertionsT(s.T()).EventuallyGatewayCondition(s.Ctx, proxyObjectMeta.Name, proxyObjectMeta.Namespace, listener.GatewayConditionAttachedListenerSets, metav1.ConditionTrue)

Expand Down
57 changes: 57 additions & 0 deletions test/e2e/features/listenerset/testdata/https-listenerset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: XListenerSet
metadata:
name: https-ls
namespace: allowed-ns
spec:
parentRef:
kind: Gateway
group: gateway.networking.k8s.io
name: gw
namespace: default
listeners:
- name: https
protocol: HTTPS
port: 8443
tls:
certificateRefs:
- group: ""
kind: Secret
name: test-tls-xls
namespace: default
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: https-ls-route
namespace: default
spec:
parentRefs:
- kind: XListenerSet
group: gateway.networking.x-k8s.io
name: https-ls
namespace: allowed-ns
hostnames:
- "https-listenerset.com"
rules:
- backendRefs:
- name: example-svc
port: 8080
---
# ReferenceGrant to allow XListenerSet in allowed-ns to reference Secret in default namespace
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-tls-secret-from-allowed-ns
namespace: default
spec:
from:
- group: gateway.networking.x-k8s.io
kind: XListenerSet
namespace: allowed-ns
to:
- group: ""
kind: Secret
20 changes: 20 additions & 0 deletions test/e2e/features/listenerset/testdata/tls-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Self-signed TLS certificate for HTTPS XListenerSet tests
# Reusing the same certificate generation approach as frontendtls tests
# Generated with:
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
# -keyout tls.key -out tls.crt \
# -subj "/C=US/ST=California/L=San Francisco/O=Example Inc./CN=example.com" \
# -addext "subjectAltName=DNS:example.com,DNS:www.example.com"
#
# Then base64 encoded for Kubernetes:
# cat tls.crt | base64 -w 0
# cat tls.key | base64 -w 0
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: test-tls-xls
namespace: default
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURwakNDQW82Z0F3SUJBZ0lVVnZ6QlFqcFpGWllFbEdGVG1JUTNJK0lVaTFZd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1p6RUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2tOaGJHbG1iM0p1YVdFeEZqQVVCZ05WQkFjTQpEVk5oYmlCR2NtRnVZMmx6WTI4eEZUQVRCZ05WQkFvTURFVjRZVzF3YkdVZ1NXNWpMakVVTUJJR0ExVUVBd3dMClpYaGhiWEJzWlM1amIyMHdIaGNOTWpVd01qSTFNakExTXpVMldoY05NelV3TWpJek1qQTFNelUyV2pCbk1Rc3cKQ1FZRFZRUUdFd0pWVXpFVE1CRUdBMVVFQ0F3S1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ3d05VMkZ1SUVaeQpZVzVqYVhOamJ6RVZNQk1HQTFVRUNnd01SWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsCkxtTnZiVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLQ2dQTVBQQWc0dXdUdnoKc3lWYnBVdk1vRGFmbnEvVGJQVzNpcU5EUyttUnkrdzhKWlgvNzkwTzNuNzdvYUJRd3o5QTdaazdza21nYjhNUwpRMGFod3ZPMzRnU0tHamwrVXQySllTL3JXNmdLTWJmUjVDNWhPVzRTbVhCTzJDWFErRk8rZm53K1VSanhWUFN1ClArcEtrTWhBVnBSdlZQZmZYMm1lT05INjN0V05aWnBGaDRvQVE4YStpMUFiZXE3VGxvOE1XRFowdHJLVGlrQnYKSUN2S1FuYi8xbjN1eEdQaytJYjZtSHZSQ0NyK2NFZ1FVNURnR1lZQ3k4cllabythRXpCQzdkTXBDdXJtZnVvZgpXSzBvbFF2UytQWXpyc0hyeFBERGY5cHB0WUg4T25uRm4zTHJoSGd0OEVOVWh4Zjhjd2lYS0Y0cVlqT2p4NWJECkdaME5kWEVDQXdFQUFhTktNRWd3SndZRFZSMFJCQ0F3SG9JTFpYaGhiWEJzWlM1amIyMkNEM2QzZHk1bGVHRnQKY0d4bExtTnZiVEFkQmdOVkhRNEVGZ1FVOXdtUUpQYnBpV1dieXZneFZ3WHNMSkxsU1Jvd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBQzhaZjA0MnlhVHFnZXpiTjZrL1lObG1MWnBWTWNUaytMajF4VXh3Y2xQRFM2ZmZPaytaCnZOajArNXFIb3U1Y05CUHlvY2FhVU52MWZPcndNMCtKZTJNZytQM25NT3Bia0RvcHhsUXQvS2N2eGJQVFJnazgKYzlaaE10T3ZlR2E4b3JIRHQrQTNaVXpwUEdiUHZwRzZDU1FWR0JnMjFrb0JCMzIzVVdjUzNQRE9iWmNLN0sySgpBYWJHbHU3bHdSazlFRDkyWEVCL3o4TDJ3TmduQjFlajhvV2ZUSS9wT0NKMEs2MnVBemVKQTI3ZUZxUGs0azdNCmY2Y3lHRjQxRzdQUnVPT2pxNmNmTGd5YVAvLzlhdWh5U2JSVlhJWG1kWTQzZ0czaWpoR2xNNXlXVEx5cVFWYUMKUVk4M0d5OXNERmN1OWgrbm1mUHpWdWpkQ2wwb29ZNmY2RkU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQ2dvRHpEendJT0xzRTcKODdNbFc2Vkx6S0EybjU2djAyejF0NHFqUTB2cGtjdnNQQ1dWLysvZER0NSsrNkdnVU1NL1FPMlpPN0pKb0cvRApFa05Hb2NMenQrSUVpaG81ZmxMZGlXRXY2MXVvQ2pHMzBlUXVZVGx1RXBsd1R0Z2wwUGhUdm41OFBsRVk4VlQwCnJqL3FTcERJUUZhVWIxVDMzMTlwbmpqUit0N1ZqV1dhUlllS0FFUEd2b3RRRzNxdTA1YVBERmcyZExheWs0cEEKYnlBcnlrSjIvOVo5N3NSajVQaUcrcGg3MFFncS9uQklFRk9RNEJtR0FzdksyR2FQbWhNd1F1M1RLUXJxNW43cQpIMWl0S0pVTDB2ajJNNjdCNjhUd3czL2FhYldCL0RwNXhaOXk2NFI0TGZCRFZJY1gvSE1JbHloZUttSXpvOGVXCnd4bWREWFZ4QWdNQkFBRUNnZ0VBQWVwQlYvQk56UGczQWg3TG5CWEhMbmRhNlVqbTBQenVQQmRoSFZFRDBEci8KT1lIbktlaGtvSWx6VFJ0ZUEzNTd2TGtOaXJENW11d0hDUmU1cGlqdkJnSWdhOURqaE1wVGw5NDN0dzI1OFdRaApYQ29tWUFoR3QwakxIdnlxWTVzM05sMTdoQWZoenhranJWZzZnQ0JVdkUwRWI1cjdISE5EbWQwS0Q5ZVJEQVhVCmEybVBvMy9zeCs2aktOdm1nbkhVNW1HYTByYTlYOWdWMmorcXkrRkwwWW1jWEphOXYwam9vTUJtck5LUTl1MEUKbFpIQ3Jod3o1Zm5WOEg1SWs5STJFc0JlV083RDBtSjErZjZiU0xkNFRjNWlpdGtLbUprU0N1Wks4bWhjWW1PTAozcFdleXcvTTFWcmdCU3Y3UnBnK2ZXUUl5WSsvN0pqMDhrY2Ryaml2MVFLQmdRRGV3TmZNQXMrSndrbDNsRzVRCkhxUXdlcEIrdGNIdlJtaE5BQVhpN0xhbWFMQ3EvcDVaVlVOa1hNTFljZG5CTWpzd2ZwM0dmVzFvWXh0cU1JWWIKU3lrSzgyNloyeG05UlpLd2loWDNzOUlBR3ZzSkFsampmOWZTa2JjU29CYmNjVnhMaGhTU05QTkxHRUVkdDY2QQpCTGlJM1ByK0NHaUZUZDFveDB5M1drY3BPd0tCZ1FDNG1aT1NmcHM3L0Qra2w2MUJCdW9nS2oxeGN4Uzk4RHVaCjVGTTJxZE1hN3hMRkNDdlNYempwOTR0ZGQ2eG9saDhPc0J0WlVwbXRhZzZ4OFpQTUhKbGxOVVNzYTU0Y3YvT2gKeVgzNzlSSDdFbFdMYVkwdHFuNU9pUDZvSnAvWm41MUI2MCtBaGg5V0NWRXhlK1JQVXE5NE51QXFTZWZicHVpUQpVejFVY3daUlF3S0JnUUNuTmtQSDFXUk5tUmJsT1BzR0VicFcyZXFWODRLOVJ6RU1mRFB2QUpxcm1ITG1LWFJjCnd2QnY2bUlwY0cxeDVXOGhIQ3I3MFRQTDVIbXo0UEVLbEFVZlAxV0xFVG5sSnREU3pSVm9lQWZ3SkZERmxvbDcKWFlCNWhRRFVibkE2MHEzaDA2aWxpRElKOFE4UWE4NEdNNFVDMkQ5aGFwWnJXdVFWdjJZTFRTMlYrUUtCZ0ZvcAoyT1J5cGt1ME56bWpRK0pCQ0ZYUmk5VS95bC9EV0xrZnhtMHFvWXZFUGJ5eTh3UjdzZ2JFKy9NWklzS3FvRnpDCk0zbDdXTWhVeHZ5dTYrdUVCSUJrZGpocEQvOG0yazZwWmJtTXg4MkQ5UGgxQTVuTWJvalpiTmlnbE83c2dSalQKWUM5OFV3M28yeGw2VTlkU29aWHI1NjJBRDVrL2V0UVRkQjh0VjJhVkFvR0JBSjBraHpPWHdPNE5DeHZhMlQ1QQo1bFJNSXJwS0NZZXd3am1VaEhOczFWejc3cFVVMG9QNFd3UmxBWHZkdUhuTjNRb3RZQTZPQ1laMXZOUkJsK3JlCk0xU0dxTFpVWjVxa0s3enphelNXRU80TDhOR2NOeXBOUHlSakpKWjh5TXRiSGpuT1VWNWJZSlZPNXcvMFJxaWYKUFpCRXg3UDhpZWZhZVVGbWs2OXRKZW1DCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
26 changes: 20 additions & 6 deletions test/e2e/features/listenerset/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ var (
invalidListenerSetNonExistingGWManifest = filepath.Join(fsutils.MustGetThisDir(), "testdata", "invalid-listenerset-non-existing-gw.yaml")
conflictedListenerSetManifest = filepath.Join(fsutils.MustGetThisDir(), "testdata", "conflicted-listenerset.yaml")
policyManifest = filepath.Join(fsutils.MustGetThisDir(), "testdata", "policies.yaml")
tlsSecretManifest = filepath.Join(fsutils.MustGetThisDir(), "testdata", "tls-secret.yaml")
httpsListenerSetManifest = filepath.Join(fsutils.MustGetThisDir(), "testdata", "https-listenerset.yaml")

gwListener1Port = 80
gwListener2Port = 8081
ls1Listener1Port = 90
ls1Listener2Port = 8091
ls2Listener1Port = 8095
ls3Listener1Port = 88
gwListener1Port = 80
gwListener2Port = 8081
ls1Listener1Port = 90
ls1Listener2Port = 8091
ls2Listener1Port = 8095
ls3Listener1Port = 88
httpsListenerPort = 8443

proxyObjectMeta = metav1.ObjectMeta{
Name: "gw",
Expand Down Expand Up @@ -72,6 +75,14 @@ var (
},
}

// TestHTTPSListenerSet
httpsListenerSet = &gwxv1a1.XListenerSet{
ObjectMeta: metav1.ObjectMeta{
Name: "https-ls",
Namespace: "allowed-ns",
},
}

expectOK = &testmatchers.HttpResponse{
StatusCode: http.StatusOK,
Body: gstruct.Ignore(),
Expand Down Expand Up @@ -115,5 +126,8 @@ var (
"TestConflictedListenerSet": {
Manifests: []string{validListenerSetManifest, conflictedListenerSetManifest},
},
"TestHTTPSListenerSet": {
Manifests: []string{tlsSecretManifest, httpsListenerSetManifest},
},
}
)