예제 #1
0
파일: apiactions.cpp 프로젝트: b0e/icinga2
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);
}
예제 #2
0
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;
}
예제 #3
0
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);
	}
}
예제 #4
0
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;
}
예제 #5
0
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 + "'."));
		}
	}
}
예제 #6
0
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() + "'.");
}
예제 #7
0
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);
		}
	}
}
예제 #8
0
/**
 * 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;
}
예제 #9
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);
			}
		}
	}

}
예제 #10
0
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;
	}
}
예제 #11
0
bool DynamicObject::HasAuthority(const String& type) const
{
	Dictionary::Ptr authorityInfo = GetAuthorityInfo();

	if (!authorityInfo || !authorityInfo->Contains(type))
		return true;

	return authorityInfo->Get(type);
}
예제 #12
0
파일: apiactions.cpp 프로젝트: b0e/icinga2
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() + "'.");
}
예제 #13
0
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 + "'.");
}
예제 #14
0
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 + "'.");
}
예제 #15
0
파일: apiactions.cpp 프로젝트: b0e/icinga2
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() + "'.");
}
예제 #16
0
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;
}
예제 #17
0
파일: apiactions.cpp 프로젝트: b0e/icinga2
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() + "'.");
}
예제 #18
0
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;
}
예제 #19
0
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() + "'.");
}
예제 #20
0
파일: infohandler.cpp 프로젝트: b0e/icinga2
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);
		}
	}
예제 #21
0
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;
}
예제 #22
0
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;
}
예제 #23
0
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);
}
예제 #24
0
파일: pkiutility.cpp 프로젝트: b0e/icinga2
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;
}
예제 #25
0
static bool DictionaryContains(const String& key)
{
	ScriptFrame *vframe = ScriptFrame::GetCurrentFrame();
	Dictionary::Ptr self = static_cast<Dictionary::Ptr>(vframe->Self);
	return self->Contains(key);
}
예제 #26
0
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;
}
예제 #27
0
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());
}
예제 #28
0
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;
}
예제 #30
0
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;
}