TLS certificate handling / Gateway TLS certificateRef validation

HIGH
traefik/traefik
Commit: d31ce5df13d7
Affected: 3.7.x prior to 3.7.0-ea.3 (i.e., before this commit)
2026-04-09 10:47 UTC

Description

The commit updates the Kubernetes gateway TLS certificate handling to perform per-ref validation, enforce permissions for TLS certificate references, and load TLS certificates per reference when multiple certificateRefs are configured on a Gateway listener. Previously, TLS handling could implicitly accept/load the first certificateRef without per-ref permission checks, potentially allowing misuse of unauthorized Secret references for TLS termination. The patch adds per-ref validation, permission checks (isReferenceGranted), and per-ref TLS loading (getTLSCert) to ensure only permitted certificateRefs are used, mitigating misconfiguration exposure and potential TLS information exposure or downgrade risk.

Proof of Concept

PoC Overview - This PoC demonstrates how the pre-fix behavior could allow an attacker to influence which TLS certificate is used for a Gateway listener by ordering multiple certificateRefs and providing an attacker-controlled Secret in a namespace the controller might not properly restrict. - The fix adds per-ref permission checks and per-ref TLS loading, preventing unauthorized Secret references from being used for TLS termination. Prerequisites (Kubernetes cluster with Traefik Gateway provider installed in a test environment): - A GatewayClass named my-gateway-class backed by traefik.io/gateway-controller - A Gateway in namespace default with a listener using HTTPS/TLS and two certificateRefs - Two Secrets containing TLS data: one legitimate (allowed) and one attacker-controlled (potentially disallowed) Files to apply (placeholders for cert data; replace with real test certs in a safe testing environment): 1) Attacker-controlled TLS secret ( attacker-secret in namespace attacker-ns ) --- apiVersion: v1 kind: Secret metadata: name: attacker-secret namespace: attacker-ns type: kubernetes.io/tls stringData: tls.crt: |- -----BEGIN CERTIFICATE----- MIIBtjCCAVugAwIBAgIJAO7Z... (test cert for attacker example) -----END CERTIFICATE----- tls.key: |- -----BEGIN PRIVATE KEY----- MIGHAgEAMBMG... (test key for attacker example) -----END PRIVATE KEY----- 2) Legitimate TLS secret ( legitimate-secret in namespace default ) --- apiVersion: v1 kind: Secret metadata: name: legitimate-secret namespace: default type: kubernetes.io/tls stringData: tls.crt: |- -----BEGIN CERTIFICATE----- MIIBlTCCATugAwIBAgIJAO9t... (legitimate test cert) -----END CERTIFICATE----- tls.key: |- -----BEGIN PRIVATE KEY----- MIGHAgEAMBMG... (legitimate test key) -----END PRIVATE KEY----- 3) Gateway resource ordering attacker-ref first (default namespace) to illustrate misconfiguration risk --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: test-gw namespace: default spec: gatewayClassName: my-gateway-class listeners: - name: https protocol: HTTPS port: 443 tls: certificateRefs: - kind: Secret name: attacker-secret namespace: attacker-ns group: "" - kind: Secret name: legitimate-secret namespace: default group: "" allowedRoutes: namespaces: from: Same 4) HTTPRoute to complete configuration (optional for PoC) – routes from gateway to a sample service --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-app-1 namespace: default spec: parentRefs: - name: test-gw kind: Gateway group: gateway.networking.k8s.io hostnames: - "example.local" rules: - matches: - path: type: Exact value: /bar backendRefs: - name: whoami port: 80 weight: 1 kind: Service group: "" What to observe: - Before fix (or if the controller ignores per-ref permissions): The Gateway listener could load attacker-secret (attacker-secret) as the TLS certificate for TLS termination if attacker-secret is listed first, potentially presenting an attacker-controlled certificate to clients connecting to https://example.local. This could enable misconfiguration exposure, info disclosure, or downgrade risks if clients reject the certificate or trust mismatch occurs. - After fix (as implemented by this commit): The Gateway controller validates each certificateRef per the namespace/gateway permissions. If an attacker-controlled secret is referenced in a way that is not permitted, the code marks the TLS reference as invalid (ListenerConditionResolvedRefs with a reason like RefNotPermitted/InvalidCertificateRef) and will not load that TLS certificate, preventing unauthorized TLS termination. How to test manually: 1) Deploy the resources with a test CA-signed certificate for legitimate-secret and a self-signed or differently issued certificate for attacker-secret. 2) Apply the Gateway manifest with attacker-secret first in certificateRefs. 3) Observe the Gateway status via kubectl describe gateway/test-gw -n default. Before the fix it may continue to serve the attacker cert if permissions are not enforced. After the fix you should see a ResolvedRefs condition false with a reason such as RefNotPermitted or InvalidCertificateRef. 4) Attempt an TLS handshake to the gateway. If the attacker-secret was incorrectly trusted, you may observe a certificate presented that does not match the expected domain. With the fix in place, TLS termination should not proceed using the unauthorized certificate, and the listener may be marked as not accepted until a valid, permitted certificateRef is provided. Notes: - This PoC uses intentionally attacker-controlled TLS secrets and an attacker-first reference order to illustrate the risk of not validating per-ref permissions for TLS certificateRefs. In real deployments, proper RBAC and Gateway API permissions should prevent cross-namespace references unless explicitly allowed. - Replace the placeholder certificate data with real-test certificates in a safe, isolated test environment.

