resolve bugs on the stable version

This commit is contained in:
bunkerity 2021-07-22 12:12:55 +02:00
parent 15bdb076c8
commit 36b8760d4d
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
9 changed files with 142 additions and 124 deletions

View File

@ -1,5 +1,16 @@
# Changelog # Changelog
## v1.2.8 - 2021/07/22
- Fix broken links in README
- Fix regex for EMAIL_LETS_ENCRYPT
- Fix regex for REMOTE_PHP and REMOTE_PHP_PATH
- Fix regex for SELF_SIGNED_*
- Fix various bugs related to web UI
- Fix bug in autoconf (missing instances parameter to reload function)
- Remove old .env files when generating a new configuration
-
## v1.2.7 - 2021/06/14 ## v1.2.7 - 2021/06/14
- Add custom robots.txt and sitemap to RTD - Add custom robots.txt and sitemap to RTD

View File

@ -432,8 +432,8 @@ bunkerized-nginx comes with a set of predefined security settings that you can (
# License # License
This project is licensed under the terms of the [GNU Affero General Public License (AGPL) version 3](https://github.com/bunkerity/bunkerized-nginx/LICENSE.md). This project is licensed under the terms of the [GNU Affero General Public License (AGPL) version 3](https://github.com/bunkerity/bunkerized-nginx/blob/master/LICENSE.md).
# Contributing # Contributing
If you would like to contribute to the project you can read the [contributing guidelines](https://github.com/bunkerity/bunkerized-nginx/CONTRIBUTING.md) to get started. If you would like to contribute to the project you can read the [contributing guidelines](https://github.com/bunkerity/bunkerized-nginx/blob/master/CONTRIBUTING.md) to get started.

View File

@ -173,7 +173,7 @@ class AutoConf :
self.__servers[id].reload() self.__servers[id].reload()
utils.log("[*] Deactivating config for " + vars["SERVER_NAME"]) utils.log("[*] Deactivating config for " + vars["SERVER_NAME"])
self.__gen_env() self.__gen_env()
if self.__config.reload() : if self.__config.reload(self.__instances) :
utils.log("[*] Deactivated config for " + vars["SERVER_NAME"]) utils.log("[*] Deactivated config for " + vars["SERVER_NAME"])
else : else :
utils.log("[!] Can't deactivate config for " + vars["SERVER_NAME"]) utils.log("[!] Can't deactivate config for " + vars["SERVER_NAME"])

View File

@ -1,6 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
import argparse, os, sys, shutil import argparse, os, sys, shutil, glob
import utils import utils
from Configurator import Configurator from Configurator import Configurator
@ -51,14 +51,10 @@ if __name__ == "__main__" :
config = configurator.get_config() config = configurator.get_config()
#print(config) #print(config)
# Remove old config # TODO : find a proper way to remove old sites
# TODO : remove unnecessary files after rendering env_list = glob.glob(args.output + "/**/*.env", recursive=True)
# for filename in os.listdir(args.output): for env in env_list :
# file_path = os.path.join(args.output, filename) os.remove(env)
# if os.path.isfile(file_path) or os.path.islink(file_path):
# os.unlink(file_path)
# elif os.path.isdir(file_path):
# shutil.rmtree(file_path)
# Generate the files from templates and config # Generate the files from templates and config
templator = Templator(config, args.templates, args.output, args.target) templator = Templator(config, args.templates, args.output, args.target)

View File

@ -525,7 +525,7 @@
"env": "EMAIL_LETS_ENCRYPT", "env": "EMAIL_LETS_ENCRYPT",
"id": "email-lets-encrypt", "id": "email-lets-encrypt",
"label": "Email lets encrypt", "label": "Email lets encrypt",
"regex": "^([a-z0-9\\-\\.]+@([a-z\\-0-9]+\\.?)|.{0})$", "regex": "^([a-z0-9\\-\\.]+@[a-z\\-0-9\\.]+|.{0})$",
"type": "text" "type": "text"
}, },
{ {
@ -615,7 +615,7 @@
"env": "SELF_SIGNED_SSL_COUNTRY", "env": "SELF_SIGNED_SSL_COUNTRY",
"id": "self-signed-ssl-country", "id": "self-signed-ssl-country",
"label": "Country of the self-signed certificate", "label": "Country of the self-signed certificate",
"regex": "^[:print:]+$", "regex": "^[A-Z]{2}$",
"type": "text" "type": "text"
}, },
{ {
@ -624,7 +624,7 @@
"env": "SELF_SIGNED_SSL_STATE", "env": "SELF_SIGNED_SSL_STATE",
"id": "self-signed-ssl-state", "id": "self-signed-ssl-state",
"label": "State of the self-signed certificate", "label": "State of the self-signed certificate",
"regex": "^[:print:]+$", "regex": "^[A-Za-z\\- ]+$",
"type": "text" "type": "text"
}, },
{ {
@ -633,7 +633,7 @@
"env": "SELF_SIGNED_SSL_CITY", "env": "SELF_SIGNED_SSL_CITY",
"id": "self-signed-ssl-city", "id": "self-signed-ssl-city",
"label": "City of the self-signed certificate", "label": "City of the self-signed certificate",
"regex": "^[:print:]+$", "regex": "^[A-Za-z\\- ]+$",
"type": "text" "type": "text"
}, },
{ {
@ -642,7 +642,7 @@
"env": "SELF_SIGNED_SSL_OU", "env": "SELF_SIGNED_SSL_OU",
"id": "self-signed-ssl-ou", "id": "self-signed-ssl-ou",
"label": "Organizational Unit of the self-signed certificate", "label": "Organizational Unit of the self-signed certificate",
"regex": "^[:print:]+$", "regex": "^[A-Za-z\\- ]+$",
"type": "text" "type": "text"
}, },
{ {
@ -651,7 +651,7 @@
"env": "SELF_SIGNED_SSL_ORG", "env": "SELF_SIGNED_SSL_ORG",
"id": "self-signed-ssl-org", "id": "self-signed-ssl-org",
"label": "Organization name of the self-signed certificate", "label": "Organization name of the self-signed certificate",
"regex": "^[:print:]+$", "regex": "^[A-Za-z\\- ]+$",
"type": "text" "type": "text"
}, },
{ {
@ -660,7 +660,7 @@
"env": "SELF_SIGNED_SSL_CN", "env": "SELF_SIGNED_SSL_CN",
"id": "self-signed-ssl-cn", "id": "self-signed-ssl-cn",
"label": "Common Name of the self-signed certificate", "label": "Common Name of the self-signed certificate",
"regex": "^[:print:]+$", "regex": "^[A-Za-z\\-\\.0-9]+$",
"type": "text" "type": "text"
} }
] ]
@ -947,7 +947,7 @@
"env": "REMOTE_PHP", "env": "REMOTE_PHP",
"id": "remote-php", "id": "remote-php",
"label": "Remote php", "label": "Remote php",
"regex": "^([a-z\\-0-9\\_]+\\.?)*$", "regex": "^[a-z\\-0-9_\\.]*$",
"type": "text" "type": "text"
}, },
{ {
@ -956,7 +956,7 @@
"env": "REMOTE_PHP_PATH", "env": "REMOTE_PHP_PATH",
"id": "remote-php-path", "id": "remote-php-path",
"label": "Remote php path", "label": "Remote php path",
"regex": "^/([A-Za-z0-9\\-]/?)*$", "regex": "^\\/[a-zA-Z\\-0-9_\\.\\/]*$",
"type": "text" "type": "text"
} }
] ]

