UI - copy from helpers, systemd service and instances page update

This commit is contained in:
bunkerity 2021-07-09 10:27:38 +02:00
parent f771ec43f1
commit 4dd1ff8479
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
13 changed files with 107 additions and 239 deletions

View File

@ -1,163 +0,0 @@
#!/bin/sh
function git_secure_checkout() {
path="$1"
commit="$2"
ret=$(pwd)
cd $path
git checkout "${commit}^{commit}"
if [ $? -ne 0 ] ; then
echo "[!] Commit hash $commit is absent from submodules $path !"
exit 3
fi
cd $ret
}
function git_secure_clone() {
repo="$1"
commit="$2"
folder=$(echo "$repo" | sed -E "s@https://github.com/.*/(.*)\.git@\1@")
git clone "$repo"
cd "$folder"
git checkout "${commit}^{commit}"
if [ $? -ne 0 ] ; then
echo "[!] Commit hash $commit is absent from repository $repo !"
exit 2
fi
cd ..
}
NTASK=$(nproc)
# install build dependencies
apk add --no-cache --virtual build autoconf libtool automake git geoip-dev yajl-dev g++ gcc curl-dev libxml2-dev pcre-dev make linux-headers libmaxminddb-dev musl-dev lua-dev gd-dev gnupg brotli-dev openssl-dev
# compile and install ModSecurity library
cd /tmp
git_secure_clone https://github.com/SpiderLabs/ModSecurity.git 753145fbd1d6751a6b14fdd700921eb3cc3a1d35
cd ModSecurity
./build.sh
git submodule init
git submodule update
git_secure_checkout bindings/python 47a6925df187f96e4593afab18dc92d5f22bd4d5
git_secure_checkout others/libinjection bf234eb2f385b969c4f803b35fda53cffdd93922
git_secure_checkout test/test-cases/secrules-language-tests d03f4c1e930440df46c1faa37d820a919704d9da
./configure --enable-static=no --disable-doxygen-doc --disable-dependency-tracking
make -j $NTASK
make install-strip
# download and install CRS rules
cd /tmp
git_secure_clone https://github.com/coreruleset/coreruleset.git 7776fe23f127fd2315bad0e400bdceb2cabb97dc
cd coreruleset
mkdir /opt/owasp
cp -r rules /opt/owasp/crs
cp crs-setup.conf.example /opt/owasp/crs.conf
# get nginx modules
cd /tmp
# ModSecurity connector for nginx
git_secure_clone https://github.com/SpiderLabs/ModSecurity-nginx.git 2497e6ac654d0b117b9534aa735b757c6b11c84f
# headers more
git_secure_clone https://github.com/openresty/headers-more-nginx-module.git d6d7ebab3c0c5b32ab421ba186783d3e5d2c6a17
# geoip
git_secure_clone https://github.com/leev/ngx_http_geoip2_module.git 1cabd8a1f68ea3998f94e9f3504431970f848fbf
# cookie
git_secure_clone https://github.com/AirisX/nginx_cookie_flag_module.git c4ff449318474fbbb4ba5f40cb67ccd54dc595d4
# brotli
git_secure_clone https://github.com/google/ngx_brotli.git 9aec15e2aa6feea2113119ba06460af70ab3ea62
# LUA requirements
git_secure_clone https://github.com/openresty/luajit2.git fe32831adcb3f5fe9259a9ce404fc54e1399bba3
cd luajit2
make -j $NTASK
make install
cd /tmp
git_secure_clone https://github.com/openresty/lua-resty-core.git b7d0a681bb41e6e3f29e8ddc438ef26fd819bb19
cd lua-resty-core
make install
cd /tmp
git_secure_clone https://github.com/openresty/lua-resty-lrucache.git b2035269ac353444ac65af3969692bcae4fc1605
cd lua-resty-lrucache
make install
cd /tmp
git_secure_clone https://github.com/openresty/lua-resty-dns.git 24c9a69808aedfaf029ae57707cdef75d83e2d19
cd lua-resty-dns
make install
cd /tmp
git_secure_clone https://github.com/bungle/lua-resty-session.git f300870ce4eee3f4903e0565c589f1faf0c1c5aa
cd lua-resty-session
cp -r lib/resty/* /usr/local/lib/lua/resty
cd /tmp
git_secure_clone https://github.com/bungle/lua-resty-random.git 17b604f7f7dd217557ca548fc1a9a0d373386480
cd lua-resty-random
make install
cd /tmp
git_secure_clone https://github.com/openresty/lua-resty-string.git 9a543f8531241745f8814e8e02475351042774ec
cd lua-resty-string
make install
cd /tmp
git_secure_clone https://github.com/openresty/lua-cjson.git 0df488874f52a881d14b5876babaa780bb6200ee
cd lua-cjson
make -j $NTASK
make install
make install-extra
cd /tmp
git_secure_clone https://github.com/ittner/lua-gd.git 2ce8e478a8591afd71e607506bc8c64b161bbd30
cd lua-gd
make -j $NTASK
make INSTALL_PATH=/usr/local/lib/lua/5.1 install
cd /tmp
git_secure_clone https://github.com/ledgetech/lua-resty-http.git 984fdc26054376384e3df238fb0f7dfde01cacf1
cd lua-resty-http
make install
cd /tmp
git_secure_clone https://github.com/Neopallium/lualogging.git cadc4e8fd652be07a65b121a3e024838db330c15
cd lualogging
cp -r src/* /usr/local/lib/lua
cd /tmp
git_secure_clone https://github.com/diegonehab/luasocket.git 5b18e475f38fcf28429b1cc4b17baee3b9793a62
cd luasocket
make -j $NTASK
make CDIR_linux=lib/lua/5.1 LDIR_linux=lib/lua install
cd /tmp
git_secure_clone https://github.com/brunoos/luasec.git c6704919bdc85f3324340bdb35c2795a02f7d625
cd luasec
make linux -j $NTASK
make LUACPATH=/usr/local/lib/lua/5.1 LUAPATH=/usr/local/lib/lua install
cd /tmp
git_secure_clone https://github.com/crowdsecurity/lua-cs-bouncer.git 3c235c813fc453dcf51a391bc9e9a36ca77958b0
cd lua-cs-bouncer
mkdir /usr/local/lib/lua/crowdsec
cp lib/*.lua /usr/local/lib/lua/crowdsec
sed -i 's/require "lrucache"/require "resty.lrucache"/' /usr/local/lib/lua/crowdsec/CrowdSec.lua
sed -i 's/require "config"/require "crowdsec.config"/' /usr/local/lib/lua/crowdsec/CrowdSec.lua
cd /tmp
git_secure_clone https://github.com/hamishforbes/lua-resty-iputils.git 3151d6485e830421266eee5c0f386c32c835dba4
cd lua-resty-iputils
make LUA_LIB_DIR=/usr/local/lib/lua install
cd /tmp
git_secure_clone https://github.com/openresty/lua-nginx-module.git 2d23bc4f0a29ed79aaaa754c11bffb1080aa44ba
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.1
# compile and install dynamic modules
cd /tmp
wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz.asc
gpg --import /tmp/nginx-keys/*.key
check=$(gpg --verify /tmp/nginx-${NGINX_VERSION}.tar.gz.asc /tmp/nginx-${NGINX_VERSION}.tar.gz 2>&1 | grep "^gpg: Good signature from ")
if [ "$check" = "" ] ; then
echo "[!] Wrong signature from nginx source !"
exit 1
fi
tar -xvzf nginx-${NGINX_VERSION}.tar.gz
cd nginx-$NGINX_VERSION
CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p')
CONFARGS=${CONFARGS/-Os -fomit-frame-pointer -g/-Os}
./configure $CONFARGS --add-dynamic-module=/tmp/ModSecurity-nginx --add-dynamic-module=/tmp/headers-more-nginx-module --add-dynamic-module=/tmp/ngx_http_geoip2_module --add-dynamic-module=/tmp/nginx_cookie_flag_module --add-dynamic-module=/tmp/lua-nginx-module --add-dynamic-module=/tmp/ngx_brotli
make -j $NTASK modules
cp ./objs/*.so /usr/lib/nginx/modules
# remove build dependencies
apk del build

View File

@ -91,7 +91,7 @@ elif [ "$OS" = "centos" ] ; then
do_and_check_cmd yum install -y $CENTOS_DEPS do_and_check_cmd yum install -y $CENTOS_DEPS
fi fi
do_and_check_cmd pip3 install --upgrade pip do_and_check_cmd pip3 install --upgrade pip
do_and_check_cmd pip3 install jinja2 certbot do_and_check_cmd pip3 install jinja2 certbot docker requests flask gunicorn
do_and_check_cmd pip3 install cryptography --upgrade do_and_check_cmd pip3 install cryptography --upgrade
# Clone the repo # Clone the repo
@ -133,6 +133,11 @@ do_and_check_cmd cp -r /tmp/bunkerized-nginx/defaults /opt/bunkerized-nginx
echo "[*] Copy settings" echo "[*] Copy settings"
do_and_check_cmd cp /tmp/bunkerized-nginx/settings.json /opt/bunkerized-nginx do_and_check_cmd cp /tmp/bunkerized-nginx/settings.json /opt/bunkerized-nginx
# Copy UI
echo "[*] Copy UI"
do_and_check_cmd cp -r /tmp/bunkerized-nginx/ui /opt/bunkerized-nginx
do_and_check_cmd cp /tmp/bunkerized-nginx/ui/bunkerized-nginx-ui.service /etc/systemd/system
# Copy bunkerized-nginx # Copy bunkerized-nginx
echo "[*] Copy bunkerized-nginx" echo "[*] Copy bunkerized-nginx"
do_and_check_cmd cp /tmp/bunkerized-nginx/helpers/bunkerized-nginx /usr/local/bin do_and_check_cmd cp /tmp/bunkerized-nginx/helpers/bunkerized-nginx /usr/local/bin
@ -216,6 +221,9 @@ do_and_check_cmd chmod u+rx /opt
do_and_check_cmd chown -R nginx:nginx /etc/nginx do_and_check_cmd chown -R nginx:nginx /etc/nginx
do_and_check_cmd find /etc/nginx -type f -exec chmod 0774 {} \; do_and_check_cmd find /etc/nginx -type f -exec chmod 0774 {} \;
do_and_check_cmd find /etc/nginx -type d -exec chmod 0775 {} \; do_and_check_cmd find /etc/nginx -type d -exec chmod 0775 {} \;
# Set permissions for /etc/systemd/system/bunkerized-nginx-ui.service
do_and_check_cmd chown root:root /etc/systemd/system/bunkerized-nginx-ui.service
do_and_check_cmd chmod 744 /etc/systemd/system/bunkerized-nginx-ui.service
# Prepare log files and folders # Prepare log files and folders
echo "[*] Prepare log files and folders" echo "[*] Prepare log files and folders"
@ -228,19 +236,17 @@ fi
if [ ! -e /var/log/nginx/error.log ] ; then if [ ! -e /var/log/nginx/error.log ] ; then
do_and_check_cmd touch /var/log/nginx/error.log do_and_check_cmd touch /var/log/nginx/error.log
fi fi
if [ ! -e /var/log/nginx/modsec_audit.log ] ; then
do_and_check_cmd touch /var/log/nginx/modsec_audit.log
fi
if [ ! -e /var/log/nginx/jobs.log ] ; then if [ ! -e /var/log/nginx/jobs.log ] ; then
do_and_check_cmd touch /var/log/nginx/jobs.log do_and_check_cmd touch /var/log/nginx/jobs.log
fi fi
do_and_check_cmd touch /var/log/nginx/modsec_audit.log if [ ! -e /var/log/nginx/ui.log ] ; then
do_and_check_cmd touch /var/log/nginx/error.log do_and_check_cmd touch /var/log/nginx/ui.log
fi
do_and_check_cmd chown -R root:nginx /var/log/nginx do_and_check_cmd chown -R root:nginx /var/log/nginx
do_and_check_cmd chown root:nginx /var/log/nginx/access.log do_and_check_cmd chmod -R 770 /var/log/nginx/
do_and_check_cmd chown root:nginx /var/log/nginx/error.log
do_and_check_cmd chown root:nginx /var/log/nginx/jobs.log
do_and_check_cmd chmod 770 /var/log/nginx/access.log
do_and_check_cmd chmod 770 /var/log/nginx/error.log
do_and_check_cmd chmod 770 /var/log/nginx/jobs.log
do_and_check_cmd chmod -R 770 /var/log/nginx
# Prepare Let's Encrypt files and folders # Prepare Let's Encrypt files and folders
echo "[*] Prepare Let's Encrypt files and folders" echo "[*] Prepare Let's Encrypt files and folders"

View File

@ -10,6 +10,10 @@ api_list["^/reload$"] = function ()
return os.execute("/usr/sbin/nginx -s reload") == 0 return os.execute("/usr/sbin/nginx -s reload") == 0
end end
api_list["^/stop$"] = function ()
return os.execute("/usr/sbin/nginx -s quit") == 0
end
function M.is_api_call (api_uri, api_whitelist_ip) function M.is_api_call (api_uri, api_whitelist_ip)
local whitelist = iputils.parse_cidrs(api_whitelist_ip) local whitelist = iputils.parse_cidrs(api_whitelist_ip)
if iputils.ip_in_cidrs(ngx.var.remote_addr, whitelist) and ngx.var.request_uri:sub(1, #api_uri) .. "/" == api_uri .. "/" then if iputils.ip_in_cidrs(ngx.var.remote_addr, whitelist) and ngx.var.request_uri:sub(1, #api_uri) .. "/" == api_uri .. "/" then

View File

@ -3,7 +3,7 @@ import json, uuid, glob, copy, re, subprocess
class Config : class Config :
def __init__(self) : def __init__(self) :
with open("/opt/settings.json", "r") as f : with open("/opt/bunkerized-nginx/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) :
@ -37,7 +37,7 @@ class Config :
conf["SERVER_NAME"] = " ".join(servers) conf["SERVER_NAME"] = " ".join(servers)
env_file = "/tmp/" + str(uuid.uuid4()) + ".env" env_file = "/tmp/" + str(uuid.uuid4()) + ".env"
self.__dict_to_env(env_file, conf) 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) proc = subprocess.run(["/opt/bunkerized-nginx/gen/main.py", "--settings", "/opt/bunkerized-nginx/settings.json", "--templates", "/opt/bunkerized-nginx/confs", "--output", "/etc/nginx", "--variables", env_file], capture_output=True)
stderr = proc.stderr.decode("ascii") stderr = proc.stderr.decode("ascii")
#stdout = proc.stdout.decode("ascii") #stdout = proc.stdout.decode("ascii")
if stderr != "" or proc.returncode != 0 : if stderr != "" or proc.returncode != 0 :

View File

@ -5,11 +5,11 @@ RUN chmod +x /tmp/dependencies.sh && \
/tmp/dependencies.sh && \ /tmp/dependencies.sh && \
rm -f /tmp/dependencies.sh rm -f /tmp/dependencies.sh
COPY gen/ /opt/gen COPY gen/ /opt/bunkerized-nginx/gen
COPY confs/site/ /opt/confs/site COPY confs/site/ /opt/bunkerized-nginx/confs/site
COPY confs/global/ /opt/confs/global COPY confs/global/ /opt/bunkerized-nginx/confs/global
COPY ui/ /opt/entrypoint COPY ui/ /opt/bunkerized-nginx/ui
COPY settings.json /opt COPY settings.json /opt/bunkerized-nginx
COPY ui/prepare.sh /tmp COPY ui/prepare.sh /tmp
RUN chmod +x /tmp/prepare.sh && \ RUN chmod +x /tmp/prepare.sh && \
@ -18,6 +18,6 @@ RUN chmod +x /tmp/prepare.sh && \
EXPOSE 5000 EXPOSE 5000
WORKDIR /opt/entrypoint WORKDIR /opt/bunkerized-nginx/ui
ENV FLASK_APP entrypoint.py USER nginx:nginx
ENTRYPOINT ["/usr/bin/python3", "-m", "flask", "run", "--host=0.0.0.0"] ENTRYPOINT ["/usr/bin/gunicorn", "--bind", "unix:bunkerized-nginx-ui.sock", "-m", "007", "wsgi:app"]

View File

@ -0,0 +1,12 @@
[Unit]
Description=Web UI for bunkerized-nginx
After=network.target
[Service]
User=nginx
Group=nginx
WorkingDirectory=/opt/bunkerized-nginx/ui
ExecStart=gunicorn --bind unix:bunkerized-nginx-ui.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
apk add py3-pip bash apk add py3-pip bash
pip3 install docker flask flask-login pip3 install docker flask flask-login requests gunicorn

View File

@ -2,20 +2,18 @@
from flask import Flask, render_template, current_app, request from flask import Flask, render_template, current_app, request
from src.Instances import Instances
from Docker import Docker from Docker import Docker
from Config import Config from Config import Config
import utils import utils
import os, json, re, copy, traceback import os, json, re, copy, traceback
app = Flask(__name__, static_url_path="/", static_folder="static", template_folder="templates") app = Flask(__name__, static_url_path="/", static_folder="static", template_folder="templates")
ABSOLUTE_URI = ""
if "ABSOLUTE_URI" in os.environ : vars = utils.get_variables()
ABSOLUTE_URI = os.environ["ABSOLUTE_URI"] app.config["ABSOLUTE_URI"] = vars["ABSOLUTE_URI"]
DOCKER_HOST = "unix:///var/run/docker.sock" app.config["INSTANCES"] = Instances(vars["DOCKER_HOST"], vars["API_URI"])
if "DOCKER_HOST" in os.environ :
DOCKER_HOST = os.environ["DOCKER_HOST"]
app.config["ABSOLUTE_URI"] = ABSOLUTE_URI
app.config["DOCKER"] = Docker(DOCKER_HOST)
app.config["CONFIG"] = Config() app.config["CONFIG"] = Config()
app.jinja_env.globals.update(env_to_summary_class=utils.env_to_summary_class) app.jinja_env.globals.update(env_to_summary_class=utils.env_to_summary_class)
app.jinja_env.globals.update(form_service_gen=utils.form_service_gen) app.jinja_env.globals.update(form_service_gen=utils.form_service_gen)
@ -26,7 +24,7 @@ app.jinja_env.globals.update(form_service_gen_multiple_values=utils.form_service
@app.route('/home') @app.route('/home')
def home() : def home() :
try : try :
instances_number = len(app.config["DOCKER"].get_instances()) instances_number = len(app.config["INSTANCES"].get_instances())
services_number = len(app.config["CONFIG"].get_services()) services_number = len(app.config["CONFIG"].get_services())
return render_template("home.html", title="Home", instances_number=instances_number, services_number=services_number) return render_template("home.html", title="Home", instances_number=instances_number, services_number=services_number)
except Exception as e : except Exception as e :
@ -40,7 +38,7 @@ def instances() :
if request.method == "POST" : if request.method == "POST" :
# Check operation # Check operation
if not "operation" in request.form or not request.form["operation"] in ["reload", "start", "stop", "restart", "delete"] : if not "operation" in request.form or not request.form["operation"] in ["reload", "start", "stop", "restart"] :
raise Exception("Missing operation parameter on /instances.") raise Exception("Missing operation parameter on /instances.")
# Check that all fields are present # Check that all fields are present
@ -49,18 +47,16 @@ def instances() :
# Do the operation # Do the operation
if request.form["operation"] == "reload" : if request.form["operation"] == "reload" :
operation = app.config["DOCKER"].reload_instance(request.form["INSTANCE_ID"]) operation = app.config["INSTANCES"].reload_instance(request.form["INSTANCE_ID"])
elif request.form["operation"] == "start" : elif request.form["operation"] == "start" :
operation = app.config["DOCKER"].start_instance(request.form["INSTANCE_ID"]) operation = app.config["INSTANCES"].start_instance(request.form["INSTANCE_ID"])
elif request.form["operation"] == "stop" : elif request.form["operation"] == "stop" :
operation = app.config["DOCKER"].stop_instance(request.form["INSTANCE_ID"]) operation = app.config["INSTANCES"].stop_instance(request.form["INSTANCE_ID"])
elif request.form["operation"] == "restart" : elif request.form["operation"] == "restart" :
operation = app.config["DOCKER"].restart_instance(request.form["INSTANCE_ID"]) operation = app.config["INSTANCES"].restart_instance(request.form["INSTANCE_ID"])
elif request.form["operation"] == "delete" :
operation = app.config["DOCKER"].delete_instance(request.form["INSTANCE_ID"])
# Display instances # Display instances
instances = app.config["DOCKER"].get_instances() instances = app.config["INSTANCES"].get_instances()
return render_template("instances.html", title="Instances", instances=instances, operation=operation) return render_template("instances.html", title="Instances", instances=instances, operation=operation)
except Exception as e : except Exception as e :

View File

@ -8,7 +8,10 @@ adduser -h /var/cache/nginx -g nginx -s /bin/sh -G nginx -D -H -u 101 nginx
chown -R root:nginx /opt chown -R root:nginx /opt
find /opt -type f -exec chmod 0740 {} \; find /opt -type f -exec chmod 0740 {} \;
find /opt -type d -exec chmod 0750 {} \; find /opt -type d -exec chmod 0750 {} \;
chmod ugo+x /opt/entrypoint/* chmod 750 /opt/bunkerized-nginx/gen/main.py
chmod ugo+x /opt/gen/main.py
chmod 770 /opt # prepare /var/log
chmod 440 /opt/settings.json mkdir /var/log/nginx
chown root:nginx /var/log/nginx
chmod 750 /var/log/nginx
ln -s /proc/1/fd/1 /var/log/nginx/ui.log

View File

@ -2,15 +2,16 @@ import docker, os, requests
class Instances : class Instances :
def __init__(self, docker_host, api) : def __init__(self, docker_host, api_uri) :
try : try :
self.__docker = docker.DockerClient(base_url=docker_host) self.__docker = docker.DockerClient(base_url=docker_host)
except : except :
self.__docker = None self.__docker = None
self.__api = api self.__api_uri = api_uri
def __instance(self, name, type, status, data=None) : def __instance(self, id, name, type, status, data=None) :
instance = {} instance = {}
instance["id"] = id
instance["name"] = name instance["name"] = name
instance["type"] = type instance["type"] = type
instance["status"] = status instance["status"] = status
@ -27,7 +28,7 @@ class Instances :
hosts.append(host) hosts.append(host)
for host in hosts : for host in hosts :
try : try :
req = requests.post("http://" + host + ":8080" + self.__api + order) req = requests.post("http://" + host + ":8080" + self.__api_uri + order)
if not req or req.status_code != 200 or req.text != "ok" : if not req or req.status_code != 200 or req.text != "ok" :
result = False result = False
except : except :
@ -40,14 +41,16 @@ class Instances :
if self.__docker != None : if self.__docker != None :
if self.__docker.swarm == None : if self.__docker.swarm == None :
for instance in self.__docker.containers.list(all=True, filters={"label" : "bunkerized-nginx.UI"}) : for instance in self.__docker.containers.list(all=True, filters={"label" : "bunkerized-nginx.UI"}) :
id = instance.id
name = instance.name name = instance.name
type = "container" type = "container"
status = "down" status = "down"
if instance.status == "running" : if instance.status == "running" :
status = "up" status = "up"
instances.append(self.__instance(name, type, status, instance)) instances.append(self.__instance(id, name, type, status, instance))
else : else :
for instance in self.__docker.services.list(all=True, filters={"label" : "bunkerized-nginx.UI"}) : for instance in self.__docker.services.list(all=True, filters={"label" : "bunkerized-nginx.UI"}) :
id = instance.id
name = instance.name name = instance.name
type = "service" type = "service"
status = "down" status = "down"
@ -55,16 +58,17 @@ class Instances :
running_tasks = instance.attrs["ServiceStatus"]["RunningTasks"] running_tasks = instance.attrs["ServiceStatus"]["RunningTasks"]
if desired_tasks > 0 and (desired_tasks == running_tasks) : if desired_tasks > 0 and (desired_tasks == running_tasks) :
status = "up" status = "up"
instances.append(self.__instance(name, type, status, instance)) instances.append(self.__instance(id, name, type, status, instance))
# Local instance # Local instance
if os.path.exists("/usr/sbin/nginx") : if os.path.exists("/usr/sbin/nginx") :
id = "local"
name = "local" name = "local"
type = "local" type = "local"
status = "down" status = "down"
if os.path.exists("/tmp/nginx.pid") : if os.path.exists("/tmp/nginx.pid") :
status = "up" status = "up"
instances.append(self.__instance(name, type, status)) instances.append(self.__instance(id, name, type, status))
return instances return instances
@ -99,7 +103,7 @@ class Instances :
proc = subprocess.run(["/usr/sbin/nginx", "-g", "daemon on;"], capture_output=True) proc = subprocess.run(["/usr/sbin/nginx", "-g", "daemon on;"], capture_output=True)
result = proc.returncode == 0 result = proc.returncode == 0
elif instance["type"] == "container" or instance["type"] == "service" : elif instance["type"] == "container" or instance["type"] == "service" :
result = self.__api_request(instance, "/start") result = False #self.__api_request(instance, "/start")
if result : if result :
return "Instance " + instance["name"] + " has been started." return "Instance " + instance["name"] + " has been started."
return "Can't start " + instance["name"] return "Can't start " + instance["name"]
@ -123,7 +127,7 @@ class Instances :
proc = subprocess.run(["/usr/sbin/nginx", "-g", "daemon on;"], capture_output=True) proc = subprocess.run(["/usr/sbin/nginx", "-g", "daemon on;"], capture_output=True)
result = proc.returncode == 0 result = proc.returncode == 0
elif instance["type"] == "container" or instance["type"] == "service" : elif instance["type"] == "container" or instance["type"] == "service" :
result = self.__api_request(instance, "/restart") result = False #self.__api_request(instance, "/restart")
if result : if result :
return "Instance " + instance["name"] + " has been restarted." return "Instance " + instance["name"] + " has been restarted."
return "Can't restart " + instance["name"] return "Can't restart " + instance["name"]

View File

@ -17,11 +17,9 @@
{% for instance in instances %} {% for instance in instances %}
{% set color = "dark" %} {% set color = "dark" %}
{% if instance["status"] == "running" %} {% if instance["status"] == "up" %}
{% set color = "success" %} {% set color = "success" %}
{% elif instance["status"] == "created" or instance["status"] == "restarting" or instance["status"] == "paused" %} {% elif instance["status"] == "down" %}
{% set color = "warning" %}
{% elif instance["status"] == "exited" or instance["status"] == "dead" %}
{% set color = "danger" %} {% set color = "danger" %}
{% endif %} {% endif %}
@ -34,27 +32,20 @@
{{ instance["name"] }} {{ instance["name"] }}
<div class="btn-group mx-2 float-end" role="group"> <div class="btn-group mx-2 float-end" role="group">
<button id="btnGroupDrop1" class="btn btn-sm dropdown-toggle btn-light" data-bs-toggle="dropdown" aria-expanded="false"> <button id="btnGroupDrop1" class="btn btn-sm dropdown-toggle btn-light" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fas fa-cogs"> manage container</i> <i class="fas fa-cogs"> manage instance</i>
</button> </button>
<ul class="dropdown-menu" aria-labelledby="btnGroupDrop1"> <ul class="dropdown-menu" aria-labelledby="btnGroupDrop1">
<li><a class="dropdown-item" href="#" onClick="return startInstance('{{ instance["id"] }}');">Start</a></li> {% if instance["type"] == "local" %}<li><a class="dropdown-item" href="#" onClick="return startInstance('{{ instance["id"] }}');">Start</a></li>{% endif %}
<li><a class="dropdown-item" href="#" onClick="return stopInstance('{{ instance["id"] }}');">Stop</a></li> <li><a class="dropdown-item" href="#" onClick="return stopInstance('{{ instance["id"] }}');">Stop</a></li>
<li><a class="dropdown-item" href="#" onClick="return restartInstance('{{ instance["id"] }}');">Restart</a></li> {% if instance["type"] == "local" %}<li><a class="dropdown-item" href="#" onClick="return restartInstance('{{ instance["id"] }}');">Restart</a></li>{% endif %}
<li><a class="dropdown-item" href="#" onClick="return deleteInstance('{{ instance["id"] }}');">Delete</a></li>
</ul> </ul>
</div> </div>
<button class="btn btn-sm mx-2 float-end btn-light" onClick="reloadInstance('{{ instance["id"] }}');"><i class="fas fa-redo-alt"></i> reload nginx</button> <button class="btn btn-sm mx-2 float-end btn-light" onClick="reloadInstance('{{ instance["id"] }}');"><i class="fas fa-redo-alt"></i> Reload configuration</button>
</div> </div>
<div class="card-body text-dark"> <div class="card-body text-dark">
<h5 class="card-title">Status : {{ instance["status"] }}</h5> <h5 class="card-title">Status : {{ instance["status"] }}</h5>
<span class="card-text"> <span class="card-text">
Environment variables :<br /> TODO
{% set envfilter = ["PATH", "NGINX_VERSION", "NJS_VERSION", "PKG_RELEASE"] %}
{% for env in instance.attrs["Config"]["Env"] %}
{% if not env.startswith("PATH=") and not env.startswith("NGINX_VERSION=") and not env.startswith("NJS_VERSION=") and not env.startswith("PKG_RELEASE=") %}
{{ env }}<br />
{% endif %}
{% endfor %}
</span> </span>
</div> </div>
</div> </div>

View File

@ -1,9 +1,20 @@
#!/usr/bin/python3 #!/usr/bin/python3
import datetime, re, json import datetime, re, json, os
def get_variables() :
vars = {}
vars["DOCKER_HOST"] = "unix:///var/run/docker.sock"
vars["API_URI"] = ""
vars["ABSOLUTE_URI"] = ""
for k in vars :
if k in os.environ :
vars[k] = os.environ[k]
return vars
def log(event) : def log(event) :
print("[" + str(datetime.datetime.now().replace(microsecond=0)) + "] " + event, flush=True) with open("/var/log/nginx/ui.log", "a") as f :
f.write("[" + str(datetime.datetime.now().replace(microsecond=0)) + "] " + event + "\n")
def env_to_summary_class(var, value) : def env_to_summary_class(var, value) :
if type(var) is list and type(value) is list : if type(var) is list and type(value) is list :

4
ui/wsgi.py Normal file
View File

@ -0,0 +1,4 @@
from entrypoint import app
if __name__ == "__main__":
app.run()