improved core plugin execution order

This commit is contained in:
florian 2023-05-19 12:39:40 +02:00
parent b32f318919
commit 179beea4d7
No known key found for this signature in database
GPG key ID: 3D80806F12602A7C
52 changed files with 435 additions and 326 deletions

View file

@ -7,7 +7,7 @@ helpers.load_plugin = function(json)
-- Open file -- Open file
local file, err, nb = io.open(json, "r") local file, err, nb = io.open(json, "r")
if not file then if not file then
return false, "can't load JSON at " .. json .. " : " .. err .. "(nb = " .. tostring(nb) .. ")" return false, "can't load JSON at " .. json .. " : " .. err .. " (nb = " .. tostring(nb) .. ")"
end end
-- Decode JSON -- Decode JSON
local ok, plugin = pcall(cjson.decode, file:read("*a")) local ok, plugin = pcall(cjson.decode, file:read("*a"))
@ -17,20 +17,80 @@ helpers.load_plugin = function(json)
end end
-- Check fields -- Check fields
local missing_fields = {} local missing_fields = {}
local required_fields = { "id", "order", "name", "description", "version", "settings" } local required_fields = { "id", "name", "description", "version", "settings", "stream" }
for i, field in ipairs(required_fields) do for i, field in ipairs(required_fields) do
if plugin[field] == nil then if plugin[field] == nil then
valid_json = false
table.insert(missing_fields, field) table.insert(missing_fields, field)
end end
end end
if #missing_fields > 0 then if #missing_fields > 0 then
return false, "missing field(s) " .. cjson.encode(missing_fields) .. " for JSON at " .. json return false, "missing field(s) " .. cjson.encode(missing_fields) .. " for JSON at " .. json
end end
-- Try require
local plugin_lua, err = helpers.require_plugin(plugin.id)
if plugin_lua == false then
return false, err
end
-- Fill phases
local phases = utils.get_phases()
plugin.phases = {}
if plugin_lua then
for i, phase in ipairs(phases) do
if plugin_lua[phase] ~= nil then
table.insert(plugin.phases, phase)
end
end
end
-- Return plugin -- Return plugin
return true, plugin return true, plugin
end end
helpers.order_plugins = function(plugins)
-- Extract orders
local file, err, nb = io.open("/usr/share/bunkerweb/core/order.json", "r")
if not file then
return false, err .. " (nb = " .. tostring(nb) .. ")"
end
local ok, orders = pcall(cjson.decode, file:read("*a"))
file:close()
if not ok then
return false, "invalid order.json : " .. err
end
-- Compute plugins/id/phases table
local plugins_phases = {}
for i, plugin in ipairs(plugins) do
plugins_phases[plugin.id] = {}
for j, phase in ipairs(plugin.phases) do
plugins_phases[plugin.id][phase] = true
end
end
-- Order result
local result_orders = {}
for i, phase in ipairs(utils.get_phases()) do
result_orders[phase] = {}
end
-- Fill order first
for phase, order in pairs(orders) do
for i, id in ipairs(order) do
local plugin = plugins_phases[id]
if plugin and plugin[phase] then
table.insert(result_orders[phase], id)
plugin[phase] = nil
end
end
end
-- Then append missing plugins to the end
for i, phase in ipairs(utils.get_phases()) do
for id, plugin in pairs(plugins_phases) do
if plugin[phase] then
table.insert(result_orders[phase], id)
plugin[phase] = nil
end
end
end
return true, result_orders
end
helpers.require_plugin = function(id) helpers.require_plugin = function(id)
-- Require call -- Require call
local ok, plugin_lua = pcall(require, id .. "/" .. id) local ok, plugin_lua = pcall(require, id .. "/" .. id)
@ -45,7 +105,7 @@ helpers.require_plugin = function(id)
return false, "missing new() method for plugin " .. id return false, "missing new() method for plugin " .. id
end end
-- Return plugin -- Return plugin
return plugin_lua, "new() call successful for plugin " .. id return plugin_lua, "require() call successful for plugin " .. id
end end
helpers.new_plugin = function(plugin_lua) helpers.new_plugin = function(plugin_lua)

View file

@ -639,4 +639,18 @@ utils.regex_match = function(str, regex, options)
return match return match
end end
utils.get_phases = function()
return {
"init",
"init_worker",
"set",
"access",
"header",
"log",
"preread",
"log_stream",
"log_default"
}
end
return utils return utils

View file

@ -62,19 +62,23 @@ server {
end end
logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")") logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")")
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call log_default() methods -- Call log_default() methods
logger:log(ngx.INFO, "calling log_default() methods of plugins ...") logger:log(ngx.INFO, "calling log_default() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.log_default) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -91,11 +95,11 @@ server {
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
else else
logger:log(ngx.INFO, plugin.id .. ":log_default() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":log_default() call successful : " .. ret.msg)
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method log_default() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method log_default() is not defined")
end end
end end
end end

View file

@ -92,9 +92,6 @@ for i, plugin_path in ipairs(plugin_paths) do
logger:log(ngx.ERR, "can't save " .. plugin.id .. " into datastore : " .. err) logger:log(ngx.ERR, "can't save " .. plugin.id .. " into datastore : " .. err)
else else
table.insert(plugins, plugin) table.insert(plugins, plugin)
table.sort(plugins, function (a, b)
return a.order < b.order
end)
logger:log(ngx.NOTICE, "loaded plugin " .. plugin.id .. " v" .. plugin.version) logger:log(ngx.NOTICE, "loaded plugin " .. plugin.id .. " v" .. plugin.version)
end end
end end
@ -105,13 +102,28 @@ if not ok then
logger:log(ngx.ERR, "can't save plugins into datastore : " .. err) logger:log(ngx.ERR, "can't save plugins into datastore : " .. err)
return false return false
end end
logger:log(ngx.NOTICE, "saved plugins into datastore")
-- Call init() methodatastore logger:log(ngx.NOTICE, "saving plugins order into datastore ...")
local ok, order = helpers.order_plugins(plugins)
if not ok then
logger:log(ngx.ERR, "can't compute plugins order : " .. err)
return false
end
for phase, id_list in pairs(order) do
logger:log(ngx.NOTICE, "plugins order for phase " .. phase .. " : " .. cjson.encode(id_list))
end
local ok, err = datastore:set("plugins_order", cjson.encode(order))
if not ok then
logger:log(ngx.ERR, "can't save plugins order into datastore : " .. err)
return false
end
logger:log(ngx.NOTICE, "saved plugins order into datastore")
-- Call init() method
logger:log(ngx.NOTICE, "calling init() methods of plugins ...") logger:log(ngx.NOTICE, "calling init() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order["init"]) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -128,9 +140,9 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":init() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":init() call failed : " .. ret.msg)
else else
logger:log(ngx.NOTICE, plugin.id .. ":init() call successful : " .. ret.msg) logger:log(ngx.NOTICE, plugin_id .. ":init() call successful : " .. ret.msg)
end end
end end
else else

View file

@ -1,145 +1,158 @@
init_by_lua_block { init_by_lua_block {
local class = require "middleclass" local class = require "middleclass"
local clogger = require "bunkerweb.logger" local clogger = require "bunkerweb.logger"
local helpers = require "bunkerweb.helpers" local helpers = require "bunkerweb.helpers"
local cdatastore = require "bunkerweb.datastore" local cdatastore = require "bunkerweb.datastore"
local cjson = require "cjson" local cjson = require "cjson"
-- Start init phase -- Start init phase
local logger = clogger:new("INIT-STREAM") local logger = clogger:new("INIT-STREAM")
local datastore = cdatastore:new() local datastore = cdatastore:new()
logger:log(ngx.NOTICE, "init-stream phase started") logger:log(ngx.NOTICE, "init-stream phase started")
-- Purge cache -- Purge cache
local cachestore = require "bunkerweb.cachestore":new() local cachestore = require "bunkerweb.cachestore":new()
local ok, err = cachestore:purge() local ok, err = cachestore:purge()
if not ok then
logger:log(ngx.ERR, "can't purge cachestore : " .. err)
end
-- Remove previous data from the datastore
logger:log(ngx.NOTICE, "deleting old keys from datastore ...")
local data_keys = {"^plugin_", "^variable_", "^plugins$", "^api_", "^misc_"}
for i, key in pairs(data_keys) do
local ok, err = datastore:delete_all(key)
if not ok then if not ok then
logger:log(ngx.ERR, "can't delete " .. key .. " from datastore : " .. err) logger:log(ngx.ERR, "can't purge cachestore : " .. err)
return false
end end
logger:log(ngx.INFO, "deleted " .. key .. " from datastore")
end -- Remove previous data from the datastore
logger:log(ngx.NOTICE, "deleted old keys from datastore") logger:log(ngx.NOTICE, "deleting old keys from datastore ...")
local data_keys = {"^plugin_", "^variable_", "^plugins$", "^api_", "^misc_"}
-- Load variables into the datastore for i, key in pairs(data_keys) do
logger:log(ngx.NOTICE, "saving variables into datastore ...") local ok, err = datastore:delete_all(key)
local file = io.open("/etc/nginx/variables.env")
if not file then
logger:log(ngx.ERR, "can't open /etc/nginx/variables.env file")
return false
end
file:close()
for line in io.lines("/etc/nginx/variables.env") do
local variable, value = line:match("(.+)=(.*)")
local ok, err = datastore:set("variable_" .. variable, value)
if not ok then
logger:log(ngx.ERR, "can't save variable " .. variable .. " into datastore : " .. err)
return false
end
logger:log(ngx.INFO, "saved variable " .. variable .. "=" .. value .. " into datastore")
end
logger:log(ngx.NOTICE, "saved variables into datastore")
-- Set API values into the datastore
logger:log(ngx.NOTICE, "saving API values into datastore ...")
local value, err = datastore:get("variable_USE_API")
if not value then
logger:log(ngx.ERR, "can't get variable USE_API from the datastore : " .. err)
return false
end
if value == "yes" then
local value, err = datastore:get("variable_API_WHITELIST_IP")
if not value then
logger:log(ngx.ERR, "can't get variable API_WHITELIST_IP from the datastore : " .. err)
return false
end
local whitelists = {}
for whitelist in value:gmatch("%S+") do
table.insert(whitelists, whitelist)
end
local ok, err = datastore:set("api_whitelist_ip", cjson.encode(whitelists))
if not ok then
logger:log(ngx.ERR, "can't save API whitelist_ip to datastore : " .. err)
return false
end
logger:log(ngx.INFO, "saved API whitelist_ip into datastore")
end
logger:log(ngx.NOTICE, "saved API values into datastore")
-- Load plugins into the datastore
logger:log(ngx.NOTICE, "saving plugins into datastore ...")
local plugins = {}
local plugin_paths = {"/usr/share/bunkerweb/core", "/etc/bunkerweb/plugins"}
for i, plugin_path in ipairs(plugin_paths) do
local paths = io.popen("find -L " .. plugin_path .. " -maxdepth 1 -type d ! -path " .. plugin_path)
for path in paths:lines() do
local ok, plugin = helpers.load_plugin(path .. "/plugin.json")
if not ok then if not ok then
logger:log(ngx.ERR, plugin) logger:log(ngx.ERR, "can't delete " .. key .. " from datastore : " .. err)
else return false
local ok, err = datastore:set("plugin_" .. plugin.id, cjson.encode(plugin))
if not ok then
logger:log(ngx.ERR, "can't save " .. plugin.id .. " into datastore : " .. err)
else
table.insert(plugins, plugin)
table.sort(plugins, function (a, b)
return a.order < b.order
end)
logger:log(ngx.NOTICE, "loaded plugin " .. plugin.id .. " v" .. plugin.version)
end
end end
logger:log(ngx.INFO, "deleted " .. key .. " from datastore")
end end
end logger:log(ngx.NOTICE, "deleted old keys from datastore")
local ok, err = datastore:set("plugins", cjson.encode(plugins))
if not ok then -- Load variables into the datastore
logger:log(ngx.ERR, "can't save plugins into datastore : " .. err) logger:log(ngx.NOTICE, "saving variables into datastore ...")
return false local file = io.open("/etc/nginx/variables.env")
end if not file then
logger:log(ngx.NOTICE, "saved plugins into datastore") logger:log(ngx.ERR, "can't open /etc/nginx/variables.env file")
return false
-- Call init() methodatastore end
logger:log(ngx.NOTICE, "calling init() methods of plugins ...") file:close()
for i, plugin in ipairs(plugins) do for line in io.lines("/etc/nginx/variables.env") do
-- Require call local variable, value = line:match("^([^=]+)=(.*)$")
local plugin_lua, err = helpers.require_plugin(plugin.id) local ok, err = datastore:set("variable_" .. variable, value)
if plugin_lua == false then if not ok then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, "can't save variable " .. variable .. " into datastore : " .. err)
elseif plugin_lua == nil then return false
logger:log(ngx.NOTICE, err) end
else logger:log(ngx.INFO, "saved variable " .. variable .. "=" .. value .. " into datastore")
-- Check if plugin has init method end
if plugin_lua.init ~= nil then logger:log(ngx.NOTICE, "saved variables into datastore")
-- New call
local ok, plugin_obj = helpers.new_plugin(plugin_lua) -- Set API values into the datastore
logger:log(ngx.NOTICE, "saving API values into datastore ...")
local value, err = datastore:get("variable_USE_API")
if not value then
logger:log(ngx.ERR, "can't get variable USE_API from the datastore : " .. err)
return false
end
if value == "yes" then
local value, err = datastore:get("variable_API_WHITELIST_IP")
if not value then
logger:log(ngx.ERR, "can't get variable API_WHITELIST_IP from the datastore : " .. err)
return false
end
local whitelists = {}
for whitelist in value:gmatch("%S+") do
table.insert(whitelists, whitelist)
end
local ok, err = datastore:set("api_whitelist_ip", cjson.encode(whitelists))
if not ok then
logger:log(ngx.ERR, "can't save API whitelist_ip to datastore : " .. err)
return false
end
logger:log(ngx.INFO, "saved API whitelist_ip into datastore")
end
logger:log(ngx.NOTICE, "saved API values into datastore")
-- Load plugins into the datastore
logger:log(ngx.NOTICE, "saving plugins into datastore ...")
local plugins = {}
local plugin_paths = {"/usr/share/bunkerweb/core", "/etc/bunkerweb/plugins"}
for i, plugin_path in ipairs(plugin_paths) do
local paths = io.popen("find -L " .. plugin_path .. " -maxdepth 1 -type d ! -path " .. plugin_path)
for path in paths:lines() do
local ok, plugin = helpers.load_plugin(path .. "/plugin.json")
if not ok then if not ok then
logger:log(ngx.ERR, plugin_obj) logger:log(ngx.ERR, plugin)
else else
local ok, ret = helpers.call_plugin(plugin_obj, "init") local ok, err = datastore:set("plugin_" .. plugin.id, cjson.encode(plugin))
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, "can't save " .. plugin.id .. " into datastore : " .. err)
elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":init() call failed : " .. ret.msg)
else else
logger:log(ngx.NOTICE, plugin.id .. ":init() call successful : " .. ret.msg) table.insert(plugins, plugin)
logger:log(ngx.NOTICE, "loaded plugin " .. plugin.id .. " v" .. plugin.version)
end end
end end
else
logger:log(ngx.NOTICE, "skipped execution of " .. plugin.id .. " because method init() is not defined")
end end
end end
end local ok, err = datastore:set("plugins", cjson.encode(plugins))
logger:log(ngx.NOTICE, "called init() methods of plugins") if not ok then
logger:log(ngx.ERR, "can't save plugins into datastore : " .. err)
logger:log(ngx.NOTICE, "init-stream phase ended") return false
end
}
logger:log(ngx.NOTICE, "saving plugins order into datastore ...")
local ok, order = helpers.order_plugins(plugins)
if not ok then
logger:log(ngx.ERR, "can't compute plugins order : " .. err)
return false
end
for phase, id_list in pairs(order) do
logger:log(ngx.NOTICE, "plugins order for phase " .. phase .. " : " .. cjson.encode(id_list))
end
local ok, err = datastore:set("plugins_order", cjson.encode(order))
if not ok then
logger:log(ngx.ERR, "can't save plugins order into datastore : " .. err)
return false
end
logger:log(ngx.NOTICE, "saved plugins order into datastore")
-- Call init() method
logger:log(ngx.NOTICE, "calling init() methods of plugins ...")
for i, plugin_id in ipairs(order["init"]) do
-- Require call
local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then
logger:log(ngx.ERR, err)
elseif plugin_lua == nil then
logger:log(ngx.NOTICE, err)
else
-- Check if plugin has init method
if plugin_lua.init ~= nil then
-- New call
local ok, plugin_obj = helpers.new_plugin(plugin_lua)
if not ok then
logger:log(ngx.ERR, plugin_obj)
else
local ok, ret = helpers.call_plugin(plugin_obj, "init")
if not ok then
logger:log(ngx.ERR, ret)
elseif not ret.ret then
logger:log(ngx.ERR, plugin_id .. ":init() call failed : " .. ret.msg)
else
logger:log(ngx.NOTICE, plugin_id .. ":init() call successful : " .. ret.msg)
end
end
else
logger:log(ngx.NOTICE, "skipped execution of " .. plugin.id .. " because method init() is not defined")
end
end
end
logger:log(ngx.NOTICE, "called init() methods of plugins")
logger:log(ngx.NOTICE, "init-stream phase ended")
}

