Value CheckerComponent::StatsFunc(Dictionary::Ptr& status, Dictionary::Ptr& perfdata) { Dictionary::Ptr nodes = make_shared<Dictionary>(); BOOST_FOREACH(const CheckerComponent::Ptr& checker, DynamicType::GetObjects<CheckerComponent>()) { unsigned long idle = checker->GetIdleServices(); unsigned long pending = checker->GetPendingServices(); Dictionary::Ptr stats = make_shared<Dictionary>(); stats->Set("idle", idle); stats->Set("pending", pending); nodes->Set(checker->GetName(), stats); String perfdata_prefix = "checkercomponent_" + checker->GetName() + "_"; perfdata->Set(perfdata_prefix + "idle", Convert::ToDouble(idle)); perfdata->Set(perfdata_prefix + "pending", Convert::ToDouble(pending)); }
void ClusterEvents::NextNotificationChangedHandler(const Notification::Ptr& notification, const MessageOrigin::Ptr& origin) { ApiListener::Ptr listener = ApiListener::GetInstance(); if (!listener) return; Dictionary::Ptr params = new Dictionary(); params->Set("notification", notification->GetName()); params->Set("next_notification", notification->GetNextNotification()); Dictionary::Ptr message = new Dictionary(); message->Set("jsonrpc", "2.0"); message->Set("method", "event::SetNextNotification"); message->Set("params", params); listener->RelayMessage(origin, notification, message, true); }
void ClusterEvents::SendNotificationsHandler(const Checkable::Ptr& checkable, NotificationType type, const CheckResult::Ptr& cr, const String& author, const String& text, const MessageOrigin::Ptr& origin) { ApiListener::Ptr listener = ApiListener::GetInstance(); if (!listener) return; Dictionary::Ptr message = MakeCheckResultMessage(checkable, cr); message->Set("method", "event::SendNotifications"); Dictionary::Ptr params = message->Get("params"); params->Set("type", type); params->Set("author", author); params->Set("text", text); listener->RelayMessage(origin, nullptr, message, true); }
void CheckerComponent::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata) { DictionaryData nodes; for (const CheckerComponent::Ptr& checker : ConfigType::GetObjectsByType<CheckerComponent>()) { unsigned long idle = checker->GetIdleCheckables(); unsigned long pending = checker->GetPendingCheckables(); nodes.emplace_back(checker->GetName(), new Dictionary({ { "idle", idle }, { "pending", pending } })); String perfdata_prefix = "checkercomponent_" + checker->GetName() + "_"; perfdata->Add(new PerfdataValue(perfdata_prefix + "idle", Convert::ToDouble(idle))); perfdata->Add(new PerfdataValue(perfdata_prefix + "pending", Convert::ToDouble(pending))); } status->Set("checkercomponent", new Dictionary(std::move(nodes))); }
void ApiClient::SendMessageSync(const Dictionary::Ptr& message) { try { ObjectLock olock(m_Stream); if (m_Stream->IsEof()) return; JsonRpc::SendMessage(m_Stream, message); if (message->Get("method") != "log::SetLogPosition") m_Seen = Utility::GetTime(); } catch (const std::exception& ex) { std::ostringstream info; info << "Error while sending JSON-RPC message for identity '" << m_Identity << "'"; Log(LogWarning, "ApiClient") << info.str(); Log(LogDebug, "ApiClient") << info.str() << "\n" << DiagnosticInformation(ex); Disconnect(); } }
String Comment::AddComment(const Checkable::Ptr& checkable, CommentType entryType, const String& author, const String& text, double expireTime, const String& id, const MessageOrigin::Ptr& origin) { String fullName; if (id.IsEmpty()) fullName = checkable->GetName() + "!" + Utility::NewUniqueID(); else fullName = id; Dictionary::Ptr attrs = new Dictionary(); attrs->Set("author", author); attrs->Set("text", text); attrs->Set("expire_time", expireTime); attrs->Set("entry_type", entryType); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); attrs->Set("host_name", host->GetName()); if (service) attrs->Set("service_name", service->GetShortName()); String zone = checkable->GetZoneName(); if (!zone.IsEmpty()) attrs->Set("zone", zone); String config = ConfigObjectUtility::CreateObjectConfig(Comment::TypeInstance, fullName, true, Array::Ptr(), attrs); Array::Ptr errors = new Array(); if (!ConfigObjectUtility::CreateObject(Comment::TypeInstance, fullName, config, errors)) { ObjectLock olock(errors); BOOST_FOREACH(const String& error, errors) { Log(LogCritical, "Comment", error); }
Object::Ptr Dictionary::GetPrototype(void) { static Dictionary::Ptr prototype; if (!prototype) { prototype = new Dictionary(); prototype->Set("len", new Function(WrapFunction(DictionaryLen), true)); prototype->Set("set", new Function(WrapFunction(DictionarySet))); prototype->Set("remove", new Function(WrapFunction(DictionaryRemove))); prototype->Set("contains", new Function(WrapFunction(DictionaryContains), true)); prototype->Set("clone", new Function(WrapFunction(DictionaryClone), true)); } return prototype; }
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() + "'."); }
std::pair<double, double> ScheduledDowntime::FindNextSegment() { time_t refts = Utility::GetTime(); tm reference = Utility::LocalTime(refts); Log(LogDebug, "ScheduledDowntime") << "Finding next scheduled downtime segment for time " << refts; Dictionary::Ptr ranges = GetRanges(); if (!ranges) return std::make_pair(0, 0); Array::Ptr segments = new Array(); Dictionary::Ptr bestSegment; double bestBegin; double now = Utility::GetTime(); ObjectLock olock(ranges); for (const Dictionary::Pair& kv : ranges) { Log(LogDebug, "ScheduledDowntime") << "Evaluating segment: " << kv.first << ": " << kv.second << " at "; Dictionary::Ptr segment = LegacyTimePeriod::FindNextSegment(kv.first, kv.second, &reference); if (!segment) continue; Log(LogDebug, "ScheduledDowntime") << "Considering segment: " << Utility::FormatDateTime("%c", segment->Get("begin")) << " -> " << Utility::FormatDateTime("%c", segment->Get("end")); double begin = segment->Get("begin"); if (begin < now) continue; if (!bestSegment || begin < bestBegin) { bestSegment = segment; bestBegin = begin; } } if (bestSegment) return std::make_pair(bestSegment->Get("begin"), bestSegment->Get("end")); else return std::make_pair(0, 0); }
bool ApiListener::UpdateConfigDir(const Dictionary::Ptr& oldConfig, const Dictionary::Ptr& newConfig, const String& configDir) { 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; } 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::trunc); fp << kv.second; fp.close(); } } 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 << Utility::GetTime(); fp.close(); } return configChange; }
void InfluxdbWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata) { DictionaryData nodes; for (const InfluxdbWriter::Ptr& influxdbwriter : ConfigType::GetObjectsByType<InfluxdbWriter>()) { size_t workQueueItems = influxdbwriter->m_WorkQueue.GetLength(); double workQueueItemRate = influxdbwriter->m_WorkQueue.GetTaskCount(60) / 60.0; size_t dataBufferItems = influxdbwriter->m_DataBuffer.size(); nodes.emplace_back(influxdbwriter->GetName(), new Dictionary({ { "work_queue_items", workQueueItems }, { "work_queue_item_rate", workQueueItemRate }, { "data_buffer_items", dataBufferItems } })); perfdata->Add(new PerfdataValue("influxdbwriter_" + influxdbwriter->GetName() + "_work_queue_items", workQueueItems)); perfdata->Add(new PerfdataValue("influxdbwriter_" + influxdbwriter->GetName() + "_work_queue_item_rate", workQueueItemRate)); perfdata->Add(new PerfdataValue("influxdbwriter_" + influxdbwriter->GetName() + "_data_queue_items", dataBufferItems)); } status->Set("influxdbwriter", new Dictionary(std::move(nodes))); }
void ClusterEvents::ForceNextNotificationChangedHandler(const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin) { ApiListener::Ptr listener = ApiListener::GetInstance(); if (!listener) return; Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); Dictionary::Ptr params = new Dictionary(); params->Set("host", host->GetName()); if (service) params->Set("service", service->GetShortName()); params->Set("forced", checkable->GetForceNextNotification()); Dictionary::Ptr message = new Dictionary(); message->Set("jsonrpc", "2.0"); message->Set("method", "event::SetForceNextNotification"); message->Set("params", params); listener->RelayMessage(origin, checkable, message, true); }
void IdoPgsqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata) { Dictionary::Ptr nodes = new Dictionary(); for (const IdoPgsqlConnection::Ptr& idopgsqlconnection : ConfigType::GetObjectsByType<IdoPgsqlConnection>()) { size_t items = idopgsqlconnection->m_QueryQueue.GetLength(); Dictionary::Ptr stats = new Dictionary(); stats->Set("version", idopgsqlconnection->GetSchemaVersion()); stats->Set("connected", idopgsqlconnection->GetConnected()); stats->Set("instance_name", idopgsqlconnection->GetInstanceName()); stats->Set("query_queue_items", items); nodes->Set(idopgsqlconnection->GetName(), stats); perfdata->Add(new PerfdataValue("idopgsqlconnection_" + idopgsqlconnection->GetName() + "_queries_rate", idopgsqlconnection->GetQueryCount(60) / 60.0)); perfdata->Add(new PerfdataValue("idopgsqlconnection_" + idopgsqlconnection->GetName() + "_queries_1min", idopgsqlconnection->GetQueryCount(60))); perfdata->Add(new PerfdataValue("idopgsqlconnection_" + idopgsqlconnection->GetName() + "_queries_5mins", idopgsqlconnection->GetQueryCount(5 * 60))); perfdata->Add(new PerfdataValue("idopgsqlconnection_" + idopgsqlconnection->GetName() + "_queries_15mins", idopgsqlconnection->GetQueryCount(15 * 60))); perfdata->Add(new PerfdataValue("idopgsqlconnection_" + idopgsqlconnection->GetName() + "_query_queue_items", items)); } status->Set("idopgsqlconnection", nodes); }
void ApiListener::SyncSendMessage(const Endpoint::Ptr& endpoint, const Dictionary::Ptr& message) { ObjectLock olock(endpoint); if (!endpoint->GetSyncing()) { Log(LogNotice, "ApiListener") << "Sending message '" << message->Get("method") << "' to '" << endpoint->GetName() << "'"; double maxTs = 0; for (const JsonRpcConnection::Ptr& client : endpoint->GetClients()) { if (client->GetTimestamp() > maxTs) maxTs = client->GetTimestamp(); } for (const JsonRpcConnection::Ptr& client : endpoint->GetClients()) { if (client->GetTimestamp() != maxTs) continue; client->SendMessage(message); } } }
void ApiClient::AutocompleteScriptHttpCompletionCallback(HttpRequest& request, HttpResponse& response, const AutocompleteScriptCompletionCallback& callback) { Dictionary::Ptr result; String body; char buffer[1024]; size_t count; while ((count = response.ReadBody(buffer, sizeof(buffer))) > 0) body += String(buffer, buffer + count); try { if (response.StatusCode < 200 || response.StatusCode > 299) { std::string message = "HTTP request failed; Code: " + Convert::ToString(response.StatusCode) + "; Body: " + body; BOOST_THROW_EXCEPTION(ScriptError(message)); } result = JsonDecode(body); Array::Ptr results = result->Get("results"); Array::Ptr suggestions; String errorMessage = "Unexpected result from API."; if (results && results->GetLength() > 0) { Dictionary::Ptr resultInfo = results->Get(0); errorMessage = resultInfo->Get("status"); if (resultInfo->Get("code") >= 200 && resultInfo->Get("code") <= 299) suggestions = resultInfo->Get("suggestions"); else BOOST_THROW_EXCEPTION(ScriptError(errorMessage)); } callback(boost::exception_ptr(), suggestions); } catch (const std::exception&) { callback(boost::current_exception(), nullptr); } }
void ObjectListUtility::PrintProperties(std::ostream& fp, const Dictionary::Ptr& props, const Dictionary::Ptr& debug_hints, int indent) { /* get debug hint props */ Dictionary::Ptr debug_hint_props; if (debug_hints) debug_hint_props = debug_hints->Get("properties"); int offset = 2; ObjectLock olock(props); for (const Dictionary::Pair& kv : props) { String key = kv.first; Value val = kv.second; /* key & value */ fp << std::setw(indent) << " " << "* " << ConsoleColorTag(Console_ForegroundGreen) << key << ConsoleColorTag(Console_Normal); /* extract debug hints for key */ Dictionary::Ptr debug_hints_fwd; if (debug_hint_props) debug_hints_fwd = debug_hint_props->Get(key); /* print dicts recursively */ if (val.IsObjectType<Dictionary>()) { fp << "\n"; PrintHints(fp, debug_hints_fwd, indent + offset); PrintProperties(fp, val, debug_hints_fwd, indent + offset); } else { fp << " = "; PrintValue(fp, val); fp << "\n"; PrintHints(fp, debug_hints_fwd, indent + offset); } } }
bool ObjectListUtility::PrintObject(std::ostream& fp, bool& first, const String& message, std::map<String, int>& type_count, const String& name_filter, const String& type_filter) { Dictionary::Ptr object = JsonDecode(message); Dictionary::Ptr properties = object->Get("properties"); String internal_name = properties->Get("__name"); String name = object->Get("name"); String type = object->Get("type"); if (!name_filter.IsEmpty() && !Utility::Match(name_filter, name) && !Utility::Match(name_filter, internal_name)) return false; if (!type_filter.IsEmpty() && !Utility::Match(type_filter, type)) return false; if (first) first = false; else fp << "\n"; Dictionary::Ptr debug_hints = object->Get("debug_hints"); fp << "Object '" << ConsoleColorTag(Console_ForegroundBlue | Console_Bold) << internal_name << ConsoleColorTag(Console_Normal) << "'"; fp << " of type '" << ConsoleColorTag(Console_ForegroundMagenta | Console_Bold) << type << ConsoleColorTag(Console_Normal) << "':\n"; Array::Ptr di = object->Get("debug_info"); if (di) { fp << ConsoleColorTag(Console_ForegroundCyan) << " % declared in '" << di->Get(0) << "', lines " << di->Get(1) << ":" << di->Get(2) << "-" << di->Get(3) << ":" << di->Get(4) << ConsoleColorTag(Console_Normal) << "\n"; } PrintProperties(fp, properties, debug_hints, 2); type_count[type]++; return true; }
bool TroubleshootCommand::CheckFeatures(InfoLog& log) { Dictionary::Ptr features = new Dictionary; std::vector<String> disabled_features; std::vector<String> enabled_features; if (!FeatureUtility::GetFeatures(disabled_features, true) || !FeatureUtility::GetFeatures(enabled_features, false)) { InfoLogLine(log, 0, LogCritical) << "Failed to collect enabled and/or disabled features. Check\n" << FeatureUtility::GetFeaturesAvailablePath() << '\n' << FeatureUtility::GetFeaturesEnabledPath() << '\n'; return false; } for (const String& feature : disabled_features) features->Set(feature, false); for (const String& feature : enabled_features) features->Set(feature, true); InfoLogLine(log) << "Enabled features:\n"; InfoLogLine(log, Console_ForegroundGreen) << '\t' << boost::algorithm::join(enabled_features, " ") << '\n'; InfoLogLine(log) << "Disabled features:\n"; InfoLogLine(log, Console_ForegroundRed) << '\t' << boost::algorithm::join(disabled_features, " ") << '\n'; if (!features->Get("checker").ToBool()) InfoLogLine(log, 0, LogWarning) << "checker is disabled, no checks can be run from this instance\n"; if (!features->Get("mainlog").ToBool()) InfoLogLine(log, 0, LogWarning) << "mainlog is disabled, please activate it and rerun icinga2\n"; if (!features->Get("debuglog").ToBool()) InfoLogLine(log, 0, LogWarning) << "debuglog is disabled, please activate it and rerun icinga2\n"; return true; }
void CheckerComponent::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata) { Dictionary::Ptr nodes = new Dictionary(); for (const CheckerComponent::Ptr& checker : ConfigType::GetObjectsByType<CheckerComponent>()) { unsigned long idle = checker->GetIdleCheckables(); unsigned long pending = checker->GetPendingCheckables(); Dictionary::Ptr stats = new Dictionary(); stats->Set("idle", idle); stats->Set("pending", pending); nodes->Set(checker->GetName(), stats); String perfdata_prefix = "checkercomponent_" + checker->GetName() + "_"; perfdata->Add(new PerfdataValue(perfdata_prefix + "idle", Convert::ToDouble(idle))); perfdata->Add(new PerfdataValue(perfdata_prefix + "pending", Convert::ToDouble(pending))); } status->Set("checkercomponent", nodes); }
void InfluxdbWriter::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr) { CONTEXT("Processing check result for '" + checkable->GetName() + "'"); if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !checkable->GetEnablePerfdata()) return; Host::Ptr host; Service::Ptr service; boost::tie(host, service) = GetHostService(checkable); MacroProcessor::ResolverList resolvers; if (service) resolvers.push_back(std::make_pair("service", service)); resolvers.push_back(std::make_pair("host", host)); resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance())); String prefix; double ts = cr->GetExecutionEnd(); // Clone the template and perform an in-place macro expansion of measurement and tag values Dictionary::Ptr tmpl_clean = service ? GetServiceTemplate() : GetHostTemplate(); Dictionary::Ptr tmpl = static_pointer_cast<Dictionary>(tmpl_clean->Clone()); tmpl->Set("measurement", MacroProcessor::ResolveMacros(tmpl->Get("measurement"), resolvers, cr)); Dictionary::Ptr tags = tmpl->Get("tags"); if (tags) { ObjectLock olock(tags); for (const Dictionary::Pair& pair : tags) { // Prevent missing macros from warning; will return an empty value // which will be filtered out in SendMetric() String missing_macro; tags->Set(pair.first, MacroProcessor::ResolveMacros(pair.second, resolvers, cr, &missing_macro)); } } SendPerfdata(tmpl, checkable, cr, ts); }
Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { if (!params) return Empty; Dictionary::Ptr result = new Dictionary(); if (!origin->FromClient->IsAuthenticated()) { ApiListener::Ptr listener = ApiListener::GetInstance(); String salt = listener->GetTicketSalt(); if (salt.IsEmpty()) { result->Set("error", "Ticket salt is not configured."); return result; } String ticket = params->Get("ticket"); String realTicket = PBKDF2_SHA1(origin->FromClient->GetIdentity(), salt, 50000); if (ticket != realTicket) { result->Set("error", "Invalid ticket."); return result; } } boost::shared_ptr<X509> cert = origin->FromClient->GetStream()->GetPeerCertificate(); EVP_PKEY *pubkey = X509_get_pubkey(cert.get()); X509_NAME *subject = X509_get_subject_name(cert.get()); boost::shared_ptr<X509> newcert = CreateCertIcingaCA(pubkey, subject); result->Set("cert", CertificateToString(newcert)); String cacertfile = GetIcingaCADir() + "/ca.crt"; boost::shared_ptr<X509> cacert = GetX509Certificate(cacertfile); result->Set("ca", CertificateToString(cacert)); return result; }
BOOST_FOREACH(const Endpoint::Ptr& endpoint, ConfigType::GetObjectsByType<Endpoint>()) { if (!endpoint->IsConnected()) continue; double ts = endpoint->GetRemoteLogPosition(); if (ts == 0) continue; Dictionary::Ptr lparams = new Dictionary(); lparams->Set("log_position", ts); Dictionary::Ptr lmessage = new Dictionary(); lmessage->Set("jsonrpc", "2.0"); lmessage->Set("method", "log::SetLogPosition"); lmessage->Set("params", lparams); BOOST_FOREACH(const JsonRpcConnection::Ptr& client, endpoint->GetClients()) client->SendMessage(lmessage); Log(LogNotice, "ApiListener") << "Setting log position for identity '" << endpoint->GetName() << "': " << Utility::FormatDateTime("%Y/%m/%d %H:%M:%S", ts); }
bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) { if (request.RequestUrl->GetPath().size() != 3) return false; if (request.RequestMethod != "POST") return false; String actionName = request.RequestUrl->GetPath()[2]; ApiAction::Ptr action = ApiAction::GetByName(actionName); if (!action) { HttpUtility::SendJsonError(response, 404, "Action '" + actionName + "' does not exist."); return true; } QueryDescription qd; Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); 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, user); } catch (const std::exception& ex) { HttpUtility::SendJsonError(response, 400, "Type/Filter was required but not provided or was invalid.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; } } else { FilterUtility::CheckPermission(user, permission); objs.push_back(ConfigObject::Ptr()); } Array::Ptr results = new Array(); Log(LogNotice, "ApiActionHandler") << "Running action " << actionName; BOOST_FOREACH(const ConfigObject::Ptr& obj, objs) { try { results->Add(action->Invoke(obj, params)); } catch (const std::exception& ex) { Dictionary::Ptr fail = new Dictionary(); fail->Set("code", 500); fail->Set("status", "Action execution failed: '" + DiagnosticInformation(ex, false) + "'."); if (HttpUtility::GetLastParameter(params, "verboseErrors")) fail->Set("diagnostic information", DiagnosticInformation(ex)); results->Add(fail); } } Dictionary::Ptr result = new Dictionary(); result->Set("results", results); response.SetStatus(200, "OK"); HttpUtility::SendJsonBody(response, result); return true; }
/** * Processes a new client connection. * * @param client The new client. */ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const String& hostname, ConnectionRole role) { CONTEXT("Handling new API client connection"); TlsStream::Ptr tlsStream; { ObjectLock olock(this); try { tlsStream = new TlsStream(client, hostname, role, m_SSLContext); } catch (const std::exception&) { Log(LogCritical, "ApiListener", "Cannot create TLS stream from client connection."); return; } } try { tlsStream->Handshake(); } catch (const std::exception& ex) { Log(LogCritical, "ApiListener", "Client TLS handshake failed"); return; } boost::shared_ptr<X509> cert = tlsStream->GetPeerCertificate(); String identity; Endpoint::Ptr endpoint; bool verify_ok = false; if (cert) { try { identity = GetCertificateCN(cert); } catch (const std::exception&) { Log(LogCritical, "ApiListener") << "Cannot get certificate common name from cert path: '" << GetCertPath() << "'."; return; } verify_ok = tlsStream->IsVerifyOK(); Log(LogInformation, "ApiListener") << "New client connection for identity '" << identity << "'" << (verify_ok ? "" : " (unauthenticated)"); if (verify_ok) endpoint = Endpoint::GetByName(identity); } else { Log(LogInformation, "ApiListener") << "New client connection (no client certificate)"; } bool need_sync = false; if (endpoint) need_sync = !endpoint->IsConnected(); ClientType ctype; if (role == RoleClient) { Dictionary::Ptr message = new Dictionary(); message->Set("jsonrpc", "2.0"); message->Set("method", "icinga::Hello"); message->Set("params", new Dictionary()); JsonRpc::SendMessage(tlsStream, message); ctype = ClientJsonRpc; } else { tlsStream->WaitForData(5); if (!tlsStream->IsDataAvailable()) { Log(LogWarning, "ApiListener", "No data received on new API connection."); return; } char firstByte; tlsStream->Peek(&firstByte, 1, false); if (firstByte >= '0' && firstByte <= '9') ctype = ClientJsonRpc; else ctype = ClientHttp; } if (ctype == ClientJsonRpc) { Log(LogNotice, "ApiListener", "New JSON-RPC client"); JsonRpcConnection::Ptr aclient = new JsonRpcConnection(identity, verify_ok, tlsStream, role); aclient->Start(); if (endpoint) { endpoint->AddClient(aclient); if (need_sync) { { ObjectLock olock(endpoint); endpoint->SetSyncing(true); } Log(LogInformation, "ApiListener") << "Sending updates for endpoint '" << endpoint->GetName() << "'."; /* sync zone file config */ SendConfigUpdate(aclient); /* sync runtime config */ SendRuntimeConfigObjects(aclient); Log(LogInformation, "ApiListener") << "Finished sending updates for endpoint '" << endpoint->GetName() << "'."; ReplayLog(aclient); } } else AddAnonymousClient(aclient); } else { Log(LogNotice, "ApiListener", "New HTTP client"); HttpServerConnection::Ptr aclient = new HttpServerConnection(identity, verify_ok, tlsStream); aclient->Start(); AddHttpClient(aclient); } }
static Dictionary::Ptr DictionaryClone(void) { ScriptFrame *vframe = ScriptFrame::GetCurrentFrame(); Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self); return self->ShallowClone(); }
static bool DictionaryContains(const String& key) { ScriptFrame *vframe = ScriptFrame::GetCurrentFrame(); Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self); return self->Contains(key); }
static void DictionarySet(const String& key, const Value& value) { ScriptFrame *vframe = ScriptFrame::GetCurrentFrame(); Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self); self->Set(key, value); }
void Checkable::ExecuteCheck() { CONTEXT("Executing check for object '" + GetName() + "'"); ASSERT(!OwnsLock()); UpdateNextCheck(); bool reachable = IsReachable(); { ObjectLock olock(this); /* don't run another check if there is one pending */ if (m_CheckRunning) return; m_CheckRunning = true; SetLastStateRaw(GetStateRaw()); SetLastStateType(GetLastStateType()); SetLastReachable(reachable); } /* keep track of scheduling info in case the check type doesn't provide its own information */ double scheduled_start = GetNextCheck(); double before_check = Utility::GetTime(); CheckResult::Ptr cr = new CheckResult(); cr->SetScheduleStart(scheduled_start); cr->SetExecutionStart(before_check); Endpoint::Ptr endpoint = GetCommandEndpoint(); bool local = !endpoint || endpoint == Endpoint::GetLocalEndpoint(); if (local) { GetCheckCommand()->Execute(this, cr, NULL, false); } else { Dictionary::Ptr macros = new Dictionary(); GetCheckCommand()->Execute(this, cr, macros, false); if (endpoint->GetConnected()) { /* perform check on remote endpoint */ Dictionary::Ptr message = new Dictionary(); message->Set("jsonrpc", "2.0"); message->Set("method", "event::ExecuteCommand"); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(this); Dictionary::Ptr params = new Dictionary(); message->Set("params", params); params->Set("command_type", "check_command"); params->Set("command", GetCheckCommand()->GetName()); params->Set("host", host->GetName()); if (service) params->Set("service", service->GetShortName()); params->Set("macros", macros); ApiListener::Ptr listener = ApiListener::GetInstance(); if (listener) listener->SyncSendMessage(endpoint, message); } else if (Application::GetInstance()->GetStartTime() < Utility::GetTime() - 30) { /* fail to perform check on unconnected endpoint */ cr->SetState(ServiceUnknown); cr->SetOutput("Remote Icinga instance '" + endpoint->GetName() + "' " + "is not connected to '" + Endpoint::GetLocalEndpoint()->GetName() + "'"); ProcessCheckResult(cr); } { ObjectLock olock(this); m_CheckRunning = false; } } }
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 void DictionaryRemove(const String& key) { ScriptFrame *vframe = ScriptFrame::GetCurrentFrame(); Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self); self->Remove(key); }