diff --git a/jobs/haproxy/spec b/jobs/haproxy/spec index 5334cf9f..0ec512a8 100644 --- a/jobs/haproxy/spec +++ b/jobs/haproxy/spec @@ -577,6 +577,8 @@ properties: ha_proxy.disable_health_check_proxy: description: "Disables the use of the PROXY protocol for health checks. Only applies if `ha_proxy.accept_proxy` is enabled." default: false + ha_proxy.enable_additional_health_check_proxy: + description: "Enable the additional health check listener with use of the PROXY protocol" ha_proxy.binding_ip: description: "If there are multiple ethernet interfaces, specify which one to bind. Set to `::` to bind to all IPv6 interfaces (no IPv4). IPv6 must be enabled on the HAProxy VM in the deployment manifest." default: "" @@ -599,7 +601,7 @@ properties: - 172.168.4.1/32 - 10.2.0.0/16 ha_proxy.expect_proxy_cidrs: - description: "List of CIDRs to enable proxy protocol for. This enables forwarding of the client source IP for hyperscalers not supporting IP dual stack (v4 & v6). This property is mutually exclusive with the accept_proxy." + description: "List of CIDRs to enable proxy protocol for. This enables the forwarding of the client source IP for hyperscalers that do not support IP dual stack (v4 & v6). This property is mutually exclusive with the accept_proxy. For backward compatibility, if the list is not empty, HAProxy will listen on an additional health check port (health_check_port + 1) with proxy protocol enabled, by implicitly setting enable_additional_health_check_proxy to true if not set explicitly." default: ~ example: expect_proxy_cidrs: diff --git a/jobs/haproxy/templates/haproxy.config.erb b/jobs/haproxy/templates/haproxy.config.erb index b718d4d9..bbe8b578 100644 --- a/jobs/haproxy/templates/haproxy.config.erb +++ b/jobs/haproxy/templates/haproxy.config.erb @@ -271,6 +271,10 @@ end if backend_ssl != "" && (enable_http2 || backend_match_http_protocol) backends += [{ name: "http-routers-http2", backend_ssl: backend_ssl, alpn: "alpn h2,http/1.1 " }] end + + # to keep backward compatibility enable_additional_health_check_proxy if expect_proxy_cidrs is not empty. + enable_additional_health_check_proxy = p("ha_proxy.enable_additional_health_check_proxy", p("ha_proxy.expect_proxy_cidrs", []).size > 0) + -%> global @@ -385,7 +389,7 @@ listen health_check_http_url acl http-routers_down nbsrv(<%= backends.first[:name] %>) eq 0 monitor fail if http-routers_down -<%- if p("ha_proxy.expect_proxy_cidrs", []).size > 0 -%> +<%- if enable_additional_health_check_proxy -%> listen health_check_http_url_proxy_protocol bind :<%= p("ha_proxy.health_check_port") + 1 %> accept-proxy mode http @@ -1101,7 +1105,7 @@ listen health_check_http_tcp-<%= tcp_proxy["name"] %> acl tcp-<%= tcp_proxy["name"] %>-routers_down nbsrv(tcp-<%= tcp_proxy["name"] %>) eq 0 monitor fail if tcp-<%= tcp_proxy["name"] %>-routers_down - <%- if p("ha_proxy.expect_proxy_cidrs", []).size > 0 -%> + <%- if enable_additional_health_check_proxy -%> listen health_check_http_tcp-<%= tcp_proxy["name"] %>_proxy_protocol bind :<%= tcp_proxy["health_check_http"] + 1 %> accept-proxy mode http diff --git a/spec/haproxy/templates/haproxy_config/healthcheck_listener_spec.rb b/spec/haproxy/templates/haproxy_config/healthcheck_listener_spec.rb index f85ac41f..aac47595 100644 --- a/spec/haproxy/templates/haproxy_config/healthcheck_listener_spec.rb +++ b/spec/haproxy/templates/haproxy_config/healthcheck_listener_spec.rb @@ -9,6 +9,7 @@ context 'when ha_proxy.enable_health_check_http is true' do let(:healthcheck_listener) { haproxy_conf['listen health_check_http_url'] } + let(:healthcheck_listener_proxy_protocol) { haproxy_conf['listen health_check_http_url_proxy_protocol'] } let(:properties) do { @@ -84,6 +85,50 @@ expect(healthcheck_listener).not_to include('tcp-request connection expect-proxy layer4 unless LOCALHOST') end end + + context 'when ha_proxy.enable_additional_health_check_proxy is also true' do + let(:properties) do + { + 'enable_health_check_http' => true, + 'accept_proxy' => true, + 'enable_additional_health_check_proxy' => true + } + end + + it 'sets expect-proxy for the healthchecks on ports 8080 and 8081' do + expect(healthcheck_listener).to include('bind :8080') + expect(healthcheck_listener).to include('tcp-request connection expect-proxy layer4 unless LOCALHOST') + expect(healthcheck_listener_proxy_protocol).to include('bind :8081 accept-proxy') + end + end + + context 'when expect_proxy_cidrs is not empty due to backward compatibility' do + let(:properties) do + { + 'enable_health_check_http' => true, + 'expect_proxy_cidrs' => ['10.5.6.7/27'] + } + end + + it 'sets expect-proxy for the healthcheck on port 8081' do + expect(healthcheck_listener).to include('bind :8080') + expect(healthcheck_listener_proxy_protocol).to include('bind :8081 accept-proxy') + end + end + + context 'when ha_proxy.enable_additional_health_check_proxy is false but accept_proxy true' do + let(:properties) do + { + 'enable_health_check_http' => true, + 'accept_proxy' => true + } + end + + it 'does not contain healthcheck_listener_proxy_protocol' do + expect(healthcheck_listener).to include('tcp-request connection expect-proxy layer4 unless LOCALHOST') + expect(haproxy_conf).not_to have_key('listen health_check_http_url_proxy_protocol') + end + end end end end