View File

@ -1,113 +1,121 @@
import json, uuid, glob, copy, re, subprocess import json, uuid, glob, copy, re, subprocess, os
class Config : class Config :
def __init__(self) : def __init__(self) :
with open("/opt/settings.json", "r") as f : with open("/opt/settings.json", "r") as f :
self.__settings = json.loads(f.read()) self.__settings = json.loads(f.read())
def __env_to_dict(self, filename) : def __env_to_dict(self, filename) :
with open(filename, "r") as f : if not os.path.isfile(filename) :
env = f.read() return {}
data = {} with open(filename, "r") as f :
for line in env.split("\n") : env = f.read()
var = line.split("=")[0] data = {}
val = line.replace(var + "=", "", 1) for line in env.split("\n") :
data[var] = val var = line.split("=")[0]
return data val = line.replace(var + "=", "", 1)
data[var] = val
return data
def __dict_to_env(self, filename, variables) : def __dict_to_env(self, filename, variables) :
env = "" env = ""
for k, v in variables.items() : for k, v in variables.items() :
env += k + "=" + v + "\n" env += k + "=" + v + "\n"
with open(filename, "w") as f : with open(filename, "w") as f :
f.write(env) f.write(env)
def __gen_conf(self, global_conf, services_conf) : def __gen_conf(self, global_conf, services_conf) :
conf = copy.deepcopy(global_conf) conf = copy.deepcopy(global_conf)
servers = conf["SERVER_NAME"].split(" ") if not "SERVER_NAME" in conf :
if conf["SERVER_NAME"] == "" : conf["SERVER_NAME"] = ""
servers = [] servers = conf["SERVER_NAME"].split(" ")
for service in services_conf : if conf["SERVER_NAME"] == "" :
first_server = service["SERVER_NAME"].split(" ")[0] servers = []
if not first_server in servers : for service in services_conf :
servers.append(first_server) first_server = service["SERVER_NAME"].split(" ")[0]
for k, v in service.items() : if not first_server in servers :
conf[first_server + "_" + k] = v servers.append(first_server)
conf["SERVER_NAME"] = " ".join(servers) for k, v in service.items() :
env_file = "/tmp/" + str(uuid.uuid4()) + ".env" conf[first_server + "_" + k] = v
self.__dict_to_env(env_file, conf) conf["SERVER_NAME"] = " ".join(servers)
proc = subprocess.run(["/bin/su", "-c", "/opt/gen/main.py --settings /opt/settings.json --templates /opt/confs --output /etc/nginx --variables " + env_file, "nginx"], capture_output=True) env_file = "/tmp/" + str(uuid.uuid4()) + ".env"
stderr = proc.stderr.decode("ascii") self.__dict_to_env(env_file, conf)
#stdout = proc.stdout.decode("ascii") proc = subprocess.run(["/opt/gen/main.py", "--settings", "/opt/settings.json", "--templates", "/opt/confs", "--output", "/etc/nginx", "--variables", env_file], capture_output=True)
if stderr != "" or proc.returncode != 0 : stderr = proc.stderr.decode("ascii")
raise Exception("Error from generator (return code = " + str(proc.returncode) + ") : " + stderr) stdout = proc.stdout.decode("ascii")
if stderr != "" or proc.returncode != 0 :
raise Exception("Error from generator (return code = " + str(proc.returncode) + ") : " + stderr + "\n" + stdout)
def get_settings(self) : def get_settings(self) :
return self.__settings return self.__settings
def get_config(self) : def get_config(self) :
return self.__env_to_dict("/etc/nginx/global.env") return self.__env_to_dict("/etc/nginx/global.env")
def get_services(self) : def get_services(self) :
services = [] services = []
for filename in glob.iglob("/etc/nginx/**/site.env") : for filename in glob.iglob("/etc/nginx/**/site.env") :
env = self.__env_to_dict(filename) env = self.__env_to_dict(filename)
services.append(env) services.append(env)
return services no_multisite = self.__env_to_dict("/etc/nginx/site.env")
if len(no_multisite) > 0 :
services.append(no_multisite)
return services
def check_variables(self, variables) : def check_variables(self, variables) :
for k, v in variables.items() : for k, v in variables.items() :
check = False check = False
for category in self.__settings : for category in self.__settings :
for param in self.__settings[category]["params"] : for param in self.__settings[category]["params"] :
multiple = False multiple = False
if param["type"] != "multiple" : if param["type"] != "multiple" :
real_params = [param] real_params = [param]
else : else :
real_params = param["params"] real_params = param["params"]
multiple = True multiple = True
for real_param in real_params : for real_param in real_params :
if (((not multiple and k == real_param["env"]) or if (((not multiple and k == real_param["env"]) or
(multiple and re.search("^" + real_param["env"] + "_" + "[0-9]+$", k))) and (multiple and re.search("^" + real_param["env"] + "_" + "[0-9]+$", k))) and
real_param["context"] == "multisite" and real_param["context"] == "multisite" and
re.search(real_param["regex"], v)) : re.search(real_param["regex"], v)) :
check = True check = True
if not check : if not check :
raise Exception("Variable " + k + " is not valid.") raise Exception("Variable " + k + " is not valid.")
def new_service(self, variables) : def new_service(self, variables) :
global_env = self.__env_to_dict("/etc/nginx/global.env") global_env = self.__env_to_dict("/etc/nginx/global.env")
services = self.get_services() services = self.get_services()
for service in services : for service in services :
if service["SERVER_NAME"] == variables["SERVER_NAME"] or service["SERVER_NAME"] in variables["SERVER_NAME"].split(" ") : if service["SERVER_NAME"] == variables["SERVER_NAME"] or service["SERVER_NAME"] in variables["SERVER_NAME"].split(" ") :
raise Exception("Service " + service["SERVER_NAME"] + " already exists.") raise Exception("Service " + service["SERVER_NAME"] + " already exists.")
services.append(variables) services.append(variables)
self.__gen_conf(global_env, services) self.__gen_conf(global_env, services)
return "Configuration for " + variables["SERVER_NAME"] + " has been generated." return "Configuration for " + variables["SERVER_NAME"] + " has been generated."
def edit_service(self, old_server_name, variables) : def edit_service(self, old_server_name, variables) :
self.delete_service(old_server_name) self.delete_service(old_server_name)
self.new_service(variables) self.new_service(variables)
return "Configuration for " + old_server_name + " has been edited." return "Configuration for " + old_server_name + " has been edited."
def delete_service(self, server_name) : def delete_service(self, server_name) :
global_env = self.__env_to_dict("/etc/nginx/global.env") global_env = self.__env_to_dict("/etc/nginx/global.env")
services = self.get_services() services = self.get_services()
new_services = [] new_services = []
found = False found = False
for service in services : for service in services :
if service["SERVER_NAME"].split(" ")[0] == server_name : if service["SERVER_NAME"].split(" ")[0] == server_name :
found = True found = True
else : else :
new_services.append(service) new_services.append(service)
if not found : if not found :
raise Exception("Can't delete missing " + server_name + " configuration.") raise Exception("Can't delete missing " + server_name + " configuration.")
new_servers = global_env["SERVER_NAME"].split(" ") new_servers = global_env["SERVER_NAME"].split(" ")
if server_name in new_servers : if server_name in new_servers :
new_servers.remove(server_name) new_servers.remove(server_name)
global_env["SERVER_NAME"] = " ".join(new_servers) global_env["SERVER_NAME"] = " ".join(new_servers)
self.__gen_conf(global_env, new_services) self.__gen_conf(global_env, new_services)
return "Configuration for " + server_name + " has been deleted." return "Configuration for " + server_name + " has been deleted."

