mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
continue work on ssl/tls fallback and management
This commit is contained in:
parent
8efcd2b8a1
commit
62449f84c0
9 changed files with 373 additions and 315 deletions
|
|
@ -13,7 +13,7 @@ function plugin:initialize(id, ctx)
|
|||
local current_phase = ngx.get_phase()
|
||||
for _, check_phase in ipairs {
|
||||
"set",
|
||||
"ssl_certificate"
|
||||
"ssl_certificate",
|
||||
"access",
|
||||
"content",
|
||||
"header_filter",
|
||||
|
|
|
|||
|
|
@ -680,6 +680,7 @@ utils.get_phases = function()
|
|||
"init_worker",
|
||||
"set",
|
||||
"access",
|
||||
"ssl_certificate",
|
||||
"header",
|
||||
"log",
|
||||
"preread",
|
||||
|
|
@ -692,6 +693,7 @@ utils.is_cosocket_available = function()
|
|||
local phases = {
|
||||
"timer",
|
||||
"access",
|
||||
"ssl_certificate",
|
||||
"preread",
|
||||
}
|
||||
local current_phase = ngx.get_phase()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ server {
|
|||
|
||||
# include LUA files
|
||||
include {{ NGINX_PREFIX }}set-lua.conf;
|
||||
include {{ NGINX_PREFIX }}ssl-certificate-lua.conf;
|
||||
include {{ NGINX_PREFIX }}access-lua.conf;
|
||||
include {{ NGINX_PREFIX }}header-lua.conf;
|
||||
include {{ NGINX_PREFIX }}log-lua.conf;
|
||||
|
||||
# include config files
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ ssl_certificate_by_lua_block {
|
|||
local cdatastore = require "bunkerweb.datastore"
|
||||
local cclusterstore = require "bunkerweb.clusterstore"
|
||||
local cjson = require "cjson"
|
||||
local ssl = require "ngx.ssl"
|
||||
|
||||
-- Don't process internal requests
|
||||
local logger = clogger:new("SSL-CERTIFICATE")
|
||||
|
|
@ -39,8 +40,6 @@ ssl_certificate_by_lua_block {
|
|||
|
||||
-- Call ssl_certificate() methods
|
||||
logger:log(ngx.INFO, "calling ssl_certificate() methods of plugins ...")
|
||||
local status = nil
|
||||
local redirect = nil
|
||||
for i, plugin_id in ipairs(order.ssl_certificate) do
|
||||
-- Require call
|
||||
local plugin_lua, err = helpers.require_plugin(plugin_id)
|
||||
|
|
@ -63,32 +62,33 @@ ssl_certificate_by_lua_block {
|
|||
logger:log(ngx.ERR, plugin_id .. ":ssl_certificate() call failed : " .. ret.msg)
|
||||
else
|
||||
logger:log(ngx.INFO, plugin_id .. ":ssl_certificate() call successful : " .. ret.msg)
|
||||
if ret.cert then
|
||||
|
||||
if ret.status then
|
||||
logger:log(ngx.INFO, plugin_id .. " is setting certificate/key : " .. ret.msg)
|
||||
local ok, err = ssl.set_cert(ret.status[1])
|
||||
if not ok then
|
||||
logger:log(ngx.ERR, "error while setting certificate : " .. err)
|
||||
else
|
||||
local ok, err = ssl.set_priv_key(ret.status[2])
|
||||
if not ok then
|
||||
logger:log(ngx.ERR, "error while setting private key : " .. err)
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
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 ssl_certificate() is not defined")
|
||||
end
|
||||
end
|
||||
end
|
||||
logger:log(ngx.INFO, "called access() methods of plugins")
|
||||
logger:log(ngx.INFO, "called ssl_certificate() methods of plugins")
|
||||
|
||||
-- Save ctx
|
||||
ngx.ctx = ctx
|
||||
|
||||
logger:log(ngx.INFO, "access phase ended")
|
||||
|
||||
-- Return status if needed
|
||||
if status then
|
||||
return ngx.exit(status)
|
||||
end
|
||||
|
||||
-- Redirect if needed
|
||||
if redirect then
|
||||
return ngx.redirect(redirect)
|
||||
end
|
||||
logger:log(ngx.INFO, "ssl_certificate phase ended")
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
132
src/common/core/customcert/customcert.lua
Normal file
132
src/common/core/customcert/customcert.lua
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
local class = require "middleclass"
|
||||
local plugin = require "bunkerweb.plugin"
|
||||
local utils = require "bunkerweb.utils"
|
||||
local ssl = require "ngx.ssl"
|
||||
|
||||
local customcert = class("customcert", plugin)
|
||||
|
||||
function customcert:initialize(ctx)
|
||||
-- Call parent initialize
|
||||
plugin.initialize(self, "customcert", ctx)
|
||||
end
|
||||
|
||||
function customcert:init()
|
||||
local ok, err = true, "success"
|
||||
if utils.has_variable("USE_CUSTOM_SSL", "yes") then
|
||||
local multisite, err = utils.get_variable("MULTISITE")
|
||||
if not multisite then
|
||||
return self:ret(false, "can't get MULTISITE variable : " .. err)
|
||||
end
|
||||
if multisite == "yes" then
|
||||
local vars, err = utils.get_multiple_variables({"USE_CUSTOM_SSL"})
|
||||
if not vars then
|
||||
return self:ret(false, "can't get USE_CUSTOM_SSL variables : " .. err)
|
||||
end
|
||||
if vars["global"]["USE_CUSTOM_SSL"] == "yes" then
|
||||
local check, data = self:read_files()
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
for server_name, multisite_vars in pairs(vars) do
|
||||
if multisite_vars["USE_CUSTOM_SSL"] == "yes" then
|
||||
local check, data = self:read_files(server_name)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data, server_name)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local check, data = self:read_files()
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
err = "custom ssl is not used"
|
||||
end
|
||||
return self:ret(ok, err)
|
||||
end
|
||||
|
||||
function customcert:ssl_certificate()
|
||||
if self.variables["USE_CUSTOM_SSL"] == "yes" then
|
||||
local global_data, err = self.datastore:get("plugin_customcert_global", true)
|
||||
if not global_data and err ~= "not found" then
|
||||
return self:ret(false, "error while getting plugin_customcert_global from datastore : " .. err)
|
||||
end
|
||||
local site_data, err = self.datastore:get("plugin_customcert_" .. self.ctx.bw.server_name, true)
|
||||
if not site_data and err ~= "not found" then
|
||||
return self:ret(false, "error while getting plugin_customcert_" .. self.ctx.bw.server_name .. " from datastore : " .. err)
|
||||
end
|
||||
if not global_data and not site_data then
|
||||
return self:ret(false, "both global and site cert are not present in datastore")
|
||||
end
|
||||
return self:ret(true, "certificate/key data found", site_data or global_data)
|
||||
end
|
||||
return self:ret(true, "custom certificate is not used")
|
||||
end
|
||||
|
||||
function customcert:read_files(server_name)
|
||||
local files = {
|
||||
"/var/cache/bunkerweb/customcert/" .. (server_name or "") .. "/cert.pem",
|
||||
"/var/cache/bunkerweb/customcert/" .. (server_name or "") .. "/key.pem"
|
||||
}
|
||||
local data = {}
|
||||
for i, file in ipairs(files) do
|
||||
local f, err = io.open(file, "r")
|
||||
if not f then
|
||||
return false, file .. " = " .. err
|
||||
end
|
||||
table.insert(data, f:read("*a"))
|
||||
f:close()
|
||||
end
|
||||
return true, data
|
||||
end
|
||||
|
||||
function customcert:load_data(data, server_name)
|
||||
-- Load certificate
|
||||
local cert_chain, err = ssl.parse_pem_cert(data[1])
|
||||
if not cert_chain then
|
||||
return false, "error while parsing pem cert : " .. err
|
||||
end
|
||||
-- Load key
|
||||
local priv_key, err = ssl.parse_priv_key(data[2])
|
||||
if not priv_key then
|
||||
return false, "error while parsing pem priv key : " .. err
|
||||
end
|
||||
local cache_key = "plugin_customcert_" .. (server_name or "global")
|
||||
local ok, err = self.datastore:set(cache_key, {cert_chain, priv_key}, nil, true)
|
||||
if not ok then
|
||||
return false, "error while setting data into datastore : " .. err
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return customcert
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
local class = require "middleclass"
|
||||
local plugin = require "bunkerweb.plugin"
|
||||
local utils = require "bunkerweb.utils"
|
||||
|
||||
local customcert = class("customcert", plugin)
|
||||
|
||||
function customcert:initialize(ctx)
|
||||
-- Call parent initialize
|
||||
plugin.initialize(self, "customcert", ctx)
|
||||
end
|
||||
|
||||
function customcert:init_worker()
|
||||
if utils.has_variable("USE_CUSTOM_SSL", "yes") then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function customcert:ssl_certificate()
|
||||
if self.variables["USE_CUSTOM_SSL"] == "yes" then
|
||||
|
||||
return true, ""
|
||||
end
|
||||
return true, "customcert is not used"
|
||||
end
|
||||
|
||||
return customcert
|
||||
|
||||
function bunkernet:initialize(ctx)
|
||||
-- Call parent initialize
|
||||
plugin.initialize(self, "bunkernet", ctx)
|
||||
-- Get BunkerNet ID and save info
|
||||
if ngx.get_phase() ~= "init" and self:is_needed() then
|
||||
local id, err = self.datastore:get("plugin_bunkernet_id", true)
|
||||
if id then
|
||||
self.bunkernet_id = id
|
||||
self.version = (self.ctx and self.ctx.bw.version) or utils.get_version()
|
||||
self.integration = (self.ctx and self.ctx.bw.integration) or utils.get_integration()
|
||||
else
|
||||
self.logger:log(ngx.ERR, "can't get BunkerNet ID from datastore : " .. err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function bunkernet:is_needed()
|
||||
-- Loading case
|
||||
if self.is_loading then
|
||||
return false
|
||||
end
|
||||
-- Request phases (no default)
|
||||
if self.is_request and (self.ctx.bw.server_name ~= "_") then
|
||||
return self.variables["USE_BUNKERNET"] == "yes"
|
||||
end
|
||||
-- Other cases : at least one service uses it
|
||||
local is_needed, err = utils.has_variable("USE_BUNKERNET", "yes")
|
||||
if is_needed == nil then
|
||||
self.logger:log(ngx.ERR, "can't check USE_BUNKERNET variable : " .. err)
|
||||
end
|
||||
return is_needed
|
||||
end
|
||||
|
||||
function bunkernet:init_worker()
|
||||
-- Check if needed
|
||||
if not self:is_needed() then
|
||||
return self:ret(true, "no service uses BunkerNet, skipping init_worker")
|
||||
end
|
||||
-- Check id
|
||||
if not self.bunkernet_id then
|
||||
return self:ret(false, "missing instance ID")
|
||||
end
|
||||
-- Send ping request
|
||||
local ok, err, status, _ = self:ping()
|
||||
if not ok then
|
||||
return self:ret(false, "error while sending request to API : " .. err)
|
||||
end
|
||||
if status ~= 200 then
|
||||
return self:ret(
|
||||
false,
|
||||
"received status " .. tostring(status) .. " from API using instance ID " .. self.bunkernet_id
|
||||
)
|
||||
end
|
||||
self.logger:log(ngx.NOTICE, "connectivity with API using instance ID " .. self.bunkernet_id .. " is successful")
|
||||
return self:ret(true, "connectivity with API using instance ID " .. self.bunkernet_id .. " is successful")
|
||||
end
|
||||
|
||||
function bunkernet:init()
|
||||
-- Check if needed
|
||||
if not self:is_needed() then
|
||||
return self:ret(true, "no service uses BunkerNet, skipping init")
|
||||
end
|
||||
-- Check if instance ID is present
|
||||
local f, err = io.open("/var/cache/bunkerweb/bunkernet/instance.id", "r")
|
||||
if not f then
|
||||
return self:ret(false, "can't read instance id : " .. err)
|
||||
end
|
||||
-- Retrieve instance ID
|
||||
local id = f:read("*all"):gsub("[\r\n]", "")
|
||||
f:close()
|
||||
-- Store ID in datastore
|
||||
local ok, err = self.datastore:set("plugin_bunkernet_id", id, nil, true)
|
||||
if not ok then
|
||||
return self:ret(false, "can't save instance ID to the datastore : " .. err)
|
||||
end
|
||||
-- Load databases
|
||||
local ret = true
|
||||
local i = 0
|
||||
local db = {
|
||||
ip = {},
|
||||
}
|
||||
local f, err = io.open("/var/cache/bunkerweb/bunkernet/ip.list", "r")
|
||||
if not f then
|
||||
ret = false
|
||||
else
|
||||
for line in f:lines() do
|
||||
if (utils.is_ipv4(line) or utils.is_ipv6(line)) and utils.ip_is_global(line) then
|
||||
table.insert(db.ip, line)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if not ret then
|
||||
return self:ret(false, "error while reading database : " .. err)
|
||||
end
|
||||
f:close()
|
||||
local ok, err = self.datastore:set("plugin_bunkernet_db", db, nil, true)
|
||||
if not ok then
|
||||
return self:ret(false, "can't store bunkernet database into datastore : " .. err)
|
||||
end
|
||||
return self:ret(true, "successfully loaded " .. tostring(i) .. " bad IPs using instance ID " .. id)
|
||||
end
|
||||
|
||||
function bunkernet:access()
|
||||
-- Check if needed
|
||||
if not self:is_needed() then
|
||||
return self:ret(true, "service doesn't use BunkerNet, skipping access")
|
||||
end
|
||||
-- Check id
|
||||
if not self.bunkernet_id then
|
||||
return self:ret(false, "missing instance ID")
|
||||
end
|
||||
-- Check if IP is global
|
||||
if not self.ctx.bw.ip_is_global then
|
||||
return self:ret(true, "IP is not global")
|
||||
end
|
||||
-- Check if whitelisted
|
||||
if self.ctx.bw.is_whitelisted == "yes" then
|
||||
return self:ret(true, "client is whitelisted")
|
||||
end
|
||||
-- Extract DB
|
||||
local db, err = self.datastore:get("plugin_bunkernet_db", true)
|
||||
if db then
|
||||
-- Check if is IP is present
|
||||
if #db.ip > 0 then
|
||||
-- luacheck: ignore 421
|
||||
local present, err = utils.is_ip_in_networks(self.ctx.bw.remote_addr, db.ip)
|
||||
if present == nil then
|
||||
return self:ret(false, "can't check if ip is in db : " .. err)
|
||||
end
|
||||
if present then
|
||||
return self:ret(true, "ip is in db", utils.get_deny_status(self.ctx))
|
||||
end
|
||||
end
|
||||
else
|
||||
return self:ret(false, "can't get bunkernet db " .. err)
|
||||
end
|
||||
return self:ret(true, "not in db")
|
||||
end
|
||||
|
||||
function bunkernet:log(bypass_checks)
|
||||
if not bypass_checks then
|
||||
-- Check if needed
|
||||
if not self:is_needed() then
|
||||
return self:ret(true, "service doesn't use BunkerNet, skipping log")
|
||||
end
|
||||
-- Check id
|
||||
if not self.bunkernet_id then
|
||||
return self:ret(false, "missing instance ID")
|
||||
end
|
||||
end
|
||||
-- Check if IP has been blocked
|
||||
local reason = utils.get_reason(self.ctx)
|
||||
if not reason then
|
||||
return self:ret(true, "ip is not blocked")
|
||||
end
|
||||
if reason == "bunkernet" then
|
||||
return self:ret(true, "skipping report because the reason is bunkernet")
|
||||
end
|
||||
-- Check if IP is global
|
||||
if not self.ctx.bw.ip_is_global then
|
||||
return self:ret(true, "IP is not global")
|
||||
end
|
||||
-- TODO : check if IP has been reported recently
|
||||
-- luacheck: ignore 212 431
|
||||
local function report_callback(premature, obj, ip, reason, method, url, headers)
|
||||
local ok, err, status, _ = obj:report(ip, reason, method, url, headers)
|
||||
if status == 429 then
|
||||
obj.logger:log(ngx.WARN, "bunkernet API is rate limiting us")
|
||||
elseif not ok then
|
||||
obj.logger:log(ngx.ERR, "can't report IP : " .. err)
|
||||
else
|
||||
obj.logger:log(ngx.NOTICE, "successfully reported IP " .. ip .. " (reason : " .. reason .. ")")
|
||||
end
|
||||
end
|
||||
|
||||
local hdr, err = ngx.timer.at(
|
||||
0,
|
||||
report_callback,
|
||||
self,
|
||||
self.ctx.bw.remote_addr,
|
||||
reason,
|
||||
self.ctx.bw.request_method,
|
||||
self.ctx.bw.request_uri,
|
||||
ngx.req.get_headers()
|
||||
)
|
||||
if not hdr then
|
||||
return self:ret(false, "can't create report timer : " .. err)
|
||||
end
|
||||
return self:ret(true, "created report timer")
|
||||
end
|
||||
|
||||
function bunkernet:log_default()
|
||||
-- Check if needed
|
||||
if not self:is_needed() then
|
||||
return self:ret(true, "no service uses BunkerNet, skipping log_default")
|
||||
end
|
||||
-- Check id
|
||||
if not self.bunkernet_id then
|
||||
return self:ret(false, "missing instance ID")
|
||||
end
|
||||
-- Check if default server is disabled
|
||||
local check, err = utils.get_variable("DISABLE_DEFAULT_SERVER", false)
|
||||
if check == nil then
|
||||
return self:ret(false, "error while getting variable DISABLE_DEFAULT_SERVER : " .. err)
|
||||
end
|
||||
if check ~= "yes" then
|
||||
return self:ret(true, "default server is not disabled")
|
||||
end
|
||||
-- Call log method
|
||||
return self:log(true)
|
||||
end
|
||||
|
||||
function bunkernet:log_stream()
|
||||
return self:log()
|
||||
end
|
||||
|
||||
function bunkernet:request(method, url, data)
|
||||
local httpc, err = http.new()
|
||||
if not httpc then
|
||||
return false, "can't instantiate http object : " .. err
|
||||
end
|
||||
local all_data = {
|
||||
id = self.bunkernet_id,
|
||||
version = self.version,
|
||||
integration = self.integration,
|
||||
}
|
||||
if data then
|
||||
for k, v in pairs(data) do
|
||||
all_data[k] = v
|
||||
end
|
||||
end
|
||||
local res, err = httpc:request_uri(self.variables["BUNKERNET_SERVER"] .. url, {
|
||||
method = method,
|
||||
body = cjson.encode(all_data),
|
||||
headers = {
|
||||
["Content-Type"] = "application/json",
|
||||
["User-Agent"] = "BunkerWeb/" .. self.version,
|
||||
},
|
||||
})
|
||||
httpc:close()
|
||||
if not res then
|
||||
return false, "error while sending request : " .. err
|
||||
end
|
||||
if res.status ~= 200 then
|
||||
return false, "status code != 200", res.status, nil
|
||||
end
|
||||
local ok, ret = pcall(cjson.decode, res.body)
|
||||
if not ok then
|
||||
return false, "error while decoding json : " .. ret
|
||||
end
|
||||
return true, "success", res.status, ret
|
||||
end
|
||||
|
||||
function bunkernet:ping()
|
||||
return self:request("GET", "/ping", {})
|
||||
end
|
||||
|
||||
function bunkernet:report(ip, reason, method, url, headers)
|
||||
local data = {
|
||||
ip = ip,
|
||||
reason = reason,
|
||||
method = method,
|
||||
url = url,
|
||||
headers = headers,
|
||||
}
|
||||
return self:request("POST", "/report", data)
|
||||
end
|
||||
|
||||
return bunkernet
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
local cjson = require "cjson"
|
||||
local class = require "middleclass"
|
||||
local plugin = require "bunkerweb.plugin"
|
||||
local utils = require "bunkerweb.utils"
|
||||
local ssl = require "ngx.ssl"
|
||||
|
||||
local letsencrypt = class("letsencrypt", plugin)
|
||||
|
||||
|
|
@ -9,6 +11,107 @@ function letsencrypt:initialize(ctx)
|
|||
plugin.initialize(self, "letsencrypt", ctx)
|
||||
end
|
||||
|
||||
function letsencrypt:init()
|
||||
local ok, err = true, "success"
|
||||
if utils.has_variable("AUTO_LETS_ENCRYPT", "yes") then
|
||||
local multisite, err = utils.get_variable("MULTISITE")
|
||||
if not multisite then
|
||||
return self:ret(false, "can't get MULTISITE variable : " .. err)
|
||||
end
|
||||
if multisite == "yes" then
|
||||
local vars, err = utils.get_multiple_variables({"AUTO_LETS_ENCRYPT"})
|
||||
if not vars then
|
||||
return self:ret(false, "can't get AUTO_LETS_ENCRYPT variables : " .. err)
|
||||
end
|
||||
for server_name, multisite_vars in pairs(vars) do
|
||||
if multisite_vars["AUTO_LETS_ENCRYPT"] == "yes" then
|
||||
local check, data = self:read_files(server_name)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data, server_name)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local server_name, err = utils.get_variable("SERVER_NAME")
|
||||
if not server_name then
|
||||
return self:ret(false, "can't get SERVER_NAME variable : " .. err)
|
||||
end
|
||||
local check, data = self:read_files(server_name:gmatch("%S+")[1])
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
err = "let's encrypt is not used"
|
||||
end
|
||||
return self:ret(ok, err)
|
||||
end
|
||||
|
||||
function letsencrypt:ssl_certificate()
|
||||
if self.variables["AUTO_LETS_ENCRYPT"] == "yes" then
|
||||
local data, err = self.datastore:get("plugin_letsencrypt_" .. self.ctx.bw.server_name, true)
|
||||
if not data then
|
||||
return self:ret(false, "error while getting plugin_letsencrypt_" .. self.ctx.bw.server_name .. " from datastore : " .. err)
|
||||
end
|
||||
return self:ret(true, "certificate/key data found", data)
|
||||
end
|
||||
return self:ret(true, "let's encrypt is not used")
|
||||
end
|
||||
|
||||
function letsencrypt:read_files(server_name)
|
||||
local files = {
|
||||
"/var/cache/bunkerweb/letsencrypt/etc/live/" .. server_name .. "/fullchain.pem",
|
||||
"/var/cache/bunkerweb/letsencrypt/etc/live/" .. server_name .. "/privkey.pem"
|
||||
}
|
||||
local data = {}
|
||||
for i, file in ipairs(files) do
|
||||
local f, err = io.open(file, "r")
|
||||
if not f then
|
||||
return false, file .. " = " .. err
|
||||
end
|
||||
table.insert(data, f:read("*a"))
|
||||
f:close()
|
||||
end
|
||||
return true, data
|
||||
end
|
||||
|
||||
function letsencrypt:load_data(data, server_name)
|
||||
-- Load certificate
|
||||
local cert_chain, err = ssl.parse_pem_cert(data[1])
|
||||
if not cert_chain then
|
||||
return false, "error while parsing pem cert : " .. err
|
||||
end
|
||||
-- Load key
|
||||
local priv_key, err = ssl.parse_priv_key(data[2])
|
||||
if not priv_key then
|
||||
return false, "error while parsing pem priv key : " .. err
|
||||
end
|
||||
local cache_key = "plugin_letsencrypt_" .. (server_name or "global")
|
||||
local ok, err = self.datastore:set(cache_key, {cert_chain, priv_key}, nil, true)
|
||||
if not ok then
|
||||
return false, "error while setting data into datastore : " .. err
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function letsencrypt:access()
|
||||
if string.sub(self.ctx.bw.uri, 1, string.len("/.well-known/acme-challenge/")) == "/.well-known/acme-challenge/" then
|
||||
self.logger:log(ngx.NOTICE, "got a visit from Let's Encrypt, let's whitelist it")
|
||||
|
|
|
|||
114
src/common/core/selfsigned/selfsigned.lua
Normal file
114
src/common/core/selfsigned/selfsigned.lua
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
local class = require "middleclass"
|
||||
local plugin = require "bunkerweb.plugin"
|
||||
local utils = require "bunkerweb.utils"
|
||||
local ssl = require "ngx.ssl"
|
||||
|
||||
local selfsigned = class("selfsigned", plugin)
|
||||
|
||||
function selfsigned:initialize(ctx)
|
||||
-- Call parent initialize
|
||||
plugin.initialize(self, "selfsigned", ctx)
|
||||
end
|
||||
|
||||
function selfsigned:init()
|
||||
local ok, err = true, "success"
|
||||
if utils.has_variable("GENERATE_SELF_SIGNED_SSL", "yes") then
|
||||
local multisite, err = utils.get_variable("MULTISITE")
|
||||
if not multisite then
|
||||
return self:ret(false, "can't get MULTISITE variable : " .. err)
|
||||
end
|
||||
if multisite == "yes" then
|
||||
local vars, err = utils.get_multiple_variables({"GENERATE_SELF_SIGNED_SSL"})
|
||||
if not vars then
|
||||
return self:ret(false, "can't get GENERATE_SELF_SIGNED_SSL variables : " .. err)
|
||||
end
|
||||
for server_name, multisite_vars in pairs(vars) do
|
||||
if multisite_vars["GENERATE_SELF_SIGNED_SSL"] == "yes" then
|
||||
local check, data = self:read_files(server_name)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data, server_name)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local server_name, err = utils.get_variable("SERVER_NAME")
|
||||
if not server_name then
|
||||
return self:ret(false, "can't get SERVER_NAME variable : " .. err)
|
||||
end
|
||||
local check, data = self:read_files(server_name:gmatch("%S+")[1])
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while reading files : " .. err)
|
||||
ok = false
|
||||
err = "error reading files"
|
||||
else
|
||||
local check, err = self:load_data(data)
|
||||
if not check then
|
||||
self.logger:log(ngx.ERR, "error while loading data : " .. err)
|
||||
ok = false
|
||||
err = "error loading data"
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
err = "self signed is not used"
|
||||
end
|
||||
return self:ret(ok, err)
|
||||
end
|
||||
|
||||
function selfsigned:ssl_certificate()
|
||||
if self.variables["GENERATE_SELF_SIGNED_SSL"] == "yes" then
|
||||
local data, err = self.datastore:get("plugin_selfsigned_" .. self.ctx.bw.server_name, true)
|
||||
if not data then
|
||||
return self:ret(false, "error while getting plugin_selfsigned_" .. self.ctx.bw.server_name .. " from datastore : " .. err)
|
||||
end
|
||||
return self:ret(true, "certificate/key data found", data)
|
||||
end
|
||||
return self:ret(true, "selfsigned is not used")
|
||||
end
|
||||
|
||||
function selfsigned:read_files(server_name)
|
||||
local files = {
|
||||
"/var/cache/bunkerweb/selfsigned/" .. server_name .. "/cert.pem",
|
||||
"/var/cache/bunkerweb/selfsigned/" .. server_name .. "/key.pem"
|
||||
}
|
||||
local data = {}
|
||||
for i, file in ipairs(files) do
|
||||
local f, err = io.open(file, "r")
|
||||
if not f then
|
||||
return false, file .. " = " .. err
|
||||
end
|
||||
table.insert(data, f:read("*a"))
|
||||
f:close()
|
||||
end
|
||||
return true, data
|
||||
end
|
||||
|
||||
function selfsigned:load_data(data, server_name)
|
||||
-- Load certificate
|
||||
local cert_chain, err = ssl.parse_pem_cert(data[1])
|
||||
if not cert_chain then
|
||||
return false, "error while parsing pem cert : " .. err
|
||||
end
|
||||
-- Load key
|
||||
local priv_key, err = ssl.parse_priv_key(data[2])
|
||||
if not priv_key then
|
||||
return false, "error while parsing pem priv key : " .. err
|
||||
end
|
||||
local cache_key = "plugin_selfsigned_" .. (server_name or "global")
|
||||
local ok, err = self.datastore:set(cache_key, {cert_chain, priv_key}, nil, true)
|
||||
if not ok then
|
||||
return false, "error while setting data into datastore : " .. err
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return selfsigned
|
||||
|
|
@ -101,6 +101,8 @@ class Templator:
|
|||
for root_conf in (
|
||||
"server.conf",
|
||||
"access-lua.conf",
|
||||
"ssl-certificate-lua.conf",
|
||||
"header-lua.conf",
|
||||
"init-lua.conf",
|
||||
"log-lua.conf",
|
||||
"set-lua.conf",
|
||||
|
|
|
|||
Loading…
Reference in a new issue