summaryrefslogtreecommitdiff
path: root/src/conf_mode/load-balancing_reverse-proxy.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode/load-balancing_reverse-proxy.py')
-rwxr-xr-xsrc/conf_mode/load-balancing_reverse-proxy.py86
1 files changed, 54 insertions, 32 deletions
diff --git a/src/conf_mode/load-balancing_reverse-proxy.py b/src/conf_mode/load-balancing_reverse-proxy.py
index 1569d8d71..09c68dadd 100755
--- a/src/conf_mode/load-balancing_reverse-proxy.py
+++ b/src/conf_mode/load-balancing_reverse-proxy.py
@@ -26,9 +26,13 @@ from vyos.utils.dict import dict_search
from vyos.utils.process import call
from vyos.utils.network import check_port_availability
from vyos.utils.network import is_listen_port_bind_service
-from vyos.pki import wrap_certificate
-from vyos.pki import wrap_private_key
+from vyos.pki import find_chain
+from vyos.pki import load_certificate
+from vyos.pki import load_private_key
+from vyos.pki import encode_certificate
+from vyos.pki import encode_private_key
from vyos.template import render
+from vyos.utils.file import write_file
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -75,12 +79,21 @@ def verify(lb):
raise ConfigError(f'"TCP" port "{tmp_port}" is used by another service')
for back, back_config in lb['backend'].items():
- if 'http-check' in back_config:
- http_check = back_config['http-check']
+ if 'http_check' in back_config:
+ http_check = back_config['http_check']
if 'expect' in http_check and 'status' in http_check['expect'] and 'string' in http_check['expect']:
raise ConfigError(f'"expect status" and "expect string" can not be configured together!')
+
+ if 'health_check' in back_config:
+ if 'mode' not in back_config or back_config['mode'] != 'tcp':
+ raise ConfigError(f'backend "{back}" can only be configured with {back_config["health_check"]} ' +
+ f'health-check whilst in TCP mode!')
+ if 'http_check' in back_config:
+ raise ConfigError(f'backend "{back}" cannot be configured with both http-check and health-check!')
+
if 'server' not in back_config:
raise ConfigError(f'"{back} server" must be configured!')
+
for bk_server, bk_server_conf in back_config['server'].items():
if 'address' not in bk_server_conf or 'port' not in bk_server_conf:
raise ConfigError(f'"backend {back} server {bk_server} address and port" must be configured!')
@@ -92,12 +105,18 @@ 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!')
+ # 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 ('mode' not in config or 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', front_config)
+ tmp = dict_search('ssl.ca_certificate', back_config)
if tmp: verify_pki_ca_certificate(lb, tmp)
@@ -118,51 +137,54 @@ def generate(lb):
if not os.path.isdir(load_balancing_dir):
os.mkdir(load_balancing_dir)
+ loaded_ca_certs = {load_certificate(c['certificate'])
+ for c in lb['pki']['ca'].values()} if 'ca' in lb['pki'] else {}
+
# SSL Certificates for frontend
for front, front_config in lb['service'].items():
- if 'ssl' in front_config:
-
- if 'certificate' in front_config['ssl']:
- cert_names = front_config['ssl']['certificate']
+ if 'ssl' not in front_config:
+ continue
- for cert_name in cert_names:
- pki_cert = lb['pki']['certificate'][cert_name]
- cert_file_path = os.path.join(load_balancing_dir, f'{cert_name}.pem')
- cert_key_path = os.path.join(load_balancing_dir, f'{cert_name}.pem.key')
+ if 'certificate' in front_config['ssl']:
+ cert_names = front_config['ssl']['certificate']
- with open(cert_file_path, 'w') as f:
- f.write(wrap_certificate(pki_cert['certificate']))
+ for cert_name in cert_names:
+ pki_cert = lb['pki']['certificate'][cert_name]
+ cert_file_path = os.path.join(load_balancing_dir, f'{cert_name}.pem')
+ cert_key_path = os.path.join(load_balancing_dir, f'{cert_name}.pem.key')
- if 'private' in pki_cert and 'key' in pki_cert['private']:
- with open(cert_key_path, 'w') as f:
- f.write(wrap_private_key(pki_cert['private']['key']))
+ loaded_pki_cert = load_certificate(pki_cert['certificate'])
+ cert_full_chain = find_chain(loaded_pki_cert, loaded_ca_certs)
- if 'ca_certificate' in front_config['ssl']:
- ca_name = front_config['ssl']['ca_certificate']
- pki_ca_cert = lb['pki']['ca'][ca_name]
- ca_cert_file_path = os.path.join(load_balancing_dir, f'{ca_name}.pem')
+ write_file(cert_file_path,
+ '\n'.join(encode_certificate(c) for c in cert_full_chain))
- with open(ca_cert_file_path, 'w') as f:
- f.write(wrap_certificate(pki_ca_cert['certificate']))
+ if 'private' in pki_cert and 'key' in pki_cert['private']:
+ loaded_key = load_private_key(pki_cert['private']['key'], passphrase=None, wrap_tags=True)
+ key_pem = encode_private_key(loaded_key, passphrase=None)
+ write_file(cert_key_path, key_pem)
# SSL Certificates for backend
for back, back_config in lb['backend'].items():
- if 'ssl' in back_config:
+ if 'ssl' not in back_config:
+ continue
- if 'ca_certificate' in back_config['ssl']:
- ca_name = back_config['ssl']['ca_certificate']
- pki_ca_cert = lb['pki']['ca'][ca_name]
- ca_cert_file_path = os.path.join(load_balancing_dir, f'{ca_name}.pem')
+ if 'ca_certificate' in back_config['ssl']:
+ ca_name = back_config['ssl']['ca_certificate']
+ ca_cert_file_path = os.path.join(load_balancing_dir, f'{ca_name}.pem')
+ ca_chains = []
- with open(ca_cert_file_path, 'w') as f:
- f.write(wrap_certificate(pki_ca_cert['certificate']))
+ pki_ca_cert = lb['pki']['ca'][ca_name]
+ loaded_ca_cert = load_certificate(pki_ca_cert['certificate'])
+ ca_full_chain = find_chain(loaded_ca_cert, loaded_ca_certs)
+ ca_chains.append('\n'.join(encode_certificate(c) for c in ca_full_chain))
+ write_file(ca_cert_file_path, '\n'.join(ca_chains))
render(load_balancing_conf_file, 'load-balancing/haproxy.cfg.j2', lb)
render(systemd_override, 'load-balancing/override_haproxy.conf.j2', lb)
return None
-
def apply(lb):
call('systemctl daemon-reload')
if not lb: