]> granicus.if.org Git - icinga2/commitdiff
Implement API permissions
authorGunnar Beutner <gunnar@beutner.name>
Mon, 28 Sep 2015 06:57:25 +0000 (08:57 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Mon, 28 Sep 2015 12:30:46 +0000 (14:30 +0200)
fixes #9088

20 files changed:
lib/cli/apisetuputility.cpp
lib/remote/actionshandler.cpp
lib/remote/apiuser.cpp
lib/remote/apiuser.hpp
lib/remote/apiuser.ti
lib/remote/configfileshandler.cpp
lib/remote/configpackageshandler.cpp
lib/remote/configstageshandler.cpp
lib/remote/createobjecthandler.cpp
lib/remote/deleteobjecthandler.cpp
lib/remote/filterutility.cpp
lib/remote/filterutility.hpp
lib/remote/httpserverconnection.cpp
lib/remote/modifyobjecthandler.cpp
lib/remote/objectqueryhandler.cpp
lib/remote/statushandler.cpp
lib/remote/typequeryhandler.cpp
test/CMakeLists.txt
test/remote-apiuser.cpp [deleted file]
tools/mkclass/classcompiler.cpp

index ca8649c3cbb51bd37fecf3229c5efb655e95283c..e231fcef07804dae197760779393500eda2eab86 100644 (file)
@@ -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();
index 7db830b675624e514e626498078dbf205902b91a..a9f580758c1783ec068605603d8fb463339fd663 100644 (file)
@@ -59,19 +59,24 @@ bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& reques
        const std::vector<String>& types = action->GetTypes();
        std::vector<Value> objs;
 
+       String permission = "actions/" + actionName;
+
        if (!types.empty()) {
                qd.Types = std::set<String>(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();
 
index 0ba44e30e3e9ca1bb8612bda50c610c412d974f5..9c26a6d88597d0f04efbdc9dd7b1b8530ea99eef 100644 (file)
@@ -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<ApiUser>()) {
index 2fa2dd6c2b62ddfb52e8256e73624cefd213315c..1c4abc551a04d41150f540cd13ee3968ea3ce9d7 100644 (file)
@@ -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);
 };
 
index 7007fb2654c590461fa60385faa837615c751403..ac4666e99c986446eb030a2390699b849845b960 100644 (file)
@@ -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;
+               };
+       };
 };
 
 }
index 28971010f04d51a18c3d13db87ad272308960b4e..cda6a96280b48cd63adc7b25f0755fbf40400a7c 100644 (file)
@@ -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 <boost/algorithm/string/join.hpp>
 #include <fstream>
@@ -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");
 
index 946c0c7aceb54a57c9ddfe4352e75f377c000f24..23a1fc57942f2dcf146d0bfae3e539cfcf37b7a9 100644 (file)
@@ -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 <boost/algorithm/string/join.hpp>
 
@@ -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<String> 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)
index f7e801d7858e43718e08993ef29e3b563dae9b40..4a9d9e1817ad1124db5f5b3ff241a9bca2086127 100644 (file)
@@ -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 <boost/foreach.hpp>
@@ -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)
index a1d4d6d962270749d16275e6fc568ef961e13627..3e0770e3932fe926cd1c1c94a35f6c57f59edcc1 100644 (file)
@@ -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");
index 6e043091e7768a796e34bd2d20c8796da5ba42c9..8d4384672fd514b455fdbc93062e79462f8d626d 100644 (file)
@@ -66,7 +66,7 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
                params->Set(attr, request.RequestUrl->GetPath()[3]);
        }
 
-       std::vector<Value> objs = FilterUtility::GetFilterTargets(qd, params);
+       std::vector<Value> objs = FilterUtility::GetFilterTargets(qd, params, user);
 
        bool cascade = HttpUtility::GetLastParameter(params, "cascade");
 