Commit Details

Author: Morten Victor Nordbye

Date: 2026-04-07 08:46 UTC

Message:

Support multiple certificateRefs in Gateway API listeners

Triage Assessment

Vulnerability Type: TLS certificate handling (validation of CertificateRefs, preventing misconfiguration exposure)

Confidence: HIGH

Reasoning:

The patch rewrites TLS certificate reference handling to support multiple certificateRefs per Gateway listener with proper validation and permission checks. It adds per-ref validation, loads the TLS certificates securely, and prevents invalid or unauthorized CertificateRefs from being accepted. This reduces risks around misconfigured or malicious certificate references affecting TLS termination and potential information exposure or downgrade, indicating a security vulnerability fix in TLS handling.

Verification Assessment

Vulnerability Type: TLS certificate handling / Gateway TLS certificateRef validation

Confidence: HIGH

Affected Versions: 3.7.x prior to 3.7.0-ea.3 (i.e., before this commit)

Code Diff

diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_certificaterefs.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_certificaterefs.yml new file mode 100644 index 0000000000..4766f554bd --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_certificaterefs.yml @@ -0,0 +1,78 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: supersecret + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJxRENDQVU2Z0F3SUJBZ0lVWU9zcjBRZ0hPQnE0a1lSQ0w1K1REZFZ0NmJRd0NnWUlLb1pJemowRUF3SXcKRmpFVU1CSUdBMVVFQXd3TFpYaGhiWEJzWlM1amIyMHdIaGNOTWpVeE1ERXdNRGN4TnpNd1doY05NelV4TURBNApNRGN4TnpNd1dqQVdNUlF3RWdZRFZRUUREQXRsZUdGdGNHeGxMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHClNNNDlBd0VIQTBJQUJET3JpdzNaUTd3SWhXcmJQUzZKRlFUM2JUb05DRjAwdlNWNWZhYjZUYlh5TDh0bHNHcmUKVFJJRjJFd2dzdGVNT2t4R0tLU2xEdnVhRHdxOHAvcVYrMHVqZWpCNE1CMEdBMVVkRGdRV0JCUk1Fa3VleFhRaApVdERnUmcxS0J2NzJDRHErRXpBZkJnTlZIU01FR0RBV2dCUk1Fa3VleFhRaFV0RGdSZzFLQnY3MkNEcStFekFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUNVR0ExVWRFUVFlTUJ5Q0MyVjRZVzF3YkdVdVkyOXRnZzBxTG1WNFlXMXcKYkdVdVkyOXRNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURzODdWazBzd0E2SGdPSmpST3llMW14RDgzcWNHeQpwZUZnb3hWOTNEeStjd0lnVjBNTUVKSmJWc1R5WkszRVErK1hjNXJFTDc4bnJKK1lJRVYrckNVV2o1VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ253Z0w1RFk0VUIxNHNNNmYKRGlrUWR0cWgyUVcxQXJmRjRmYzFVRnppZmRHaFJBTkNBQVF6cTRzTjJVTzhDSVZxMnowdWlSVUU5MjA2RFFoZApOTDBsZVgybStrMjE4aS9MWmJCcTNrMFNCZGhNSUxMWGpEcE1SaWlrcFE3N21nOEt2S2Y2bGZ0TAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t + +--- +apiVersion: v1 +kind: Secret +metadata: + name: supersecret2 + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJxRENDQVU2Z0F3SUJBZ0lVWU9zcjBRZ0hPQnE0a1lSQ0w1K1REZFZ0NmJRd0NnWUlLb1pJemowRUF3SXcKRmpFVU1CSUdBMVVFQXd3TFpYaGhiWEJzWlM1amIyMHdIaGNOTWpVeE1ERXdNRGN4TnpNd1doY05NelV4TURBNApNRGN4TnpNd1dqQVdNUlF3RWdZRFZRUUREQXRsZUdGdGNHeGxMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHClNNNDlBd0VIQTBJQUJET3JpdzNaUTd3SWhXcmJQUzZKRlFUM2JUb05DRjAwdlNWNWZhYjZUYlh5TDh0bHNHcmUKVFJJRjJFd2dzdGVNT2t4R0tLU2xEdnVhRHdxOHAvcVYrMHVqZWpCNE1CMEdBMVVkRGdRV0JCUk1Fa3VleFhRaApVdERnUmcxS0J2NzJDRHErRXpBZkJnTlZIU01FR0RBV2dCUk1Fa3VleFhRaFV0RGdSZzFLQnY3MkNEcStFekFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUNVR0ExVWRFUVFlTUJ5Q0MyVjRZVzF3YkdVdVkyOXRnZzBxTG1WNFlXMXcKYkdVdVkyOXRNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURzODdWazBzd0E2SGdPSmpST3llMW14RDgzcWNHeQpwZUZnb3hWOTNEeStjd0lnVjBNTUVKSmJWc1R5WkszRVErK1hjNXJFTDc4bnJKK1lJRVYrckNVV2o1VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ253Z0w1RFk0VUIxNHNNNmYKRGlrUWR0cWgyUVcxQXJmRjRmYzFVRnppZmRHaFJBTkNBQVF6cTRzTjJVTzhDSVZxMnowdWlSVUU5MjA2RFFoZApOTDBsZVgybStrMjE4aS9MWmJCcTNrMFNCZGhNSUxMWGpEcE1SaWlrcFE3N21nOEt2S2Y2bGZ0TAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t + +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: + - name: https + protocol: HTTPS + port: 443 + tls: + certificateRefs: + - kind: Secret + name: supersecret + group: "" + - kind: Secret + name: supersecret2 + group: "" + allowedRoutes: + namespaces: + from: Same + +--- +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: http-app-1 + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - "foo.com" + rules: + - matches: + - path: + type: Exact + value: /bar + backendRefs: + - name: whoami + port: 80 + weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_certificaterefs_one_missing.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_certificaterefs_one_missing.yml new file mode 100644 index 0000000000..7fa32e0c60 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_certificaterefs_one_missing.yml @@ -0,0 +1,67 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: supersecret + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJxRENDQVU2Z0F3SUJBZ0lVWU9zcjBRZ0hPQnE0a1lSQ0w1K1REZFZ0NmJRd0NnWUlLb1pJemowRUF3SXcKRmpFVU1CSUdBMVVFQXd3TFpYaGhiWEJzWlM1amIyMHdIaGNOTWpVeE1ERXdNRGN4TnpNd1doY05NelV4TURBNApNRGN4TnpNd1dqQVdNUlF3RWdZRFZRUUREQXRsZUdGdGNHeGxMbU52YlRCWk1CTUdCeXFHU000OUFnRUdDQ3FHClNNNDlBd0VIQTBJQUJET3JpdzNaUTd3SWhXcmJQUzZKRlFUM2JUb05DRjAwdlNWNWZhYjZUYlh5TDh0bHNHcmUKVFJJRjJFd2dzdGVNT2t4R0tLU2xEdnVhRHdxOHAvcVYrMHVqZWpCNE1CMEdBMVVkRGdRV0JCUk1Fa3VleFhRaApVdERnUmcxS0J2NzJDRHErRXpBZkJnTlZIU01FR0RBV2dCUk1Fa3VleFhRaFV0RGdSZzFLQnY3MkNEcStFekFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUNVR0ExVWRFUVFlTUJ5Q0MyVjRZVzF3YkdVdVkyOXRnZzBxTG1WNFlXMXcKYkdVdVkyOXRNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUNJUURzODdWazBzd0E2SGdPSmpST3llMW14RDgzcWNHeQpwZUZnb3hWOTNEeStjd0lnVjBNTUVKSmJWc1R5WkszRVErK1hjNXJFTDc4bnJKK1lJRVYrckNVV2o1VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ253Z0w1RFk0VUIxNHNNNmYKRGlrUWR0cWgyUVcxQXJmRjRmYzFVRnppZmRHaFJBTkNBQVF6cTRzTjJVTzhDSVZxMnowdWlSVUU5MjA2RFFoZApOTDBsZVgybStrMjE4aS9MWmJCcTNrMFNCZGhNSUxMWGpEcE1SaWlrcFE3N21nOEt2S2Y2bGZ0TAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t + +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: + - name: https + protocol: HTTPS + port: 443 + tls: + certificateRefs: + - kind: Secret + name: supersecret + group: "" + - kind: Secret + name: missing-secret + group: "" + allowedRoutes: + namespaces: + from: Same + +--- +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: http-app-1 + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - "foo.com" + rules: + - matches: + - path: + type: Exact + value: /bar + backendRefs: + - name: whoami + port: 80 + weight: 1 + kind: Service + group: "" diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index cd7c9ad2e7..7910dc4534 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -428,7 +428,7 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context) *dynamic.C } func (p *Provider) loadGatewayListeners(ctx context.Context, gateway *gatev1.Gateway, conf *dynamic.Configuration) []gatewayListener { - tlsConfigs := make(map[string]*tls.CertAndStores) + tlsCerts := make(map[string]*tls.CertAndStores) allocatedListeners := make(map[string]struct{}) gatewayListeners := make([]gatewayListener, len(gateway.Spec.Listeners)) @@ -529,30 +529,22 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, gateway *gatev1.Gat // TLS if listener.Protocol == gatev1.HTTPSProtocolType || listener.Protocol == gatev1.TLSProtocolType { - if listener.TLS == nil || (len(listener.TLS.CertificateRefs) == 0 && listener.TLS.Mode != nil && *listener.TLS.Mode != gatev1.TLSModePassthrough) { - // update "Detached" status with "UnsupportedProtocol" reason + if listener.TLS == nil { gatewayListeners[i].Status.Conditions = append(gatewayListeners[i].Status.Conditions, metav1.Condition{ Type: string(gatev1.ListenerConditionAccepted), Status: metav1.ConditionFalse, ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point - Message: fmt.Sprintf("No TLS configuration for Gateway Listener %s:%d and protocol %q", - listener.Name, listener.Port, listener.Protocol), + Message: fmt.Sprintf("No TLS configuration for Gateway Listener %s:%d and protocol %q", listener.Name, listener.Port, listener.Protocol), }) - continue } - var tlsModeType gatev1.TLSModeType - if listener.TLS.Mode != nil { - tlsModeType = *listener.TLS.Mode - } - - isTLSPassthrough := tlsModeType == gatev1.TLSModePassthrough + tlsMode := ptr.Deref(listener.TLS.Mode, gatev1.TLSModeTerminate) + isTLSPassthrough := tlsMode == gatev1.TLSModePassthrough if isTLSPassthrough && len(listener.TLS.CertificateRefs) > 0 { - // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayTLSConfig log.Ctx(ctx).Warn().Msg("In case of Passthrough TLS mode, no TLS settings take effect as the TLS session from the client is NOT terminated at the Gateway") } @@ -560,7 +552,7 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, gateway *gatev1.Gat // Protocol TLS -> Passthrough -> TLSRoute // Protocol TLS -> Terminate -> TLSRoute // Protocol HTTPS -> Terminate -> HTTPRoute - if listener.Protocol == gatev1.HTTPSProtocolType && isTLSPassthrough { + if isTLSPassthrough && listener.Protocol == gatev1.HTTPSProtocolType { gatewayListeners[i].Status.Conditions = append(gatewayListeners[i].Status.Conditions, metav1.Condition{ Type: string(gatev1.ListenerConditionAccepted), Status: metav1.ConditionFalse, @@ -569,13 +561,11 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, gateway *gatev1.Gat Reason: string(gatev1.ListenerReasonUnsupportedProtocol), Message: "HTTPS protocol is not supported with TLS mode Passthrough", }) - continue } if !isTLSPassthrough { if len(listener.TLS.CertificateRefs) == 0 { - // update "ResolvedRefs" status true with "InvalidCertificateRef" reason gatewayListeners[i].Status.Conditions = append(gatewayListeners[i].Status.Conditions, metav1.Condition{ Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, @@ -584,74 +574,73 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, gateway *gatev1.Gat Reason: string(gatev1.ListenerReasonInvalidCertificateRef), Message: "One TLS CertificateRef is required in Terminate mode", }) - continue } - // TODO Should we support multiple certificates? - certificateRef := listener.TLS.CertificateRefs[0] - - if certificateRef.Kind == nil || *certificateRef.Kind != "Secret" || - certificateRef.Group == nil || (*certificateRef.Group != "" && *certificateRef.Group != groupCore) { - // update "ResolvedRefs" status true with "InvalidCertificateRef" reason - gatewayListeners[i].Status.Conditions = append(gatewayListeners[i].Status.Conditions, metav1.Condition{ - Type: string(gatev1.ListenerConditionResolvedRefs), - Status: metav1.ConditionFalse, - ObservedGeneration: gateway.Generation, - LastTransitionTime: metav1.Now(), - Reason: string(gatev1.ListenerReasonInvalidCertificateRef), - Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind: %s/%s", groupToString(certificateRef.Group), kindToString(certificateRef.Kind)), - }) + var errCertConditions []metav1.Condition + listenerTLSCerts := make(map[string]*tls.CertAndStores) + for _, certificateRef := range listener.TLS.CertificateRefs { + if certificateRef.Kind == nil || *certificateRef.Kind != "Secret" || certificateRef.Group == nil || (*certificateRef.Group != "" && *certificateRef.Group != groupCore) { + errCertConditions = append(errCertConditions, metav1.Condition{ + Type: string(gatev1.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, + LastTransitionTime: metav1.Now(), + Reason: string(gatev1.ListenerReasonInvalidCertificateRef), + Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind: %s/%s", groupToString(certificateRef.Group), kindToString(certificateRef.Kind)), + }) + continue + } - continue - } + certificateNamespace := string(ptr.Deref(certificateRef.Namespace, gatev1.Namespace(gateway.Namespace))) + if err := p.isReferenceGranted(kindGateway, gateway.Namespace, groupCore, "Secret", string(certificateRef.Name), certificateNamespace); err != nil { + errCertConditions = append(errCertConditions, metav1.Condition{ + Type: string(gatev1.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, + LastTransitionTime: metav1.Now(), + Reason: string(gatev1.ListenerReasonRefNotPermitted), + Message: fmt.Sprintf("Cannot reference CertificateRef %s/%s: %s", certificateNamespace, certificateRef.Name, err), + }) + continue + } - certificateNamespace := gateway.Namespace - if certificateRef.Namespace != nil && string(*certificateRef.Namespace) != gateway.Namespace { - certificateNamespace = string(*certificateRef.Namespace) + configKey := certificateNamespace + "/" + string(certificateRef.Name) + if _, tlsExists := listenerTLSCerts[configKey]; !tlsExists { + tlsCert, err := p.getTLSCert(certificateRef.Name, certificateNamespace) + if err != nil { + errCertConditions = append(errCertConditions, metav1.Condition{ + Type: string(gatev1.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, + LastTransitionTime: metav1.Now(), + Reason: string(gatev1.ListenerReasonInvalidCertificateRef), + Message: fmt.Sprintf("Cannot load CertificateRef %s/%s: %s", certificateNamespace, certificateRef.Name, err), + }) + continue + } + listenerTLSCerts[configKey] = tlsCert + } } - if err := p.isReferenceGranted(kindGateway, gateway.Namespace, groupCore, "Secret", string(certificateRef.Name), ce ... [truncated]
← Back to Alerts View on GitHub →