in src/modules/compliance/src/lib/Engine.cpp [113:207]
Optional<Error> Engine::SetProcedure(const std::string& ruleName, const std::string& payload)
{
if (ruleName.empty())
{
return Error("Rule name is empty", EINVAL);
}
mDatabase.erase(ruleName);
auto ruleJSON = DecodeB64Json(payload);
if (!ruleJSON.HasValue())
{
// Fall back to plain JSON, both formats are supported
ruleJSON = compliance::ParseJson(payload.c_str());
if (!ruleJSON.HasValue())
{
OsConfigLogError(Log(), "Failed to parse JSON: %s", ruleJSON.Error().message.c_str());
return ruleJSON.Error();
}
}
auto object = json_value_get_object(ruleJSON.Value().get());
if (nullptr == object)
{
return Error("Failed to parse JSON object");
}
auto jsonValue = json_object_get_value(object, "audit");
if (nullptr == jsonValue)
{
return Error("Missing 'audit' object");
}
if (json_value_get_type(jsonValue) != JSONObject)
{
return Error("The 'audit' value is not an object");
}
auto procedure = Procedure{};
auto error = procedure.SetAudit(jsonValue);
if (error)
{
return error.Value();
}
if (nullptr == procedure.Audit())
{
OsConfigLogError(Log(), "Failed to copy 'audit' object");
return Error("Out of memory");
}
jsonValue = json_object_get_value(object, "remediate");
if (nullptr != jsonValue)
{
if (json_value_get_type(jsonValue) != JSONObject)
{
return Error("The 'remediate' value is not an object");
}
error = procedure.SetRemediation(jsonValue);
if (error)
{
return error.Value();
}
if (nullptr == procedure.Remediation())
{
OsConfigLogError(Log(), "Failed to copy 'remediate' object");
return Error("Out of memory");
}
}
jsonValue = json_object_get_value(object, "parameters");
if (nullptr != jsonValue)
{
if (json_value_get_type(jsonValue) != JSONObject)
{
return Error("The 'parameters' value is not an object");
}
auto paramsObj = json_value_get_object(jsonValue);
auto count = json_object_get_count(paramsObj);
for (decltype(count) i = 0; i < count; ++i)
{
const char* key = json_object_get_name(paramsObj, i);
const char* val = json_object_get_string(paramsObj, key);
if ((nullptr == key) || (nullptr == val))
{
OsConfigLogError(Log(), "Failed to get parameter name and value");
return Error("Failed to get parameter name and value");
}
procedure.SetParameter(key, val);
}
}
mDatabase.emplace(std::move(ruleName), std::move(procedure));
return Optional<Error>();
}