View file

@ -56,23 +56,23 @@ local ready_work = function(premature)
logger:log(ngx.INFO, "init_worker phase started") logger:log(ngx.INFO, "init_worker phase started")
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
local ok, err = lock:unlock() local ok, err = lock:unlock()
if not ok then if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err) logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end end
return return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call init_worker() methods -- Call init_worker() methods
logger:log(ngx.INFO, "calling init_worker() methods of plugins ...") logger:log(ngx.INFO, "calling init_worker() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.init_worker) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -89,13 +89,13 @@ local ready_work = function(premature)
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":init_worker() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":init_worker() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":init_worker() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":init_worker() call successful : " .. ret.msg)
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method init_worker() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method init_worker() is not defined")
end end
end end
end end

View file

@ -42,21 +42,25 @@ else
logger:log(ngx.INFO, "IP " .. ngx.ctx.bw.remote_addr .. " is not banned") logger:log(ngx.INFO, "IP " .. ngx.ctx.bw.remote_addr .. " is not banned")
end end
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call access() methods -- Call access() methods
logger:log(ngx.INFO, "calling access() methods of plugins ...") logger:log(ngx.INFO, "calling access() methods of plugins ...")
local status = nil local status = nil
local redirect = nil local redirect = nil
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.access) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -73,27 +77,27 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":access() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":access() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":access() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":access() call successful : " .. ret.msg)
end end
if ret.status then if ret.status then
if ret.status == utils.get_deny_status() then if ret.status == utils.get_deny_status() then
ngx.ctx.reason = plugin.id ngx.ctx.reason = plugin_id
logger:log(ngx.WARN, "denied access from " .. plugin.id .. " : " .. ret.msg) logger:log(ngx.WARN, "denied access from " .. plugin_id .. " : " .. ret.msg)
else else
logger:log(ngx.NOTICE, plugin.id .. " returned status " .. tostring(ret.status) .. " : " .. ret.msg) logger:log(ngx.NOTICE, plugin_id .. " returned status " .. tostring(ret.status) .. " : " .. ret.msg)
end end
status = ret.status status = ret.status
break break
elseif ret.redirect then elseif ret.redirect then
logger:log(ngx.NOTICE, plugin.id .. " redirect to " .. ret.redirect .. " : " .. ret.msg) logger:log(ngx.NOTICE, plugin_id .. " redirect to " .. ret.redirect .. " : " .. ret.msg)
redirect = ret.redirect redirect = ret.redirect
break break
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method access() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method access() is not defined")
end end
end end
end end

