You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

398 lines
12 KiB

#!/usr/bin/python3.6
# coding: utf8
import locale
from dialog import Dialog
import os
import pynginxconfig
import re
from goto import with_goto
# import sys
# import getopt
import subprocess
import shlex
nginx_dir = "/etc/nginx"
nginx_available_sites = nginx_dir + "/sites_available/"
nginx_enabled_sites = nginx_dir + "/sites_enabled/"
nginx_templates = nginx_dir + "/templates/"
template_host = 'host.conf'
template_ssl = 'host_ssl.conf'
errcode = list()
errcode.append(False)
errcode.append(True)
errcode.append("string can't be empty")
errcode.append('English letters only. To issue for an Internationalized Domain Name, use Punycode.')
errcode.append('string must be numerical')
errcode.append('')
def get_available():
f = os.listdir(nginx_available_sites)
return f
def check_if_enabled(vhost_file):
if os.path.exists(nginx_enabled_sites + vhost_file):
return True
else:
return False
def check_cert(domain):
if os.path.isfile('/etc/letsencrypt/live/' + domain.split(' ')[0] + '/cert.pem'):
return True
else:
return False
def make_list(delete=False):
t = tuple()
x = get_available()
a = list()
for vhost in x:
if delete is not True:
t = (vhost, get_server_name(vhost), check_if_enabled(vhost))
a.append(t)
else:
t = (vhost, get_server_name(vhost), False)
a.append(t)
s = sorted(a, key=lambda dom: dom[1])
return s
def enable_vhost(vhost):
try:
os.symlink(nginx_available_sites + vhost, nginx_enabled_sites + vhost)
except FileExistsError:
pass
return True
def renew_enabled(vhosts):
a = get_available()
for vhost in a:
if vhost in vhosts:
if check_if_enabled(vhost):
pass
else:
enable_vhost(vhost)
else:
if check_if_enabled(vhost):
os.unlink(nginx_enabled_sites + vhost)
else:
pass
restart_nginx()
return True
def get_server_name(vhost_file):
i = int()
if vhost_file == 'default.conf':
ret = 'default.conf'
else:
vhost = pynginxconfig.NginxConfig()
vhost.loadf(nginx_available_sites + vhost_file)
try:
ret = vhost.get([('server',), 'server_name'])[1]
except:
ret = "None"
return ret
def enable_redirect(cfg):
filename = cfg
vhost = pynginxconfig.NginxConfig()
vhost.loadf(nginx_available_sites + filename)
vhost[0]['value'].insert(7, ('rewrite', '^ https://$http_host$request_uri? permanent'))
vhost.savef(nginx_available_sites + filename)
return
def is_ascii(s):
pattern = r'[^.a-zA-Z0-9- ]'
if len(s) != 0:
if re.search(pattern, s):
return 3
else:
return 1
else:
return 2
def is_num(s):
pattern = r'[^0-9]'
if len(s) != 0:
if re.search(pattern, s):
return 4
else:
return 1
else:
return 2
def check_data(data):
msg = list()
ret = True
rc = is_ascii(data['Domain'])
if rc != True:
ret = False
msg.append("Domain: " + str(errcode[rc]))
rc = is_ascii(data['SubDomain'])
if data['SubDomain'] != '':
if rc != True:
ret = False
msg.append("SubDomain: " + str(errcode[rc]))
rc = is_ascii(data['Backend_Addr'])
if rc != True:
ret = False
msg.append("Backend_Addr: " + str(errcode[rc]))
rc = is_num(data['Backend_Port'])
if rc != True:
ret = False
msg.append("Backend_Port: " + str(errcode[rc]))
return ret, msg
def delete_vhosts(vhosts):
for vhost in vhosts:
try:
os.unlink(nginx_enabled_sites + vhost)
except:
pass
try:
os.unlink(nginx_available_sites + vhost)
except:
pass
restart_nginx()
def form_one():
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog")
d.set_background_title("NGINX domains managment")
ret, tags = d.menu("Select action?", width=60, height=10,
choices=[("Add", "Add new domain"),
("Enable/Disable", "Enable/Disable selected domains"),
("Delete", "Delete selected domains")],
title="")
return ret, tags
def edit_form(domain='', subdomain='', backend_addr='', backend_port='80'):
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog")
ret, val = d.mixedform("Fill the form:\n \n Enter additional domians separate by space\n (for example: www.domain.ru xxx.domain.ru)", height=14, width=60,
elements=[("Domain name", 1, 3, domain, 1, 22, 30, 255, 0),
("Additional domains", 2, 3, subdomain, 2, 22, 30, 65535, 0),
("Backend addr", 3, 3, backend_addr, 3, 22, 30, 255, 0),
("Backend port", 4, 3, backend_port, 4, 22, 30, 5, 0)]
)
if ret == 'ok':
ret = show_yesno('Do you want to do automatically redirect from HTTP to HTTPS?')
if ret == 'ok':
values = {'Domain': val[0], 'SubDomain': val[1], 'Backend_Addr': val[2], 'Backend_Port': val[3], 'redirect': True}
else:
values = {'Domain': val[0], 'SubDomain': val[1], 'Backend_Addr': val[2], 'Backend_Port': val[3], 'redirect': False}
return ret, values
else:
return ret, ""
def select_form():
vlist = make_list()
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog")
ret, dom_list = d.checklist("Enable or disable sites", height=30, width=120, list_height=30, choices=vlist)
if ret == "ok":
show_info("Please wait. Work in progress")
renew_enabled(dom_list)
return ret
def delete_form():
vlist = make_list(True)
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog")
ret, dom_list = d.checklist("Select to delete:", height=30, width=120, list_height=30, choices=vlist)
if ret == "ok":
if show_yesno('Are you sure?\n\nThese domains will be deleted:\n\n' + '\n'.join(dom_list)) == "ok":
show_info("Please wait. Work in progress")
delete_vhosts(dom_list)
else:
return ret
def show_yesno(msg):
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog")
ret = d.yesno(msg, height=10, width=60)
return ret
def create_domain(vhost, ssl=False):
if ssl is not True:
filename = vhost['Domain'] + '.conf'
template = nginx_templates + template_host
else:
filename = vhost['Domain'] + '_ssl.conf'
template = nginx_templates + template_ssl
domains = vhost['Domain'] + ' '
for dom in vhost['SubDomain']:
domains += dom
vconfig = pynginxconfig.NginxConfig()
vconfig.loadf(template)
server_str = vconfig.get([('server',), 'server_name'])[1].replace('[domain_names]', domains)
log_str = vconfig.get([('server',), 'error_log'])[1].replace('[domain_name]', vhost['Domain'])
if ssl:
cert_str = vconfig.get([('server',), 'ssl_certificate'])[1].replace('[domain_name]', vhost['Domain'])
cert_key_str = vconfig.get([('server',), 'ssl_certificate_key'])[1].replace('[domain_name]', vhost['Domain'])
vconfig.set([('server',), 'ssl_certificate'], cert_str)
vconfig.set([('server',), 'ssl_certificate_key'], cert_key_str)
backend_str = vconfig.get([('server',), 'set'])[1].replace('[host_name]', vhost['Backend_Addr']).replace('[host_port]', vhost['Backend_Port'])
vconfig.set([('server',), 'server_name'], server_str)
vconfig.set([('server',), 'error_log'], log_str)
vconfig.set([('server',), 'set'], backend_str)
#if vhost['redirect'] is not True:
# vconfig.remove([('server',), 'rewrite'])
vconfig.savef(nginx_available_sites + filename)
return domains, filename
def create_cert(domains):
if check_cert(domains) is not True:
cmd = 'certbot certonly --agree-tos --email admin@shopband.ru --webroot -w /var/www/lets -d ' + domains.rstrip().replace(' ', ' -d ')
ret = subprocess.run(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if ret.returncode != 0:
msg = "Error getting ssl certs\nThe SSL configuration is written to " + nginx_available_sites + ", " \
"but not enabled.\nGet SSL certs manualy and make symlink to " + nginx_enabled_sites
show_error(msg + "\nLog saved into " + domains.split(' ')[0] + ".log")
f = open('./' + domains.split(' ')[0] + ".log", 'w')
f.write(ret.stderr.decode("utf-8"))
f.close()
return False
elif ret.returncode == 0:
return True
else:
return False
else:
return True
def restart_nginx():
ret = subprocess.run(shlex.split('/usr/sbin/nginx -t -c /etc/nginx/nginx.conf'), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if ret.returncode != 0:
show_error(ret.stderr.decode("utf-8"))
return False
elif ret.returncode == 0:
ret = subprocess.run(shlex.split('service nginx restart'), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if ret.returncode != 0:
show_error(ret.stderr.decode("utf-8"))
return False
return True
def show_info(msg):
s_width = len(msg)
if s_width > 56:
s_width = 56
d = Dialog(dialog="dialog")
d.infobox(msg, height=3, width=s_width+4)
return
def show_error(msg):
txt = ''
if isinstance(msg, list):
for err in msg:
txt = txt + err + '\n'
else:
txt = msg
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog")
d.msgbox(text=txt, width=80, height=20)
return txt
def enable_site(cfg, domains='', ssl=False):
if ssl is True:
if create_cert(domains):
enable_vhost(cfg)
else:
return False
else:
enable_vhost(cfg)
if restart_nginx():
return True
else:
return False
# if ssl:
# ret_code = create_cert(domains)
# if ret_code:
# enable_vhost(filename)
# else:
# show_error(msg)
# else:
# enable_vhost(filename)
pass
@with_goto
def start_it():
label .start
vals = {'Domain': '', 'SubDomain': '', 'Backend_Addr': '', 'Backend_Port': '80'}
rc, action = form_one()
if rc == 'ok':
if action == "Add":
label .add
ret, vals = edit_form(vals['Domain'], vals['SubDomain'], vals['Backend_Addr'], vals['Backend_Port'])
if ret is not 'ok':
goto .start
else:
ret_code, msg = check_data(vals)
if ret_code is not True:
show_error(msg)
goto .add
else:
# Create HTTP config
domains, cfg = create_domain(vals)
show_info("Please wait. Work in progress")
if enable_site(cfg) is not True:
goto .start
else:
http_config = cfg
# Create HTTPS config
domains, cfg = create_domain(vals, True)
show_info("Please wait. Work in progress")
if enable_site(cfg, domains, True) is not True:
print("false")
goto .start
else:
if vals['redirect'] is True:
enable_redirect(http_config)
restart_nginx()
goto .start
elif action == "Enable/Disable":
label .endis
ret = select_form()
goto .start
elif action == "Delete":
label .delete
delete_form()
goto .start
start_it()

Powered by TurnKey Linux.