summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2025-04-28 22:08:46 +0200
committerChristian Breunig <christian@breunig.cc>2025-04-28 22:10:08 +0200
commitf8b0d74eecabdd16cb0cd6239c8095ed6d2321e3 (patch)
treee200a77ba323f8dad89900f3260532c843359c3b
parent6abf68da33aa71913872730e24396f366c4dc9fa (diff)
downloadvyos-1x-f8b0d74eecabdd16cb0cd6239c8095ed6d2321e3.tar.gz
vyos-1x-f8b0d74eecabdd16cb0cd6239c8095ed6d2321e3.zip
haproxy: T7122: automatically reverse-proxy to certbot
Automatically render HaProxy rules to reverse-proxy ACME challanges when the requested certificate was issued using ACME.
-rw-r--r--data/templates/load-balancing/haproxy.cfg.j213
-rw-r--r--src/conf_mode/load-balancing_haproxy.py23
2 files changed, 26 insertions, 10 deletions
diff --git a/data/templates/load-balancing/haproxy.cfg.j2 b/data/templates/load-balancing/haproxy.cfg.j2
index 2287cb815..400936474 100644
--- a/data/templates/load-balancing/haproxy.cfg.j2
+++ b/data/templates/load-balancing/haproxy.cfg.j2
@@ -64,9 +64,19 @@ frontend {{ front }}-http
{% else %}
bind [::]:80 v4v6
{% endif %}
- redirect scheme https code 301 if !{ ssl_fc }
+{% if front_config.ssl.acme_certificate is vyos_defined %}
+ acl acme_acl path_beg /.well-known/acme-challenge/
+ use_backend certbot_{{ front }}_backend if acme_acl
+{% endif %}
+ redirect scheme https code 301 if !acme_acl
+{% endif %}
+
+{% if front_config.ssl.acme_certificate is vyos_defined %}
+backend certbot_{{ front }}_backend
+ server fe_{{ front }}_acme 127.0.0.1:65080
{% endif %}
+
frontend {{ front }}
{% set ssl_front = [] %}
{% if front_config.ssl.certificate is vyos_defined and front_config.ssl.certificate is iterable %}
@@ -248,6 +258,5 @@ backend {{ back }}
{% if back_config.timeout.server is vyos_defined %}
timeout server {{ back_config.timeout.server }}s
{% endif %}
-
{% endfor %}
{% endif %}
diff --git a/src/conf_mode/load-balancing_haproxy.py b/src/conf_mode/load-balancing_haproxy.py
index 92bf818dc..f176009a0 100644
--- a/src/conf_mode/load-balancing_haproxy.py
+++ b/src/conf_mode/load-balancing_haproxy.py
@@ -22,6 +22,7 @@ from shutil import rmtree
from vyos.config import Config
from vyos.configverify import verify_pki_certificate
from vyos.configverify import verify_pki_ca_certificate
+from vyos.defaults import internal_ports
from vyos.utils.dict import dict_search
from vyos.utils.process import call
from vyos.utils.network import check_port_availability
@@ -58,6 +59,14 @@ def get_config(config=None):
with_recursive_defaults=True,
with_pki=True)
+ lb['certbot_port'] = internal_ports['certbot_haproxy']
+
+ if 'service' in lb:
+ for front, front_config in lb['service'].items():
+ for cert in dict_search('ssl.certificate', front_config) or []:
+ if dict_search(f'pki.certificate.{cert}.acme', lb):
+ lb['service'][front]['ssl'].update({'acme_certificate': {}})
+
return lb
def verify(lb):
@@ -85,6 +94,9 @@ def verify(lb):
raise ConfigError(f'service {front} must have at least one mime-type configured to use'
f'http_compression!')
+ for cert in dict_search('ssl.certificate', front_config) or []:
+ verify_pki_certificate(lb, cert)
+
for back, back_config in lb['backend'].items():
if 'http_check' in back_config:
http_check = back_config['http_check']
@@ -112,20 +124,15 @@ def verify(lb):
if {'no_verify', 'ca_certificate'} <= set(back_config['ssl']):
raise ConfigError(f'backend {back} cannot have both ssl options no-verify and ca-certificate set!')
+ tmp = dict_search('ssl.ca_certificate', back_config)
+ if tmp: verify_pki_ca_certificate(lb, tmp)
+
# Check if http-response-headers are configured in any frontend/backend where mode != http
for group in ['service', 'backend']:
for config_name, config in lb[group].items():
if 'http_response_headers' in config and config['mode'] != 'http':
raise ConfigError(f'{group} {config_name} must be set to http mode to use http_response_headers!')
- for front, front_config in lb['service'].items():
- for cert in dict_search('ssl.certificate', front_config) or []:
- verify_pki_certificate(lb, cert)
-
- for back, back_config in lb['backend'].items():
- tmp = dict_search('ssl.ca_certificate', back_config)
- if tmp: verify_pki_ca_certificate(lb, tmp)
-
def generate(lb):
if not lb: