Make it so the UI and the scheduler no longer run as root in Linux

This commit is contained in:
Théophile Diot 2023-04-26 12:05:30 +02:00
parent a7849a6e7a
commit ab43bf84a1
No known key found for this signature in database
GPG Key ID: E752C80DB72BB014
9 changed files with 42 additions and 40 deletions

View File

@ -186,7 +186,11 @@ if __name__ == "__main__":
retries += 1
sleep(5)
proc = run(["nginx", "-s", "reload"], stdin=DEVNULL, stderr=STDOUT)
proc = run(
["sudo", "/usr/sbin/nginx", "-s", "reload"],
stdin=DEVNULL,
stderr=STDOUT,
)
if proc.returncode != 0:
status = 1
logger.error("Error while reloading nginx")

View File

@ -1,4 +1,3 @@
from datetime import datetime
from logging import (
CRITICAL,
DEBUG,
@ -31,10 +30,6 @@ class BWLogger(Logger):
stack_info=False,
stacklevel=1,
):
if self.name == "UI":
with open("/var/log/nginx/ui.log", "a") as f:
f.write(f"[{datetime.now().replace(microsecond=0)}] {msg}\n")
return super(BWLogger, self)._log(
level, msg, args, exc_info, extra, stack_info, stacklevel
)

View File

@ -5,7 +5,7 @@ After=bunkerweb.service
[Service]
Restart=no
User=root
User=nginx
PIDFile=/var/tmp/bunkerweb/ui.pid
ExecStart=/usr/share/bunkerweb/scripts/bunkerweb-ui.sh start
ExecStop=/usr/share/bunkerweb/scripts/bunkerweb-ui.sh stop

View File

@ -1,13 +1,13 @@
#!/bin/bash
# Set the PYTHONPATH
export PYTHONPATH=/usr/share/bunkerweb/deps/python
export PYTHONPATH=/usr/share/bunkerweb/deps/python:/usr/share/bunkerweb/ui
# Create the ui.env file if it doesn't exist
if [ ! -f /etc/bunkerweb/ui.env ]; then
echo "ADMIN_USERNAME=admin" > /etc/bunkerweb/ui.env
echo "ADMIN_PASSWORD=changeme" >> /etc/bunkerweb/ui.env
echo "ABSOLUTE_URI=http://mydomain.ext/mypath/" >> /etc/bunkerweb/ui.env
echo "ABSOLUTE_URI=http://bwadm.example.com/changeme/" >> /etc/bunkerweb/ui.env
fi
# Function to start the UI
@ -18,7 +18,7 @@ start() {
fi
source /etc/bunkerweb/ui.env
export $(cat /etc/bunkerweb/ui.env)
python3 -m gunicorn --graceful-timeout=0 --bind=127.0.0.1:7000 --chdir /usr/share/bunkerweb/ui/ --workers=1 --threads=4 main:app &
python3 -m gunicorn main:app --worker-class gevent --bind 127.0.0.1:7000 --graceful-timeout 0 --access-logfile - --error-logfile - &
echo $! > /var/tmp/bunkerweb/ui.pid
}

View File

@ -80,9 +80,12 @@ function start() {
log "SYSTEMCTL" "" "Starting BunkerWeb service ..."
echo "nginx ALL=(ALL) NOPASSWD: /usr/sbin/nginx" > /etc/sudoers.d/bunkerweb
chown -R nginx:nginx /etc/nginx
# Create dummy variables.env
if [ ! -f /etc/bunkerweb/variables.env ]; then
echo -ne "# remove IS_LOADING=yes when your config is ready\nIS_LOADING=yes\nHTTP_PORT=80\nHTTPS_PORT=443\nAPI_LISTEN_IP=127.0.0.1\nSERVER_NAME=\n" > /etc/bunkerweb/variables.env
sudo -E -u nginx -g nginx /bin/bash -c "echo -ne '\# remove IS_LOADING=yes when your config is ready\nIS_LOADING=yes\nHTTP_PORT=80\nHTTPS_PORT=443\nAPI_LISTEN_IP=127.0.0.1\nSERVER_NAME=\n' > /etc/bunkerweb/variables.env"
log "SYSTEMCTL" "" "Created dummy variables.env file"
fi
@ -101,8 +104,8 @@ function start() {
if [ "$HTTPS_PORT" = "" ] ; then
HTTPS_PORT="8443"
fi
echo -ne "IS_LOADING=yes\nHTTP_PORT=${HTTP_PORT}\nHTTPS_PORT=${HTTPS_PORT}\nAPI_LISTEN_IP=127.0.0.1\nSERVER_NAME=\n" > /var/tmp/bunkerweb/tmp.env
/usr/share/bunkerweb/gen/main.py --variables /var/tmp/bunkerweb/tmp.env --no-linux-reload
sudo -E -u nginx -g nginx /bin/bash -c "echo -ne 'IS_LOADING=yes\nHTTP_PORT=${HTTP_PORT}\nHTTPS_PORT=${HTTPS_PORT}\nAPI_LISTEN_IP=127.0.0.1\nSERVER_NAME=\n' > /var/tmp/bunkerweb/tmp.env"
sudo -E -u nginx -g nginx /bin/bash -c "/usr/share/bunkerweb/gen/main.py --variables /var/tmp/bunkerweb/tmp.env --no-linux-reload"
if [ $? -ne 0 ] ; then
log "SYSTEMCTL" "❌" "Error while generating config from /var/tmp/bunkerweb/tmp.env"
exit 1
@ -134,9 +137,9 @@ function start() {
# Update database
log "SYSTEMCTL" "" "Updating database ..."
if [ ! -f /var/lib/bunkerweb/db.sqlite3 ]; then
/usr/share/bunkerweb/gen/save_config.py --variables /etc/bunkerweb/variables.env --init
else
/usr/share/bunkerweb/gen/save_config.py --variables /etc/bunkerweb/variables.env
sudo -E -u nginx -g nginx /bin/bash -c "/usr/share/bunkerweb/gen/save_config.py --variables /etc/bunkerweb/variables.env --init"
else
sudo -E -u nginx -g nginx /bin/bash -c "/usr/share/bunkerweb/gen/save_config.py --variables /etc/bunkerweb/variables.env"
fi
if [ $? -ne 0 ] ; then
log "SYSTEMCTL" "❌" "save_config failed"
@ -146,7 +149,7 @@ function start() {
# Execute scheduler
log "SYSTEMCTL" " " "Executing scheduler ..."
/usr/share/bunkerweb/scheduler/main.py --variables /etc/bunkerweb/variables.env
sudo -E -u nginx -g nginx /bin/bash -c "/usr/share/bunkerweb/scheduler/main.py --variables /etc/bunkerweb/variables.env"
if [ "$?" -ne 0 ] ; then
log "SYSTEMCTL" "❌" "Scheduler failed"
exit 1

View File

@ -79,7 +79,10 @@ class JobScheduler(ApiCaller):
if self.__integration not in ("Autoconf", "Swarm", "Kubernetes", "Docker"):
self.__logger.info("Reloading nginx ...")
proc = run(
["nginx", "-s", "reload"], stdin=DEVNULL, stderr=PIPE, env=self.__env
["sudo", "/usr/sbin/nginx", "-s", "reload"],
stdin=DEVNULL,
stderr=PIPE,
env=self.__env,
)
reload = proc.returncode == 0
if reload:

View File

@ -315,9 +315,6 @@ if __name__ == "__main__":
"Looks like BunkerWeb configuration is already generated, will not generate it again ..."
)
if Path("/var/lib/bunkerweb/db.sqlite3").exists():
chmod("/var/lib/bunkerweb/db.sqlite3", 0o760)
first_run = True
while True:
# Instantiate scheduler
@ -386,7 +383,7 @@ if __name__ == "__main__":
# Stop temp nginx
logger.info("Stopping temp nginx ...")
proc = subprocess_run(
["/usr/sbin/nginx", "-s", "stop"],
["sudo", "/usr/sbin/nginx", "-s", "stop"],
stdin=DEVNULL,
stderr=STDOUT,
env=deepcopy(env),
@ -408,7 +405,7 @@ if __name__ == "__main__":
# Start nginx
logger.info("Starting nginx ...")
proc = subprocess_run(
["/usr/sbin/nginx"],
["sudo", "/usr/sbin/nginx"],
stdin=DEVNULL,
stderr=STDOUT,
env=deepcopy(env),
@ -475,7 +472,7 @@ if __name__ == "__main__":
# Reloading the nginx server.
proc = subprocess_run(
# Reload nginx
["/usr/sbin/nginx", "-s", "reload"],
["sudo", "/usr/sbin/nginx", "-s", "reload"],
stdin=DEVNULL,
stderr=STDOUT,
env=deepcopy(env),

View File

@ -55,7 +55,7 @@ from kubernetes.client.exceptions import ApiException as kube_ApiException
from os import _exit, getenv, getpid, listdir
from re import match as re_match
from requests import get
from shutil import move, rmtree, copytree
from shutil import move, rmtree
from signal import SIGINT, signal, SIGTERM
from subprocess import PIPE, Popen, call
from tarfile import CompressionError, HeaderError, ReadError, TarError, open as tar_open
@ -80,10 +80,6 @@ from utils import (
from logger import setup_logger
from Database import Database
if not Path("/var/log/nginx/ui.log").exists():
Path("/var/log/nginx").mkdir(parents=True, exist_ok=True)
Path("/var/log/nginx/ui.log").touch()
logger = setup_logger("UI", getenv("LOG_LEVEL", "INFO"))
@ -113,8 +109,8 @@ def handle_stop(signum, frame):
signal(SIGINT, handle_stop)
signal(SIGTERM, handle_stop)
Path("/var/tmp/bunkerweb/ui.pid").write_text(str(getpid()))
if not Path("/var/tmp/bunkerweb/ui.pid").is_file():
Path("/var/tmp/bunkerweb/ui.pid").write_text(str(getpid()))
# Flask app
app = Flask(

View File

@ -1,5 +1,5 @@
from pathlib import Path
from subprocess import run
from subprocess import DEVNULL, STDOUT, run
from sys import path as sys_path
from typing import Any, Optional, Union
@ -56,8 +56,9 @@ class Instance:
if self._type == "local":
return (
run(
["sudo", "systemctl", "reload", "bunkerweb"],
capture_output=True,
["sudo", "/usr/sbin/nginx", "-s", "reload"],
stdin=DEVNULL,
stderr=STDOUT,
).returncode
== 0
)
@ -68,8 +69,9 @@ class Instance:
if self._type == "local":
return (
run(
["sudo", "systemctl", "start", "bunkerweb"],
capture_output=True,
["sudo", "/usr/sbin/nginx"],
stdin=DEVNULL,
stderr=STDOUT,
).returncode
== 0
)
@ -80,8 +82,9 @@ class Instance:
if self._type == "local":
return (
run(
["sudo", "systemctl", "stop", "bunkerweb"],
capture_output=True,
["sudo", "/usr/sbin/nginx", "-s", "stop"],
stdin=DEVNULL,
stderr=STDOUT,
).returncode
== 0
)
@ -92,8 +95,9 @@ class Instance:
if self._type == "local":
return (
run(
["sudo", "systemctl", "restart", "bunkerweb"],
capture_output=True,
["sudo", "/usr/sbin/nginx", "-s", "restart"],
stdin=DEVNULL,
stderr=STDOUT,
).returncode
== 0
)