index a127172a7867841a16066ab5377cd3af2f8057ac..e8c9503cb9d1fb324add4c03e00042a05ef3f14a 100644 (file)
@@ -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<Value>& 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<Value>& result, const Object::Ptr& target)
+{
+       if (EvaluateFilter(permissionFrame, permissionFilter, target) && EvaluateFilter(frame, ufilter, target))
                result.push_back(target);
 }
 
-std::vector<Value> 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>()) {
+                               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<Expression *> 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<Value> FilterUtility::GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user)
 {
        std::vector<Value> result;
 
@@ -115,6 +179,11 @@ std::vector<Value> 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<Value> 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<Value> 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<Value> 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("<API query>", filter);
                ScriptFrame frame;
                frame.Sandboxed = true;
+               Dictionary::Ptr uvars = new Dictionary();
+
+               Expression *ufilter = ConfigCompiler::CompileText("<API query>", 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;
index 176110597301dea40af14564de9407c5eea5ef14..f2b13260dfc4fadaa9f4fde7d40e28d91ef31a95 100644 (file)
@@ -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 <set>
@@ -54,6 +56,7 @@ struct QueryDescription
 {
        std::set<String> 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<Value> GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query);
+       static void CheckPermission(const ApiUser::Ptr& user, const String& permission, Expression **filter = NULL);
+       static std::vector<Value> GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query, const ApiUser::Ptr& user);
 };
 
 }
index 2c7e18902c9a554c8225fd122ac2e69781b5b166..4348be986caf43b66a7ec5b3f01fa28954f89178 100644 (file)
@@ -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();
        }
 
index b01810fe6995968c0b4308b8fe93926100e732bc..12c8b343c8877ce2c10e739a6ac75847b7f83852 100644 (file)
@@ -59,7 +59,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
                params->Set(attr, request.RequestUrl->GetPath()[3]);
        }
 
-       std::vector<Value> objs = FilterUtility::GetFilterTargets(qd, params);
+       std::vector<Value> objs = FilterUtility::GetFilterTargets(qd, params, user);
 
        Dictionary::Ptr attrs = params->Get("attrs");
 
index 909dabfb2b6d7a1c74f3b4ab69ba12826f74eda2..ae8276a19240668f38d6708ee124a5e255195227 100644 (file)
@@ -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<String> 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<Value> objs = FilterUtility::GetFilterTargets(qd, params);
+       std::vector<Value> objs = FilterUtility::GetFilterTargets(qd, params, user);
 
        Array::Ptr results = new Array();
 
index d3ac9fd08a21752a0f5d4755f5ac1527e763c6dc..5ffc829ea45a14361a236ed959cbdd346809de45 100644 (file)
@@ -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<void (const Value&)>& addTarget) const override
+       {
+               typedef std::pair<String, StatsFunction::Ptr> 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<String, StatsFunction::Ptr> 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<Value> objs = FilterUtility::GetFilterTargets(qd, params, user);
 
-                       results->Add(resultInner);
-               }
-       }
+       Array::Ptr results = Array::FromVector(objs);
 
        result->Set("results", results);
 
index 9fbeee05a79337b30fa0ca2eec1944ea8deb5a62..966323e818a253b4900ac08d0d2c6fc3e31bd37f 100644 (file)
@@ -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<Value> objs = FilterUtility::GetFilterTargets(qd, params);
+       std::vector<Value> 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");
index b8cbca6b21f095e8311c51f3ddbb6c0e6b87d863..01488d3d9f0e3028dcc436393c62056f4c0cbf52 100644 (file)
@@ -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 (file)
index b641780..0000000
+++ /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 <boost/test/unit_test.hpp>
-
-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()
index 1dafd7c67088ddd54eaeb7526fff1aace883bbf5..bc16add54bb022fd8d5fbb84070c9426f64b5421 100644 (file)
@@ -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<Rule>::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<ConfigObject *>(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<ConfigObject>(object), location, \"Required dictionary item '" << srule.Pattern << "' is not set.\"));" << std::endl;
                                        } else if (rule.Type == "Array") {
                                                int index = -1;
                                                std::stringstream idxbuf;