View File

@ -17,8 +17,10 @@ class Docker :
return self.__client.containers.get(id) return self.__client.containers.get(id)
def reload_instance(self, id) : def reload_instance(self, id) :
self.get_instance(id).kill(signal="SIGHUP") if self.get_instance(id).status == "running" :
return "Instance " + id + " has been reloaded." self.get_instance(id).kill(signal="SIGHUP")
return "Instance " + id + " has been reloaded."
return "Instance " + id + " is not running, skipping reload."
def start_instance(self, id) : def start_instance(self, id) :
self.get_instance(id).start() self.get_instance(id).start()

View File

@ -25,7 +25,7 @@
{% if param["type"] != "multiple" and param["context"] == "multisite" %} {% if param["type"] != "multiple" and param["context"] == "multisite" %}
<div class="row mb-3" id="form-new-{{ param["id"] }}"> <div class="row mb-3" id="form-new-{{ param["id"] }}">
{% set default = {"value": param["default"]} %} {% set default = {"value": param["default"]} %}
{% if param["env"] in config["CONFIG"].get_config() %} {% if param["env"] in config["CONFIG"].get_config() and param["env"] != "SERVER_NAME" %}
{% set x = default.update({"value": config["CONFIG"].get_config()[param["env"]]}) %} {% set x = default.update({"value": config["CONFIG"].get_config()[param["env"]]}) %}
{% endif %} {% endif %}
{{ form_service_gen("form-new-" + param["id"], param["label"], param["type"], default["value"], param["env"])|safe }} {{ form_service_gen("form-new-" + param["id"], param["label"], param["type"], default["value"], param["env"])|safe }}
@ -57,4 +57,4 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -58,12 +58,13 @@
</div> </div>
</div> </div>
{% include "services-new.html" %}
{% include "services-edit.html" %} {% include "services-edit.html" %}
{% include "services-delete.html" %} {% include "services-delete.html" %}
{% endfor %} {% endfor %}
{% include "services-new.html" %}
</div> </div>
{% endblock %} {% endblock %}