From 36b8760d4dedc1ba6cf9cbb4757842e4fa5c89c7 Mon Sep 17 00:00:00 2001
From: bunkerity
Date: Thu, 22 Jul 2021 12:12:55 +0200
Subject: [PATCH 1/3] resolve bugs on the stable version
---
CHANGELOG.md | 11 ++
README.md | 4 +-
autoconf/AutoConf.py | 2 +-
gen/main.py | 14 +--
settings.json | 18 +--
ui/Config.py | 204 +++++++++++++++++----------------
ui/Docker.py | 6 +-
ui/templates/services-new.html | 4 +-
ui/templates/services.html | 3 +-
9 files changed, 142 insertions(+), 124 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc1782b..0b07210 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
# 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
- Add custom robots.txt and sitemap to RTD
diff --git a/README.md b/README.md
index d08f2e5..e66fa38 100644
--- a/README.md
+++ b/README.md
@@ -432,8 +432,8 @@ bunkerized-nginx comes with a set of predefined security settings that you can (
# 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
-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.
diff --git a/autoconf/AutoConf.py b/autoconf/AutoConf.py
index cea1b83..5651e6b 100644
--- a/autoconf/AutoConf.py
+++ b/autoconf/AutoConf.py
@@ -173,7 +173,7 @@ class AutoConf :
self.__servers[id].reload()
utils.log("[*] Deactivating config for " + vars["SERVER_NAME"])
self.__gen_env()
- if self.__config.reload() :
+ if self.__config.reload(self.__instances) :
utils.log("[*] Deactivated config for " + vars["SERVER_NAME"])
else :
utils.log("[!] Can't deactivate config for " + vars["SERVER_NAME"])
diff --git a/gen/main.py b/gen/main.py
index 6729740..0f0d728 100755
--- a/gen/main.py
+++ b/gen/main.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
-import argparse, os, sys, shutil
+import argparse, os, sys, shutil, glob
import utils
from Configurator import Configurator
@@ -51,14 +51,10 @@ if __name__ == "__main__" :
config = configurator.get_config()
#print(config)
- # Remove old config
- # TODO : remove unnecessary files after rendering
-# for filename in os.listdir(args.output):
-# file_path = os.path.join(args.output, filename)
-# 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)
+ # TODO : find a proper way to remove old sites
+ env_list = glob.glob(args.output + "/**/*.env", recursive=True)
+ for env in env_list :
+ os.remove(env)
# Generate the files from templates and config
templator = Templator(config, args.templates, args.output, args.target)
diff --git a/settings.json b/settings.json
index 2c64861..114177e 100644
--- a/settings.json
+++ b/settings.json
@@ -525,7 +525,7 @@
"env": "EMAIL_LETS_ENCRYPT",
"id": "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"
},
{
@@ -615,7 +615,7 @@
"env": "SELF_SIGNED_SSL_COUNTRY",
"id": "self-signed-ssl-country",
"label": "Country of the self-signed certificate",
- "regex": "^[:print:]+$",
+ "regex": "^[A-Z]{2}$",
"type": "text"
},
{
@@ -624,7 +624,7 @@
"env": "SELF_SIGNED_SSL_STATE",
"id": "self-signed-ssl-state",
"label": "State of the self-signed certificate",
- "regex": "^[:print:]+$",
+ "regex": "^[A-Za-z\\- ]+$",
"type": "text"
},
{
@@ -633,7 +633,7 @@
"env": "SELF_SIGNED_SSL_CITY",
"id": "self-signed-ssl-city",
"label": "City of the self-signed certificate",
- "regex": "^[:print:]+$",
+ "regex": "^[A-Za-z\\- ]+$",
"type": "text"
},
{
@@ -642,7 +642,7 @@
"env": "SELF_SIGNED_SSL_OU",
"id": "self-signed-ssl-ou",
"label": "Organizational Unit of the self-signed certificate",
- "regex": "^[:print:]+$",
+ "regex": "^[A-Za-z\\- ]+$",
"type": "text"
},
{
@@ -651,7 +651,7 @@
"env": "SELF_SIGNED_SSL_ORG",
"id": "self-signed-ssl-org",
"label": "Organization name of the self-signed certificate",
- "regex": "^[:print:]+$",
+ "regex": "^[A-Za-z\\- ]+$",
"type": "text"
},
{
@@ -660,7 +660,7 @@
"env": "SELF_SIGNED_SSL_CN",
"id": "self-signed-ssl-cn",
"label": "Common Name of the self-signed certificate",
- "regex": "^[:print:]+$",
+ "regex": "^[A-Za-z\\-\\.0-9]+$",
"type": "text"
}
]
@@ -947,7 +947,7 @@
"env": "REMOTE_PHP",
"id": "remote-php",
"label": "Remote php",
- "regex": "^([a-z\\-0-9\\_]+\\.?)*$",
+ "regex": "^[a-z\\-0-9_\\.]*$",
"type": "text"
},
{
@@ -956,7 +956,7 @@
"env": "REMOTE_PHP_PATH",
"id": "remote-php-path",
"label": "Remote php path",
- "regex": "^/([A-Za-z0-9\\-]/?)*$",
+ "regex": "^\\/[a-zA-Z\\-0-9_\\.\\/]*$",
"type": "text"
}
]
diff --git a/ui/Config.py b/ui/Config.py
index 7d8ad88..9ef0433 100644
--- a/ui/Config.py
+++ b/ui/Config.py
@@ -1,113 +1,121 @@
-import json, uuid, glob, copy, re, subprocess
+import json, uuid, glob, copy, re, subprocess, os
class Config :
- def __init__(self) :
- with open("/opt/settings.json", "r") as f :
- self.__settings = json.loads(f.read())
+ def __init__(self) :
+ with open("/opt/settings.json", "r") as f :
+ self.__settings = json.loads(f.read())
- def __env_to_dict(self, filename) :
- with open(filename, "r") as f :
- env = f.read()
- data = {}
- for line in env.split("\n") :
- var = line.split("=")[0]
- val = line.replace(var + "=", "", 1)
- data[var] = val
- return data
+ def __env_to_dict(self, filename) :
+ if not os.path.isfile(filename) :
+ return {}
+ with open(filename, "r") as f :
+ env = f.read()
+ data = {}
+ for line in env.split("\n") :
+ var = line.split("=")[0]
+ val = line.replace(var + "=", "", 1)
+ data[var] = val
+ return data
- def __dict_to_env(self, filename, variables) :
- env = ""
- for k, v in variables.items() :
- env += k + "=" + v + "\n"
- with open(filename, "w") as f :
- f.write(env)
+ def __dict_to_env(self, filename, variables) :
+ env = ""
+ for k, v in variables.items() :
+ env += k + "=" + v + "\n"
+ with open(filename, "w") as f :
+ f.write(env)
- def __gen_conf(self, global_conf, services_conf) :
- conf = copy.deepcopy(global_conf)
- servers = conf["SERVER_NAME"].split(" ")
- if conf["SERVER_NAME"] == "" :
- servers = []
- for service in services_conf :
- first_server = service["SERVER_NAME"].split(" ")[0]
- if not first_server in servers :
- servers.append(first_server)
- for k, v in service.items() :
- conf[first_server + "_" + k] = v
- conf["SERVER_NAME"] = " ".join(servers)
- env_file = "/tmp/" + str(uuid.uuid4()) + ".env"
- self.__dict_to_env(env_file, conf)
- 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)
- stderr = proc.stderr.decode("ascii")
- #stdout = proc.stdout.decode("ascii")
- if stderr != "" or proc.returncode != 0 :
- raise Exception("Error from generator (return code = " + str(proc.returncode) + ") : " + stderr)
+ def __gen_conf(self, global_conf, services_conf) :
+ conf = copy.deepcopy(global_conf)
+ if not "SERVER_NAME" in conf :
+ conf["SERVER_NAME"] = ""
+ servers = conf["SERVER_NAME"].split(" ")
+ if conf["SERVER_NAME"] == "" :
+ servers = []
+ for service in services_conf :
+ first_server = service["SERVER_NAME"].split(" ")[0]
+ if not first_server in servers :
+ servers.append(first_server)
+ for k, v in service.items() :
+ conf[first_server + "_" + k] = v
+ conf["SERVER_NAME"] = " ".join(servers)
+ env_file = "/tmp/" + str(uuid.uuid4()) + ".env"
+ self.__dict_to_env(env_file, conf)
+ proc = subprocess.run(["/opt/gen/main.py", "--settings", "/opt/settings.json", "--templates", "/opt/confs", "--output", "/etc/nginx", "--variables", env_file], capture_output=True)
+ stderr = proc.stderr.decode("ascii")
+ 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) :
- return self.__settings
+ def get_settings(self) :
+ return self.__settings
- def get_config(self) :
- return self.__env_to_dict("/etc/nginx/global.env")
+ def get_config(self) :
+ return self.__env_to_dict("/etc/nginx/global.env")
- def get_services(self) :
- services = []
- for filename in glob.iglob("/etc/nginx/**/site.env") :
- env = self.__env_to_dict(filename)
- services.append(env)
- return services
+ def get_services(self) :
+ services = []
+ for filename in glob.iglob("/etc/nginx/**/site.env") :
+ env = self.__env_to_dict(filename)
+ services.append(env)
+ 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) :
- for k, v in variables.items() :
- check = False
- for category in self.__settings :
- for param in self.__settings[category]["params"] :
- multiple = False
- if param["type"] != "multiple" :
- real_params = [param]
- else :
- real_params = param["params"]
- multiple = True
- for real_param in real_params :
- if (((not multiple and k == real_param["env"]) or
- (multiple and re.search("^" + real_param["env"] + "_" + "[0-9]+$", k))) and
- real_param["context"] == "multisite" and
- re.search(real_param["regex"], v)) :
- check = True
- if not check :
- raise Exception("Variable " + k + " is not valid.")
+ def check_variables(self, variables) :
+ for k, v in variables.items() :
+ check = False
+ for category in self.__settings :
+ for param in self.__settings[category]["params"] :
+ multiple = False
+ if param["type"] != "multiple" :
+ real_params = [param]
+ else :
+ real_params = param["params"]
+ multiple = True
+ for real_param in real_params :
+ if (((not multiple and k == real_param["env"]) or
+ (multiple and re.search("^" + real_param["env"] + "_" + "[0-9]+$", k))) and
+ real_param["context"] == "multisite" and
+ re.search(real_param["regex"], v)) :
+ check = True
+ if not check :
+ raise Exception("Variable " + k + " is not valid.")
- def new_service(self, variables) :
- global_env = self.__env_to_dict("/etc/nginx/global.env")
- services = self.get_services()
- for service in services :
- if service["SERVER_NAME"] == variables["SERVER_NAME"] or service["SERVER_NAME"] in variables["SERVER_NAME"].split(" ") :
- raise Exception("Service " + service["SERVER_NAME"] + " already exists.")
- services.append(variables)
- self.__gen_conf(global_env, services)
- return "Configuration for " + variables["SERVER_NAME"] + " has been generated."
+ def new_service(self, variables) :
+ global_env = self.__env_to_dict("/etc/nginx/global.env")
+ services = self.get_services()
+ for service in services :
+ if service["SERVER_NAME"] == variables["SERVER_NAME"] or service["SERVER_NAME"] in variables["SERVER_NAME"].split(" ") :
+ raise Exception("Service " + service["SERVER_NAME"] + " already exists.")
+ services.append(variables)
+ self.__gen_conf(global_env, services)
+ return "Configuration for " + variables["SERVER_NAME"] + " has been generated."
- def edit_service(self, old_server_name, variables) :
- self.delete_service(old_server_name)
- self.new_service(variables)
- return "Configuration for " + old_server_name + " has been edited."
+ def edit_service(self, old_server_name, variables) :
+ self.delete_service(old_server_name)
+ self.new_service(variables)
+ return "Configuration for " + old_server_name + " has been edited."
- def delete_service(self, server_name) :
- global_env = self.__env_to_dict("/etc/nginx/global.env")
- services = self.get_services()
- new_services = []
- found = False
- for service in services :
- if service["SERVER_NAME"].split(" ")[0] == server_name :
- found = True
- else :
- new_services.append(service)
- if not found :
- raise Exception("Can't delete missing " + server_name + " configuration.")
- new_servers = global_env["SERVER_NAME"].split(" ")
- if server_name in new_servers :
- new_servers.remove(server_name)
- global_env["SERVER_NAME"] = " ".join(new_servers)
- self.__gen_conf(global_env, new_services)
- return "Configuration for " + server_name + " has been deleted."
+ def delete_service(self, server_name) :
+ global_env = self.__env_to_dict("/etc/nginx/global.env")
+ services = self.get_services()
+ new_services = []
+ found = False
+ for service in services :
+ if service["SERVER_NAME"].split(" ")[0] == server_name :
+ found = True
+ else :
+ new_services.append(service)
+ if not found :
+ raise Exception("Can't delete missing " + server_name + " configuration.")
+ new_servers = global_env["SERVER_NAME"].split(" ")
+ if server_name in new_servers :
+ new_servers.remove(server_name)
+ global_env["SERVER_NAME"] = " ".join(new_servers)
+ self.__gen_conf(global_env, new_services)
+ return "Configuration for " + server_name + " has been deleted."
+
diff --git a/ui/Docker.py b/ui/Docker.py
index 2facce6..aeafb8a 100644
--- a/ui/Docker.py
+++ b/ui/Docker.py
@@ -17,8 +17,10 @@ class Docker :
return self.__client.containers.get(id)
def reload_instance(self, id) :
- self.get_instance(id).kill(signal="SIGHUP")
- return "Instance " + id + " has been reloaded."
+ if self.get_instance(id).status == "running" :
+ 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) :
self.get_instance(id).start()
diff --git a/ui/templates/services-new.html b/ui/templates/services-new.html
index c5285d7..2957809 100644
--- a/ui/templates/services-new.html
+++ b/ui/templates/services-new.html
@@ -25,7 +25,7 @@
{% if param["type"] != "multiple" and param["context"] == "multisite" %}
{% 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"]]}) %}
{% endif %}
{{ form_service_gen("form-new-" + param["id"], param["label"], param["type"], default["value"], param["env"])|safe }}
@@ -57,4 +57,4 @@
-
\ No newline at end of file
+
diff --git a/ui/templates/services.html b/ui/templates/services.html
index 7b06486..2517af4 100644
--- a/ui/templates/services.html
+++ b/ui/templates/services.html
@@ -58,12 +58,13 @@
- {% include "services-new.html" %}
{% include "services-edit.html" %}
{% include "services-delete.html" %}
{% endfor %}
+ {% include "services-new.html" %}
+
{% endblock %}
From 3178545c2fa24b179026e79e6cef6ecee65a8522 Mon Sep 17 00:00:00 2001
From: bunkerity
Date: Thu, 22 Jul 2021 14:36:07 +0200
Subject: [PATCH 2/3] v1.2.8 release
---
CHANGELOG.md | 1 -
README.md | 2 +-
VERSION | 2 +-
docs/conf.py | 2 +-
4 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b07210..c5b73f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,6 @@
- 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
diff --git a/README.md b/README.md
index e66fa38..98af66b 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-
+
diff --git a/VERSION b/VERSION
index c04c650..db6fb4a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.7
+1.2.8
diff --git a/docs/conf.py b/docs/conf.py
index 6b077bf..437a930 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -50,7 +50,7 @@ copyright = '2021, bunkerity'
author = 'bunkerity'
# The full version, including alpha/beta/rc tags
-release = 'v1.2.7'
+release = 'v1.2.8'
# -- General configuration ---------------------------------------------------
From a60fbbb5b36c589a00fb72db3a4c8e819ae12922 Mon Sep 17 00:00:00 2001
From: bunkerity
Date: Thu, 22 Jul 2021 14:50:09 +0200
Subject: [PATCH 3/3] hotfix - fix CVE-2021-33560
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 484cc6c..71abe8d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,8 +26,8 @@ RUN chmod +x /tmp/prepare.sh && \
/tmp/prepare.sh && \
rm -f /tmp/prepare.sh
-# Fix CVE-2021-22901, CVE-2021-22898 and CVE-2021-22897
-RUN apk add "curl>=7.77.0-r0"
+# Fix CVE-2021-22901, CVE-2021-22898, CVE-2021-22897 and CVE-2021-33560
+RUN apk add "curl>=7.77.0-r0" "libgcrypt>=1.8.8-r0"
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge /plugins