-
Notifications
You must be signed in to change notification settings - Fork 2
/
gen_conf.py
137 lines (112 loc) · 4.93 KB
/
gen_conf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import yaml
import os
INDENTATION = ' ' * 4
def load_haproxy_conf():
with open('haproxy.yaml', 'r') as yaml_file:
return yaml.load(yaml_file, Loader=yaml.FullLoader)
def load_domains_conf():
with open('domains.yaml', 'r') as yaml_file:
return yaml.load(yaml_file, Loader=yaml.FullLoader)
def get_inbound_template():
return {
'frontend inbound': {
'bind': ['*:80', '*:443 ssl crt /opt/haproxy/ssl'],
'http-request add-header': 'X-Forwarded-Proto https',
'acl': [],
'redirect': None,
'use_backend': []
}
}
def should_print_empty_line(key, value, already_printed):
if len(value) > 1 and key not in ['option', 'server'] and not already_printed:
return True
return False
def dump_haproxy_conf(haproxy_conf):
with open('haproxy.cfg', 'w') as output_file:
for key, value in haproxy_conf.items():
output_file.write(f'{key}\n')
already_printed = False
for key2, value2 in value.items():
if type(value2) == dict:
for key3, value3 in value2.items():
output_file.write(f'{INDENTATION}{key2} {key3} {value3}\n')
already_printed = False
continue
elif type(value2) == list:
if should_print_empty_line(key2, value2, already_printed):
output_file.write('\n')
for value3 in value2:
output_file.write(f'{INDENTATION}{key2} {value3}\n')
if should_print_empty_line(key2, value2, False):
output_file.write('\n')
already_printed = True
continue
if value2:
output_file.write(f'{INDENTATION}{key2} {value2}\n')
already_printed = False
continue
output_file.write(f'{INDENTATION}{key2}\n')
already_printed = False
output_file.write('\n')
def update_haproxy_conf_with_domains(haproxy_conf, domains_conf):
inbound_template = get_inbound_template()
non_ssl_domains = []
for i, kv in enumerate(domains_conf.items()):
key, value = kv
domains_string = ' '.join([f'-i {domain}' for domain in value['domains']])
inbound_template['frontend inbound']['acl'].append(
f'is_domain{i} hdr(host) {domains_string}')
if 'force_ssl' in value and not value['force_ssl']:
non_ssl_domains.append(i)
inbound_template['frontend inbound']['use_backend'].append(f'domain{i} if is_domain{i}')
server_lines = []
j = 0
if 'endpoints' in value:
check_string = ''
if len(value['endpoints']) > 1:
check_string = 'check '
for endpoint in value['endpoints']:
server_lines.append(
f"s{i}{j} {endpoint} {check_string}maxconn {haproxy_conf['global']['maxconn']}")
j += 1
if 'ssl_endpoints' in value:
ssl_check_string = ''
if len(value['ssl_endpoints']) > 1:
ssl_check_string = 'check '
for ssl_endpoint in value['ssl_endpoints']:
server_lines.append(
f"s{i}{j} {ssl_endpoint} {ssl_check_string}ssl maxconn {haproxy_conf['global']['maxconn']}"
)
j += 1
inbound_template[f'backend domain{i} # {key}'] = {
'balance': 'roundrobin',
'option': ['httpclose', 'forwardfor'],
'server': server_lines
}
neg_string = ' '.join([f'!is_domain{i}' for i in non_ssl_domains])
inbound_template['frontend inbound'][
'redirect'] = f"scheme https code 301 if {neg_string} !{{ ssl_fc }}"
haproxy_conf.update(inbound_template)
def dump_certbot_scripts(domains_conf):
domains = []
for _, value in domains_conf.items():
domains += value['domains']
with open('get-certs.sh', 'w') as get_certs_file:
get_certs_file.write('#!/bin/bash\n')
certonly_base_cmd = f"certbot certonly --non-interactive --keep --expand --agree-tos -m {os.environ['LETSENCRYPT_EMAIL']} --standalone -d"
for domain in domains:
get_certs_file.write(f'{certonly_base_cmd} {domain}\n')
with open('load-certs.sh', 'w') as load_certs_file:
load_certs_file.write('#!/bin/bash\n')
for domain in domains:
load_certs_file.write(
f'cat /etc/letsencrypt/live/{domain}/fullchain.pem /etc/letsencrypt/live/{domain}/privkey.pem > /opt/haproxy/ssl/{domain}.pem\n'
)
if __name__ == "__main__":
haproxy_conf = load_haproxy_conf()
domains_conf = load_domains_conf()
update_haproxy_conf_with_domains(haproxy_conf, domains_conf)
dump_haproxy_conf(haproxy_conf)
dump_certbot_scripts(domains_conf)