From e78dafb695427113c32f0a5b88ac70746a349b78 Mon Sep 17 00:00:00 2001 From: apkatsikas Date: Mon, 27 Apr 2026 15:39:22 -0400 Subject: [PATCH 1/4] fix(translator): set ListenerSet and listener Accepted:True for InvalidCertificateRef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a ListenerSet listener has an unresolvable TLS certificate reference (InvalidCertificateRef or RefNotPermitted), Accepted: False was incorrectly set on both the listener and ListenerSet object. The Gateway API spec places InvalidCertificateRef exclusively under ResolvedRefs, not Accepted — a missing certificate is a reference resolution concern, not a structural one. Fixes #8870 Signed-off-by: apkatsikas --- internal/gatewayapi/listenerset.go | 59 ++- ...policy-with-routing-type-listener.out.yaml | 5 + .../gateway-with-attached-routes.out.yaml | 5 + ...nvalid-multiple-tls-configuration.out.yaml | 5 + ...nfiguration-secret-does-not-exist.out.yaml | 5 + ...uration-secret-in-other-namespace.out.yaml | 5 + ...configuration-secret-is-not-valid.out.yaml | 5 + .../listenerset-conflict-listeners.out.yaml | 8 +- .../listenerset-cross-namespace.out.yaml | 8 +- .../testdata/listenerset-grpcroute.out.yaml | 8 +- .../testdata/listenerset-httproute.out.yaml | 4 +- ...tps-tls-misuses-gateway-namespace.out.yaml | 13 +- ...tls-mixed-valid-and-missing-secret.in.yaml | 112 ++++++ ...ls-mixed-valid-and-missing-secret.out.yaml | 360 ++++++++++++++++++ ...tenerset-https-tls-same-namespace.out.yaml | 4 +- ...et-https-tls-secret-does-not-exist.in.yaml | 73 ++++ ...t-https-tls-secret-does-not-exist.out.yaml | 230 +++++++++++ .../testdata/listenerset-invalid.out.yaml | 6 +- .../listenerset-no-maching-listener.out.yaml | 4 +- .../testdata/listenerset-tcproute.out.yaml | 4 +- .../testdata/listenerset-tlsroute.out.yaml | 4 +- .../testdata/listenerset-udproute.out.yaml | 4 +- internal/gatewayapi/validate.go | 27 +- 23 files changed, 899 insertions(+), 59 deletions(-) create mode 100644 internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml create mode 100644 internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml create mode 100644 internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml create mode 100644 internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml diff --git a/internal/gatewayapi/listenerset.go b/internal/gatewayapi/listenerset.go index 68cdb575ed..03cbfebcac 100644 --- a/internal/gatewayapi/listenerset.go +++ b/internal/gatewayapi/listenerset.go @@ -113,48 +113,69 @@ func (t *Translator) ProcessListenerSetStatus(listenerSets []*gwapiv1.ListenerSe } // Calculate status based on listeners - allListenersValid := true - anyListenerValid := false + allListenersAccepted := true + anyListenerAccepted := false + allListenersProgrammed := true + anyListenerProgrammed := false for _, lStatus := range ls.Status.Listeners { accepted := false + programmed := false for _, cond := range lStatus.Conditions { if cond.Type == string(gwapiv1.ListenerEntryConditionAccepted) && cond.Status == metav1.ConditionTrue { accepted = true - break + } + if cond.Type == string(gwapiv1.ListenerConditionProgrammed) && cond.Status == metav1.ConditionTrue { + programmed = true } } - anyListenerValid = anyListenerValid || accepted - allListenersValid = allListenersValid && accepted + anyListenerAccepted = anyListenerAccepted || accepted + allListenersAccepted = allListenersAccepted && accepted + anyListenerProgrammed = anyListenerProgrammed || programmed + allListenersProgrammed = allListenersProgrammed && programmed } var ( lsAccepted bool - lsReason gwapiv1.ListenerSetConditionReason + lsAcceptedReason gwapiv1.ListenerSetConditionReason + lsAcceptedMsg string + lsProgrammed bool lsProgrammedReason gwapiv1.ListenerSetConditionReason - lsMsg string + lsProgrammedMsg string ) switch { - case allListenersValid: + case allListenersAccepted: lsAccepted = true - lsReason = gwapiv1.ListenerSetReasonAccepted - lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed - lsMsg = "All listeners are valid" - case anyListenerValid: // TODO: implement PartiallyInvalid conditions when Gateway API supports it + lsAcceptedReason = gwapiv1.ListenerSetReasonAccepted + lsAcceptedMsg = "All listeners are accepted" + case anyListenerAccepted: // TODO: implement PartiallyInvalid conditions when Gateway API supports it lsAccepted = true - lsReason = gwapiv1.ListenerSetReasonListenersNotValid - lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed - lsMsg = "Some listeners are invalid" + lsAcceptedReason = gwapiv1.ListenerSetReasonListenersNotValid + lsAcceptedMsg = "Some listeners are invalid" default: lsAccepted = false - lsReason = gwapiv1.ListenerSetReasonListenersNotValid + lsAcceptedReason = gwapiv1.ListenerSetReasonListenersNotValid + lsAcceptedMsg = "No listeners are accepted" + } + + switch { + case allListenersProgrammed: + lsProgrammed = true + lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed + lsProgrammedMsg = "All listeners are programmed" + case anyListenerProgrammed: + lsProgrammed = true + lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed + lsProgrammedMsg = "Some listeners are not programmed" + default: + lsProgrammed = false lsProgrammedReason = gwapiv1.ListenerSetReasonListenersNotValid - lsMsg = "All listeners are invalid" + lsProgrammedMsg = "No listeners are programmed" } - status.UpdateListenerSetStatusAccepted(ls, lsAccepted, lsReason, lsMsg) - status.UpdateListenerSetStatusProgrammed(ls, lsAccepted, lsProgrammedReason, lsMsg) + status.UpdateListenerSetStatusAccepted(ls, lsAccepted, lsAcceptedReason, lsAcceptedMsg) + status.UpdateListenerSetStatusProgrammed(ls, lsProgrammed, lsProgrammedReason, lsProgrammedMsg) } } diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml index 41827b1006..04c0af5b6d 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml @@ -126,6 +126,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml index f11b451baf..430bf42173 100644 --- a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml @@ -108,6 +108,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml index 82b7f2918d..69173449ba 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml @@ -97,6 +97,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml index fdf22c3ae1..e71962d4a8 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml @@ -27,6 +27,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml index be22741fa9..d92e039aa1 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml @@ -28,6 +28,11 @@ gateways: reason: RefNotPermitted status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml index 5ab341a973..84a07d67f8 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml @@ -27,6 +27,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml b/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml index de19b641c4..c8ead033c5 100644 --- a/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml @@ -130,12 +130,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are accepted reason: ListenersNotValid status: "False" type: Accepted - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are programmed reason: ListenersNotValid status: "False" type: Programmed @@ -215,7 +215,7 @@ listenerSets: status: "True" type: Accepted - lastTransitionTime: null - message: Some listeners are invalid + message: Some listeners are not programmed reason: Programmed status: "True" type: Programmed @@ -300,7 +300,7 @@ listenerSets: status: "True" type: Accepted - lastTransitionTime: null - message: Some listeners are invalid + message: Some listeners are not programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml index 22f5f6236c..3c2b82ad7a 100644 --- a/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml @@ -170,12 +170,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed @@ -227,12 +227,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml b/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml index 7b44839908..512f312629 100644 --- a/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml @@ -198,12 +198,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed @@ -254,12 +254,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml index 69aa62ae91..d80d3c20ce 100644 --- a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml @@ -240,12 +240,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml index 25283fbf2c..e01fcc3707 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml @@ -128,12 +128,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are invalid - reason: ListenersNotValid - status: "False" + message: All listeners are accepted + reason: Accepted + status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are programmed reason: ListenersNotValid status: "False" type: Programmed @@ -146,6 +146,11 @@ listenerSets: reason: RefNotPermitted status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: ListenersNotValid diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml new file mode 100644 index 0000000000..5079af121a --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml @@ -0,0 +1,112 @@ +namespaces: +- apiVersion: v1 + kind: Namespace + metadata: + name: gateway +- apiVersion: v1 + kind: Namespace + metadata: + name: xls + labels: + allow-xls: "true" +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: gateway + name: composite-gateway + spec: + gatewayClassName: envoy-gateway-class + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + listeners: + - name: core-http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + namespace: xls + name: https-xls + spec: + parentRef: + name: composite-gateway + namespace: gateway + listeners: + - name: extra-https-valid + protocol: HTTPS + port: 8443 + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + allowedRoutes: + namespaces: + from: All + - name: extra-https-missing-cert + protocol: HTTPS + port: 8444 + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-missing + namespace: xls + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: route-valid + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + namespace: xls + name: https-xls + sectionName: extra-https-valid + rules: + - backendRefs: + - name: service-1 + port: 8080 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: route-missing-cert + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + namespace: xls + name: https-xls + sectionName: extra-https-missing-cert + rules: + - backendRefs: + - name: service-1 + port: 8080 +secrets: +- apiVersion: v1 + kind: Secret + metadata: + namespace: xls + name: tls-secret-1 + type: kubernetes.io/tls + data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lVRUZNaFA5ZUo5WEFCV3NRNVptNmJSazJjTE5Rd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xabTl2TG1KaGNpNWpiMjB3SGhjTk1qUXdNakk1TURrek1ERXdXaGNOTXpRdwpNakkyTURrek1ERXdXakFXTVJRd0VnWURWUVFEREF0bWIyOHVZbUZ5TG1OdmJUQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFKbEk2WXhFOVprQ1BzNnBDUXhickNtZWl4OVA1RGZ4OVJ1NUxENFQKSm1kVzdJS2R0UVYvd2ZMbXRzdTc2QithVGRDaldlMEJUZmVPT1JCYlIzY1BBRzZFbFFMaWNsUVVydW4zcStncwpKcEsrSTdjSStqNXc4STY4WEg1V1E3clZVdGJ3SHBxYncrY1ZuQnFJVU9MaUlhdGpJZjdLWDUxTTF1RjljZkVICkU0RG5jSDZyYnI1OS9SRlpCc2toeHM1T3p3Sklmb2hreXZGd2V1VHd4Sy9WcGpJKzdPYzQ4QUJDWHBOTzlEL3EKRWgrck9hdWpBTWNYZ0hRSVRrQ2lpVVRjVW82TFNIOXZMWlB0YXFmem9acTZuaE1xcFc2NUUxcEF3RjNqeVRUeAphNUk4SmNmU0Zqa2llWjIwTFVRTW43TThVNHhIamFvL2d2SDBDQWZkQjdSTFUyc0NBd0VBQWFOVE1GRXdIUVlEClZSME9CQllFRk9SQ0U4dS8xRERXN2loWnA3Y3g5dFNtUG02T01COEdBMVVkSXdRWU1CYUFGT1JDRTh1LzFERFcKN2loWnA3Y3g5dFNtUG02T01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnQ1M3pqc3FUYUg1YThFMmNodm1XQWdDcnhSSzhiVkxNeGl3TkdqYm1FUFJ6K3c2TngrazBBOEtFY0lEc0tjClNYY2k1OHU0b1didFZKQmx6YS9adWpIUjZQMUJuT3BsK2FveTc4NGJiZDRQMzl3VExvWGZNZmJCQ20xdmV2aDkKQUpLbncyWnRxcjRta2JMY3hFcWxxM3NCTEZBUzlzUUxuS05DZTJjR0xkVHAyYm9HK3FjZ3lRZ0NJTTZmOEVNdgpXUGlmQ01NR3V6Sy9HUkY0YlBPL1lGNDhld0R1M1VlaWgwWFhkVUFPRTlDdFVhOE5JaGMxVVBhT3pQcnRZVnFyClpPR2t2L0t1K0I3OGg4U0VzTzlYclFjdXdiT25KeDZLdFIrYWV5a3ZBcFhDUTNmWkMvYllLQUFSK1A4QUpvUVoKYndJVW1YaTRnajVtK2JLUGhlK2lyK0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml new file mode 100644 index 0000000000..3902ceb42e --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml @@ -0,0 +1,360 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: composite-gateway + namespace: gateway + spec: + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: core-http + port: 80 + protocol: HTTP + status: + attachedListenerSets: 1 + 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: core-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: + name: route-valid + namespace: default + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-valid + rules: + - backendRefs: + - name: service-1 + port: 8080 + 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: + group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-valid +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: route-missing-cert + namespace: default + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-missing-cert + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: There are no ready listeners for this parent ref + reason: NoReadyListeners + status: "False" + 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: + group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-missing-cert +infraIR: + gateway/composite-gateway: + proxy: + listeners: + - name: gateway/composite-gateway/core-http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + - name: gateway/composite-gateway/xls/https-xls/extra-https-valid + ports: + - containerPort: 8443 + name: https-8443 + protocol: HTTPS + servicePort: 8443 + - name: gateway/composite-gateway/xls/https-xls/extra-https-missing-cert + ports: + - containerPort: 8444 + name: https-8444 + protocol: HTTPS + servicePort: 8444 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: composite-gateway + gateway.envoyproxy.io/owning-gateway-namespace: gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: gateway/composite-gateway + namespace: envoy-gateway-system +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + name: https-xls + namespace: xls + spec: + listeners: + - allowedRoutes: + namespaces: + from: All + name: extra-https-valid + port: 8443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + mode: Terminate + - allowedRoutes: + namespaces: + from: All + name: extra-https-missing-cert + port: 8444 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-missing + namespace: xls + mode: Terminate + parentRef: + name: composite-gateway + namespace: gateway + status: + conditions: + - lastTransitionTime: null + message: All listeners are accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Some listeners are not programmed + reason: Programmed + status: "True" + type: Programmed + 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 + - lastTransitionTime: null + message: No conflicts detected + reason: NoConflicts + status: "False" + type: Conflicted + name: extra-https-valid + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: 'No valid secrets exist: certificate refs 0: Secret xls/tls-secret-missing + does not exist.' + reason: InvalidCertificateRef + status: "False" + type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener is invalid, see other Conditions for details. + reason: ListenersNotValid + status: "False" + type: Programmed + name: extra-https-missing-cert + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +xdsIR: + gateway/composite-gateway: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: core-http + name: gateway/composite-gateway/core-http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + - address: 0.0.0.0 + externalPort: 8443 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: extra-https-valid + name: gateway/composite-gateway/xls/https-xls/extra-https-valid + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8443 + routes: + - destination: + metadata: + kind: HTTPRoute + name: route-valid + namespace: default + name: httproute/default/route-valid/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/route-valid/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: route-valid + namespace: default + name: httproute/default/route-valid/rule/0/match/-1/* + tls: + alpnProtocols: null + certificates: + - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lVRUZNaFA5ZUo5WEFCV3NRNVptNmJSazJjTE5Rd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xabTl2TG1KaGNpNWpiMjB3SGhjTk1qUXdNakk1TURrek1ERXdXaGNOTXpRdwpNakkyTURrek1ERXdXakFXTVJRd0VnWURWUVFEREF0bWIyOHVZbUZ5TG1OdmJUQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFKbEk2WXhFOVprQ1BzNnBDUXhickNtZWl4OVA1RGZ4OVJ1NUxENFQKSm1kVzdJS2R0UVYvd2ZMbXRzdTc2QithVGRDaldlMEJUZmVPT1JCYlIzY1BBRzZFbFFMaWNsUVVydW4zcStncwpKcEsrSTdjSStqNXc4STY4WEg1V1E3clZVdGJ3SHBxYncrY1ZuQnFJVU9MaUlhdGpJZjdLWDUxTTF1RjljZkVICkU0RG5jSDZyYnI1OS9SRlpCc2toeHM1T3p3Sklmb2hreXZGd2V1VHd4Sy9WcGpJKzdPYzQ4QUJDWHBOTzlEL3EKRWgrck9hdWpBTWNYZ0hRSVRrQ2lpVVRjVW82TFNIOXZMWlB0YXFmem9acTZuaE1xcFc2NUUxcEF3RjNqeVRUeAphNUk4SmNmU0Zqa2llWjIwTFVRTW43TThVNHhIamFvL2d2SDBDQWZkQjdSTFUyc0NBd0VBQWFOVE1GRXdIUVlEClZSME9CQllFRk9SQ0U4dS8xRERXN2loWnA3Y3g5dFNtUG02T01COEdBMVVkSXdRWU1CYUFGT1JDRTh1LzFERFcKN2loWnA3Y3g5dFNtUG02T01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnQ1M3pqc3FUYUg1YThFMmNodm1XQWdDcnhSSzhiVkxNeGl3TkdqYm1FUFJ6K3c2TngrazBBOEtFY0lEc0tjClNYY2k1OHU0b1didFZKQmx6YS9adWpIUjZQMUJuT3BsK2FveTc4NGJiZDRQMzl3VExvWGZNZmJCQ20xdmV2aDkKQUpLbncyWnRxcjRta2JMY3hFcWxxM3NCTEZBUzlzUUxuS05DZTJjR0xkVHAyYm9HK3FjZ3lRZ0NJTTZmOEVNdgpXUGlmQ01NR3V6Sy9HUkY0YlBPL1lGNDhld0R1M1VlaWgwWFhkVUFPRTlDdFVhOE5JaGMxVVBhT3pQcnRZVnFyClpPR2t2L0t1K0I3OGg4U0VzTzlYclFjdXdiT25KeDZLdFIrYWV5a3ZBcFhDUTNmWkMvYllLQUFSK1A4QUpvUVoKYndJVW1YaTRnajVtK2JLUGhlK2lyK0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + name: xls/tls-secret-1 + privateKey: '[redacted]' + - address: 0.0.0.0 + externalPort: 8444 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: extra-https-missing-cert + name: gateway/composite-gateway/xls/https-xls/extra-https-missing-cert + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8444 + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml index c4161ade75..781ab63b5a 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml @@ -134,12 +134,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml new file mode 100644 index 0000000000..493e6a6b9f --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml @@ -0,0 +1,73 @@ +namespaces: +- apiVersion: v1 + kind: Namespace + metadata: + name: gateway +- apiVersion: v1 + kind: Namespace + metadata: + name: xls + labels: + allow-xls: "true" +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: gateway + name: composite-gateway + spec: + gatewayClassName: envoy-gateway-class + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + listeners: + - name: core-http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + namespace: xls + name: https-xls + spec: + parentRef: + name: composite-gateway + namespace: gateway + listeners: + - name: extra-https + protocol: HTTPS + port: 8443 + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: route-extra-https + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + namespace: xls + name: https-xls + sectionName: extra-https + rules: + - backendRefs: + - name: service-1 + port: 8080 diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml new file mode 100644 index 0000000000..b42b32a006 --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml @@ -0,0 +1,230 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: composite-gateway + namespace: gateway + spec: + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: core-http + port: 80 + protocol: HTTP + status: + attachedListenerSets: 1 + 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: core-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: + name: route-extra-https + namespace: default + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: There are no ready listeners for this parent ref + reason: NoReadyListeners + status: "False" + 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: + group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https +infraIR: + gateway/composite-gateway: + proxy: + listeners: + - name: gateway/composite-gateway/core-http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + - name: gateway/composite-gateway/xls/https-xls/extra-https + ports: + - containerPort: 8443 + name: https-8443 + protocol: HTTPS + servicePort: 8443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: composite-gateway + gateway.envoyproxy.io/owning-gateway-namespace: gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: gateway/composite-gateway + namespace: envoy-gateway-system +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + name: https-xls + namespace: xls + spec: + listeners: + - allowedRoutes: + namespaces: + from: All + name: extra-https + port: 8443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + mode: Terminate + parentRef: + name: composite-gateway + namespace: gateway + status: + conditions: + - lastTransitionTime: null + message: All listeners are accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: No listeners are programmed + reason: ListenersNotValid + status: "False" + type: Programmed + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: 'No valid secrets exist: certificate refs 0: Secret xls/tls-secret-1 + does not exist.' + reason: InvalidCertificateRef + status: "False" + type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener is invalid, see other Conditions for details. + reason: ListenersNotValid + status: "False" + type: Programmed + name: extra-https + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +xdsIR: + gateway/composite-gateway: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: core-http + name: gateway/composite-gateway/core-http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + - address: 0.0.0.0 + externalPort: 8443 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: extra-https + name: gateway/composite-gateway/xls/https-xls/extra-https + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8443 + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/listenerset-invalid.out.yaml b/internal/gatewayapi/testdata/listenerset-invalid.out.yaml index 449d97e743..e09a3482d6 100644 --- a/internal/gatewayapi/testdata/listenerset-invalid.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-invalid.out.yaml @@ -240,12 +240,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are accepted reason: ListenersNotValid status: "False" type: Accepted - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are programmed reason: ListenersNotValid status: "False" type: Programmed @@ -315,7 +315,7 @@ listenerSets: status: "True" type: Accepted - lastTransitionTime: null - message: Some listeners are invalid + message: Some listeners are not programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml b/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml index 8c7309b61c..1dcf2f3339 100644 --- a/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml @@ -193,12 +193,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml b/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml index bc69e734fb..efefe794c2 100644 --- a/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml @@ -92,12 +92,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml b/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml index cb8d2b95bf..40d297c879 100644 --- a/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml @@ -116,12 +116,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-udproute.out.yaml b/internal/gatewayapi/testdata/listenerset-udproute.out.yaml index 5339bbc54a..5e3287a6cd 100644 --- a/internal/gatewayapi/testdata/listenerset-udproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-udproute.out.yaml @@ -92,12 +92,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index 528a0f03da..0d127843c8 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -289,15 +289,24 @@ func (t *Translator) validateListenerConditions(listener *ListenerContext) { return } - // Edge case: only one condition which is ResolvedRefs=False, Reason=PartiallyInvalidCertificateRef - // In this case, we can still consider the listener as ready because we only program the listener using only the valid certificates. - if len(lConditions) == 1 && lConditions[0].Type == string(gwapiv1.ListenerConditionResolvedRefs) && - lConditions[0].Reason == string(status.ListenerReasonPartiallyInvalidCertificateRef) { - listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, - "Listener has been successfully translated") - listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionTrue, gwapiv1.ListenerReasonProgrammed, - "Sending translated listener configuration to the data plane") - return + var onlyResolvedRefFailure = len(lConditions) == 1 && lConditions[0].Type == string(gwapiv1.ListenerConditionResolvedRefs) + if onlyResolvedRefFailure { + switch lConditions[0].Reason { + case string(status.ListenerReasonPartiallyInvalidCertificateRef): + // The listener is ready because we program it using only the valid certificates. + listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, + "Listener has been successfully translated") + listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionTrue, gwapiv1.ListenerReasonProgrammed, + "Sending translated listener configuration to the data plane") + return + case string(gwapiv1.ListenerReasonInvalidCertificateRef), string(gwapiv1.ListenerReasonRefNotPermitted): + // The listener configuration is semantically valid, but the listener cannot serve traffic with an invalid certificate. + listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, + "Listener has been successfully translated") + listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionFalse, gwapiv1.ListenerReasonInvalid, + "Listener is invalid, see other Conditions for details.") + return + } } // Any condition on the listener apart from Programmed=true indicates an error. From f8aefdd70f6120523ef0b8f282faac8afbd0dafc Mon Sep 17 00:00:00 2001 From: apkatsikas Date: Mon, 27 Apr 2026 22:09:03 -0400 Subject: [PATCH 2/4] chore: fix gofumpt formatting in validateListenerConditions Signed-off-by: apkatsikas --- internal/gatewayapi/validate.go | 2 +- release-notes/current.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index 0d127843c8..230a69f341 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -289,7 +289,7 @@ func (t *Translator) validateListenerConditions(listener *ListenerContext) { return } - var onlyResolvedRefFailure = len(lConditions) == 1 && lConditions[0].Type == string(gwapiv1.ListenerConditionResolvedRefs) + onlyResolvedRefFailure := len(lConditions) == 1 && lConditions[0].Type == string(gwapiv1.ListenerConditionResolvedRefs) if onlyResolvedRefFailure { switch lConditions[0].Reason { case string(status.ListenerReasonPartiallyInvalidCertificateRef): diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 331df07552..86ab1854e7 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -12,6 +12,7 @@ new features: | bug fixes: | Fixed SecurityPolicy merge using the wrong policy as the owner for resource references and IR generation. + Fixed ListenerSet and its listeners incorrectly setting `Accepted: False` for InvalidCertificateRef and RefNotPermitted, inconsistent with Gateway behavior and the Gateway API spec. # Enhancements that improve performance. performance improvements: | From f1343cb0e5efa86fe91673c8130816f82fb3f514 Mon Sep 17 00:00:00 2001 From: apkatsikas Date: Fri, 1 May 2026 14:40:03 -0400 Subject: [PATCH 3/4] fix(translator): separate RefNotPermitted from InvalidCertificateRef handling Unlike InvalidCertificateRef, RefNotPermitted should not set Accepted:True. Update unit test fixtures to match. Signed-off-by: apkatsikas --- ...s-configuration-secret-in-other-namespace.out.yaml | 5 ----- ...erset-https-tls-misuses-gateway-namespace.out.yaml | 11 +++-------- internal/gatewayapi/validate.go | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml index d92e039aa1..be22741fa9 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml @@ -28,11 +28,6 @@ gateways: reason: RefNotPermitted status: "False" type: ResolvedRefs - - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml index e01fcc3707..f56dd359de 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml @@ -128,9 +128,9 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are accepted - reason: Accepted - status: "True" + message: No listeners are accepted + reason: ListenersNotValid + status: "False" type: Accepted - lastTransitionTime: null message: No listeners are programmed @@ -146,11 +146,6 @@ listenerSets: reason: RefNotPermitted status: "False" type: ResolvedRefs - - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: ListenersNotValid diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index 230a69f341..4332403a71 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -299,7 +299,7 @@ func (t *Translator) validateListenerConditions(listener *ListenerContext) { listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionTrue, gwapiv1.ListenerReasonProgrammed, "Sending translated listener configuration to the data plane") return - case string(gwapiv1.ListenerReasonInvalidCertificateRef), string(gwapiv1.ListenerReasonRefNotPermitted): + case string(gwapiv1.ListenerReasonInvalidCertificateRef): // The listener configuration is semantically valid, but the listener cannot serve traffic with an invalid certificate. listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, "Listener has been successfully translated") From c607a5d41a630bd920c7c6e8b82132c05fa10280 Mon Sep 17 00:00:00 2001 From: zirain Date: Fri, 8 May 2026 08:19:09 +0800 Subject: [PATCH 4/4] fix gen Signed-off-by: zirain --- ...licting-listeners-one-invalid-ref.out.yaml | 5 +++++ ...ls-mixed-valid-and-missing-secret.out.yaml | 20 ------------------- ...t-https-tls-secret-does-not-exist.out.yaml | 20 ------------------- 3 files changed, 5 insertions(+), 40 deletions(-) diff --git a/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml b/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml index 663bd2014f..67882951e3 100644 --- a/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml @@ -39,6 +39,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml index 3902ceb42e..c9cd6c9736 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml @@ -134,12 +134,6 @@ infraIR: name: https-8443 protocol: HTTPS servicePort: 8443 - - name: gateway/composite-gateway/xls/https-xls/extra-https-missing-cert - ports: - - containerPort: 8444 - name: https-8444 - protocol: HTTPS - servicePort: 8444 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: composite-gateway @@ -339,20 +333,6 @@ xdsIR: - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lVRUZNaFA5ZUo5WEFCV3NRNVptNmJSazJjTE5Rd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xabTl2TG1KaGNpNWpiMjB3SGhjTk1qUXdNakk1TURrek1ERXdXaGNOTXpRdwpNakkyTURrek1ERXdXakFXTVJRd0VnWURWUVFEREF0bWIyOHVZbUZ5TG1OdmJUQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFKbEk2WXhFOVprQ1BzNnBDUXhickNtZWl4OVA1RGZ4OVJ1NUxENFQKSm1kVzdJS2R0UVYvd2ZMbXRzdTc2QithVGRDaldlMEJUZmVPT1JCYlIzY1BBRzZFbFFMaWNsUVVydW4zcStncwpKcEsrSTdjSStqNXc4STY4WEg1V1E3clZVdGJ3SHBxYncrY1ZuQnFJVU9MaUlhdGpJZjdLWDUxTTF1RjljZkVICkU0RG5jSDZyYnI1OS9SRlpCc2toeHM1T3p3Sklmb2hreXZGd2V1VHd4Sy9WcGpJKzdPYzQ4QUJDWHBOTzlEL3EKRWgrck9hdWpBTWNYZ0hRSVRrQ2lpVVRjVW82TFNIOXZMWlB0YXFmem9acTZuaE1xcFc2NUUxcEF3RjNqeVRUeAphNUk4SmNmU0Zqa2llWjIwTFVRTW43TThVNHhIamFvL2d2SDBDQWZkQjdSTFUyc0NBd0VBQWFOVE1GRXdIUVlEClZSME9CQllFRk9SQ0U4dS8xRERXN2loWnA3Y3g5dFNtUG02T01COEdBMVVkSXdRWU1CYUFGT1JDRTh1LzFERFcKN2loWnA3Y3g5dFNtUG02T01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnQ1M3pqc3FUYUg1YThFMmNodm1XQWdDcnhSSzhiVkxNeGl3TkdqYm1FUFJ6K3c2TngrazBBOEtFY0lEc0tjClNYY2k1OHU0b1didFZKQmx6YS9adWpIUjZQMUJuT3BsK2FveTc4NGJiZDRQMzl3VExvWGZNZmJCQ20xdmV2aDkKQUpLbncyWnRxcjRta2JMY3hFcWxxM3NCTEZBUzlzUUxuS05DZTJjR0xkVHAyYm9HK3FjZ3lRZ0NJTTZmOEVNdgpXUGlmQ01NR3V6Sy9HUkY0YlBPL1lGNDhld0R1M1VlaWgwWFhkVUFPRTlDdFVhOE5JaGMxVVBhT3pQcnRZVnFyClpPR2t2L0t1K0I3OGg4U0VzTzlYclFjdXdiT25KeDZLdFIrYWV5a3ZBcFhDUTNmWkMvYllLQUFSK1A4QUpvUVoKYndJVW1YaTRnajVtK2JLUGhlK2lyK0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= name: xls/tls-secret-1 privateKey: '[redacted]' - - address: 0.0.0.0 - externalPort: 8444 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway - sectionName: extra-https-missing-cert - name: gateway/composite-gateway/xls/https-xls/extra-https-missing-cert - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8444 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml index b42b32a006..bf0b1fa843 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml @@ -92,12 +92,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: gateway/composite-gateway/xls/https-xls/extra-https - ports: - - containerPort: 8443 - name: https-8443 - protocol: HTTPS - servicePort: 8443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: composite-gateway @@ -209,20 +203,6 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 - - address: 0.0.0.0 - externalPort: 8443 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway - sectionName: extra-https - name: gateway/composite-gateway/xls/https-xls/extra-https - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8443 readyListener: address: 0.0.0.0 ipFamily: IPv4