Description
HAproxy Ingress Helm chart version: 1.41.0
HAproxy version: v3.0.1 92320ea.dirty
Container Image: docker.io/haproxytech/kubernetes-ingress:3.0.1
Summary: if a value of response-set-header annotation has a header value with spaces which is enclosed in double quotes, the ingress controller can't start anymore.
Assumptions made:
- Ingress Controller watches for ingress objects with ingressClass==haproxy
Repoduction steps:
- deploy the following ingress object:
kind: Ingress
metadata:
annotations:
haproxy.org/response-set-header: |
Cache-Control "no-store,no-cache,private"
Strict-Transport-Security "max-age=31536000"
X-Frame-Options "ALLOW-FROM https://some-site"
Content-Security-Policy "frame-ancestors 'self' https://some.site"
kubernetes.io/ingress.class: haproxy
name: ingress-controller-killer
spec:
rules:
- host: some.site
http:
paths:
- backend:
service:
name: some-service
port:
number: 80
path: /some-path
pathType: Prefix
- terminate one of Ingress Controller's pods.
Expected behaviour: a new pod starts and switches to the Ready state
Actual behaviour: a new pod starts but crashes.
Error message in the pod's log:
msg="config parsing [/etc/haproxy/haproxy.cfg.c3e0b01c-3c12-4798-a6c7-c25c6020c4f4:58]: 'http-response set-header' expects either 'if' or 'unless' followed by a condition but found 'https://some-site'."
msg="config Error(s) found in configuration file /etc/haproxy/haproxy.cfg.c3e0b01c-3c12-4798-a6c7-c25c6020c4f4"
This is how does the rules for X-Frame-Options and Content-Security-Policy headers look like in the HAproxy configuration:
http-response set-header X-Frame-Options ""ALLOW-FROM https://some.site/"" if { var(txn.path_match) -m dom 9df1f33483cfca6f432369cfe05c0787 }
http-response set-header Content-Security-Policy ""frame-ancestors 'self' https://some.site/"" if { var(txn.path_match) -m dom 7f6be0c4820a0b0ab6e0de0908a1e165 }
Problem analysis:
- it seems that HAproxy is smart enough to add double quotes around header values with spaces by itself;
- if the double quotes were already added in the annotation, an additional set of double quotes is added;
- that additional set of double quotes breaks parsing process as the second double quote is considered as an end of value, so next keyword expected to be "if" or "unless", but actually we still get the value's content there.
Consequences: this is a serious security problem because a cluster's user with restricted privileges which is only able to create ingress objects in some namespace can render the Ingress Controller serving the whole cluster to stop. A pod should be terminated to cause the problem, but it normally happens relatively often as nodes are drained or some of them disconnect due to outages.
Additional thoughts: it seems that the problem should exist also for other annotations where the same quoting logic for values containing spaces is applicable.