View file

@ -23,19 +23,23 @@ elseif errors then
end end
logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")") logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")")
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call header() methods -- Call header() methods
logger:log(ngx.INFO, "calling header() methods of plugins ...") logger:log(ngx.INFO, "calling header() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.header) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -52,13 +56,13 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":header() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":header() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":header() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":header() call successful : " .. ret.msg)
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method header() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method header() is not defined")
end end
end end
end end

View file

@ -23,19 +23,23 @@ elseif errors then
end end
logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")") logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")")
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call log() methods -- Call log() methods
logger:log(ngx.INFO, "calling log() methods of plugins ...") logger:log(ngx.INFO, "calling log() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.log) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -52,13 +56,13 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":log() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":log() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":log() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":log() call successful : " .. ret.msg)
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method log() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method log() is not defined")
end end
end end
end end

View file

@ -38,19 +38,23 @@ elseif errors then
end end
logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")") logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")")
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call set() methods -- Call set() methods
logger:log(ngx.INFO, "calling set() methods of plugins ...") logger:log(ngx.INFO, "calling set() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.set) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -67,13 +71,13 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":set() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":set() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":set() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":set() call successful : " .. ret.msg)
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method set() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method set() is not defined")
end end
end end
end end

View file

@ -23,19 +23,23 @@ elseif errors then
end end
logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")") logger:log(ngx.INFO, "ngx.ctx filled (ret = " .. ret .. ")")
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call log_stream() methods -- Call log_stream() methods
logger:log(ngx.INFO, "calling log_stream() methods of plugins ...") logger:log(ngx.INFO, "calling log_stream() methods of plugins ...")
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.log_stream) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -52,13 +56,13 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":log_stream() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":log_stream() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":log_stream() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":log_stream() call successful : " .. ret.msg)
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method log_stream() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method log_stream() is not defined")
end end
end end
end end

View file

@ -36,20 +36,24 @@ else
logger:log(ngx.INFO, "IP " .. ngx.ctx.bw.remote_addr .. " is not banned") logger:log(ngx.INFO, "IP " .. ngx.ctx.bw.remote_addr .. " is not banned")
end end
-- Get plugins -- Get plugins order
local plugins, err = datastore:get("plugins") local order, err = datastore:get("plugins_order")
if not plugins then if not order then
logger:log(ngx.ERR, "can't get plugins from datastore : " .. err) logger:log(ngx.ERR, "can't get plugins order from datastore : " .. err)
return false local ok, err = lock:unlock()
if not ok then
logger:log(ngx.ERR, "lock:unlock() failed : " .. err)
end
return
end end
plugins = cjson.decode(plugins) order = cjson.decode(order)
-- Call preread() methods -- Call preread() methods
logger:log(ngx.INFO, "calling preread() methods of plugins ...") logger:log(ngx.INFO, "calling preread() methods of plugins ...")
local status = nil local status = nil
for i, plugin in ipairs(plugins) do for i, plugin_id in ipairs(order.preread) do
-- Require call -- Require call
local plugin_lua, err = helpers.require_plugin(plugin.id) local plugin_lua, err = helpers.require_plugin(plugin_id)
if plugin_lua == false then if plugin_lua == false then
logger:log(ngx.ERR, err) logger:log(ngx.ERR, err)
elseif plugin_lua == nil then elseif plugin_lua == nil then
@ -66,23 +70,23 @@ for i, plugin in ipairs(plugins) do
if not ok then if not ok then
logger:log(ngx.ERR, ret) logger:log(ngx.ERR, ret)
elseif not ret.ret then elseif not ret.ret then
logger:log(ngx.ERR, plugin.id .. ":preread() call failed : " .. ret.msg) logger:log(ngx.ERR, plugin_id .. ":preread() call failed : " .. ret.msg)
else else
logger:log(ngx.INFO, plugin.id .. ":preread() call successful : " .. ret.msg) logger:log(ngx.INFO, plugin_id .. ":preread() call successful : " .. ret.msg)
end end
if ret.status then if ret.status then
if ret.status == utils.get_deny_status() then if ret.status == utils.get_deny_status() then
ngx.ctx.reason = plugin.id ngx.ctx.reason = plugin_id
logger:log(ngx.WARN, "denied access from " .. plugin.id .. " : " .. ret.msg) logger:log(ngx.WARN, "denied access from " .. plugin_id .. " : " .. ret.msg)
else else
logger:log(ngx.NOTICE, plugin.id .. " returned status " .. tostring(ret.status) .. " : " .. ret.msg) logger:log(ngx.NOTICE, plugin_id .. " returned status " .. tostring(ret.status) .. " : " .. ret.msg)
end end
status = ret.status status = ret.status
break break
end end
end end
else else
logger:log(ngx.INFO, "skipped execution of " .. plugin.id .. " because method preread() is not defined") logger:log(ngx.INFO, "skipped execution of " .. plugin_id .. " because method preread() is not defined")
end end
end end
end end

View file

