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;
+}
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);
#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
{
}
}
+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()));
+ }
+ }
+}
//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());
#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;
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()));
+ }
+ }
+ }
+}
\ No newline at end of file
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());
}
%type CustomVarObject {
+ %validator "ValidateCustomAttributes",
%attribute %dictionary "vars",
}
%type Command %inherits CustomVarObject {
%validator "ValidateCommandAttributes",
+ %validator "ValidateCommandArguments",
+ %validator "ValidateEnvironmentVariables",
%require "execute",
%attribute %function "execute",
using namespace icinga;
REGISTER_TYPE(GraphiteWriter);
+REGISTER_SCRIPTFUNCTION(ValidateNameTemplates, &GraphiteWriter::ValidateNameTemplates);
REGISTER_STATSFUNCTION(GraphiteWriterStats, &GraphiteWriter::StatsFunc);
ObjectLock olock(perfdata);
BOOST_FOREACH(const Value& val, perfdata) {
PerfdataValue::Ptr pdv;
-
+
if (val.IsObjectType<PerfdataValue>())
pdv = val;
else {
continue;
}
}
-
+
String escaped_key = EscapeMetric(pdv->GetLabel());
boost::algorithm::replace_all(escaped_key, "::", ".");
} 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()));
+ }
+}
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);
******************************************************************************/
%type PerfdataWriter {
+ %validator "ValidateFormatTemplates",
+
%attribute %string "host_perfdata_path",
%attribute %string "service_perfdata_path",
%attribute %string "host_temp_path",
}
%type GraphiteWriter {
+ %validator "ValidateNameTemplates",
+
%attribute %string "host",
%attribute %string "port",
%attribute %string "host_name_template",
%attribute %string "host",
%attribute %string "port",
}
-
#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);
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()));
+ }
+}
\ No newline at end of file
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);
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()