mirror of
https://github.com/Icinga/icinga2.git
synced 2025-04-08 17:05:25 +02:00
Add macro config validator for command args, env, custom attr, perfdata templates
fixes #7311
This commit is contained in:
parent
477f7a713c
commit
8ca57cba03
@ -1256,3 +1256,23 @@ String Utility::UnescapeString(const String& s)
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
bool Utility::ValidateMacroString(const String& macro)
|
||||
{
|
||||
if (macro.IsEmpty())
|
||||
return true;
|
||||
|
||||
size_t pos_first, pos_second, offset;
|
||||
offset = 0;
|
||||
|
||||
while((pos_first = macro.FindFirstOf("$", offset)) != String::NPos) {
|
||||
pos_second = macro.FindFirstOf("$", pos_first + 1);
|
||||
|
||||
if (pos_second == String::NPos)
|
||||
return false;
|
||||
|
||||
offset = pos_second + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -118,6 +118,8 @@ public:
|
||||
static String EscapeString(const String& s, const String& chars);
|
||||
static String UnescapeString(const String& s);
|
||||
|
||||
static bool ValidateMacroString(const String& macro);
|
||||
|
||||
static void SetThreadName(const String& name, bool os = true);
|
||||
static String GetThreadName(void);
|
||||
|
||||
|
@ -20,11 +20,15 @@
|
||||
#include "icinga/command.hpp"
|
||||
#include "base/function.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/objectlock.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(Command);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateCommandAttributes, &Command::ValidateAttributes);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateCommandArguments, &Command::ValidateArguments);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateEnvironmentVariables, &Command::ValidateEnvironmentVariables);
|
||||
|
||||
int Command::GetModifiedAttributes(void) const
|
||||
{
|
||||
@ -52,3 +56,55 @@ void Command::ValidateAttributes(const String& location, const Command::Ptr& obj
|
||||
}
|
||||
}
|
||||
|
||||
void Command::ValidateArguments(const String& location, const Command::Ptr& object)
|
||||
{
|
||||
Dictionary::Ptr arguments = object->GetArguments();
|
||||
|
||||
if (!arguments)
|
||||
return;
|
||||
|
||||
ObjectLock olock(arguments);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, arguments) {
|
||||
const Value& arginfo = kv.second;
|
||||
Value argval;
|
||||
|
||||
if (arginfo.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr argdict = arginfo;
|
||||
|
||||
if (argdict->Contains("value"))
|
||||
argval = argdict->Get("value");
|
||||
} else
|
||||
argval = arginfo;
|
||||
|
||||
if (argval.IsEmpty())
|
||||
continue;
|
||||
|
||||
String argstr = argval;
|
||||
|
||||
if(!Utility::ValidateMacroString(argstr)) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + argstr + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Command::ValidateEnvironmentVariables(const String& location, const Command::Ptr& object)
|
||||
{
|
||||
Dictionary::Ptr env = object->GetEnv();
|
||||
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
ObjectLock olock(env);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, env) {
|
||||
const Value& envval = kv.second;
|
||||
|
||||
if (!envval.IsString() || envval.IsEmpty())
|
||||
continue;
|
||||
|
||||
if(!Utility::ValidateMacroString(envval)) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + envval + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
//virtual Dictionary::Ptr Execute(const Object::Ptr& context) = 0;
|
||||
|
||||
static void ValidateAttributes(const String& location, const Command::Ptr& object);
|
||||
static void ValidateArguments(const String& location, const Command::Ptr& object);
|
||||
static void ValidateEnvironmentVariables(const String& location, const Command::Ptr& object);
|
||||
|
||||
int GetModifiedAttributes(void) const;
|
||||
void SetModifiedAttributes(int flags, const MessageOrigin& origin = MessageOrigin());
|
||||
|
@ -19,10 +19,15 @@
|
||||
|
||||
#include "icinga/customvarobject.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/function.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/objectlock.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(CustomVarObject);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateCustomAttributes, &CustomVarObject::ValidateCustomAttributes);
|
||||
|
||||
boost::signals2::signal<void (const CustomVarObject::Ptr&, const Dictionary::Ptr& vars, const MessageOrigin&)> CustomVarObject::OnVarsChanged;
|
||||
|
||||
@ -61,3 +66,57 @@ bool CustomVarObject::IsVarOverridden(const String& name) const
|
||||
|
||||
return vars_override->Contains(name);
|
||||
}
|
||||
|
||||
void CustomVarObject::ValidateCustomAttributes(const String& location, const CustomVarObject::Ptr& object)
|
||||
{
|
||||
Dictionary::Ptr vars = object->GetVars();
|
||||
|
||||
if (!vars)
|
||||
return;
|
||||
|
||||
/* string, array, dictionary */
|
||||
ObjectLock olock(vars);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
|
||||
const Value& varval = kv.second;
|
||||
|
||||
if (varval.IsObjectType<Dictionary>()) {
|
||||
/* only one dictonary level */
|
||||
Dictionary::Ptr varval_dict = varval;
|
||||
|
||||
ObjectLock xlock(varval_dict);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv_var, varval_dict) {
|
||||
if(kv_var.second.IsEmpty())
|
||||
continue;
|
||||
|
||||
if(!Utility::ValidateMacroString(kv_var.second)) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + kv_var.second + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
} else if (varval.IsObjectType<Array>()) {
|
||||
/* check all array entries */
|
||||
Array::Ptr varval_arr = varval;
|
||||
|
||||
ObjectLock ylock (varval_arr);
|
||||
BOOST_FOREACH(const Value& arrval, varval_arr) {
|
||||
if (arrval.IsEmpty())
|
||||
continue;
|
||||
|
||||
if(!Utility::ValidateMacroString(arrval)) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + arrval + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (varval.IsEmpty())
|
||||
continue;
|
||||
|
||||
String varstr = varval;
|
||||
|
||||
if(!Utility::ValidateMacroString(varstr)) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + varstr + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -61,6 +61,8 @@ public:
|
||||
|
||||
static boost::signals2::signal<void (const CustomVarObject::Ptr&, const Dictionary::Ptr& vars, const MessageOrigin&)> OnVarsChanged;
|
||||
|
||||
static void ValidateCustomAttributes(const String& location, const CustomVarObject::Ptr& object);
|
||||
|
||||
Dictionary::Ptr GetVars(void) const;
|
||||
void SetVars(const Dictionary::Ptr& vars, const MessageOrigin& origin = MessageOrigin());
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
}
|
||||
|
||||
%type CustomVarObject {
|
||||
%validator "ValidateCustomAttributes",
|
||||
%attribute %dictionary "vars",
|
||||
}
|
||||
|
||||
@ -193,6 +194,8 @@
|
||||
|
||||
%type Command %inherits CustomVarObject {
|
||||
%validator "ValidateCommandAttributes",
|
||||
%validator "ValidateCommandArguments",
|
||||
%validator "ValidateEnvironmentVariables",
|
||||
|
||||
%require "execute",
|
||||
%attribute %function "execute",
|
||||
|
@ -43,6 +43,7 @@
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(GraphiteWriter);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateNameTemplates, &GraphiteWriter::ValidateNameTemplates);
|
||||
|
||||
REGISTER_STATSFUNCTION(GraphiteWriterStats, &GraphiteWriter::StatsFunc);
|
||||
|
||||
@ -146,7 +147,7 @@ void GraphiteWriter::SendPerfdata(const String& prefix, const CheckResult::Ptr&
|
||||
ObjectLock olock(perfdata);
|
||||
BOOST_FOREACH(const Value& val, perfdata) {
|
||||
PerfdataValue::Ptr pdv;
|
||||
|
||||
|
||||
if (val.IsObjectType<PerfdataValue>())
|
||||
pdv = val;
|
||||
else {
|
||||
@ -158,7 +159,7 @@ void GraphiteWriter::SendPerfdata(const String& prefix, const CheckResult::Ptr&
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String escaped_key = EscapeMetric(pdv->GetLabel());
|
||||
boost::algorithm::replace_all(escaped_key, "::", ".");
|
||||
|
||||
@ -230,3 +231,15 @@ Value GraphiteWriter::EscapeMacroMetric(const Value& value)
|
||||
} else
|
||||
return EscapeMetric(value);
|
||||
}
|
||||
|
||||
void GraphiteWriter::ValidateNameTemplates(const String& location, const GraphiteWriter::Ptr& object)
|
||||
{
|
||||
if(!Utility::ValidateMacroString(object->GetHostNameTemplate())) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + object->GetHostNameTemplate() + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
if (!Utility::ValidateMacroString(object->GetServiceNameTemplate())) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + object->GetServiceNameTemplate() + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
|
||||
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
|
||||
|
||||
static void ValidateNameTemplates(const String& location, const GraphiteWriter::Ptr& object);
|
||||
|
||||
protected:
|
||||
virtual void Start(void);
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
******************************************************************************/
|
||||
|
||||
%type PerfdataWriter {
|
||||
%validator "ValidateFormatTemplates",
|
||||
|
||||
%attribute %string "host_perfdata_path",
|
||||
%attribute %string "service_perfdata_path",
|
||||
%attribute %string "host_temp_path",
|
||||
@ -28,6 +30,8 @@
|
||||
}
|
||||
|
||||
%type GraphiteWriter {
|
||||
%validator "ValidateNameTemplates",
|
||||
|
||||
%attribute %string "host",
|
||||
%attribute %string "port",
|
||||
%attribute %string "host_name_template",
|
||||
@ -44,4 +48,3 @@
|
||||
%attribute %string "host",
|
||||
%attribute %string "port",
|
||||
}
|
||||
|
||||
|
@ -27,12 +27,14 @@
|
||||
#include "base/convert.hpp"
|
||||
#include "base/utility.hpp"
|
||||
#include "base/context.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/application.hpp"
|
||||
#include "base/statsfunction.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(PerfdataWriter);
|
||||
REGISTER_SCRIPTFUNCTION(ValidateFormatTemplates, &PerfdataWriter::ValidateFormatTemplates);
|
||||
|
||||
REGISTER_STATSFUNCTION(PerfdataWriterStats, &PerfdataWriter::StatsFunc);
|
||||
|
||||
@ -138,3 +140,14 @@ void PerfdataWriter::RotationTimerHandler(void)
|
||||
RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath());
|
||||
}
|
||||
|
||||
void PerfdataWriter::ValidateFormatTemplates(const String& location, const PerfdataWriter::Ptr& object)
|
||||
{
|
||||
if(!Utility::ValidateMacroString(object->GetHostFormatTemplate())) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + object->GetHostFormatTemplate() + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
if (!Utility::ValidateMacroString(object->GetServiceFormatTemplate())) {
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
|
||||
location + ": Closing $ not found in macro format string '" + object->GetHostFormatTemplate() + "'.", object->GetDebugInfo()));
|
||||
}
|
||||
}
|
@ -42,6 +42,8 @@ public:
|
||||
|
||||
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
|
||||
|
||||
static void ValidateFormatTemplates(const String& location, const PerfdataWriter::Ptr& object);
|
||||
|
||||
protected:
|
||||
virtual void Start(void);
|
||||
|
||||
|
@ -51,6 +51,17 @@ BOOST_AUTO_TEST_CASE(simple)
|
||||
Array::Ptr result = MacroProcessor::ResolveMacros("$testD$", resolvers);
|
||||
BOOST_CHECK(result->GetLength() == 2);
|
||||
|
||||
/* verify the config validator macro checks */
|
||||
BOOST_CHECK(Utility::ValidateMacroString("$host.address") == false);
|
||||
BOOST_CHECK(Utility::ValidateMacroString("host.vars.test$") == false);
|
||||
|
||||
BOOST_CHECK(Utility::ValidateMacroString("host.vars.test$") == false);
|
||||
BOOST_CHECK(Utility::ValidateMacroString("$template::test$abc$") == false);
|
||||
|
||||
BOOST_CHECK(Utility::ValidateMacroString("$$test $host.vars.test$") == true);
|
||||
|
||||
BOOST_CHECK(Utility::ValidateMacroString("test $host.vars.test$") == true);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
x
Reference in New Issue
Block a user