@ -1,6 +1,5 @@
{ {
"id": "antibot", "id": "antibot",
"order": 9,
"name": "Antibot", "name": "Antibot",
"description": "Bot detection by using a challenge.", "description": "Bot detection by using a challenge.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "authbasic", "id": "authbasic",
"order": 999,
"name": "Auth basic", "name": "Auth basic",
"description": "Enforce login before accessing a resource or the whole site using HTTP basic auth method.", "description": "Enforce login before accessing a resource or the whole site using HTTP basic auth method.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "badbehavior", "id": "badbehavior",
"order": 999,
"name": "Bad behavior", "name": "Bad behavior",
"description": "Ban IP generating too much 'bad' HTTP status code in a period of time.", "description": "Ban IP generating too much 'bad' HTTP status code in a period of time.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "blacklist", "id": "blacklist",
"order": 2,
"name": "Blacklist", "name": "Blacklist",
"description": "Deny access based on internal and external IP/network/rDNS/ASN blacklists.", "description": "Deny access based on internal and external IP/network/rDNS/ASN blacklists.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "brotli", "id": "brotli",
"order": 999,
"name": "Brotli", "name": "Brotli",
"description": "Compress HTTP requests with the brotli algorithm.", "description": "Compress HTTP requests with the brotli algorithm.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "bunkernet", "id": "bunkernet",
"order": 7,
"name": "BunkerNet", "name": "BunkerNet",
"description": "Share threat data with other BunkerWeb instances via BunkerNet.", "description": "Share threat data with other BunkerWeb instances via BunkerNet.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "clientcache", "id": "clientcache",
"order": 999,
"name": "Client cache", "name": "Client cache",
"description": "Manage caching for clients.", "description": "Manage caching for clients.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "cors", "id": "cors",
"order": 999,
"name": "CORS", "name": "CORS",
"description": "Cross-Origin Resource Sharing.", "description": "Cross-Origin Resource Sharing.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "country", "id": "country",
"order": 4,
"name": "Country", "name": "Country",
"description": "Deny access based on the country of the client IP.", "description": "Deny access based on the country of the client IP.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "customcert", "id": "customcert",
"order": 999,
"name": "Custom HTTPS certificate", "name": "Custom HTTPS certificate",
"description": "Choose custom certificate for HTTPS.", "description": "Choose custom certificate for HTTPS.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "db", "id": "db",
"order": 999,
"name": "DB", "name": "DB",
"description": "Integrate easily the Database.", "description": "Integrate easily the Database.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "dnsbl", "id": "dnsbl",
"order": 5,
"name": "DNSBL", "name": "DNSBL",
"description": "Deny access based on external DNSBL servers.", "description": "Deny access based on external DNSBL servers.",
"version": "1.0", "version": "1.0",

View file

@ -5,9 +5,9 @@
error_page {{ code }} {{ page }}; error_page {{ code }} {{ page }};
location = {{ page }} { location = {{ page }} {
root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %}; root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
modsecurity off; modsecurity off;
internal; internal;
auth_basic off; auth_basic off;
} }
{% endfor %} {% endfor %}

View file

@ -1,6 +1,5 @@
{ {
"id": "errors", "id": "errors",
"order": 999,
"name": "Errors", "name": "Errors",
"description": "Manage default error pages", "description": "Manage default error pages",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "greylist", "id": "greylist",
"order": 3,
"name": "Greylist", "name": "Greylist",
"description": "Allow access while keeping security features based on internal and external IP/network/rDNS/ASN greylists.", "description": "Allow access while keeping security features based on internal and external IP/network/rDNS/ASN greylists.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "gzip", "id": "gzip",
"order": 999,
"name": "Gzip", "name": "Gzip",
"description": "Compress HTTP requests with the gzip algorithm.", "description": "Compress HTTP requests with the gzip algorithm.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "headers", "id": "headers",
"order": 999,
"name": "Headers", "name": "Headers",
"description": "Manage HTTP headers sent to clients.", "description": "Manage HTTP headers sent to clients.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "inject", "id": "inject",
"order": 999,
"name": "HTML injection", "name": "HTML injection",
"description": "Inject custom HTML code before the </body> tag.", "description": "Inject custom HTML code before the </body> tag.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "jobs", "id": "jobs",
"order": 999,
"name": "Jobs", "name": "Jobs",
"description": "Fake core plugin for internal jobs.", "description": "Fake core plugin for internal jobs.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "letsencrypt", "id": "letsencrypt",
"order": 999,
"name": "Let's Encrypt", "name": "Let's Encrypt",
"description": "Automatic creation, renewal and configuration of Let's Encrypt certificates.", "description": "Automatic creation, renewal and configuration of Let's Encrypt certificates.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "limit", "id": "limit",
"order": 8,
"name": "Limit", "name": "Limit",
"description": "Limit maximum number of requests and connections.", "description": "Limit maximum number of requests and connections.",
"version": "1.0", "version": "1.0",

View file

@ -9,24 +9,19 @@ function misc:initialize()
plugin.initialize(self, "misc") plugin.initialize(self, "misc")
end end
function misc:set() function misc:access()
-- Check if method is allowed -- Check if method is valid
local method = ngx.ctx.bw.request_method local method = ngx.ctx.bw.request_method
if not method or not utils.regex_match(method, "^[A-Z]+$") then
return self:ret(true, "method is not valid", ngx.HTTP_BAD_REQUEST)
end
-- Check if method is allowed
for allowed_method in self.variables["ALLOWED_METHODS"]:gmatch("[^|]+") do for allowed_method in self.variables["ALLOWED_METHODS"]:gmatch("[^|]+") do
if method == allowed_method then if method == allowed_method then
return self:ret(true, "method " .. method .. " is allowed") return self:ret(true, "method " .. method .. " is allowed")
end end
end end
ngx.ctx.bw.plugin_misc_method_not_allowed = true return self:ret(true, "method " .. method .. " not is allowed", ngx.HTTP_NOT_ALLOWED)
return self:ret(true, "method " .. method .. " not is allowed")
end
function misc:access()
-- Check if method is allowed
if ngx.ctx.bw.plugin_misc_method_not_allowed then
return self:ret(true, "method " .. ngx.ctx.bw.request_method .. " is not allowed", ngx.HTTP_NOT_ALLOWED)
end
return self:ret(true, "method " .. ngx.ctx.bw.request_method .. " is allowed")
end end
return misc return misc

View file

@ -1,6 +1,5 @@
{ {
"id": "misc", "id": "misc",
"order": 0,
"name": "Miscellaneous", "name": "Miscellaneous",
"description": "Miscellaneous settings.", "description": "Miscellaneous settings.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "modsecurity", "id": "modsecurity",
"order": 999,
"name": "ModSecurity", "name": "ModSecurity",
"description": "Management of the ModSecurity WAF.", "description": "Management of the ModSecurity WAF.",
"version": "1.0", "version": "1.0",

View file

@ -0,0 +1,55 @@
{
"init": [
"sessions",
"whitelist",
"blacklist",
"greylist",
"bunkernet",
"limit"
],
"init_worker": [
"redis",
"bunkernet",
"dnsbl"
],
"set": [
"whitelist"
],
"access": [
"whitelist",
"letsencrypt",
"blacklist",
"greylist",
"country",
"dnsbl",
"bunkernet",
"reversescan",
"limit",
"misc",
"cors",
"antibot"
],
"headers": [
"cors"
],
"log": [
"badbheavior",
"bunkernet"
],
"preread": [
"whitelist",
"blacklist",
"greylist",
"country",
"dnsbl",
"reversescan"
],
"log_stream": [
"badbehavior",
"bunkernet"
],
"log_default": [
"badbheavior",
"bunkernet"
]
}

View file

@ -1,6 +1,5 @@
{ {
"id": "php", "id": "php",
"order": 999,
"name": "PHP", "name": "PHP",
"description": "Manage local or remote PHP-FPM.", "description": "Manage local or remote PHP-FPM.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "realip", "id": "realip",
"order": 999,
"name": "Real IP", "name": "Real IP",
"description": "Get real IP of clients when BunkerWeb is behind a reverse proxy / load balancer.", "description": "Get real IP of clients when BunkerWeb is behind a reverse proxy / load balancer.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "redirect", "id": "redirect",
"order": 999,
"name": "Redirect", "name": "Redirect",
"description": "Manage HTTP redirects.", "description": "Manage HTTP redirects.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "redis", "id": "redis",
"order": 999,
"name": "Redis", "name": "Redis",
"description": "Redis server configuration when using BunkerWeb in cluster mode.", "description": "Redis server configuration when using BunkerWeb in cluster mode.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "reverseproxy", "id": "reverseproxy",
"order": 999,
"name": "Reverse proxy", "name": "Reverse proxy",
"description": "Manage reverse proxy configurations.", "description": "Manage reverse proxy configurations.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "reversescan", "id": "reversescan",
"order": 6,
"name": "Reverse scan", "name": "Reverse scan",
"description": "Scan clients ports to detect proxies or servers.", "description": "Scan clients ports to detect proxies or servers.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "selfsigned", "id": "selfsigned",
"order": 999,
"name": "Self-signed certificate", "name": "Self-signed certificate",
"description": "Generate self-signed certificate.", "description": "Generate self-signed certificate.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "sessions", "id": "sessions",
"order": 999,
"name": "Sessions", "name": "Sessions",
"description": "Management of session used by other plugins.", "description": "Management of session used by other plugins.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "ui", "id": "ui",
"order": 999,
"name": "UI", "name": "UI",
"description": "Integrate easily the BunkerWeb UI.", "description": "Integrate easily the BunkerWeb UI.",
"version": "1.0", "version": "1.0",

View file

@ -1,6 +1,5 @@
{ {
"id": "whitelist", "id": "whitelist",
"order": 1,
"name": "Whitelist", "name": "Whitelist",
"description": "Allow access based on internal and external IP/network/rDNS/ASN whitelists.", "description": "Allow access based on internal and external IP/network/rDNS/ASN whitelists.",
"version": "1.0", "version": "1.0",

View file

@ -281,7 +281,6 @@ class Database:
settings = plugin settings = plugin
plugin = { plugin = {
"id": "general", "id": "general",
"order": 999,
"name": "General", "name": "General",
"description": "The general settings for the server", "description": "The general settings for the server",
"version": "0.1", "version": "0.1",
@ -963,8 +962,8 @@ class Database:
db_plugin = ( db_plugin = (
session.query(Plugins) session.query(Plugins)
.with_entities( .with_entities(
Plugins.order,
Plugins.name, Plugins.name,
Plugins.stream,
Plugins.description, Plugins.description,
Plugins.version, Plugins.version,
Plugins.method, Plugins.method,
@ -985,8 +984,8 @@ class Database:
updates = {} updates = {}
if plugin["order"] != db_plugin.order: if plugin["stream"] != db_plugin.stream:
updates[Plugins.order] = plugin["order"] updates[Plugins.stream] = plugin["stream"]
if plugin["name"] != db_plugin.name: if plugin["name"] != db_plugin.name:
updates[Plugins.name] = plugin["name"] updates[Plugins.name] = plugin["name"]
@ -1380,7 +1379,7 @@ class Database:
session.query(Plugins) session.query(Plugins)
.with_entities( .with_entities(
Plugins.id, Plugins.id,
Plugins.order, Plugins.stream,
Plugins.name, Plugins.name,
Plugins.description, Plugins.description,
Plugins.version, Plugins.version,
@ -1389,20 +1388,18 @@ class Database:
Plugins.data, Plugins.data,
Plugins.checksum, Plugins.checksum,
) )
.order_by(Plugins.order)
.all() .all()
if with_data if with_data
else session.query(Plugins) else session.query(Plugins)
.with_entities( .with_entities(
Plugins.id, Plugins.id,
Plugins.order, Plugins.stream,
Plugins.name, Plugins.name,
Plugins.description, Plugins.description,
Plugins.version, Plugins.version,
Plugins.external, Plugins.external,
Plugins.method, Plugins.method,
) )
.order_by(Plugins.order)
.all() .all()
): ):
if external and not plugin.external: if external and not plugin.external:
@ -1416,7 +1413,7 @@ class Database:
) )
data = { data = {
"id": plugin.id, "id": plugin.id,
"order": plugin.order, "stream": plugin.stream,
"name": plugin.name, "name": plugin.name,
"description": plugin.description, "description": plugin.description,
"version": plugin.version, "version": plugin.version,

View file

@ -102,7 +102,6 @@ class Configurator:
return loads(Path(path).read_text()) return loads(Path(path).read_text())
def __load_plugins(self, path: str, _type: str = "core") -> List[Dict[str, Any]]: def __load_plugins(self, path: str, _type: str = "core") -> List[Dict[str, Any]]:
orders = {}
plugins = [] plugins = []
files = glob(f"{path}/*/plugin.json") files = glob(f"{path}/*/plugin.json")
for file in files: for file in files:
@ -116,16 +115,6 @@ class Configurator:
) )
continue continue
if data["order"] not in orders:
orders[data["order"]] = [data["id"]]
else:
if len(orders[data["order"]]) > 1 and data["order"] != 999:
self.__logger.warning(
f"Plugin {data['id']} have the same order than {', '.join(orders[data['order']])}. Therefor, the execution order will be random."
)
orders[data["order"]].append(data["id"])
if _type == "external": if _type == "external":
plugin_content = BytesIO() plugin_content = BytesIO()
with tar_open(fileobj=plugin_content, mode="w:gz") as tar: with tar_open(fileobj=plugin_content, mode="w:gz") as tar:
@ -275,7 +264,6 @@ class Configurator:
key in plugin.keys() key in plugin.keys()
for key in [ for key in [
"id", "id",
"order",
"name", "name",
"description", "description",
"version", "version",
@ -285,7 +273,7 @@ class Configurator:
): ):
return ( return (
False, False,
f"Missing mandatory keys for plugin {plugin.get('id', 'unknown')} (id, order, name, description, version, stream, settings)", f"Missing mandatory keys for plugin {plugin.get('id', 'unknown')} (id, name, description, version, stream, settings)",
) )
if not self.__plugin_id_rx.match(plugin["id"]): if not self.__plugin_id_rx.match(plugin["id"]):
@ -293,8 +281,6 @@ class Configurator:
False, False,
f"Invalid id for plugin {plugin['id']} (Can only contain numbers, letters, underscores and hyphens (min 1 characters and max 64))", f"Invalid id for plugin {plugin['id']} (Can only contain numbers, letters, underscores and hyphens (min 1 characters and max 64))",
) )
elif not isinstance(plugin["order"], int):
return False, f"Invalid order for plugin {plugin['id']}, must be a number"
elif len(plugin["name"]) > 128: elif len(plugin["name"]) > 128:
return ( return (
False, False,

View file

@ -187,23 +187,6 @@ if __name__ == "__main__":
) )
sys_exit(1) sys_exit(1)
# Check core plugins orders
logger.info("Checking core plugins orders ...")
core_plugins = {}
files = glob(f"{args.core}/*/plugin.json")
for file in files:
try:
core_plugin = loads(Path(file).read_text())
if core_plugin["order"] not in core_plugins:
core_plugins[core_plugin["order"]] = []
core_plugins[core_plugin["order"]].append(core_plugin)
except:
logger.error(
f"Exception while loading JSON from {file} : {format_exc()}",
)
if args.variables: if args.variables:
logger.info(f"Variables : {args.variables}") logger.info(f"Variables : {args.variables}")

View file

@ -159,7 +159,6 @@ login_manager.login_view = "login"
user = User(vars["ADMIN_USERNAME"], vars["ADMIN_PASSWORD"]) user = User(vars["ADMIN_USERNAME"], vars["ADMIN_PASSWORD"])
PLUGIN_KEYS = [ PLUGIN_KEYS = [
"id", "id",
"order",
"name", "name",
"description", "description",
"version", "version",

View file

@ -144,7 +144,6 @@ class Config:
0, 0,
{ {
"id": "general", "id": "general",
"order": 999,
"name": "General", "name": "General",
"description": "The general settings for the server", "description": "The general settings for the server",
"version": "0.1", "version": "0.1",