Thank you for all the work on haproxy-ingress. We've been running it in production for years and it's been great. We hit an issue after upgrading from v0.15 to v0.17.0-alpha.1 that took a while to pin down.
Description of the problem
When any ingress in the cluster has ssl-passthrough enabled, the HTTPS frontend is named _front_https__local instead of _front_https. This is expected -- the TLS frontend does SNI inspection and passes through to the local HTTPS frontend.
But the generated backend configs still check for _front_https when setting txn.pathID:
http-request set-var-fmt(req.fe) "%f"
http-request set-var(txn.pathID) var(req.base),map_dir(...) if { var(req.fe) -m str _front_https }
Since %f returns _front_https__local (the real frontend name), the -m str _front_https exact match never succeeds. txn.pathID is never set, and every conditional rule that depends on it is silently skipped.
This affects all HTTPS backends in the cluster, not just the one with ssl-passthrough. Features like rewrite-target and per-path HSTS stop working for every ingress.
Expected behavior
The backend pathID condition should match the actual frontend name. Either the condition should check for _front_https__local when ssl-passthrough is active, or the %f variable should resolve to whatever name the backend expects.
With the pathID set correctly, rewrite-target and other path-dependent features should work as they did in v0.15.
Steps to reproduce the problem
- Have at least one ingress with
ingress.kubernetes.io/ssl-passthrough: "true" (this triggers the __local suffix on the HTTPS frontend name)
- Have a separate, unrelated ingress with
haproxy-ingress.github.io/rewrite-target set
- Send an HTTPS request that should be rewritten
- The request arrives at the backend with the original path -- the
replace-path rule in the generated config never fires because txn.pathID is empty
In our case, requests to www.ntppool.org/api/data/dns/counts should be rewritten to /api/dns/counts before reaching the backend. Instead they arrive as /api/data/dns/counts and the backend returns 404.
Environment information
HAProxy Ingress version: v0.17.0-alpha.1
Command-line options:
--default-backend-service=$(POD_NAMESPACE)/default-http-backend
--default-ssl-certificate=$(POD_NAMESPACE)/ewrlb-tls
--configmap=$(POD_NAMESPACE)/haproxy-ingress
--tcp-services-configmap=$(POD_NAMESPACE)/haproxy-tcp
--watch-gateway
--publish-service=haproxy-ingress/haproxy-ingress
Global options:
access-log: "true"
backend-server-naming: pod
forwardfor: update
max-connections: "4000"
slots-min-free: "2"
timeout-client: 110s
Ingress objects:
The ssl-passthrough ingress (triggers the __local frontend rename):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/ssl-passthrough: "true"
name: monitor-api
namespace: ntppool
spec:
ingressClassName: haproxy
rules:
- host: api.mon.ntppool.dev
http:
paths:
- backend:
service:
name: monitor-api
port:
number: 443
path: /
pathType: Prefix
The rewrite-target ingress (broken by the frontend name mismatch):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
haproxy-ingress.github.io/rewrite-target: /api
name: ntppool-data-api
namespace: ntppool
spec:
ingressClassName: haproxy
rules:
- host: www.ntppool.org
http:
paths:
- backend:
service:
name: data-api
port:
number: 80
path: /api/data
pathType: Prefix
tls:
- hosts:
- www.ntppool.org
secretName: ntppool-data-api-tls
The generated haproxy.cfg for the data-api backend shows the mismatch:
frontend _front_https__local
...
backend ntppool_data-api_8030
...
http-request set-var-fmt(req.fe) "%f"
# req.fe is now "_front_https__local"
# This never matches because of the __local suffix:
http-request set-var(txn.pathID) var(req.base),map_dir(...) if { var(req.fe) -m str _front_https }
# So pathID is empty, and this replace-path is skipped:
http-request replace-path '^/api/data(.*)$' '/api\1' if { var(txn.pathID) -m str path12 }
Thank you for all the work on haproxy-ingress. We've been running it in production for years and it's been great. We hit an issue after upgrading from v0.15 to v0.17.0-alpha.1 that took a while to pin down.
Description of the problem
When any ingress in the cluster has ssl-passthrough enabled, the HTTPS frontend is named
_front_https__localinstead of_front_https. This is expected -- the TLS frontend does SNI inspection and passes through to the local HTTPS frontend.But the generated backend configs still check for
_front_httpswhen settingtxn.pathID:Since
%freturns_front_https__local(the real frontend name), the-m str _front_httpsexact match never succeeds.txn.pathIDis never set, and every conditional rule that depends on it is silently skipped.This affects all HTTPS backends in the cluster, not just the one with ssl-passthrough. Features like
rewrite-targetand per-path HSTS stop working for every ingress.Expected behavior
The backend pathID condition should match the actual frontend name. Either the condition should check for
_front_https__localwhen ssl-passthrough is active, or the%fvariable should resolve to whatever name the backend expects.With the pathID set correctly,
rewrite-targetand other path-dependent features should work as they did in v0.15.Steps to reproduce the problem
ingress.kubernetes.io/ssl-passthrough: "true"(this triggers the__localsuffix on the HTTPS frontend name)haproxy-ingress.github.io/rewrite-targetsetreplace-pathrule in the generated config never fires becausetxn.pathIDis emptyIn our case, requests to
www.ntppool.org/api/data/dns/countsshould be rewritten to/api/dns/countsbefore reaching the backend. Instead they arrive as/api/data/dns/countsand the backend returns 404.Environment information
HAProxy Ingress version:
v0.17.0-alpha.1Command-line options:
Global options:
Ingress objects:
The ssl-passthrough ingress (triggers the
__localfrontend rename):The rewrite-target ingress (broken by the frontend name mismatch):
The generated haproxy.cfg for the data-api backend shows the mismatch: