Skip to content

Commit

Permalink
Merge pull request #3546 from c-po/haproxy
Browse files Browse the repository at this point in the history
reverse-proxy: T6419: build full CA chain when verifying backend server
  • Loading branch information
c-po authored May 30, 2024
2 parents 138be55 + 4b189a7 commit 5978273
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 45 deletions.
2 changes: 1 addition & 1 deletion data/templates/load-balancing/haproxy.cfg.j2
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ frontend {{ front }}
bind {{ address | bracketize_ipv6 }}:{{ front_config.port }} {{ ssl_directive }} {{ ssl_front | join(' ') }}
{% endfor %}
{% else %}
bind :::{{ front_config.port }} v4v6 {{ ssl_directive }} {{ ssl_front | join(' ') }}
bind [::]:{{ front_config.port }} v4v6 {{ ssl_directive }} {{ ssl_front | join(' ') }}
{% endif %}
{% if front_config.redirect_http_to_https is vyos_defined %}
http-request redirect scheme https unless { ssl_fc }
Expand Down
23 changes: 23 additions & 0 deletions op-mode-definitions/reverse-proxy.xml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="restart">
<children>
<node name="reverse-proxy">
<properties>
<help>Restart reverse-proxy service</help>
</properties>
<command>if cli-shell-api existsActive load-balancing reverse-proxy; then sudo systemctl restart haproxy.service; else echo "Reverse-Proxy not configured"; fi</command>
</node>
</children>
</node>
<node name="show">
<children>
<node name="reverse-proxy">
<properties>
<help>Show load-balancing reverse-proxy</help>
</properties>
<command>sudo ${vyos_op_scripts_dir}/reverseproxy.py show</command>
</node>
</children>
</node>
</interfaceDefinition>
13 changes: 0 additions & 13 deletions op-mode-definitions/show-reverse-proxy.xml.in

This file was deleted.

4 changes: 2 additions & 2 deletions smoketest/scripts/cli/test_load-balancing_reverse-proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def test_01_lb_reverse_proxy_domain(self):

# Frontend
self.assertIn(f'frontend {frontend}', config)
self.assertIn(f'bind :::{front_port} v4v6', config)
self.assertIn(f'bind [::]:{front_port} v4v6', config)
self.assertIn(f'mode {mode}', config)
for domain in domains_bk_first:
self.assertIn(f'acl {rule_ten} hdr(host) -i {domain}', config)
Expand Down Expand Up @@ -371,7 +371,7 @@ def test_06_lb_reverse_proxy_tcp_mode(self):

# Frontend
self.assertIn(f'frontend {frontend}', config)
self.assertIn(f'bind :::{front_port} v4v6', config)
self.assertIn(f'bind [::]:{front_port} v4v6', config)
self.assertIn(f'mode {mode}', config)

self.assertIn(f'tcp-request inspect-delay {tcp_request_delay}', config)
Expand Down
65 changes: 36 additions & 29 deletions src/conf_mode/load-balancing_reverse-proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@
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()
Expand Down Expand Up @@ -124,51 +128,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:
Expand Down

0 comments on commit 5978273

Please sign in to comment.