Melhorias na reconfiguração de validadores

OPENBUS-2968 Reconfiguração dinâmica do barramento

Revisão do código de reconfiguração dos validadores:
- retirei a operação reloadValidator
+ adicionei a operação addValidator
Quando houver falha na carga ou na remoção do validador, será emitida
uma ServiceFailure com a causa original.

OPENBUS-3008 API dos validadores de senha passa a ter uma operação para
finalização

O código de finalização dos validores do AccessControl foi movido para o
main do busservices. Agora o main cuida tanto da carga quanto remoção.
No término do processo (chamada do shutdown) as exceções ServiceFailure
oriundas do término dos validadores são tratadas e salvas nos logs.

Adição de novos testes sobre validadores e sua reconfiguração dinâmica.
parent 04aa9c28
......@@ -66,22 +66,25 @@ interface Configuration {
StrSeq getAdmins() raises (ServiceFailure);
/**
* \brief Recarrega um validador de login.
*
* O validador é carregado se o mesmo não existir.
* \brief Adiciona um validador de login. Caso o validador já tiver sido
* adicionado, nada será feito.
*
* \param validator Nome do pacote Lua da implementação do validador.
*/
void reloadValidator(in string validator) raises (ServiceFailure);
void addValidator(in string validator) raises (ServiceFailure);
/**
* \brief Remove um validador de login.
* \brief Remove um validador de login. Caso o validador não tenha sido
* adicionado antes, nada será feito.
*
* \param validator Nome do pacote Lua da implementação do validador.
*/
void delValidator(in string validator) raises (ServiceFailure);
/**
* \brief Retorna a lista de validadores.
*
* \return Lista de validadores
* \return Lista dos nomes dos pacotes Lua da implementação dos validadores.
*/
StrSeq getValidators() raises (ServiceFailure);
......
......@@ -196,8 +196,8 @@ return function(...)
--revoke-admin-from="<user1> <user2> ... <userN>"
* Mostra a lista de administradores:
--get-admins
* Recarrega um validador de login. Se o não existir o validador é carregado:
--reload-validator=<validator>
* Adiciona um validador de login:
--add-validator=<validator>
* Remove um validador de login:
--del-validator=<validator>
* Mostra a lista de validadores:
......@@ -375,7 +375,7 @@ return function(...)
["get-admins"] = {
{n = 0, params = {}},
};
["reload-validator"] = {
["add-validator"] = {
{n = 1, params = {}},
};
["del-validator"] = {
......@@ -1432,16 +1432,12 @@ return function(...)
return handleConfigurationGetCall(cmd, "getAdmins", "admins")
end
local function handleValidator(cmd, action)
return handleConfigurationCall(cmd, action.."Validator")
end
handlers["reload-validator"] = function(cmd)
return handleValidator(cmd, "reload")
handlers["add-validator"] = function(cmd)
return handleConfigurationCall(cmd, "addValidator")
end
handlers["del-validator"] = function(cmd)
return handleValidator(cmd, "del")
return handleConfigurationCall(cmd, "delValidator")
end
handlers["get-validators"] = function(cmd)
......
......@@ -360,20 +360,6 @@ function AccessControl:shutdown()
unschedule(sweeper)
end
self.sweeper = false -- indicate no sweeper shall run anymore
for _, validator in pairs(self.passwordValidators) do
if type(validator) == "table" and type(validator.finalize) == "function" then
local ok, errmsg = xpcall(validator.finalize, traceback)
if not ok then
log:exception(msg.FailedPasswordValidatorFinalization:tag{
validator = validator.name,
errmsg = errmsg,
})
end
log:admin(msg.PasswordValidatorTerminated:tag{
validator = validator.name
})
end
end
log:admin(msg.AccessControlShutDown)
end
......
......@@ -149,7 +149,35 @@ return function(...)
end
end
local function loadValidatorModule(package)
local validators = {}
local function unloadValidator(validator)
package.loaded[validator.name] = nil
validators[validator.name] = nil
local ok, errmsg = pcall(validator.finalize)
if not ok then
ServiceFailure{
message = msg.FailedPasswordValidatorTermination:tag{
validator = validator.name,
errmsg = errmsg or msg.UnspecifiedTerminationFailure,
}
}
end
return true
end
local function unloadValidators()
for _, validator in pairs(validators) do
local ok, errmsg = pcall(unloadValidator, validator)
if not ok then
log:exception(errmsg)
end
log:admin(msg.PasswordValidatorUnloaded:tag{
validator = validator.name
})
end
end
local function loadValidator(package)
local ok, result = pcall(require, package)
if not ok then
log:misconfig(msg.UnableToLoadPasswordValidator:tag{
......@@ -158,55 +186,33 @@ return function(...)
})
return false, errcode.UnableToLoadPasswordValidator, result
end
local validate, finalize = result(Configs)
if validate == nil then
local errmsg = finalize
local ok, validate, finalize = pcall(result, Configs)
if not ok or validate == nil then
local errmsg = (not ok and validate) or finalize
log:misconfig(msg.UnableToInitializePasswordValidator:tag{
validator = package,
error = errmsg,
})
return false, errcode.UnableToInitializePasswordValidator, errmsg
end
return true, validate, finalize
end
validators[package] = {
name = package,
validate = validate,
finalize = finalize,
}
local validators = {}
local function loadValidator(validator)
local loaded
if validators[validator] then
pcall(validators[validator].finalize)
package.loaded[validator] = nil
loaded = true
end
local ok, validate, finalize = loadValidatorModule(validator)
if not ok then
local errcode = validate
local errmsg = finalize
return false, errcode, errmsg
else
validators[validator] = {
name = validator,
validate = validate,
finalize = finalize,
}
local suffix
if loaded then
suffix = "Reloaded"
else
suffix = "Loaded"
end
local phrase = "PasswordValidator"..suffix
log:config(msg[phrase]:tag{name=validator})
end
return true
end
local function loadValidators()
local hasValidator = false
for _, validator in pairs(Configs.validator) do
for _, package in pairs(Configs.validator) do
if not hasValidator then hasValidator = true end
local ok, errcode, errmsg = loadValidator(validator)
local ok, errcode, errmsg = loadValidator(package)
if not ok then return false, errcode, errmsg end
log:config(msg.PasswordValidatorLoaded:tag{ validator = package })
end
if not hasValidator then
log:misconfig(msg.NoPasswordValidators)
......@@ -557,20 +563,25 @@ Options:
return getList(adminUsers)
end
function Configuration:reloadValidator(validator)
local res, _, errmsg = loadValidator(validator)
if not res then
return ServiceFailure{
message = msg.UnableToLoadPasswordValidator:tag{errmsg = errmsg}
}
function Configuration:addValidator(name)
if not validators[name] then
local ok, _, errmsg = loadValidator(name)
if not ok then
ServiceFailure{
message = msg.UnableToLoadPasswordValidator:tag{
validator = name,
error = errmsg,
}
}
end
log:admin(msg.PasswordValidatorLoaded:tag{validator = name})
end
end
function Configuration:delValidator(validator)
if validators[validator] then
package.loaded[validator] = nil
validators[validator] = nil
log:config(msg.PasswordValidatorRemoved:tag{validator = validator})
function Configuration:delValidator(name)
if validators[name] then
unloadValidator(validators[name])
log:admin(msg.PasswordValidatorUnloaded:tag{validator = name})
end
end
......@@ -580,7 +591,7 @@ Options:
function Configuration:setMaxChannels(maxchannels)
if not resetMaxChannels(orb, maxchannels) then
return ServiceFailure{
ServiceFailure{
message = msg.InvalidMaximumChannelLimit:tag{value=maxchannels}
}
end
......@@ -592,7 +603,7 @@ Options:
local function updateLogLevel(log, loglevel)
if not setLogLevel(log, loglevel) then
return ServiceFailure{
ServiceFailure{
message = msg.InvalidLogLevel:tag{value=loglevel}
}
end
......@@ -667,6 +678,7 @@ Options:
self.context:deactivateComponent()
orb:shutdown()
facets.AccessControl:shutdown()
unloadValidators()
log:uptime(msg.CoreServicesTerminated)
end,
}
......
......@@ -20,7 +20,7 @@ end
-------------------------------------------------------------------------------
local function finalize()
os.execute("rm -f " ..outputfile)
os.remove(outputfile)
end
local function readOutput()
......@@ -112,9 +112,11 @@ assert(execute("--del-category=CTG02"))
assert(execute("--set-max-channels=100"))
assert(execute("--set-log-level=5"))
assert(execute("--set-oil-log-level=5"))
assert(execute("--reload-validator=openbus.test.core.services.BadPasswordValidator"))
assert(execute("--del-validator=openbus.test.core.services.BadPasswordValidator"))
assert(execute("--reload-validator=openbus.test.core.services.BadPasswordValidator"))
assert(execute("--add-validator=openbus.test.core.services.BadPasswordValidator"))
assert(not execute("--del-validator=openbus.test.core.services.BadPasswordValidator"))
assert(execute("--add-validator=openbus.test.core.services.BadPasswordValidator"))
assert(not execute("--add-validator=openbus.test.core.services.ErrorTestValidator"))
assert(not execute("--add-validator=openbus.test.core.services.NullValidationValidator"))
assert(execute("--grant-admin-to='peter'"))
login="--login=peter "
password="--password=peter "
......
return function(configs)
error{"Should fail when found an error at configuration time!"}
end
return function(configs)
return nil, "Should fail initializing a validator with some wrong configuration!"
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment