Split haproxy horizon config into 'base' frontend and 'horizon' backend

Several new features have been added to openstack-ansible which
require special handling on port 80/443, such as support for
LetsEncrypt and security.txt. This causes a confusing situation
when several different features are served by the 'horizon' haproxy
frontend/backend when horizon itself may not necessarily be deployed.

This patch splits the haproxy config for port 80/443 into a 'base'
frontend which is always deployed and is responsible for handling
requests for LetsEncrypt and security.txt with all other traffic being
handled by a default 'horizon' backend.

The 'horizon' backend is only deployed when the horizon service is
enabled, i.e. when the horizon_all ansible group has members.

Depends-On: https://review.opendev.org/c/openstack/openstack-ansible-haproxy_server/+/876157
Depends-On: https://review.opendev.org/c/openstack/openstack-ansible-rabbitmq_server/+/876436
Change-Id: I7bdf71faa761897cc2a0e01d1af1ccb4946f10f5
This commit is contained in:
Jonathan Rosser 2023-03-02 14:24:56 +00:00 committed by Damian Dabrowski
parent d09dfbbae0
commit 1694b142bc
2 changed files with 37 additions and 8 deletions

View File

@ -74,6 +74,24 @@ openstack_haproxy_horizon_stick_table:
- "http-request deny deny_status 429 if { sc_http_req_rate(0) gt 20 } { path_beg /auth } !{ src {{haproxy_stick_table_allowlist_networks | join(' } !{ src ') }} }"
- "http-request deny deny_status 429 if { sc_http_err_rate(0) gt 20 } !{ src {{haproxy_stick_table_allowlist_networks | join(' } !{ src ') }} }"
# haproxy 'base' frontend-only service that is used always deployed for port 80 redirect and 443
# this potentially supports horizon dashboard, security.txt and certbot
# plus any other user defined custom backend
haproxy_base_service:
haproxy_service_name: base
haproxy_frontend_only: true
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_ssl_all_vips: true
haproxy_port: "{{ haproxy_ssl | ternary(443,80) }}"
haproxy_redirect_http_port: 80
haproxy_balance_type: http
haproxy_service_enabled: true
haproxy_redirect_scheme: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary('https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }', 'https if !{ ssl_fc }') }}"
haproxy_frontend_acls: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary(haproxy_ssl_letsencrypt_acl, {}) }}"
haproxy_acls: "{{ keystone_security_txt_content is defined | ternary(haproxy_security_txt_acl, {}) }}"
haproxy_frontend_raw: "{{ (haproxy_ssl | bool and haproxy_security_headers is defined) | ternary( haproxy_security_headers + [ haproxy_horizon_csp | default(haproxy_security_headers_csp)], []) }}"
haproxy_default_backend: "{{ (groups['horizon_all'] | length > 0) | ternary('horizon', '') }}"
haproxy_adjutant_api_service:
haproxy_service_name: adjutant_api
haproxy_backend_nodes: "{{ groups['adjutant_api'] | default([]) }}"
@ -222,22 +240,15 @@ haproxy_heat_api_service:
haproxy_service_enabled: "{{ groups['heat_api'] is defined and groups['heat_api'] | length > 0 }}"
haproxy_horizon_service:
haproxy_backend_only: true #only describe the backends, frontend is in `base`
haproxy_service_name: horizon
haproxy_backend_nodes: "{{ groups['horizon_all'] | default([]) }}"
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_ssl_all_vips: true
haproxy_port: "{{ haproxy_ssl | ternary(443,80) }}"
haproxy_backend_port: 80
haproxy_redirect_http_port: 80
haproxy_balance_type: http
haproxy_balance_alg: source
haproxy_backend_options:
- "httpchk HEAD /auth/login/ HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
haproxy_service_enabled: "{{ groups['horizon_all'] is defined and groups['horizon_all'] | length > 0 }}"
haproxy_redirect_scheme: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary('https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }', 'https if !{ ssl_fc }') }}"
haproxy_frontend_acls: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary(haproxy_ssl_letsencrypt_acl, {}) }}"
haproxy_acls: "{{ keystone_security_txt_content is defined | ternary(haproxy_security_txt_acl, {}) }}"
haproxy_frontend_raw: "{{ (haproxy_ssl | bool and haproxy_security_headers is defined) | ternary( haproxy_security_headers + [ haproxy_horizon_csp | default(haproxy_security_headers_csp)], []) }}"
haproxy_stick_table: "{{ openstack_haproxy_horizon_stick_table }}"
haproxy_ironic_api_service:
@ -572,6 +583,7 @@ haproxy_zun_console_service:
haproxy_service_enabled: "{{ groups['zun_api'] is defined and groups['zun_api'] | length > 0 }}"
haproxy_default_services:
- service: "{{ haproxy_base_service | combine(haproxy_base_service_overrides | default({})) }}"
- service: "{{ haproxy_adjutant_api_service | combine(haproxy_adjutant_api_service_overrides | default({})) }}"
- service: "{{ haproxy_aodh_api_service | combine(haproxy_aodh_api_service_overrides | default({})) }}"
- service: "{{ haproxy_barbican_service | combine(haproxy_barbican_service_overrides | default({})) }}"

View File

@ -0,0 +1,17 @@
---
features:
- |
The configuration for serving port 80/443 in haproxy was previously
associated with the Horizon service, but additional features such as
handling certificate issuance with certbot and serving security.txt
also need configuration in the same haproxy frontend. The existing
variable ``haproxy_horizon_service`` now only describes the haproxy
backend for horizon, and a new variable ``haproxy_base_service``
configures the haproxy frontend for any services using port 80/443.
upgrades:
- |
Any existing overrides of ``haproxy_horizon_service`` should be
adjusted to account for this variable now only describing the haproxy
backend for horizon, and any overrides for LetsEncrypt, security.txt
or other customisation of the haproxy frontend for port 80/443
should be moved to ``haproxy_base_service`` or ``haproxy_base_service_overrides``.