Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Cannot add comment for non-existent object"); if (!params->Contains("author") || !params->Contains("comment")) return ApiActions::CreateResult(403, "Comments require author and comment."); String commentName = Comment::AddComment(checkable, CommentUser, HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), 0); Comment::Ptr comment = Comment::GetByName(commentName); Dictionary::Ptr additional = new Dictionary(); additional->Set("name", commentName); additional->Set("legacy_id", comment->GetLegacyId()); return ApiActions::CreateResult(200, "Successfully added comment '" + commentName + "' for object '" + checkable->GetName() + "'.", additional); }
bool ApiListener::UpdateConfigDir(const Dictionary::Ptr& oldConfig, const Dictionary::Ptr& newConfig, const String& configDir, bool authoritative) { bool configChange = false; if (oldConfig->Contains(".timestamp") && newConfig->Contains(".timestamp")) { double oldTS = Convert::ToDouble(oldConfig->Get(".timestamp")); double newTS = Convert::ToDouble(newConfig->Get(".timestamp")); /* skip update if our config is newer */ if (oldTS <= newTS) return false; } { ObjectLock olock(newConfig); BOOST_FOREACH(const Dictionary::Pair& kv, newConfig) { if (oldConfig->Get(kv.first) != kv.second) { configChange = true; String path = configDir + "/" + kv.first; Log(LogInformation, "ApiListener") << "Updating configuration file: " << path; //pass the directory and generate a dir tree, if not existing already Utility::MkDirP(Utility::DirName(path), 0755); std::ofstream fp(path.CStr(), std::ofstream::out | std::ostream::binary | std::ostream::trunc); fp << kv.second; fp.close(); } } } ObjectLock xlock(oldConfig); BOOST_FOREACH(const Dictionary::Pair& kv, oldConfig) { if (!newConfig->Contains(kv.first)) { configChange = true; String path = configDir + "/" + kv.first; (void) unlink(path.CStr()); } } String tsPath = configDir + "/.timestamp"; if (!Utility::PathExists(tsPath)) { std::ofstream fp(tsPath.CStr(), std::ofstream::out | std::ostream::trunc); fp << std::fixed << Utility::GetTime(); fp.close(); } if (authoritative) { String authPath = configDir + "/.authoritative"; if (!Utility::PathExists(authPath)) { std::ofstream fp(authPath.CStr(), std::ofstream::out | std::ostream::trunc); fp.close(); } } return configChange; }
void JsonRpcConnection::MessageHandler(const String& jsonString) { Dictionary::Ptr message = JsonRpc::DecodeMessage(jsonString); m_Seen = Utility::GetTime(); if (m_HeartbeatTimeout != 0) m_NextHeartbeat = Utility::GetTime() + m_HeartbeatTimeout; if (m_Endpoint && message->Contains("ts")) { double ts = message->Get("ts"); /* ignore old messages */ if (ts < m_Endpoint->GetRemoteLogPosition()) return; m_Endpoint->SetRemoteLogPosition(ts); } MessageOrigin::Ptr origin = new MessageOrigin(); origin->FromClient = this; if (m_Endpoint) { if (m_Endpoint->GetZone() != Zone::GetLocalZone()) origin->FromZone = m_Endpoint->GetZone(); else origin->FromZone = Zone::GetByName(message->Get("originZone")); } String method = message->Get("method"); Log(LogNotice, "JsonRpcConnection") << "Received '" << method << "' message from '" << m_Identity << "'"; Dictionary::Ptr resultMessage = new Dictionary(); try { ApiFunction::Ptr afunc = ApiFunction::GetByName(method); if (!afunc) BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + method + "' does not exist.")); resultMessage->Set("result", afunc->Invoke(origin, message->Get("params"))); } catch (const std::exception& ex) { /* TODO: Add a user readable error message for the remote caller */ resultMessage->Set("error", DiagnosticInformation(ex)); std::ostringstream info; info << "Error while processing message for identity '" << m_Identity << "'"; Log(LogWarning, "JsonRpcConnection") << info.str() << "\n" << DiagnosticInformation(ex); } if (message->Contains("id")) { resultMessage->Set("jsonrpc", "2.0"); resultMessage->Set("id", message->Get("id")); SendMessage(resultMessage); } }
Value ClusterEvents::SendNotificationsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); if (!endpoint) { Log(LogNotice, "ClusterEvents") << "Discarding 'send notification' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; return Empty; } Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) return Empty; Checkable::Ptr checkable; if (params->Contains("service")) checkable = host->GetServiceByShortName(params->Get("service")); else checkable = host; if (!checkable) return Empty; if (origin->FromZone && origin->FromZone != Zone::GetLocalZone()) { Log(LogNotice, "ClusterEvents") << "Discarding 'send custom notification' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; return Empty; } CheckResult::Ptr cr; Array::Ptr vperf; if (params->Contains("cr")) { cr = new CheckResult(); Dictionary::Ptr vcr = params->Get("cr"); if (vcr && vcr->Contains("performance_data")) { vperf = vcr->Get("performance_data"); if (vperf) vcr->Remove("performance_data"); Deserialize(cr, vcr, true); } } NotificationType type = static_cast<NotificationType>(static_cast<int>(params->Get("type"))); String author = params->Get("author"); String text = params->Get("text"); Checkable::OnNotificationsRequested(checkable, type, cr, author, text, origin); return Empty; }
void Command::Validate(int types, const ValidationUtils& utils) { ObjectImpl<Command>::Validate(types, utils); Dictionary::Ptr arguments = GetArguments(); if (!(types & FAConfig)) return; if (arguments) { if (!GetCommandLine().IsObjectType<Array>()) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("command"), "Attribute 'command' must be an array if the 'arguments' attribute is set.")); 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")) { Value argvalue = argdict->Get("value"); if (argvalue.IsString() && !MacroProcessor::ValidateMacroString(argvalue)) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("arguments")(kv.first)("value"), "Validation failed: Closing $ not found in macro format string '" + argvalue + "'.")); } if (argdict->Contains("set_if")) { Value argsetif = argdict->Get("set_if"); if (argsetif.IsString() && !MacroProcessor::ValidateMacroString(argsetif)) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("arguments")(kv.first)("set_if"), "Closing $ not found in macro format string '" + argsetif + "'.")); } } else if (arginfo.IsString()) { if (!MacroProcessor::ValidateMacroString(arginfo)) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("arguments")(kv.first), "Closing $ not found in macro format string '" + arginfo + "'.")); } } } Dictionary::Ptr env = GetEnv(); if (env) { ObjectLock olock(env); BOOST_FOREACH(const Dictionary::Pair& kv, env) { const Value& envval = kv.second; if (!envval.IsString() || envval.IsEmpty()) continue; if (!MacroProcessor::ValidateMacroString(envval)) BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("env")(kv.first), "Closing $ not found in macro format string '" + envval + "'.")); } } }
Dictionary::Ptr ApiActions::ProcessCheckResult(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Cannot process passive check result for non-existent object."); if (!checkable->GetEnablePassiveChecks()) return ApiActions::CreateResult(403, "Passive checks are disabled for object '" + checkable->GetName() + "'."); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); if (!params->Contains("exit_status")) return ApiActions::CreateResult(403, "Parameter 'exit_status' is required."); int exitStatus = HttpUtility::GetLastParameter(params, "exit_status"); ServiceState state; if (!service) { if (exitStatus == 0) state = ServiceOK; else if (exitStatus == 1) state = ServiceCritical; else return ApiActions::CreateResult(403, "Invalid 'exit_status' for Host " + checkable->GetName() + "."); } else { state = PluginUtility::ExitStatusToState(exitStatus); } if (!params->Contains("plugin_output")) return ApiActions::CreateResult(403, "Parameter 'plugin_output' is required"); CheckResult::Ptr cr = new CheckResult(); cr->SetOutput(HttpUtility::GetLastParameter(params, "plugin_output")); cr->SetState(state); cr->SetCheckSource(HttpUtility::GetLastParameter(params, "check_source")); cr->SetPerformanceData(params->Get("performance_data")); cr->SetCommand(params->Get("check_command")); checkable->ProcessCheckResult(cr); /* Reschedule the next check. The side effect of this is that for as long * as we receive passive results for a service we won't execute any * active checks. */ checkable->SetNextCheck(Utility::GetTime() + checkable->GetCheckInterval()); return ApiActions::CreateResult(200, "Successfully processed check result for object '" + checkable->GetName() + "'."); }
void UserDbObject::OnConfigUpdate(void) { Dictionary::Ptr fields = new Dictionary(); User::Ptr user = static_pointer_cast<User>(GetObject()); /* contact addresses */ Log(LogDebug, "UserDbObject") << "contact addresses for '" << user->GetName() << "'"; Dictionary::Ptr vars = user->GetVars(); if (vars) { /* This is sparta. */ for (int i = 1; i <= 6; i++) { String key = "address" + Convert::ToString(i); if (!vars->Contains(key)) continue; String val = vars->Get(key); fields->Set("contact_id", DbValue::FromObjectInsertID(user)); fields->Set("address_number", i); fields->Set("address", val); fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ DbQuery query; query.Type = DbQueryInsert; query.Table = "contact_addresses"; query.Fields = fields; OnQuery(query); } } }
/** * The entry point for the "ca list" CLI command. * * @returns An exit status. */ int CAListCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const { Dictionary::Ptr requests = PkiUtility::GetCertificateRequests(); if (vm.count("json")) std::cout << JsonEncode(requests); else { ObjectLock olock(requests); std::cout << "Fingerprint | Timestamp | Signed | Subject\n"; std::cout << "-----------------------------------------------------------------|--------------------------|--------|--------\n"; for (auto& kv : requests) { Dictionary::Ptr request = kv.second; std::cout << kv.first << " | " /* << Utility::FormatDateTime("%Y/%m/%d %H:%M:%S", request->Get("timestamp")) */ << request->Get("timestamp") << " | " << (request->Contains("cert_response") ? "*" : " ") << " " << " | " << request->Get("subject") << "\n"; } } return 0; }
void ConfigObject::DumpModifiedAttributes(const std::function<void(const ConfigObject::Ptr&, const String&, const Value&)>& callback) { for (const Type::Ptr& type : Type::GetAllTypes()) { auto *dtype = dynamic_cast<ConfigType *>(type.get()); if (!dtype) continue; for (const ConfigObject::Ptr& object : dtype->GetObjects()) { Dictionary::Ptr originalAttributes = object->GetOriginalAttributes(); if (!originalAttributes) continue; ObjectLock olock(originalAttributes); for (const Dictionary::Pair& kv : originalAttributes) { String key = kv.first; Type::Ptr type = object->GetReflectionType(); std::vector<String> tokens = key.Split("."); String fieldName = tokens[0]; int fid = type->GetFieldId(fieldName); Value currentValue = object->GetField(fid); Value modifiedValue; if (tokens.size() > 1) { Value current = currentValue; for (std::vector<String>::size_type i = 1; i < tokens.size() - 1; i++) { if (!current.IsObjectType<Dictionary>()) BOOST_THROW_EXCEPTION(std::invalid_argument("Value must be a dictionary.")); Dictionary::Ptr dict = current; const String& key = tokens[i]; if (!dict->Contains(key)) break; current = dict->Get(key); } if (!current.IsObjectType<Dictionary>()) BOOST_THROW_EXCEPTION(std::invalid_argument("Value must be a dictionary.")); Dictionary::Ptr dict = current; const String& key = tokens[tokens.size() - 1]; modifiedValue = dict->Get(key); } else modifiedValue = currentValue; callback(object, key, modifiedValue); } } } }
wxPGProperty *MainForm::ValueToProperty(const String& name, const Value& value) { wxPGProperty *prop; if (value.IsNumber()) { prop = new wxFloatProperty(name.GetData(), wxPG_LABEL, value); prop->SetAttribute(wxPG_ATTR_UNITS, "Number"); return prop; } else if (value.IsBoolean()) { prop = new wxBoolProperty(name.GetData(), wxPG_LABEL, value); prop->SetAttribute(wxPG_ATTR_UNITS, "Boolean"); return prop; } else if (value.IsObjectType<Array>()) { wxArrayString val; Array::Ptr arr = value; { ObjectLock olock(arr); for (const Value& aitem : arr) { String val1 = aitem; val.Add(val1.GetData()); } } prop = new wxArrayStringProperty(name.GetData(), wxPG_LABEL, val); prop->SetAttribute(wxPG_ATTR_UNITS, "Array"); return prop; } else if (value.IsObjectType<Dictionary>()) { wxStringProperty *prop = new wxStringProperty(name.GetData(), wxPG_LABEL); Dictionary::Ptr dict = value; { ObjectLock olock(dict); for (const Dictionary::Pair& kv : dict) { if (kv.first != "type") prop->AppendChild(ValueToProperty(kv.first, kv.second)); } } String type = "Dictionary"; if (dict->Contains("type")) type = dict->Get("type"); prop->SetAttribute(wxPG_ATTR_UNITS, type.GetData()); return prop; } else if (value.IsEmpty() && !value.IsString()) { prop = new wxStringProperty(name.GetData(), wxPG_LABEL, ""); prop->SetAttribute(wxPG_ATTR_UNITS, "Empty"); return prop; } else { String val = value; prop = new wxStringProperty(name.GetData(), wxPG_LABEL, val.GetData()); prop->SetAttribute(wxPG_ATTR_UNITS, "String"); return prop; } }
bool DynamicObject::HasAuthority(const String& type) const { Dictionary::Ptr authorityInfo = GetAuthorityInfo(); if (!authorityInfo || !authorityInfo->Contains(type)) return true; return authorityInfo->Get(type); }
Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Cannot acknowledge problem for non-existent object."); if (!params->Contains("author") || !params->Contains("comment")) return ApiActions::CreateResult(403, "Acknowledgements require author and comment."); AcknowledgementType sticky = AcknowledgementNormal; bool notify = false; double timestamp = 0.0; if (params->Contains("sticky")) sticky = AcknowledgementSticky; if (params->Contains("notify")) notify = true; if (params->Contains("expiry")) timestamp = HttpUtility::GetLastParameter(params, "expiry"); else timestamp = 0; Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); if (!service) { if (host->GetState() == HostUp) return ApiActions::CreateResult(409, "Host " + checkable->GetName() + " is UP."); } else { if (service->GetState() == ServiceOK) return ApiActions::CreateResult(409, "Service " + checkable->GetName() + " is OK."); } Comment::AddComment(checkable, CommentAcknowledgement, HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), timestamp); checkable->AcknowledgeProblem(HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), sticky, notify, timestamp); return ApiActions::CreateResult(200, "Successfully acknowledged problem for object '" + checkable->GetName() + "'."); }
Dictionary::Ptr ApiActions::RemoveCommentByID(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { if (!params->Contains("comment_id")) return ApiActions::CreateResult(403, "Parameter 'comment_id' is required."); String comment_id = HttpUtility::GetLastParameter(params, "comment_id"); Comment::RemoveComment(comment_id); return ApiActions::CreateResult(200, "Successfully removed comment '" + comment_id + "'."); }
Dictionary::Ptr ApiActions::RemoveDowntimeByID(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { if (!params->Contains("downtime_id")) return ApiActions::CreateResult(403, "Parameter 'downtime_id' is required."); String downtime_id = HttpUtility::GetLastParameter(params, "downtime_id"); Downtime::RemoveDowntime(downtime_id, true); return ApiActions::CreateResult(200, "Successfully removed downtime '" + downtime_id + "'."); }
Dictionary::Ptr ApiActions::SendCustomNotification(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Cannot send notification for non-existent object."); if (!params->Contains("author")) return ApiActions::CreateResult(403, "Parameter 'author' is required."); if (!params->Contains("comment")) return ApiActions::CreateResult(403, "Parameter 'comment' is required."); if (Convert::ToBool(HttpUtility::GetLastParameter(params, "force"))) checkable->SetForceNextNotification(true); Checkable::OnNotificationsRequested(checkable, NotificationCustom, checkable->GetLastCheckResult(), HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), MessageOrigin::Ptr()); return ApiActions::CreateResult(200, "Successfully sent custom notification for object '" + checkable->GetName() + "'."); }
Dictionary::Ptr DynamicObject::Serialize(int attributeTypes) const { Dictionary::Ptr update = boost::make_shared<Dictionary>(); ASSERT(!OwnsLock()); ObjectLock olock(this); InternalSerialize(update, attributeTypes); /* Make sure our own InternalSerialize() method was called. */ ASSERT(update->Contains("__marker")); update->Remove("__marker"); return update; }
Dictionary::Ptr ApiActions::DelayNotification(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Cannot delay notifications for non-existent object"); if (!params->Contains("timestamp")) return ApiActions::CreateResult(403, "A timestamp is required to delay notifications"); BOOST_FOREACH(const Notification::Ptr& notification, checkable->GetNotifications()) { notification->SetNextNotification(HttpUtility::GetLastParameter(params, "timestamp")); } return ApiActions::CreateResult(200, "Successfully delayed notifications for object '" + checkable->GetName() + "'."); }
Value ClusterEvents::NextCheckChangedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); if (!endpoint) { Log(LogNotice, "ClusterEvents") << "Discarding 'next check changed' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; return Empty; } Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) return Empty; Checkable::Ptr checkable; if (params->Contains("service")) checkable = host->GetServiceByShortName(params->Get("service")); else checkable = host; if (!checkable) return Empty; if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { Log(LogNotice, "ClusterEvents") << "Discarding 'next check changed' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; return Empty; } double nextCheck = params->Get("next_check"); if (nextCheck < Application::GetStartTime() + 60) return Empty; checkable->SetNextCheck(params->Get("next_check"), false, origin); return Empty; }
Dictionary::Ptr ApiActions::RescheduleCheck(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Cannot reschedule check for non-existent object."); if (Convert::ToBool(HttpUtility::GetLastParameter(params, "force"))) checkable->SetForceNextCheck(true); double nextCheck; if (params->Contains("next_check")) nextCheck = HttpUtility::GetLastParameter(params, "next_check"); else nextCheck = Utility::GetTime(); checkable->SetNextCheck(nextCheck); return ApiActions::CreateResult(200, "Successfully rescheduled check for object '" + checkable->GetName() + "'."); }
bool InfoHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) { if (request.RequestUrl->GetPath().size() > 2) return false; if (request.RequestMethod != "GET") return false; if (request.RequestUrl->GetPath().empty()) { response.SetStatus(302, "Found"); response.AddHeader("Location", "/v1"); return true; } if (request.RequestUrl->GetPath()[0] != "v1" || request.RequestUrl->GetPath().size() != 1) return false; response.SetStatus(200, "OK"); std::vector<String> permInfo; Array::Ptr permissions = user->GetPermissions(); if (permissions) { ObjectLock olock(permissions); BOOST_FOREACH(const Value& permission, permissions) { String name; bool hasFilter = false; if (permission.IsObjectType<Dictionary>()) { Dictionary::Ptr dpermission = permission; name = dpermission->Get("permission"); hasFilter = dpermission->Contains("filter"); } else name = permission; if (hasFilter) name += " (filtered)"; permInfo.push_back(name); } }
Value ClusterEvents::AcknowledgementSetAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); if (!endpoint) { Log(LogNotice, "ClusterEvents") << "Discarding 'acknowledgement set' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; return Empty; } Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) return Empty; Checkable::Ptr checkable; if (params->Contains("service")) checkable = host->GetServiceByShortName(params->Get("service")); else checkable = host; if (!checkable) return Empty; if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { Log(LogNotice, "ClusterEvents") << "Discarding 'acknowledgement set' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; return Empty; } checkable->AcknowledgeProblem(params->Get("author"), params->Get("comment"), static_cast<AcknowledgementType>(static_cast<int>(params->Get("acktype"))), params->Get("notify"), params->Get("persistent"), params->Get("expiry"), origin); return Empty; }
Value ClusterEvents::AcknowledgementClearedAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); if (!endpoint) { Log(LogNotice, "ClusterEvents") << "Discarding 'acknowledgement cleared' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; return Empty; } Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) return Empty; Checkable::Ptr checkable; if (params->Contains("service")) checkable = host->GetServiceByShortName(params->Get("service")); else checkable = host; if (!checkable) return Empty; if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { Log(LogNotice, "ClusterEvents") << "Discarding 'acknowledgement cleared' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; return Empty; } checkable->ClearAcknowledgement(origin); return Empty; }
Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) { Checkable::Ptr checkable = static_pointer_cast<Checkable>(object); if (!checkable) return ApiActions::CreateResult(404, "Can't schedule downtime for non-existent object."); if (!params->Contains("start_time") || !params->Contains("end_time") || !params->Contains("duration") || !params->Contains("author") || !params->Contains("comment")) { return ApiActions::CreateResult(404, "Options 'start_time', 'end_time', 'duration', 'author' and 'comment' are required"); } bool fixed = false; if (params->Contains("fixed")) fixed = HttpUtility::GetLastParameter(params, "fixed"); String downtime_id = Downtime::AddDowntime(checkable, HttpUtility::GetLastParameter(params, "author"), HttpUtility::GetLastParameter(params, "comment"), HttpUtility::GetLastParameter(params, "start_time"), HttpUtility::GetLastParameter(params, "end_time"), fixed, HttpUtility::GetLastParameter(params, "trigger_id"), HttpUtility::GetLastParameter(params, "duration")); Downtime::Ptr downtime = Downtime::GetByName(downtime_id); int legacy_id = downtime->GetLegacyId(); Dictionary::Ptr additional = new Dictionary(); additional->Set("downtime_id", downtime_id); additional->Set("legacy_id", legacy_id); return ApiActions::CreateResult(200, "Successfully scheduled downtime with id '" + downtime_id + "' for object '" + checkable->GetName() + "'.", additional); }
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile, const String& certfile, const String& cafile, const boost::shared_ptr<X509>& trustedCert, const String& ticket) { TcpSocket::Ptr client = new TcpSocket(); try { client->Connect(host, port); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "'"; Log(LogDebug, "cli") << "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex); return 1; } boost::shared_ptr<SSL_CTX> sslContext; try { sslContext = MakeSSLContext(certfile, keyfile); } catch (const std::exception& ex) { Log(LogCritical, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'."; Log(LogDebug, "cli") << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "':\n" << DiagnosticInformation(ex); return 1; } TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext); try { stream->Handshake(); } catch (const std::exception&) { Log(LogCritical, "cli", "Client TLS handshake failed."); return 1; } boost::shared_ptr<X509> peerCert = stream->GetPeerCertificate(); if (X509_cmp(peerCert.get(), trustedCert.get())) { Log(LogCritical, "cli", "Peer certificate does not match trusted certificate."); return 1; } Dictionary::Ptr request = new Dictionary(); String msgid = Utility::NewUniqueID(); request->Set("jsonrpc", "2.0"); request->Set("id", msgid); request->Set("method", "pki::RequestCertificate"); Dictionary::Ptr params = new Dictionary(); params->Set("ticket", String(ticket)); request->Set("params", params); JsonRpc::SendMessage(stream, request); String jsonString; Dictionary::Ptr response; StreamReadContext src; for (;;) { StreamReadStatus srs = JsonRpc::ReadMessage(stream, &jsonString, src); if (srs == StatusEof) break; if (srs != StatusNewItem) continue; response = JsonRpc::DecodeMessage(jsonString); if (response && response->Contains("error")) { Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log (notice or debug)."); #ifdef I2_DEBUG /* we shouldn't expose master errors to the user in production environments */ Log(LogCritical, "cli", response->Get("error")); #endif /* I2_DEBUG */ return 1; } if (response && (response->Get("id") != msgid)) continue; break; } if (!response) { Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log."); return 1; } Dictionary::Ptr result = response->Get("result"); if (result->Contains("error")) { Log(LogCritical, "cli", result->Get("error")); return 1; } std::ofstream fpcert; fpcert.open(certfile.CStr()); fpcert << result->Get("cert"); fpcert.close(); if (fpcert.fail()) { Log(LogCritical, "cli") << "Could not write certificate to file '" << certfile << "'."; return 1; } Log(LogInformation, "cli") << "Writing signed certificate to file '" << certfile << "'."; std::ofstream fpca; fpca.open(cafile.CStr()); fpca << result->Get("ca"); fpca.close(); if (fpca.fail()) { Log(LogCritical, "cli") << "Could not open CA certificate file '" << cafile << "' for writing."; return 1; } Log(LogInformation, "cli") << "Writing CA certificate to file '" << cafile << "'."; return 0; }
static bool DictionaryContains(const String& key) { ScriptFrame *vframe = ScriptFrame::GetCurrentFrame(); Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self); return self->Contains(key); }
bool ApiClient::ProcessMessage(void) { Dictionary::Ptr message; if (m_Stream->IsEof()) return false; try { message = JsonRpc::ReadMessage(m_Stream); } catch (const openssl_error& ex) { const unsigned long *pe = boost::get_error_info<errinfo_openssl_error>(ex); if (pe && *pe == 0) return false; /* Connection was closed cleanly */ throw; } if (!message) return false; if (message->Get("method") != "log::SetLogPosition") m_Seen = Utility::GetTime(); if (m_Endpoint && message->Contains("ts")) { double ts = message->Get("ts"); /* ignore old messages */ if (ts < m_Endpoint->GetRemoteLogPosition()) return true; m_Endpoint->SetRemoteLogPosition(ts); } MessageOrigin origin; origin.FromClient = GetSelf(); if (m_Endpoint) { if (m_Endpoint->GetZone() != Zone::GetLocalZone()) origin.FromZone = m_Endpoint->GetZone(); else origin.FromZone = Zone::GetByName(message->Get("originZone")); } String method = message->Get("method"); Log(LogNotice, "ApiClient") << "Received '" << method << "' message from '" << m_Identity << "'"; Dictionary::Ptr resultMessage = make_shared<Dictionary>(); try { ApiFunction::Ptr afunc = ApiFunction::GetByName(method); if (!afunc) BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + method + "' does not exist.")); resultMessage->Set("result", afunc->Invoke(origin, message->Get("params"))); } catch (const std::exception& ex) { resultMessage->Set("error", DiagnosticInformation(ex)); } if (message->Contains("id")) { resultMessage->Set("jsonrpc", "2.0"); resultMessage->Set("id", message->Get("id")); JsonRpc::SendMessage(m_Stream, resultMessage); } return true; }
void ConfigObject::RestoreAttribute(const String& attr, bool updateVersion) { Type::Ptr type = GetReflectionType(); std::vector<String> tokens = attr.Split("."); String fieldName = tokens[0]; int fid = type->GetFieldId(fieldName); Value currentValue = GetField(fid); Dictionary::Ptr original_attributes = GetOriginalAttributes(); if (!original_attributes) return; Value oldValue = original_attributes->Get(attr); Value newValue; if (tokens.size() > 1) { newValue = currentValue.Clone(); Value current = newValue; if (current.IsEmpty()) BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot restore non-existent object attribute")); String prefix = tokens[0]; for (std::vector<String>::size_type i = 1; i < tokens.size() - 1; i++) { if (!current.IsObjectType<Dictionary>()) BOOST_THROW_EXCEPTION(std::invalid_argument("Value must be a dictionary.")); Dictionary::Ptr dict = current; const String& key = tokens[i]; prefix += "." + key; if (!dict->Contains(key)) BOOST_THROW_EXCEPTION(std::invalid_argument("Cannot restore non-existent object attribute")); current = dict->Get(key); } if (!current.IsObjectType<Dictionary>()) BOOST_THROW_EXCEPTION(std::invalid_argument("Value must be a dictionary.")); Dictionary::Ptr dict = current; const String& key = tokens[tokens.size() - 1]; prefix += "." + key; std::vector<String> restoredAttrs; { ObjectLock olock(original_attributes); for (const auto& kv : original_attributes) { std::vector<String> originalTokens = String(kv.first).Split("."); if (tokens.size() > originalTokens.size()) continue; bool match = true; for (std::vector<String>::size_type i = 0; i < tokens.size(); i++) { if (tokens[i] != originalTokens[i]) { match = false; break; } } if (!match) continue; Dictionary::Ptr dict; if (tokens.size() == originalTokens.size()) dict = current; else { Value currentSub = current; for (std::vector<String>::size_type i = tokens.size() - 1; i < originalTokens.size() - 1; i++) { dict = currentSub; currentSub = dict->Get(originalTokens[i]); if (!currentSub.IsObjectType<Dictionary>()) { currentSub = new Dictionary(); dict->Set(originalTokens[i], currentSub); } } dict = currentSub; } dict->Set(originalTokens[originalTokens.size() - 1], kv.second); restoredAttrs.push_back(kv.first); } } for (const String& attr : restoredAttrs) original_attributes->Remove(attr); } else { newValue = oldValue; } original_attributes->Remove(attr); SetField(fid, newValue); if (updateVersion) SetVersion(Utility::GetTime()); }
void PluginUtility::ExecuteCommand(const Command::Ptr& commandObj, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, const MacroProcessor::ResolverList& macroResolvers, const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros, const boost::function<void(const Value& commandLine, const ProcessResult&)>& callback) { Value raw_command = commandObj->GetCommandLine(); Dictionary::Ptr raw_arguments = commandObj->GetArguments(); Value command; if (!raw_arguments || raw_command.IsObjectType<Array>()) command = MacroProcessor::ResolveMacros(raw_command, macroResolvers, cr, NULL, Utility::EscapeShellArg, resolvedMacros, useResolvedMacros); else { Array::Ptr arr = new Array(); arr->Add(raw_command); command = arr; } if (raw_arguments) { std::vector<CommandArgument> args; ObjectLock olock(raw_arguments); BOOST_FOREACH(const Dictionary::Pair& kv, raw_arguments) { const Value& arginfo = kv.second; CommandArgument arg; arg.Key = kv.first; bool required = false; String argval; if (arginfo.IsObjectType<Dictionary>()) { Dictionary::Ptr argdict = arginfo; argval = argdict->Get("value"); if (argdict->Contains("required")) required = argdict->Get("required"); arg.SkipKey = argdict->Get("skip_key"); arg.Order = argdict->Get("order"); String set_if = argdict->Get("set_if"); if (!set_if.IsEmpty()) { String missingMacro; String set_if_resolved = MacroProcessor::ResolveMacros(set_if, macroResolvers, cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros); if (!missingMacro.IsEmpty()) continue; try { if (!Convert::ToLong(set_if_resolved)) continue; } catch (const std::exception& ex) { /* tried to convert a string */ Log(LogWarning, "PluginUtility") << "Error evaluating set_if value '" << set_if_resolved << "': " << ex.what(); continue; } } } else argval = arginfo; if (argval.IsEmpty()) arg.SkipValue = true; String missingMacro; arg.Value = MacroProcessor::ResolveMacros(argval, macroResolvers, cr, &missingMacro, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros); if (!missingMacro.IsEmpty()) { if (required) { String message = "Non-optional macro '" + missingMacro + "' used in argument '" + arg.Key + "' is missing while executing command '" + commandObj->GetName() + "' for object '" + checkable->GetName() + "'"; Log(LogWarning, "PluginUtility", message); if (callback) { ProcessResult pr; pr.PID = -1; pr.ExecutionStart = Utility::GetTime(); pr.ExecutionStart = pr.ExecutionStart; pr.ExitStatus = 3; /* Unknown */ pr.Output = message; callback(Empty, pr); } return; } continue; } args.push_back(arg); } std::sort(args.begin(), args.end()); Array::Ptr command_arr = command; BOOST_FOREACH(const CommandArgument& arg, args) { if (!arg.SkipKey) command_arr->Add(arg.Key); if (!arg.SkipValue) command_arr->Add(arg.Value); } } Dictionary::Ptr envMacros = new Dictionary(); Dictionary::Ptr env = commandObj->GetEnv(); if (env) { ObjectLock olock(env); BOOST_FOREACH(const Dictionary::Pair& kv, env) { String name = kv.second; Value value = MacroProcessor::ResolveMacros(name, macroResolvers, cr, NULL, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros); envMacros->Set(kv.first, value); } }
bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { if (request.RequestUrl->GetPath().size() != 4) return false; if (request.RequestMethod != "PUT") return false; Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { HttpUtility::SendJsonError(response, 400, "Invalid type specified."); 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"); Dictionary::Ptr attrs = params->Get("attrs"); Dictionary::Ptr result1 = new Dictionary(); int code; String status; Array::Ptr errors = new Array(); bool ignoreOnError = false; if (params->Contains("ignore_on_error")) ignoreOnError = HttpUtility::GetLastParameter(params, "ignore_on_error"); String config = ConfigObjectUtility::CreateObjectConfig(type, name, ignoreOnError, templates, attrs); if (!ConfigObjectUtility::CreateObject(type, name, config, errors)) { result1->Set("errors", errors); HttpUtility::SendJsonError(response, 500, "Object could not be created."); return true; } ConfigType::Ptr dtype = ConfigType::GetByName(type->GetName()); ConfigObject::Ptr obj = dtype->GetObject(name); result1->Set("code", 200); if (obj) result1->Set("status", "Object was created"); else if (!obj && ignoreOnError) result1->Set("status", "Object was not created but 'ignore_on_error' was set to true"); Array::Ptr results = new Array(); results->Add(result1); Dictionary::Ptr result = new Dictionary(); result->Set("results", results); response.SetStatus(200, "OK"); HttpUtility::SendJsonBody(response, result); return true; }
bool IcingaApplication::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const { double now = Utility::GetTime(); if (macro == "timet") { *result = static_cast<long>(now); return true; } else if (macro == "long_date_time") { *result = Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", now); return true; } else if (macro == "short_date_time") { *result = Utility::FormatDateTime("%Y-%m-%d %H:%M:%S", now); return true; } else if (macro == "date") { *result = Utility::FormatDateTime("%Y-%m-%d", now); return true; } else if (macro == "time") { *result = Utility::FormatDateTime("%H:%M:%S %z", now); return true; } else if (macro == "uptime") { *result = Utility::FormatDuration(Utility::GetTime() - Application::GetStartTime()); return true; } Dictionary::Ptr vars = GetVars(); if (vars && vars->Contains(macro)) { *result = vars->Get(macro); return true; } if (macro.Contains("num_services")) { ServiceStatistics ss = CIB::CalculateServiceStats(); if (macro == "num_services_ok") { *result = ss.services_ok; return true; } else if (macro == "num_services_warning") { *result = ss.services_warning; return true; } else if (macro == "num_services_critical") { *result = ss.services_critical; return true; } else if (macro == "num_services_unknown") { *result = ss.services_unknown; return true; } else if (macro == "num_services_pending") { *result = ss.services_pending; return true; } else if (macro == "num_services_unreachable") { *result = ss.services_unreachable; return true; } else if (macro == "num_services_flapping") { *result = ss.services_flapping; return true; } else if (macro == "num_services_in_downtime") { *result = ss.services_in_downtime; return true; } else if (macro == "num_services_acknowledged") { *result = ss.services_acknowledged; return true; } } else if (macro.Contains("num_hosts")) { HostStatistics hs = CIB::CalculateHostStats(); if (macro == "num_hosts_up") { *result = hs.hosts_up; return true; } else if (macro == "num_hosts_down") { *result = hs.hosts_down; return true; } else if (macro == "num_hosts_pending") { *result = hs.hosts_pending; return true; } else if (macro == "num_hosts_unreachable") { *result = hs.hosts_unreachable; return true; } else if (macro == "num_hosts_flapping") { *result = hs.hosts_flapping; return true; } else if (macro == "num_hosts_in_downtime") { *result = hs.hosts_in_downtime; return true; } else if (macro == "num_hosts_acknowledged") { *result = hs.hosts_acknowledged; return true; } } return false; }