mirror of
https://github.com/bunkerity/bunkerized-nginx
synced 2023-12-13 21:30:18 +01:00
176 lines
5.2 KiB
Lua
176 lines
5.2 KiB
Lua
local datastore = require "datastore"
|
|
local utils = require "utils"
|
|
local cjson = require "cjson"
|
|
local plugins = require "plugins"
|
|
local upload = require "resty.upload"
|
|
local logger = require "logger"
|
|
|
|
local api = {global = {GET = {}, POST = {}, PUT = {}, DELETE = {}}}
|
|
|
|
api.response = function(self, http_status, api_status, msg)
|
|
local resp = {}
|
|
resp["status"] = api_status
|
|
resp["msg"] = msg
|
|
return http_status, resp
|
|
end
|
|
|
|
api.global.GET["^/ping$"] = function(api)
|
|
return api:response(ngx.HTTP_OK, "success", "pong")
|
|
end
|
|
|
|
api.global.POST["^/jobs$"] = function(api)
|
|
-- ngx.req.read_body()
|
|
-- local data = ngx.req.get_body_data()
|
|
-- if not data then
|
|
-- local data_file = ngx.req.get_body_file()
|
|
-- if data_file then
|
|
-- local file = io.open(data_file)
|
|
-- data = file:read("*a")
|
|
-- file:close()
|
|
-- end
|
|
-- end
|
|
-- local ok, env = pcall(cjson.decode, data)
|
|
-- if not ok then
|
|
-- return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "can't decode JSON : " .. env)
|
|
-- end
|
|
-- local file = io.open("/opt/bunkerweb/tmp/jobs.env", "w+")
|
|
-- for k, v in pairs(env) do
|
|
-- file:write(k .. "=" .. v .. "\n")
|
|
-- end
|
|
-- file:close()
|
|
local status = os.execute("/opt/bunkerweb/helpers/scheduler-restart.sh")
|
|
if status == 0 then
|
|
return api:response(ngx.HTTP_OK, "success", "jobs executed and scheduler started")
|
|
end
|
|
return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "exit status = " .. tostring(status))
|
|
end
|
|
|
|
api.global.POST["^/reload$"] = function(api)
|
|
local status = os.execute("/usr/sbin/nginx -s reload")
|
|
if status == 0 then
|
|
return api:response(ngx.HTTP_OK, "success", "reload successful")
|
|
end
|
|
return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "exit status = " .. tostring(status))
|
|
end
|
|
|
|
api.global.POST["^/stop$"] = function(api)
|
|
local status = os.execute("/usr/sbin/nginx -s quit")
|
|
if status == 0 then
|
|
return api:response(ngx.HTTP_OK, "success", "stop successful")
|
|
end
|
|
return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "exit status = " .. tostring(status))
|
|
end
|
|
|
|
api.global.POST["^/confs$"] = function(api)
|
|
local tmp = "/opt/bunkerweb/tmp/api_" .. ngx.var.uri:sub(2) .. ".tar.gz"
|
|
local destination = "/opt/bunkerweb/" .. ngx.var.uri:sub(2)
|
|
if ngx.var.uri == "/confs" then
|
|
destination = "/etc/nginx"
|
|
elseif ngx.var.uri == "/data" then
|
|
destination = "/data"
|
|
end
|
|
local form, err = upload:new(4096)
|
|
if not form then
|
|
return api:response(ngx.HTTP_BAD_REQUEST, "error", err)
|
|
end
|
|
form:set_timeout(1000)
|
|
local file = io.open(tmp, "w+")
|
|
while true do
|
|
local typ, res, err = form:read()
|
|
if not typ then
|
|
file:close()
|
|
return api:response(ngx.HTTP_BAD_REQUEST, "error", err)
|
|
end
|
|
if typ == "eof" then
|
|
break
|
|
end
|
|
if typ == "body" then
|
|
file:write(res)
|
|
end
|
|
end
|
|
file:flush()
|
|
file:close()
|
|
local status = os.execute("rm -rf " .. destination .. "/*")
|
|
if status ~= 0 then
|
|
return api:response(ngx.HTTP_BAD_REQUEST, "error", "can't remove old files")
|
|
end
|
|
status = os.execute("tar xzf " .. tmp .. " -C " .. destination)
|
|
if status ~= 0 then
|
|
return api:response(ngx.HTTP_BAD_REQUEST, "error", "can't extract archive")
|
|
end
|
|
return api:response(ngx.HTTP_OK, "success", "saved data at " .. destination)
|
|
end
|
|
|
|
api.global.POST["^/data$"] = api.global.POST["^/confs$"]
|
|
|
|
api.global.POST["^/unban$"] = function(api)
|
|
ngx.req.read_body()
|
|
local data = ngx.req.get_body_data()
|
|
if not data then
|
|
local data_file = ngx.req.get_body_file()
|
|
if data_file then
|
|
local file = io.open(data_file)
|
|
data = file:read("*a")
|
|
file:close()
|
|
end
|
|
end
|
|
local ok, ip = pcall(cjson.decode, data)
|
|
if not ok then
|
|
return api:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "can't decode JSON : " .. env)
|
|
end
|
|
datastore:delete("bans_ip_" .. ip["ip"])
|
|
return api:response(ngx.HTTP_OK, "success", "ip " .. ip["ip"] .. " unbanned")
|
|
end
|
|
|
|
api.is_allowed_ip = function(self)
|
|
local data, err = datastore:get("api_whitelist_ip")
|
|
if not data then
|
|
return false, "can't access api_allowed_ips in datastore"
|
|
end
|
|
if utils.is_ip_in_networks(ngx.var.remote_addr, cjson.decode(data).data) then
|
|
return true, "ok"
|
|
end
|
|
return false, "IP is not in API_WHITELIST_IP"
|
|
end
|
|
|
|
api.do_api_call = function(self)
|
|
if self.global[ngx.var.request_method] ~= nil then
|
|
for uri, api_fun in pairs(self.global[ngx.var.request_method]) do
|
|
if string.match(ngx.var.uri, uri) then
|
|
local status, resp = api_fun(self)
|
|
local ret = true
|
|
if status ~= ngx.HTTP_OK then
|
|
ret = false
|
|
end
|
|
return ret, resp["msg"], status, cjson.encode(resp)
|
|
end
|
|
end
|
|
end
|
|
local list, err = plugins:list()
|
|
if not list then
|
|
local status, resp = self:response(ngx.HTTP_INTERNAL_SERVER_ERROR, "error", "can't list loaded plugins : " .. err)
|
|
return false, resp["msg"], ngx.HTTP_INTERNAL_SERVER_ERROR, resp
|
|
end
|
|
for i, plugin in ipairs(list) do
|
|
if pcall(require, plugin.id .. "/" .. plugin.id) then
|
|
local plugin_lua = require(plugin.id .. "/" .. plugin.id)
|
|
if plugin_lua.api ~= nil then
|
|
local matched, status, resp = plugin_lua.api()
|
|
if matched then
|
|
local ret = true
|
|
if status ~= ngx.HTTP_OK then
|
|
ret = false
|
|
end
|
|
return ret, resp["msg"], status, cjson.encode(resp)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local resp = {}
|
|
resp["status"] = "error"
|
|
resp["msg"] = "not found"
|
|
return false, "error", ngx.HTTP_NOT_FOUND, cjson.encode(resp)
|
|
end
|
|
|
|
return api
|