userinterface: nginx backend for http access

This commit is contained in:
Vivek Kumar Dutta 2024-04-19 22:05:47 +05:30
parent 3857f5d3ee
commit 893c292150
9 changed files with 416 additions and 40 deletions

23
userinterface/Config.in Normal file
View file

@ -0,0 +1,23 @@
if PACKAGE_userinterface
choice
prompt "Select backend of user interface HTTP Access management"
default USERINTERFACE_HTTPACCESS_BACKEND_NGINX
depends on PACKAGE_userinterface
help
Select which backend daemon to use for User Interface HTTP Access
config USERINTERFACE_HTTPACCESS_BACKEND_NGINX
bool "Use nginx backend"
help
Enable this option to use nginx for HTTP Access.
endchoice
config USERINTERFACE_HTTPACCESS_MIGRATE_NGINX_CONFIG
bool "migrate nginx config"
depends on USERINTERFACE_HTTPACCESS_BACKEND_NGINX
default y
help
Migrate nginx to userinterface on firmware upgrade
endif

View file

@ -5,39 +5,72 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=userinterface
PKG_VERSION:=1.0.0
PKG_VERSION:=1.1.0
LOCAL_DEV:=0
ifneq ($(LOCAL_DEV),1)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/userinterface.git
PKG_SOURCE_VERSION:=8fd2afed32dea24ac5e0ce31f17b645ba852493f
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MIRROR_HASH:=skip
endif
PKG_LICENSE:=BSD-3-Clause
PKG_LICENSE_FILES:=LICENSE
include $(INCLUDE_DIR)/package.mk
include ../bbfdm/bbfdm.mk
define Package/userinterface
SECTION:=utils
CATEGORY:=Utilities
SUBMENU:=TRx69
TITLE:=Package to add Device.UserInterface. datamodel support using bbfdm
DEPENDS:=+libbbfdm-api +USERINTERFACE_HTTPACCESS_BACKEND_NGINX:nginx
MENU:=1
endef
MAKE_PATH:=src
define Package/userinterface/description
Package to add Device.UserInterface. datamodel support
endef
define Build/Compile
# Pass
define Package/$(PKG_NAME)/config
source "$(SOURCE)/Config.in"
endef
ifeq ($(LOCAL_DEV),1)
define Build/Prepare
$(CP) -rf ~/git/userinterface/* $(PKG_BUILD_DIR)/
endef
endif
define Package/userinterface/install
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
$(INSTALL_DIR) $(1)/etc/userinterface
# Install service
$(INSTALL_DATA) ./files/etc/config/userinterface $(1)/etc/config/userinterface
$(INSTALL_DATA) ./files/lib/upgrade/keep.d/userinterface $(1)/lib/upgrade/keep.d/userinterface
$(INSTALL_BIN) ./files/etc/init.d/userinterface $(1)/etc/init.d/userinterface
$(INSTALL_BIN) ./files/etc/uci-defaults/93-userinterface-firewall $(1)/etc/uci-defaults/93-userinterface-firewall
$(INSTALL_BIN) ./files/etc/uci-defaults/94-userinterface-json $(1)/etc/uci-defaults/94-userinterface-json
$(INSTALL_BIN) ./files/etc/firewall.userinterface $(1)/etc/firewall.userinterface
# Install datamodel microservice
$(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/src/libuserinterface.so $(1) $(PKG_NAME)
# Install backend
ifeq ($(CONFIG_USERINTERFACE_HTTPACCESS_BACKEND_NGINX),y)
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
$(INSTALL_BIN) ./files/backend/nginx/http_access $(1)/etc/userinterface/http_access
$(INSTALL_BIN) ./files/backend/nginx/userinterface_rpc $(1)/usr/libexec/rpcd/userinterface
ifeq ($(CONFIG_USERINTERFACE_HTTPACCESS_MIGRATE_NGINX_CONFIG),y)
$(INSTALL_BIN) ./files/backend/nginx/95-migrate-nginx-userinterface $(1)/etc/uci-defaults/95-migrate-nginx-userinterface
endif
endif
endef
$(eval $(call BuildPackage,userinterface))

View file

@ -1,9 +0,0 @@
#
# Copyright (C) 2023 IOPSYS
#
define BbfdmInstallPlugin
$(INSTALL_DIR) $(1)/etc/bbfdm/plugins
$(INSTALL_DATA) $(2) $(1)/etc/bbfdm/plugins/
endef

View file

@ -0,0 +1,116 @@
#!/bin/sh
. /lib/functions.sh
DEBUG=0
get_options() {
local name sec options tmp
name="$1"
sec="$2"
tmp="$name.$sec"
options=$(uci -X show ${tmp}|grep "${tmp}\."|sed "s/${tmp}\.//g"|sed "s/=.*$//g"|sort|uniq)
echo ${options}
}
parse_nginx_server() {
port=""
allow_host=""
protocol="HTTP"
# Check if section is already present in userinterface uci
sec=$(uci -q get userinterface."${1}")
if [ -n "${sec}" ]; then
# Section already present
return 0
fi
# Create a new http_access section
uci -q set userinterface."${1}"="http_access"
uci -q set userinterface."${1}".protocol="HTTP"
for option in $(get_options nginx ${1});
do
case ${option} in
uci_enable)
config_get_bool tmp "${1}" "${option}" 1
uci_set nginx ${1} ${option}
uci -q set userinterface."${1}".enable=$tmp
;;
uci_access)
config_get tmp "${1}" "${option}"
uci_set nginx ${1} ${option}
uci -q set userinterface."${1}".access=$tmp
;;
uci_interface)
config_get tmp "${1}" "${option}"
uci_set nginx ${1} ${option}
uci -q set userinterface."${1}".interface=$tmp
;;
listen)
config_get tmp "${1}" "${option}"
port="$(echo ${tmp}|grep -o '[[:digit:]]*'|head -n 1)"
uci -q set userinterface."${1}".port=$port
;;
ssl_certificate)
uci_set userinterface "${1}" protocol "HTTPS"
if [ "${DEBUG}" -eq 1 ]; then
config_get tmp "${1}" "${option}"
uci_set userinterface "${1}" "_nginx_${option}" "$tmp"
fi
;;
root)
config_get tmp "${1}" "${option}"
uci -q set userinterface."${1}".path_prefix=$tmp
;;
include)
allow_host=""
config_get tmp "${1}" "${option}"
for i in $tmp; do
if [[ "${i}" == allow_host_* ]]; then
allow_host=$(cat /etc/nginx/${i} | grep allow | cut -d' ' -f 2 | cut -d';' -f 1)
break
else
if [ "${DEBUG}" -eq 1 ]; then
uci_add_list userinterface "${1}" "_nginx_${option}" "$tmp"
fi
fi
done
for i in $allow_host; do
uci_add_list userinterface "${1}" "allow_host" "${i}"
done
;;
server_name|access_log|error_log)
;;
*)
if [ "${DEBUG}" -eq 1 ]; then
config_get tmp "${1}" "${option}"
uci_set userinterface "${1}" "_nginx_${option}" "$tmp"
fi
;;
esac
done
}
migrate_global_config() {
local en
config_get_bool en global uci_enable ""
if [ -n "${en}" ]; then
uci_set userinterface "global" "enable" "${en}"
else
uci_set userinterface "global" "enable" "1"
fi
}
migrate_uci_userinterface() {
migrate_global_config
config_load nginx
config_foreach parse_nginx_server server
}
migrate_uci_userinterface

View file

@ -0,0 +1,135 @@
#!/bin/sh
# This is a library to handler HTTP Access using nginx
. /lib/functions.sh
log() {
echo "$@"| logger -t http.init -s info
}
get_options() {
local name sec options tmp
name="$1"
sec="$2"
tmp="$name.$sec"
options=$(uci -X show ${tmp}|grep "${tmp}\."|sed "s/${tmp}\.//g"|sed "s/=.*$//g"|sort|uniq)
echo ${options}
}
_set_server_params() {
local enable port path_prefix allow_host
local protocol activationdate
local options val opt nginx_sec
if [[ "${1}" = "removed_"* ]]; then
# This instance has been deleted so need to remove from nginx uci
config_get nginx_sec "${1}" section_name
if [ -n "${nginx_sec}" ]; then
uci -q delete nginx."${nginx_sec}"
fi
uci -q delete userinterface."${1}"
return 0
fi
config_get_bool enable "${1}" enable 1
config_get port "${1}" port
config_get path_prefix "${1}" path_prefix
config_get allow_host "${1}" allow_host
config_get protocol "${1}" protocol
config_get activationdate "${1}" activationdate
if [ "$enable" -eq "0" ]; then
uci -q delete nginx."${1}"
return 0
fi
if [ -z "${port}" ]; then
uci -q delete nginx."${1}"
return 0
fi
if [ -z "${activationdate}" ]; then
uci_set userinterface "$1" activationdate "$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
fi
# Check if section is present in nginx
nginx_sec=$(uci -q get nginx."${1}")
if [ -z "${nginx_sec}" ]; then
# Add new server section in nginx
uci -q set nginx."${1}"="server"
uci -q set nginx."${1}".server_name=${1}
fi
uci -q set nginx."${1}".root=$path_prefix
uci -q delete nginx."${1}".listen
if [ "${protocol}" = "HTTPS" ]; then
uci -q add_list nginx."${1}".listen="$port ssl"
uci -q add_list nginx."${1}".listen="[::]:$port ssl"
else
uci -q add_list nginx."${1}".listen=$port
uci -q add_list nginx."${1}".listen=[::]:$port
fi
# Configure allowed hosts
nginx_includes=$(uci -q get nginx."${1}".include)
for i in ${nginx_includes}; do
if [[ "${i}" == "allow_host_"* ]]; then
uci -q del_list nginx."${1}".include="${i}"
log "Removing /etc/nginx/${i}"
rm -rf "/etc/nginx/${i}"
break
fi
done
if [ -n "${allow_host}" ]; then
host_file_path="/etc/nginx/allow_host_${1}"
for i in $allow_host; do
echo "allow $i;" >> "${host_file_path}"
done
echo "deny all;" >> "${host_file_path}"
uci -q add_list nginx."${1}".include="allow_host_${1}"
fi
# Copy all _nginx_ specific parameters, if present
options="$(get_options userinterface "${1}")"
for opt in ${options}; do
config_get val "${1}" "${opt}"
if [[ "$opt" = "_nginx_"* ]]; then
uci_set nginx "${1}" "${opt//_nginx_}" "${val}"
fi
done
}
# Public APIs
http_access_configure() {
# Set server parameters in nginx
config_load userinterface
config_foreach _set_server_params http_access
uci commit nginx
uci commit userinterface
}
http_access_service_start() {
procd_open_instance userinterface
/etc/init.d/nginx start
procd_close_instance
# Inject firewall rules
/etc/firewall.userinterface
}
http_access_service_stop() {
/etc/init.d/nginx stop
}

View file

@ -0,0 +1,86 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
get_nginx_status() {
port="${1}"
nginx_pid=$(pgrep "nginx: master process")
json_init
if [ -z "${nginx_pid}" ]; then
json_add_string "server_status" "Error"
json_dump
return
fi
state="Error"
netstat -nltp | grep "${nginx_pid}/uci.conf" | awk '{print $4}' > /tmp/http_status
while read server; do
if [ -z "${server}" ]; then
continue
fi
sport=$(echo "${server##*:}")
if [ "${sport}" -eq "${port}" ]; then
state="Up"
break
fi
done < /tmp/http_status
rm -rf /tmp/http_status
json_add_string "server_status" "${state}"
json_dump
return
}
get_nginx_session_list() {
netstat -ntp | grep nginx | awk '{print $4,$5}' > /tmp/http_session
json_init
json_add_array "http_sessions"
while read server client; do
if [ -z "${server}" ] || [ -z "${client}" ]; then
continue
fi
sport=$(echo "${server##*:}")
cip=$(echo "${client}" | sed 's/:[^:]*$//g')
cport=$(echo "${client##*:}")
json_add_object ""
json_add_string "server_port" "${sport}"
json_add_string "client_ip" "${cip}"
json_add_string "client_port" "${cport}"
json_close_object
done < /tmp/http_session
json_close_array
json_dump
rm -rf /tmp/http_session
return
}
case "$1" in
list)
echo '{ "http_session": {}, "http_status": {"port":"String"} }'
;;
call)
case "$2" in
http_session)
get_nginx_session_list
;;
http_status)
read -r input
json_load "${input}"
json_get_var port "port"
json_cleanup
get_nginx_status "${port}"
;;
esac
;;
esac

View file

@ -5,29 +5,31 @@ STOP=01
USE_PROCD=1
. /etc/userinterface/http_access
start_service() {
local enable
config_load userinterface
config_get_bool enable global enable 1
config_get_bool enable global enable 0
if [ ! -f "/etc/config/nginx" ]; then
if [ "${enable}" -eq "0" ]; then
return 0
fi
if [ "${enable}" -eq "1" ]; then
ubus call service state '{"name":"nginx", "spawn":true}'
else
ubus call service state '{"name":"nginx", "spawn":false}'
fi
# Inject firewall rules
procd_open_instance userinterface
/etc/firewall.userinterface
procd_close_instance
http_access_configure
http_access_service_start
}
service_triggers()
{
procd_add_reload_trigger "userinterface" "nginx"
stop_service() {
http_access_service_stop
}
reload_service() {
stop
start
}
service_triggers() {
procd_add_reload_trigger "userinterface"
}

View file

@ -1,9 +0,0 @@
#!/bin/sh
# This deletes the userinterface json plugin if exists in case of upgrade
if [ -f "/etc/bbfdm/json/UserInterface.json" ]; then
rm /etc/bbfdm/json/UserInterface.json
fi
exit 0

View file

@ -1 +0,0 @@
/etc/nginx/allow_host_*