From: Gunnar Beutner Date: Mon, 28 Sep 2015 06:57:25 +0000 (+0200) Subject: Implement API permissions X-Git-Tag: v2.4.0~270 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=425a1a01665f11d6c266243f8402779650c5a3fc;p=icinga2 Implement API permissions fixes #9088 --- diff --git a/lib/cli/apisetuputility.cpp b/lib/cli/apisetuputility.cpp index ca8649c3c..e231fcef0 100644 --- a/lib/cli/apisetuputility.cpp +++ b/lib/cli/apisetuputility.cpp @@ -172,6 +172,8 @@ int ApiSetupUtility::SetupMasterApiUser(const String& cn) << "object ApiUser \"" << api_username << "\" {\n" << " password = \"" << api_password << "\"\n" << " //client_cn = \"\"\n" + << "\n" + << " permissions = [ \"*\" ]\n" << "}\n"; fp.close(); diff --git a/lib/remote/actionshandler.cpp b/lib/remote/actionshandler.cpp index 7db830b67..a9f580758 100644 --- a/lib/remote/actionshandler.cpp +++ b/lib/remote/actionshandler.cpp @@ -59,19 +59,24 @@ bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& reques const std::vector& types = action->GetTypes(); std::vector objs; + String permission = "actions/" + actionName; + if (!types.empty()) { qd.Types = std::set(types.begin(), types.end()); + qd.Permission = permission; try { - objs = FilterUtility::GetFilterTargets(qd, params); + objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { HttpUtility::SendJsonError(response, 400, "Type/Filter was required but not provided or was invalid.", request.GetVerboseErrors() ? DiagnosticInformation(ex) : ""); return true; } - } else + } else { + FilterUtility::CheckPermission(user, permission); objs.push_back(ConfigObject::Ptr()); + } Array::Ptr results = new Array(); diff --git a/lib/remote/apiuser.cpp b/lib/remote/apiuser.cpp index 0ba44e30e..9c26a6d88 100644 --- a/lib/remote/apiuser.cpp +++ b/lib/remote/apiuser.cpp @@ -25,21 +25,6 @@ using namespace icinga; REGISTER_TYPE(ApiUser); -String ApiUser::GetPassword(void) const -{ - return "*****"; -} - -void ApiUser::SetPassword(const String& password) -{ - SetPasswordRaw(password); -} - -bool ApiUser::CheckPassword(const String& password) const -{ - return password == GetPasswordRaw(); -} - ApiUser::Ptr ApiUser::GetByClientCN(const String& cn) { BOOST_FOREACH(const ApiUser::Ptr& user, ConfigType::GetObjectsByType()) { diff --git a/lib/remote/apiuser.hpp b/lib/remote/apiuser.hpp index 2fa2dd6c2..1c4abc551 100644 --- a/lib/remote/apiuser.hpp +++ b/lib/remote/apiuser.hpp @@ -35,10 +35,6 @@ public: DECLARE_OBJECT(ApiUser); DECLARE_OBJECTNAME(ApiUser); - String GetPassword(void) const; - void SetPassword(const String& password); - bool CheckPassword(const String& password) const; - static ApiUser::Ptr GetByClientCN(const String& cn); }; diff --git a/lib/remote/apiuser.ti b/lib/remote/apiuser.ti index 7007fb265..ac4666e99 100644 --- a/lib/remote/apiuser.ti +++ b/lib/remote/apiuser.ti @@ -18,6 +18,7 @@ ******************************************************************************/ #include "base/configobject.hpp" +#include "base/function.hpp" library remote; @@ -26,8 +27,20 @@ namespace icinga class ApiUser : ConfigObject { - [config, protected] String password (PasswordRaw); + [config] String password; [config] String client_cn (ClientCN); + [config] array(Value) permissions; +}; + +validator ApiUser { + Array permissions { + String "*"; + Dictionary "*" { + required permission; + String permission; + Function filter; + }; + }; }; } diff --git a/lib/remote/configfileshandler.cpp b/lib/remote/configfileshandler.cpp index 28971010f..cda6a9628 100644 --- a/lib/remote/configfileshandler.cpp +++ b/lib/remote/configfileshandler.cpp @@ -20,6 +20,7 @@ #include "remote/configfileshandler.hpp" #include "remote/configpackageutility.hpp" #include "remote/httputility.hpp" +#include "remote/filterutility.hpp" #include "base/exception.hpp" #include #include @@ -55,6 +56,8 @@ void ConfigFilesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& reques params->Set("path", boost::algorithm::join(tmpPath, "/")); } + FilterUtility::CheckPermission(user, "config/query"); + String packageName = HttpUtility::GetLastParameter(params, "package"); String stageName = HttpUtility::GetLastParameter(params, "stage"); diff --git a/lib/remote/configpackageshandler.cpp b/lib/remote/configpackageshandler.cpp index 946c0c7ac..23a1fc579 100644 --- a/lib/remote/configpackageshandler.cpp +++ b/lib/remote/configpackageshandler.cpp @@ -20,6 +20,7 @@ #include "remote/configpackageshandler.hpp" #include "remote/configpackageutility.hpp" #include "remote/httputility.hpp" +#include "remote/filterutility.hpp" #include "base/exception.hpp" #include @@ -49,6 +50,8 @@ bool ConfigPackagesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& void ConfigPackagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + FilterUtility::CheckPermission(user, "config/query"); + std::vector packages = ConfigPackageUtility::GetPackages(); Array::Ptr results = new Array(); @@ -70,6 +73,8 @@ void ConfigPackagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& req void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + FilterUtility::CheckPermission(user, "config/modify"); + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); if (request.RequestUrl->GetPath().size() >= 4) @@ -106,6 +111,8 @@ void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& re void ConfigPackagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + FilterUtility::CheckPermission(user, "config/modify"); + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); if (request.RequestUrl->GetPath().size() >= 4) diff --git a/lib/remote/configstageshandler.cpp b/lib/remote/configstageshandler.cpp index f7e801d78..4a9d9e181 100644 --- a/lib/remote/configstageshandler.cpp +++ b/lib/remote/configstageshandler.cpp @@ -20,6 +20,7 @@ #include "remote/configstageshandler.hpp" #include "remote/configpackageutility.hpp" #include "remote/httputility.hpp" +#include "remote/filterutility.hpp" #include "base/application.hpp" #include "base/exception.hpp" #include @@ -51,6 +52,8 @@ bool ConfigStagesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r void ConfigStagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + FilterUtility::CheckPermission(user, "config/query"); + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); if (request.RequestUrl->GetPath().size() >= 4) @@ -91,6 +94,8 @@ void ConfigStagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& reque void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + FilterUtility::CheckPermission(user, "config/modify"); + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); if (request.RequestUrl->GetPath().size() >= 4) @@ -136,6 +141,8 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ void ConfigStagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { + FilterUtility::CheckPermission(user, "config/modify"); + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); if (request.RequestUrl->GetPath().size() >= 4) diff --git a/lib/remote/createobjecthandler.cpp b/lib/remote/createobjecthandler.cpp index a1d4d6d96..3e0770e39 100644 --- a/lib/remote/createobjecthandler.cpp +++ b/lib/remote/createobjecthandler.cpp @@ -48,6 +48,8 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r return true; } + FilterUtility::CheckPermission(user, "objects/create/" + type->GetName()); + String name = request.RequestUrl->GetPath()[3]; Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); Array::Ptr templates = params->Get("templates"); diff --git a/lib/remote/deleteobjecthandler.cpp b/lib/remote/deleteobjecthandler.cpp index 6e043091e..8d4384672 100644 --- a/lib/remote/deleteobjecthandler.cpp +++ b/lib/remote/deleteobjecthandler.cpp @@ -66,7 +66,7 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r params->Set(attr, request.RequestUrl->GetPath()[3]); } - std::vector objs = FilterUtility::GetFilterTargets(qd, params); + std::vector objs = FilterUtility::GetFilterTargets(qd, params, user); bool cascade = HttpUtility::GetLastParameter(params, "cascade"); diff --git a/lib/remote/filterutility.cpp b/lib/remote/filterutility.cpp index a127172a7..e8c9503cb 100644 --- a/lib/remote/filterutility.cpp +++ b/lib/remote/filterutility.cpp @@ -78,13 +78,23 @@ String ConfigObjectTargetProvider::GetPluralName(const String& type) const return Type::GetByName(type)->GetPluralName(); } -static void FilteredAddTarget(ScriptFrame& frame, Expression *ufilter, std::vector& result, const Object::Ptr& target) +static bool EvaluateFilter(ScriptFrame& frame, Expression *filter, const Object::Ptr& target) { + if (!filter) + return true; + Type::Ptr type = target->GetReflectionType(); - String varName = type->GetName(); - boost::algorithm::to_lower(varName); + String varName = type->GetName().ToLower(); + + Dictionary::Ptr vars; + + if (frame.Self.IsEmpty()) { + vars = new Dictionary(); + frame.Self = vars; + } else + vars = frame.Self; - frame.Locals->Set(varName, target); + vars->Set(varName, target); for (int fid = 0; fid < type->GetFieldCount(); fid++) { Field field = type->GetFieldInfo(fid); @@ -97,14 +107,68 @@ static void FilteredAddTarget(ScriptFrame& frame, Expression *ufilter, std::vect varName = field.TypeName; boost::algorithm::to_lower(varName); - frame.Locals->Set(varName, joinedObj); + vars->Set(varName, joinedObj); } - if (Convert::ToBool(ufilter->Evaluate(frame))) + return Convert::ToBool(filter->Evaluate(frame)); +} + +static void FilteredAddTarget(ScriptFrame& permissionFrame, Expression *permissionFilter, + ScriptFrame& frame, Expression *ufilter, std::vector& result, const Object::Ptr& target) +{ + if (EvaluateFilter(permissionFrame, permissionFilter, target) && EvaluateFilter(frame, ufilter, target)) result.push_back(target); } -std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query) +void FilterUtility::CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **permissionFilter) +{ + if (permissionFilter) + *permissionFilter = NULL; + + if (permission.IsEmpty()) + return; + + bool foundPermission = false; + String requiredPermission = permission.ToLower(); + + Array::Ptr permissions = user->GetPermissions(); + if (permissions) { + ObjectLock olock(permissions); + BOOST_FOREACH(const Value& item, permissions) { + String permission; + Function::Ptr filter; + if (item.IsObjectType()) { + Dictionary::Ptr dict = item; + permission = dict->Get("permission"); + filter = dict->Get("filter"); + } else + permission = item; + + permission = permission.ToLower(); + + if (!Utility::Match(permission, requiredPermission)) + continue; + + foundPermission = true; + + if (filter && permissionFilter) { + std::vector args; + args.push_back(new GetScopeExpression(ScopeLocal)); + FunctionCallExpression *fexpr = new FunctionCallExpression(new IndexerExpression(MakeLiteral(filter), MakeLiteral("call")), args); + + if (!*permissionFilter) + *permissionFilter = fexpr; + else + *permissionFilter = new LogicalOrExpression(*permissionFilter, fexpr); + } + } + } + + if (!foundPermission) + BOOST_THROW_EXCEPTION(ScriptError("Missing permission: " + requiredPermission)); +} + +std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user) { std::vector result; @@ -115,6 +179,11 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c else provider = new ConfigObjectTargetProvider(); + Expression *permissionFilter; + CheckPermission(user, qd.Permission, &permissionFilter); + + ScriptFrame permissionFrame; + BOOST_FOREACH(const String& type, qd.Types) { String attr = type; boost::algorithm::to_lower(attr); @@ -122,8 +191,12 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c if (attr == "type") attr = "name"; - if (query->Contains(attr)) - result.push_back(provider->GetTargetByName(type, HttpUtility::GetLastParameter(query, attr))); + if (query->Contains(attr)) { + Object::Ptr target = provider->GetTargetByName(type, HttpUtility::GetLastParameter(query, attr)); + + if (EvaluateFilter(permissionFrame, permissionFilter, target)) + result.push_back(target); + } attr = provider->GetPluralName(type); boost::algorithm::to_lower(attr); @@ -133,7 +206,10 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c if (names) { ObjectLock olock(names); BOOST_FOREACH(const String& name, names) { - result.push_back(provider->GetTargetByName(type, name)); + Object::Ptr target = provider->GetTargetByName(type, name); + + if (EvaluateFilter(permissionFrame, permissionFilter, target)) + result.push_back(target); } } } @@ -159,20 +235,26 @@ std::vector FilterUtility::GetFilterTargets(const QueryDescription& qd, c if (qd.Types.find(type) == qd.Types.end()) BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type specified for this query.")); - Expression *ufilter = ConfigCompiler::CompileText("", filter); ScriptFrame frame; frame.Sandboxed = true; + Dictionary::Ptr uvars = new Dictionary(); + + Expression *ufilter = ConfigCompiler::CompileText("", filter); Dictionary::Ptr filter_vars = query->Get("filter_vars"); if (filter_vars) { ObjectLock olock(filter_vars); BOOST_FOREACH(const Dictionary::Pair& kv, filter_vars) { - frame.Locals->Set(kv.first, kv.second); + uvars->Set(kv.first, kv.second); } } + frame.Self = uvars; + try { - provider->FindTargets(type, boost::bind(&FilteredAddTarget, boost::ref(frame), ufilter, boost::ref(result), _1)); + provider->FindTargets(type, boost::bind(&FilteredAddTarget, + boost::ref(permissionFrame), permissionFilter, + boost::ref(frame), ufilter, boost::ref(result), _1)); } catch (const std::exception& ex) { delete ufilter; throw; diff --git a/lib/remote/filterutility.hpp b/lib/remote/filterutility.hpp index 176110597..f2b13260d 100644 --- a/lib/remote/filterutility.hpp +++ b/lib/remote/filterutility.hpp @@ -21,6 +21,8 @@ #define FILTERUTILITY_H #include "remote/i2-remote.hpp" +#include "remote/apiuser.hpp" +#include "config/expression.hpp" #include "base/dictionary.hpp" #include "base/configobject.hpp" #include @@ -54,6 +56,7 @@ struct QueryDescription { std::set Types; TargetProvider::Ptr Provider; + String Permission; }; /** @@ -65,7 +68,8 @@ class I2_REMOTE_API FilterUtility { public: static Type::Ptr TypeFromPluralName(const String& pluralName); - static std::vector GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query); + static void CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **filter = NULL); + static std::vector GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user); }; } diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index 2c7e18902..4348be986 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -141,7 +141,7 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request) else { user = ApiUser::GetByName(username); - if (!user || !user->CheckPassword(password)) + if (user && user->GetPassword() != password) user.reset(); } diff --git a/lib/remote/modifyobjecthandler.cpp b/lib/remote/modifyobjecthandler.cpp index b01810fe6..12c8b343c 100644 --- a/lib/remote/modifyobjecthandler.cpp +++ b/lib/remote/modifyobjecthandler.cpp @@ -59,7 +59,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r params->Set(attr, request.RequestUrl->GetPath()[3]); } - std::vector objs = FilterUtility::GetFilterTargets(qd, params); + std::vector objs = FilterUtility::GetFilterTargets(qd, params, user); Dictionary::Ptr attrs = params->Get("attrs"); diff --git a/lib/remote/objectqueryhandler.cpp b/lib/remote/objectqueryhandler.cpp index 909dabfb2..ae8276a19 100644 --- a/lib/remote/objectqueryhandler.cpp +++ b/lib/remote/objectqueryhandler.cpp @@ -45,6 +45,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re QueryDescription qd; qd.Types.insert(type->GetName()); + qd.Permission = "objects/query/" + type->GetName(); std::vector joinAttrs; joinAttrs.push_back(""); @@ -66,7 +67,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re params->Set(attr, request.RequestUrl->GetPath()[3]); } - std::vector objs = FilterUtility::GetFilterTargets(qd, params); + std::vector objs = FilterUtility::GetFilterTargets(qd, params, user); Array::Ptr results = new Array(); diff --git a/lib/remote/statushandler.cpp b/lib/remote/statushandler.cpp index d3ac9fd08..5ffc829ea 100644 --- a/lib/remote/statushandler.cpp +++ b/lib/remote/statushandler.cpp @@ -19,6 +19,7 @@ #include "remote/statushandler.hpp" #include "remote/httputility.hpp" +#include "remote/filterutility.hpp" #include "base/serializer.hpp" #include "base/statsfunction.hpp" @@ -26,6 +27,48 @@ using namespace icinga; REGISTER_URLHANDLER("/v1/status", StatusHandler); +class StatusTargetProvider : public TargetProvider +{ +public: + DECLARE_PTR_TYPEDEFS(StatusTargetProvider); + + virtual void FindTargets(const String& type, + const boost::function& addTarget) const override + { + typedef std::pair kv_pair; + BOOST_FOREACH(const kv_pair& kv, StatsFunctionRegistry::GetInstance()->GetItems()) { + addTarget(GetTargetByName("Status", kv.first)); + } + } + + virtual Value GetTargetByName(const String& type, const String& name) const override + { + StatsFunction::Ptr func = StatsFunctionRegistry::GetInstance()->GetItem(name); + + Dictionary::Ptr result = new Dictionary(); + + Dictionary::Ptr status = new Dictionary(); + Array::Ptr perfdata = new Array(); + func->Invoke(status, perfdata); + + result->Set("name", name); + result->Set("status", status); + result->Set("perfdata", perfdata); + + return result; + } + + virtual bool IsValidType(const String& type) const override + { + return type == "Status"; + } + + virtual String GetPluralName(const String& type) const override + { + return "statuses"; + } +}; + bool StatusHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { Dictionary::Ptr result = new Dictionary(); @@ -37,46 +80,22 @@ bool StatusHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request return true; } - if (request.RequestUrl->GetPath().size() < 2) { - response.SetStatus(400, "Bad request"); - HttpUtility::SendJsonBody(response, result); - return true; - } - - Array::Ptr results = new Array(); - Dictionary::Ptr resultInner = new Dictionary(); - if (request.RequestUrl->GetPath().size() > 2) { + QueryDescription qd; + qd.Types.insert("Status"); + qd.Provider = new StatusTargetProvider(); + qd.Permission = "status/query"; - StatsFunction::Ptr funcptr = StatsFunctionRegistry::GetInstance()->GetItem(request.RequestUrl->GetPath()[2]); - resultInner = new Dictionary(); + Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); - if (!funcptr) - return false; + params->Set("type", "Status"); - results->Add(resultInner); + if (request.RequestUrl->GetPath().size() >= 3) + params->Set("name", request.RequestUrl->GetPath()[2]); - Dictionary::Ptr status = new Dictionary(); - Array::Ptr perfdata = new Array(); - funcptr->Invoke(status, perfdata); - - resultInner->Set("status", status); - resultInner->Set("perfdata", perfdata); - } else { - typedef std::pair kv_pair; - BOOST_FOREACH(const kv_pair& kv, StatsFunctionRegistry::GetInstance()->GetItems()) { - resultInner = new Dictionary(); - Dictionary::Ptr funcStatus = new Dictionary(); - Array::Ptr funcPData = new Array(); - kv.second->Invoke(funcStatus, funcPData); - - resultInner->Set("name", kv.first); - resultInner->Set("status", funcPData); - resultInner->Set("perfdata", funcPData); + std::vector objs = FilterUtility::GetFilterTargets(qd, params, user); - results->Add(resultInner); - } - } + Array::Ptr results = Array::FromVector(objs); result->Set("results", results); diff --git a/lib/remote/typequeryhandler.cpp b/lib/remote/typequeryhandler.cpp index 9fbeee05a..966323e81 100644 --- a/lib/remote/typequeryhandler.cpp +++ b/lib/remote/typequeryhandler.cpp @@ -77,11 +77,14 @@ public: bool TypeQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { - if (request.RequestMethod != "GET") - return false; + Dictionary::Ptr result = new Dictionary(); - if (request.RequestUrl->GetPath().size() < 2) - return false; + if (request.RequestMethod != "GET") { + response.SetStatus(400, "Bad request"); + result->Set("info", "Request must be type GET"); + HttpUtility::SendJsonBody(response, result); + return true; + } QueryDescription qd; qd.Types.insert("Type"); @@ -97,7 +100,7 @@ bool TypeQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& requ if (request.RequestUrl->GetPath().size() >= 3) params->Set("name", request.RequestUrl->GetPath()[2]); - std::vector objs = FilterUtility::GetFilterTargets(qd, params); + std::vector objs = FilterUtility::GetFilterTargets(qd, params, user); Array::Ptr results = new Array(); @@ -154,7 +157,6 @@ bool TypeQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& requ } } - Dictionary::Ptr result = new Dictionary(); result->Set("results", results); response.SetStatus(200, "OK"); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b8cbca6b2..01488d3d9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,7 +24,7 @@ set(base_test_SOURCES base-stream.cpp base-string.cpp base-timer.cpp base-type.cpp base-value.cpp config-ops.cpp icinga-macros.cpp icinga-perfdata.cpp test.cpp - remote-url.cpp remote-apiuser.cpp + remote-url.cpp ) set(livestatus_test_SOURCES @@ -107,8 +107,6 @@ add_boost_test(base icinga_perfdata/ignore_invalid_warn_crit_min_max icinga_perfdata/invalid icinga_perfdata/multi - remote_apiuser/get_password - remote_apiuser/check_password remote_url/id_and_path remote_url/parameters remote_url/get_and_set diff --git a/test/remote-apiuser.cpp b/test/remote-apiuser.cpp deleted file mode 100644 index b641780d8..000000000 --- a/test/remote-apiuser.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * Icinga 2 * - * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License * - * as published by the Free Software Foundation; either version 2 * - * of the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the Free Software Foundation * - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * - ******************************************************************************/ - -#include "remote/apiuser.hpp" -#include - -using namespace icinga; - -BOOST_AUTO_TEST_SUITE(remote_apiuser) - -BOOST_AUTO_TEST_CASE(construct) -{ - ApiUser::Ptr apiuser = new ApiUser(); - BOOST_CHECK(apiuser); -} - -BOOST_AUTO_TEST_CASE(get_password) -{ - ApiUser::Ptr apiuser = new ApiUser(); - apiuser->SetPassword("icingar0xx"); - - BOOST_CHECK(apiuser->GetPassword() == "*****"); -} - -BOOST_AUTO_TEST_CASE(check_password) -{ - ApiUser::Ptr apiuser = new ApiUser(); - apiuser->SetPassword("icingar0xx"); - - BOOST_CHECK(apiuser->CheckPassword("1cing4r0xx") == false); - BOOST_CHECK(apiuser->CheckPassword("icingar0xx") == true); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index 1dafd7c67..bc16add54 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -1089,10 +1089,11 @@ void ClassCompiler::CodeGenValidator(const std::string& name, const std::string& else m_Impl << "\t\t" << "const Dictionary::Ptr& dict = value;" << std::endl; - m_Impl << (type_check ? "\t" : "") << "\t\t" << "ObjectLock olock(dict);" << std::endl - << (type_check ? "\t" : "") << "\t\t" << "BOOST_FOREACH(const Dictionary::Pair& kv, dict) {" << std::endl - << (type_check ? "\t" : "") << "\t\t\t" << "const String& akey = kv.first;" << std::endl - << (type_check ? "\t" : "") << "\t\t\t" << "const Value& avalue = kv.second;" << std::endl; + m_Impl << (type_check ? "\t" : "") << "\t\t" << "{" << std::endl + << (type_check ? "\t" : "") << "\t\t\t" << "ObjectLock olock(dict);" << std::endl + << (type_check ? "\t" : "") << "\t\t\t" << "BOOST_FOREACH(const Dictionary::Pair& kv, dict) {" << std::endl + << (type_check ? "\t" : "") << "\t\t\t\t" << "const String& akey = kv.first;" << std::endl + << (type_check ? "\t" : "") << "\t\t\t\t" << "const Value& avalue = kv.second;" << std::endl; indent = true; } else if (rule.Type == "Array") { if (type_check) @@ -1101,9 +1102,10 @@ void ClassCompiler::CodeGenValidator(const std::string& name, const std::string& m_Impl << "\t\t" << "const Array::Ptr& arr = value;" << std::endl; m_Impl << (type_check ? "\t" : "") << "\t\t" << "Array::SizeType anum = 0;" << std::endl - << (type_check ? "\t" : "") << "\t\t" << "ObjectLock olock(arr);" << std::endl - << (type_check ? "\t" : "") << "\t\t" << "BOOST_FOREACH(const Value& avalue, arr) {" << std::endl - << (type_check ? "\t" : "") << "\t\t\t" << "String akey = Convert::ToString(anum);" << std::endl; + << (type_check ? "\t" : "") << "\t\t" << "{" << std::endl + << (type_check ? "\t" : "") << "\t\t\t" << "ObjectLock olock(arr);" << std::endl + << (type_check ? "\t" : "") << "\t\t\t" << "BOOST_FOREACH(const Value& avalue, arr) {" << std::endl + << (type_check ? "\t" : "") << "\t\t\t\t" << "String akey = Convert::ToString(anum);" << std::endl; indent = true; } else { m_Impl << (type_check ? "\t" : "") << "\t\t" << "String akey = \"\";" << std::endl @@ -1117,15 +1119,17 @@ void ClassCompiler::CodeGenValidator(const std::string& name, const std::string& else subvalidator_prefix = name; - m_Impl << (type_check ? "\t" : "") << (indent ? "\t" : "") << "\t\t" << "location.push_back(akey);" << std::endl - << (type_check ? "\t" : "") << (indent ? "\t" : "") << "\t\t" << "TIValidate" << subvalidator_prefix << "_" << i << "(object, akey, avalue, location, utils);" << std::endl - << (type_check ? "\t" : "") << (indent ? "\t" : "") << "\t\t" << "location.pop_back();" << std::endl; + m_Impl << (type_check ? "\t" : "") << (indent ? "\t\t" : "") << "\t\t" << "location.push_back(akey);" << std::endl + << (type_check ? "\t" : "") << (indent ? "\t\t" : "") << "\t\t" << "TIValidate" << subvalidator_prefix << "_" << i << "(object, akey, avalue, location, utils);" << std::endl + << (type_check ? "\t" : "") << (indent ? "\t\t" : "") << "\t\t" << "location.pop_back();" << std::endl; if (rule.Type == "Array") - m_Impl << (type_check ? "\t" : "") << "\t\t\t" << "anum++;" << std::endl; + m_Impl << (type_check ? "\t" : "") << "\t\t\t\t" << "anum++;" << std::endl; - if (rule.Type == "Dictionary" || rule.Type == "Array") - m_Impl << (type_check ? "\t" : "") << "\t\t" << "}" << std::endl; + if (rule.Type == "Dictionary" || rule.Type == "Array") { + m_Impl << (type_check ? "\t" : "") << "\t\t\t" << "}" << std::endl + << (type_check ? "\t" : "") << "\t\t" << "}" << std::endl; + } for (std::vector::size_type i = 0; i < rule.Rules.size(); i++) { const Rule& srule = rule.Rules[i]; @@ -1134,8 +1138,8 @@ void ClassCompiler::CodeGenValidator(const std::string& name, const std::string& continue; if (rule.Type == "Dictionary") { - m_Impl << (type_check ? "\t" : "") << "\t\t" << "if (dict.Get(\"" << srule.Pattern << "\").IsEmpty())" << std::endl - << (type_check ? "\t" : "") << "\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast(this), location, \"Required dictionary item '" << srule.Pattern << "' is not set.\"));" << std::endl; + m_Impl << (type_check ? "\t" : "") << "\t\t" << "if (dict->Get(\"" << srule.Pattern << "\").IsEmpty())" << std::endl + << (type_check ? "\t" : "") << "\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast(object), location, \"Required dictionary item '" << srule.Pattern << "' is not set.\"));" << std::endl; } else if (rule.Type == "Array") { int index = -1; std::stringstream idxbuf;