fix(coraza): ensure haproxy.cfg ends with LF when SPOE backend appended
All checks were successful
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 54s

The SPOE backend block from hap_coraza_spoa_backend.tpl was being appended
last to config_parts. The template's render output doesn't end with a
newline (and config_parts is joined with '\n' BETWEEN elements, not after
the last one), so the resulting haproxy.cfg ended on `server coraza-spoa
...` with no trailing LF. HAProxy refuses to parse such files:

    [ALERT] config: parsing [/etc/haproxy/haproxy.cfg:288]: Missing LF
    on last line, file might have been truncated at position 70.

Match the existing pattern at the previous-last config_parts.append
(line 1850 uses `'\n'.join(config_backends) + '\n'`) and add an explicit
'\n' on the coraza block append.

Caught immediately on staging: HTTP 000 to localhost:80 because HAProxy
never started; gunicorn/management API kept serving on :8000 fine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 17:03:56 -07:00
parent 3e1f9dda2b
commit 4769f67fe9

View File

@@ -1852,11 +1852,13 @@ backend default-backend
# Coraza WAF backend + SPOE engine config file (only when env var set). # Coraza WAF backend + SPOE engine config file (only when env var set).
# Writing /etc/haproxy/coraza-spoe.cfg here keeps it in sync with the # Writing /etc/haproxy/coraza-spoe.cfg here keeps it in sync with the
# filter line that hap_listener.tpl just rendered into the frontend. # filter line that hap_listener.tpl just rendered into the frontend.
# Explicit trailing '\n' because this is now the LAST config_part —
# HAProxy fails parse with "Missing LF on last line" otherwise.
if coraza_spoe_backend: if coraza_spoe_backend:
coraza_backend_block = template_env.get_template( coraza_backend_block = template_env.get_template(
'hap_coraza_spoa_backend.tpl' 'hap_coraza_spoa_backend.tpl'
).render(agent_target=coraza_spoe_backend) ).render(agent_target=coraza_spoe_backend)
config_parts.append(coraza_backend_block) config_parts.append(coraza_backend_block + '\n')
coraza_spoe_cfg = template_env.get_template( coraza_spoe_cfg = template_env.get_template(
'hap_coraza_spoe_engine.tpl' 'hap_coraza_spoe_engine.tpl'