Edit the way the UI updates the config

This commit is contained in:
TheophileDiot 2022-11-20 11:02:52 +01:00
parent b7f60dbdc7
commit 5a95e67030
5 changed files with 80 additions and 43 deletions

View File

@ -9,4 +9,5 @@ CHANGELOG.md
CONTRIBUTING.md
LICENSE.md
README.md
SECURITY.md
SECURITY.md
ui

View File

@ -330,18 +330,17 @@ class Database:
global_values = []
db_services = (
session.query(Services)
.with_entities(Services.id)
.filter_by(method=method)
.with_entities(Services.id, Services.method)
.all()
)
db_ids = [service.id for service in db_services]
services = config.get("SERVER_NAME", "").split(" ")
if db_services:
db_services = [service.id for service in db_services]
missing_ids = [
service
service.id
for service in db_services
if service not in services
if (service.method == method) and service.id not in services
]
if missing_ids:
@ -373,9 +372,9 @@ class Database:
except StopIteration:
continue
if server_name not in db_services:
if server_name not in db_ids:
to_put.append(Services(id=server_name, method=method))
db_services.append(server_name)
db_ids.append(server_name)
key = key.replace(f"{server_name}_", "")
setting = (
@ -471,7 +470,16 @@ class Database:
}
)
else:
if "SERVER_NAME" in config and config["SERVER_NAME"] != "":
if (
"SERVER_NAME" in config
and config["SERVER_NAME"] != ""
and not (
session.query(Services)
.with_entities(Services.id)
.filter_by(id=config["SERVER_NAME"].split(" ")[0])
.first()
)
):
to_put.append(
Services(
id=config["SERVER_NAME"].split(" ")[0], method=method

View File

@ -4,8 +4,8 @@ from argparse import ArgumentParser
from glob import glob
from itertools import chain
from json import loads
from os import R_OK, W_OK, X_OK, access, environ, getenv, path
from os.path import exists
from os import R_OK, X_OK, access, environ, getenv, listdir, path, walk
from os.path import exists, join
from re import compile as re_compile
from sys import exit as sys_exit, path as sys_path
from traceback import format_exc
@ -108,6 +108,12 @@ if __name__ == "__main__":
action="store_true",
help="Only initialize the database",
)
parser.add_argument(
"--method",
default="scheduler",
type=str,
help="The method that is used to save the config",
)
args = parser.parse_args()
logger.info("Save config started ...")
@ -127,9 +133,12 @@ if __name__ == "__main__":
with open("/usr/share/bunkerweb/INTEGRATION", "r") as f:
integration = f.read().strip()
logger.info(f"Detected {integration} integration")
if args.init:
logger.info(f"Detected {integration} integration")
config_files = None
db = None
apis = []
# Check existences and permissions
logger.info("Checking arguments ...")
@ -194,10 +203,31 @@ if __name__ == "__main__":
for k, v in environ.items()
if custom_confs_rx.match(k)
]
root_dirs = listdir("/etc/bunkerweb/configs")
for (root, dirs, files) in walk("/etc/bunkerweb/configs", topdown=True):
if (
root != "configs"
and (dirs and not root.split("/")[-1] in root_dirs)
or files
):
path_exploded = root.split("/")
for file in files:
with open(join(root, file), "r") as f:
custom_confs.append(
{
"value": f.read(),
"exploded": (
f"{path_exploded.pop()}"
if path_exploded[-1] not in root_dirs
else "",
path_exploded[-1],
file.replace(".conf", ""),
),
}
)
elif integration == "Kubernetes":
corev1 = kube_client.CoreV1Api()
tmp_config = {}
apis = []
for pod in corev1.list_pod_for_all_namespaces(watch=False).items:
if (
@ -280,7 +310,6 @@ if __name__ == "__main__":
tmp_config = {}
custom_confs = []
apis = []
for instance in (
docker_client.containers.list(filters={"label": "bunkerweb.INSTANCE"})
@ -354,10 +383,10 @@ if __name__ == "__main__":
if args.init:
sys_exit(0)
err = db.save_config(config_files, "scheduler")
err = db.save_config(config_files, args.method)
if not err:
err1 = db.save_custom_configs(custom_confs, "scheduler")
err1 = db.save_custom_configs(custom_confs, args.method)
else:
err = None
err1 = None

View File

@ -20,7 +20,6 @@ RUN apk add --no-cache --virtual .build-deps g++ gcc musl-dev jpeg-dev zlib-dev
# Copy files
# can't exclude specific files/dir from . so we are copying everything by hand
COPY src/common/api /usr/share/bunkerweb/api
COPY src/common/confs /usr/share/bunkerweb/confs
COPY src/common/db /usr/share/bunkerweb/db
COPY src/common/core /usr/share/bunkerweb/core
COPY src/common/gen /usr/share/bunkerweb/gen
@ -46,7 +45,7 @@ RUN apk add --no-cache bash file && \
for dir in $(echo "/usr/share/bunkerweb /etc/bunkerweb") ; do find ${dir} -type f -exec chmod 0740 {} \; ; done && \
for dir in $(echo "/usr/share/bunkerweb /etc/bunkerweb") ; do find ${dir} -type d -exec chmod 0750 {} \; ; done && \
chmod 770 /var/cache/bunkerweb /var/lib/bunkerweb /var/tmp/bunkerweb && \
chmod 750 /usr/share/bunkerweb/gen/main.py /usr/share/bunkerweb/deps/python/bin/* && \
chmod 750 /usr/share/bunkerweb/gen/*.py /usr/share/bunkerweb/deps/python/bin/* && \
chmod 660 /usr/share/bunkerweb/INTEGRATION
# Fix CVEs

View File

@ -1,5 +1,5 @@
from copy import deepcopy
from os import listdir
from os import listdir, remove
from time import sleep
from flask import flash
from os.path import exists, isfile
@ -147,13 +147,8 @@ class Config:
self.__dict_to_env(env_file, conf)
proc = run(
[
"/usr/share/bunkerweb/gen/main.py",
"--settings",
"/usr/share/bunkerweb/settings.json",
"--templates",
"/usr/share/bunkerweb/confs",
"--output",
"/etc/nginx",
"python3",
"/usr/share/bunkerweb/gen/save_config.py",
"--variables",
env_file,
"--method",
@ -166,11 +161,7 @@ class Config:
if proc.returncode != 0:
raise Exception(f"Error from generator (return code = {proc.returncode})")
err = self.__db.save_config(conf, "ui")
if err:
self.__logger.error(
f"Can't save config in database: {err}",
)
remove(env_file)
def get_plugins_settings(self) -> dict:
return self.__plugins_settings
@ -181,7 +172,7 @@ class Config:
def get_settings(self) -> dict:
return self.__settings
def get_config(self) -> dict:
def get_config(self, methods: bool = True) -> dict:
"""Get the nginx variables env file and returns it as a dict
Returns
@ -191,13 +182,13 @@ class Config:
"""
if exists("/usr/sbin/nginx"):
return {
k: {"value": v, "method": "ui"}
k: ({"value": v, "method": "ui"} if methods is True else v)
for k, v in self.__env_to_dict("/etc/nginx/variables.env").items()
}
return self.__db.get_config(methods=True)
return self.__db.get_config(methods=methods)
def get_services(self) -> list[dict]:
def get_services(self, methods: bool = True) -> list[dict]:
"""Get nginx's services
Returns
@ -208,15 +199,20 @@ class Config:
if exists("/usr/sbin/nginx"):
services = []
for filename in iglob("/etc/nginx/**/variables.env"):
service = filename.split("/")[3]
env = {
k: {"value": v, "method": "ui"}
k.replace(f"{service}_", ""): (
{"value": v, "method": "ui"} if methods is True else v
)
for k, v in self.__env_to_dict(filename).items()
if k.startswith(f"{service}_")
or k in self.__plugins_settings.keys()
}
services.append(env)
return services
return self.__db.get_services_settings(methods=True)
return self.__db.get_services_settings(methods=methods)
def check_variables(self, variables: dict, _global: bool = False) -> int:
"""Testify that the variables passed are valid
@ -265,7 +261,9 @@ class Config:
return error
def reload_config(self) -> None:
self.__gen_conf(self.get_config(), self.get_services())
self.__gen_conf(
self.get_config(methods=False), self.get_services(methods=False)
)
def new_service(self, variables: dict) -> Tuple[str, int]:
"""Creates a new service from the given variables
@ -285,7 +283,7 @@ class Config:
Exception
raise this if the service already exists
"""
services = self.get_services()
services = self.get_services(methods=False)
for service in services:
if service["SERVER_NAME"] == variables["SERVER_NAME"] or service[
"SERVER_NAME"
@ -293,7 +291,7 @@ class Config:
return f"Service {service['SERVER_NAME']} already exists.", 1
services.append(variables)
self.__gen_conf(self.get_config(), services)
self.__gen_conf(self.get_config(methods=False), services)
return f"Configuration for {variables['SERVER_NAME']} has been generated.", 0
def edit_service(self, old_server_name: str, variables: dict) -> Tuple[str, int]:
@ -332,7 +330,9 @@ class Config:
str
the confirmation message
"""
self.__gen_conf(self.get_config() | variables, self.get_services())
self.__gen_conf(
self.get_config(methods=False) | variables, self.get_services(methods=False)
)
return f"The global configuration has been edited."
def delete_service(self, service_name: str) -> Tuple[str, int]:
@ -353,8 +353,8 @@ class Config:
Exception
raises this if the service_name given isn't found
"""
full_env = self.get_config()
services = self.get_services()
full_env = self.get_config(methods=False)
services = self.get_services(methods=False)
new_services = []
found = False