2014-09-18 04:20:30 +00:00
|
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <functional>
|
|
|
|
#include <memory>
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <boost/make_shared.hpp>
|
2014-09-23 01:35:12 +00:00
|
|
|
#include <boost/thread.hpp>
|
2014-09-19 08:54:33 +00:00
|
|
|
#include <boost/thread/locks.hpp>
|
|
|
|
#include <boost/thread/mutex.hpp>
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
#include "osquery/status.h"
|
2014-09-19 08:54:33 +00:00
|
|
|
#include "osquery/database.h"
|
2014-09-24 15:03:16 +00:00
|
|
|
#include "osquery/registry.h"
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
struct Monitor;
|
2014-10-03 15:14:36 +00:00
|
|
|
class EventPublisher;
|
2014-10-03 15:08:06 +00:00
|
|
|
class EventSubscriber;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
typedef const std::string EventPublisherID;
|
2014-09-19 08:54:33 +00:00
|
|
|
typedef const std::string EventID;
|
|
|
|
typedef uint32_t EventContextID;
|
2014-09-18 04:20:30 +00:00
|
|
|
typedef uint32_t EventTime;
|
2014-09-25 17:17:32 +00:00
|
|
|
typedef std::pair<EventID, EventTime> EventRecord;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief An EventPublisher will define a MonitorContext for EventSubscriber%s to use.
|
2014-09-30 19:50:14 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* Most EventPublisher%s will reqire specific information for interacting with an OS
|
|
|
|
* to receive events. The MonitorContext contains information the EventPublisher will
|
2014-09-30 19:50:14 +00:00
|
|
|
* use to register OS API callbacks, create monitoring/listening handles, etc.
|
|
|
|
*
|
|
|
|
* Linux `inotify` should implement a MonitorContext that monitors filesystem
|
|
|
|
* events based on a filesystem path. `libpcap` will monitor on networking
|
|
|
|
* protocols at various stacks. Process creation may monitor on process name,
|
|
|
|
* parent pid, etc.
|
|
|
|
*/
|
2014-09-18 04:20:30 +00:00
|
|
|
struct MonitorContext {};
|
2014-09-30 19:50:14 +00:00
|
|
|
|
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief An EventSubscriber EventCallback method will receive an EventContext.
|
2014-09-30 19:50:14 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* The EventContext contains the event-related data supplied by an EventPublisher
|
2014-10-03 15:08:06 +00:00
|
|
|
* when the event occures. If a monitoring EventSubscriber is should be called
|
|
|
|
* for the event the EventSubscriber%'s EventCallback is passed an EventContext.
|
2014-09-30 19:50:14 +00:00
|
|
|
*/
|
2014-09-25 17:17:32 +00:00
|
|
|
struct EventContext {
|
2014-10-03 15:14:36 +00:00
|
|
|
/// An unique counting ID specific to the EventPublisher%'s fired events.
|
2014-09-25 17:17:32 +00:00
|
|
|
EventContextID id;
|
2014-09-30 19:50:14 +00:00
|
|
|
/// The time the event occured.
|
2014-09-25 17:17:32 +00:00
|
|
|
EventTime time;
|
2014-09-30 19:50:14 +00:00
|
|
|
/// The string representation of the time, often used for indexing.
|
2014-09-25 17:17:32 +00:00
|
|
|
std::string time_string;
|
|
|
|
};
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-24 17:20:58 +00:00
|
|
|
typedef std::shared_ptr<Monitor> MonitorRef;
|
2014-10-03 15:14:36 +00:00
|
|
|
typedef std::shared_ptr<EventPublisher> EventPublisherRef;
|
2014-09-24 17:20:58 +00:00
|
|
|
typedef std::shared_ptr<MonitorContext> MonitorContextRef;
|
|
|
|
typedef std::shared_ptr<EventContext> EventContextRef;
|
2014-10-03 15:08:06 +00:00
|
|
|
typedef std::shared_ptr<EventSubscriber> EventSubscriberRef;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-25 17:17:32 +00:00
|
|
|
typedef std::function<Status(EventContextRef, bool)> EventCallback;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// An EventPublisher must track every monitor added.
|
2014-09-19 08:54:33 +00:00
|
|
|
typedef std::vector<MonitorRef> MonitorVector;
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// The EventFactory tracks every EventPublisher and the name it specifies.
|
|
|
|
typedef std::map<EventPublisherID, EventPublisherRef> EventPublisherMap;
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/// The set of search-time binned lookup tables.
|
|
|
|
extern const std::vector<size_t> kEventTimeLists;
|
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief Helper type casting methods for EventPublisher classes.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* A new osquery EventPublisher should subclass EventPublisher and use the following:
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* @code{.cpp}
|
|
|
|
* #include "osquery/events.h"
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* class MyEventPublisher: public EventPublisher {
|
|
|
|
* DECLARE_EVENTTYPE(MyEventPublisher, MyMonitorContext, MyEventContext);
|
2014-09-24 15:03:16 +00:00
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* This assumes new EventPublisher%s will always include a custom MonitorContext
|
2014-10-03 15:08:06 +00:00
|
|
|
* and EventContext. In the above example MyMonitorContext allows EventSubscriber%s
|
2014-09-24 15:03:16 +00:00
|
|
|
* to downselect or customize what events to handle. And MyEventContext includes
|
2014-10-03 15:14:36 +00:00
|
|
|
* fields specific to the new EventPublisher.
|
2014-09-24 15:03:16 +00:00
|
|
|
*/
|
2014-09-24 18:25:05 +00:00
|
|
|
#define DECLARE_EVENTTYPE(TYPE, MONITOR, EVENT) \
|
|
|
|
public: \
|
2014-10-03 15:14:36 +00:00
|
|
|
EventPublisherID type() const { return #TYPE; } \
|
2014-09-25 17:17:32 +00:00
|
|
|
bool shouldFire(const MonitorContextRef mc, const EventContextRef ec) { \
|
|
|
|
if (#MONITOR == "MonitorContext" && #EVENT == "EventContext") \
|
|
|
|
return true; \
|
|
|
|
return shouldFire(getMonitorContext(mc), getEventContext(ec)); \
|
|
|
|
} \
|
2014-09-24 17:20:58 +00:00
|
|
|
static std::shared_ptr<EVENT> getEventContext(EventContextRef context) { \
|
|
|
|
return std::static_pointer_cast<EVENT>(context); \
|
2014-09-24 18:25:05 +00:00
|
|
|
} \
|
2014-09-24 17:20:58 +00:00
|
|
|
static std::shared_ptr<MONITOR> getMonitorContext( \
|
2014-09-24 18:25:05 +00:00
|
|
|
MonitorContextRef context) { \
|
2014-09-24 17:20:58 +00:00
|
|
|
return std::static_pointer_cast<MONITOR>(context); \
|
2014-09-24 18:25:05 +00:00
|
|
|
} \
|
2014-09-24 17:20:58 +00:00
|
|
|
static std::shared_ptr<EVENT> createEventContext() { \
|
|
|
|
return std::make_shared<EVENT>(); \
|
2014-09-25 17:17:32 +00:00
|
|
|
} \
|
|
|
|
static std::shared_ptr<MONITOR> createMonitorContext() { \
|
|
|
|
return std::make_shared<MONITOR>(); \
|
2014-09-22 21:35:07 +00:00
|
|
|
}
|
2014-09-19 08:54:33 +00:00
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief Required getter and namespace helper methods for EventSubscriber%s.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* A new osquery `EventSubscriber` should subclass EventSubscriber with the following:
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* @code{.cpp}
|
|
|
|
* #include "osquery/events.h"
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* class MyEventSubscriber: public EventSubscriber {
|
2014-10-03 15:14:36 +00:00
|
|
|
* DECLARE_EVENTMODULE(MyEventSubscriber, MyEventPublisher);
|
2014-09-24 15:03:16 +00:00
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* EventSubscriber%s should be specific to an EventPublisher.
|
2014-09-24 15:03:16 +00:00
|
|
|
*/
|
2014-09-24 18:25:05 +00:00
|
|
|
#define DECLARE_EVENTMODULE(NAME, TYPE) \
|
|
|
|
public: \
|
2014-09-25 17:17:32 +00:00
|
|
|
static std::shared_ptr<NAME> getInstance() { \
|
2014-09-24 17:20:58 +00:00
|
|
|
static auto q = std::shared_ptr<NAME>(new NAME()); \
|
2014-09-24 18:25:05 +00:00
|
|
|
return q; \
|
2014-09-25 17:17:32 +00:00
|
|
|
} \
|
|
|
|
static QueryData genTable() __attribute__((used)) { \
|
|
|
|
return getInstance()->get(0, 0); \
|
2014-09-24 18:25:05 +00:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
private: \
|
2014-10-03 15:14:36 +00:00
|
|
|
EventPublisherID name() const { return #NAME; } \
|
|
|
|
EventPublisherID type() const { return #TYPE; } \
|
2014-09-25 17:17:32 +00:00
|
|
|
NAME() {}
|
2014-09-23 03:33:58 +00:00
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief Required callin EventSubscriber method declaration helper.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* An EventSubscriber will include 1 or more EventCallback methods. Consider the
|
2014-09-24 15:03:16 +00:00
|
|
|
* following flow: (1) Event occurs, (2) EventCallback is called with the
|
|
|
|
* event details, (3) details logged, (4) details are queried.
|
|
|
|
*
|
|
|
|
* The above logic can be supplied in a class-like namespace with static
|
|
|
|
* callin/callback functions:
|
|
|
|
*
|
|
|
|
* @code{.cpp}
|
|
|
|
* #include "osquery/events.h"
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* class MyEventSubscriber: public EventSubscriber {
|
2014-10-03 15:14:36 +00:00
|
|
|
* DECLARE_EVENTMODULE(MyEventSubscriber, MyEventPublisher);
|
2014-09-24 15:03:16 +00:00
|
|
|
* DECLARE_CALLBACK(MyCallback, MyEventContext)
|
|
|
|
*
|
|
|
|
* Status ModuleMyCallback(EventContextID, EventTime, MyEventContext);
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* And then somewhere else in code the callback can be registered:
|
|
|
|
*
|
|
|
|
* @code{.cpp}
|
2014-10-03 15:14:36 +00:00
|
|
|
* EventFactory::addMonitor("MyEventPublisher", my_monitor_context,
|
2014-10-03 15:08:06 +00:00
|
|
|
* MyEventSubscriber::MyCallback);
|
2014-09-24 15:03:16 +00:00
|
|
|
* @endcode
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* The binding from static method, function pointer, and EventSubscriber
|
2014-09-24 15:03:16 +00:00
|
|
|
* instance boilerplate code is added automatically.
|
|
|
|
* Note: The macro will append `Module` to `MyCallback`.
|
|
|
|
*/
|
2014-09-25 17:17:32 +00:00
|
|
|
#define DECLARE_CALLBACK(NAME, EVENT) \
|
|
|
|
public: \
|
|
|
|
static Status Event##NAME(const EventContextRef ec, bool reserved) { \
|
|
|
|
auto ec_ = std::static_pointer_cast<EVENT>(ec); \
|
|
|
|
return getInstance()->NAME(ec_); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
private: \
|
|
|
|
void BindTo##NAME(const MonitorContextRef mc) { \
|
|
|
|
EventFactory::addMonitor(type(), mc, Event##NAME); \
|
2014-09-23 03:33:58 +00:00
|
|
|
}
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-25 17:17:32 +00:00
|
|
|
/**
|
|
|
|
* @brief Bind a monitor context to a declared EventCallback for this module.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* Binding refers to the association of a callback for this EventSubscriber to
|
2014-09-25 17:17:32 +00:00
|
|
|
* a configured MonitorContext. Under the hood "binding" creates a factory
|
2014-10-03 15:14:36 +00:00
|
|
|
* Monitor for the EventPublisher used by the EventSubscriber. Such that when an event
|
|
|
|
* of the EventPublisher is fired, if the event details match the specifics of the
|
2014-09-25 17:17:32 +00:00
|
|
|
* MonitorContext the EventMonitor%'s EventCallback will be called.
|
|
|
|
*
|
|
|
|
* @code{.cpp}
|
|
|
|
* #include "osquery/events.h"
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* class MyEventSubscriber: public EventSubscriber {
|
2014-10-03 15:14:36 +00:00
|
|
|
* DECLARE_EVENTMODULE(MyEventSubscriber, MyEventPublisher);
|
2014-09-25 17:17:32 +00:00
|
|
|
* DECLARE_CALLBACK(MyCallback, MyEventContext);
|
|
|
|
*
|
|
|
|
* public:
|
|
|
|
* void init() {
|
2014-10-03 15:14:36 +00:00
|
|
|
* auto mc = MyEventPublisher::createMonitorContext();
|
2014-09-25 17:17:32 +00:00
|
|
|
* mc->requirement = "SOME_SPECIFIC_DETAIL";
|
|
|
|
* BIND_CALLBACK(MyCallback, mc);
|
|
|
|
* }
|
|
|
|
* Status MyCallback(const MyEventContextRef ec) {}
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*
|
|
|
|
* The symbol `MyCallback` must match in `DECLARE_CALLBACK`, `BIND_CALLBACK` and
|
2014-10-03 15:08:06 +00:00
|
|
|
* as a member of this EventSubscriber.
|
2014-09-25 17:17:32 +00:00
|
|
|
*
|
|
|
|
* @param NAME The symbol for the EventCallback method used in DECLARE_CALLBACK.
|
|
|
|
* @param MC The MonitorContext to bind.
|
|
|
|
*/
|
|
|
|
#define BIND_CALLBACK(NAME, MC) \
|
|
|
|
EventFactory::addMonitor(type(), MC, Event##NAME);
|
|
|
|
|
2014-09-18 04:20:30 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief A Monitor is used to configure an EventPublisher and bind a callback.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* A Monitor is the input to an EventPublisher when the EventPublisher decides on
|
2014-09-24 15:03:16 +00:00
|
|
|
* the scope and details of the events it watches and generates. An example
|
|
|
|
* includes a filesystem change event. A monitor would include a path with
|
|
|
|
* optional recursion and attribute selectors as well as a callback function
|
|
|
|
* to fire when an event for that path and selector occurs.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* A Monitor also functions to greatly scope an EventPublisher%'s work.
|
2014-09-24 15:03:16 +00:00
|
|
|
* Using the same filesystem example and the Linux inotify subsystem a Monitor
|
|
|
|
* limits the number of inode watches to only those requested by appropriate
|
2014-10-03 15:08:06 +00:00
|
|
|
* EventSubscriber%s.
|
|
|
|
* Note: EventSubscriber%s and Monitors can be configured by the osquery user.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* Monitors are usually created with EventFactory members:
|
2014-09-18 04:20:30 +00:00
|
|
|
*
|
2014-09-24 15:03:16 +00:00
|
|
|
* @code{.cpp}
|
2014-10-03 15:14:36 +00:00
|
|
|
* EventFactory::addMonitor("MyEventPublisher", my_monitor_context);
|
2014-09-24 15:03:16 +00:00
|
|
|
* @endcode
|
2014-09-18 04:20:30 +00:00
|
|
|
*/
|
|
|
|
struct Monitor {
|
2014-09-21 21:29:28 +00:00
|
|
|
public:
|
2014-10-03 15:14:36 +00:00
|
|
|
/// An EventPublisher%-specific MonitorContext.
|
2014-09-18 04:20:30 +00:00
|
|
|
MonitorContextRef context;
|
2014-09-30 19:50:14 +00:00
|
|
|
/// An EventMonitor member EventCallback method.
|
2014-09-18 04:20:30 +00:00
|
|
|
EventCallback callback;
|
|
|
|
|
2014-09-24 17:20:58 +00:00
|
|
|
static MonitorRef create() { return std::make_shared<Monitor>(); }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
static MonitorRef create(const MonitorContextRef mc, EventCallback ec = 0) {
|
2014-09-24 17:20:58 +00:00
|
|
|
auto monitor = std::make_shared<Monitor>();
|
2014-09-18 04:20:30 +00:00
|
|
|
monitor->context = mc;
|
|
|
|
monitor->callback = ec;
|
|
|
|
return monitor;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
/**
|
2014-09-18 04:20:30 +00:00
|
|
|
* @brief Generate OS events of a type (FS, Network, Syscall, ioctl).
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* A 'class' of OS events is abstracted into an EventPublisher responsible for
|
2014-09-24 15:03:16 +00:00
|
|
|
* remaining as agile as possible given a known-set of monitors.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* The lifecycle of an EventPublisher may include, `setUp`, `configure`, `run`,
|
2014-09-24 15:03:16 +00:00
|
|
|
* `tearDown`, and `fire`. `setUp` and `tearDown` happen when osquery starts and
|
|
|
|
* stops either as a daemon or interactive shell. `configure` is a pseudo-start
|
2014-10-03 15:14:36 +00:00
|
|
|
* called every time a Monitor is added. EventPublisher%s can adjust their
|
2014-09-24 15:03:16 +00:00
|
|
|
* scope/agility specific to each added monitor by overriding `addMonitor`,
|
|
|
|
* and or globally in `configure`.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* Not all EventPublisher%s leverage pure async OS APIs, and most will require a run
|
2014-09-24 15:03:16 +00:00
|
|
|
* loop either polling with a timeout on a descriptor or for a change. When
|
|
|
|
* osquery initializes the EventFactory will optionally create a thread for each
|
2014-10-03 15:14:36 +00:00
|
|
|
* EventPublisher using `run` as the thread's entrypoint. This is called in a
|
2014-09-24 15:03:16 +00:00
|
|
|
* within-thread loop where returning a FAILED status ends the run loop and
|
|
|
|
* shuts down the thread.
|
|
|
|
*
|
|
|
|
* To opt-out of polling in a thread consider the following run implementation:
|
2014-09-18 04:20:30 +00:00
|
|
|
*
|
2014-09-24 15:03:16 +00:00
|
|
|
* @code{.cpp}
|
|
|
|
* Status run() { return Status(1, "Not Implemented") }
|
|
|
|
* @endcode
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* The final lifecycle component, `fire` will iterate over the EventPublisher
|
2014-09-24 15:03:16 +00:00
|
|
|
* Monitor%s and call `shouldFire` for each, using the EventContext fired.
|
|
|
|
* The `shouldFire` method should check the monitor-specific selectors and only
|
|
|
|
* call the Monitor%'s callback function is the EventContext (thus event)
|
|
|
|
* matches.
|
2014-09-18 04:20:30 +00:00
|
|
|
*/
|
2014-10-03 15:14:36 +00:00
|
|
|
class EventPublisher {
|
2014-09-21 21:29:28 +00:00
|
|
|
public:
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
|
|
|
* @brief A new Monitor was added, potentially change state based on all
|
2014-10-03 15:14:36 +00:00
|
|
|
* monitors for this EventPublisher.
|
2014-09-30 19:50:14 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* `configure` allows the EventPublisher to optimize on the state of all monitors.
|
2014-09-30 19:50:14 +00:00
|
|
|
* An example is Linux `inotify` where multiple EventMonitor%s will monitor
|
|
|
|
* identical paths, e.g., /etc for config changes. Since Linux `inotify` has
|
|
|
|
* a monitor limit, `configure` can depup paths.
|
|
|
|
*/
|
2014-09-18 04:20:30 +00:00
|
|
|
virtual void configure() {}
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
|
|
|
* @brief Perform handle opening, OS API callback registration.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* `setUp` is the event framework's EventPublisher constructor equivilent. When
|
|
|
|
* `setUp` is called the EventPublisher is running in a dedicated thread and may
|
2014-09-30 19:50:14 +00:00
|
|
|
* manage/allocate/wait for resources.
|
|
|
|
*/
|
2014-09-18 04:20:30 +00:00
|
|
|
virtual void setUp() {}
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
|
|
|
* @brief Perform handle closing, resource cleanup.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* osquery is about to end, the EventPublisher should close handle descriptors
|
2014-09-30 19:50:14 +00:00
|
|
|
* unblock resources, and prepare to exit.
|
|
|
|
*/
|
2014-09-18 04:20:30 +00:00
|
|
|
virtual void tearDown() {}
|
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
|
|
|
* @brief Implement a step of an optional run loop.
|
|
|
|
*
|
|
|
|
* @return A SUCCESS status will immediately call `run` again. A FAILED status
|
|
|
|
* will exit the run loop and the thread.
|
|
|
|
*/
|
2014-09-19 08:54:33 +00:00
|
|
|
virtual Status run();
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief A new EventSubscriber is monitoring events of this EventPublisher.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* @param monitor The Monitor context information and optional EventCallback.
|
|
|
|
*
|
|
|
|
* @return If the Monitor is not appropriate (mismatched type) fail.
|
|
|
|
*/
|
2014-09-23 03:33:58 +00:00
|
|
|
virtual Status addMonitor(const MonitorRef monitor) {
|
2014-09-19 08:54:33 +00:00
|
|
|
monitors_.push_back(monitor);
|
2014-09-18 04:20:30 +00:00
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Number of Monitor%s watching this EventPublisher.
|
2014-09-22 21:35:07 +00:00
|
|
|
size_t numMonitors() { return monitors_.size(); }
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief The number of events fired by this EventPublisher.
|
2014-09-30 19:50:14 +00:00
|
|
|
*
|
|
|
|
* @return The number of events.
|
|
|
|
*/
|
2014-09-23 03:33:58 +00:00
|
|
|
size_t numEvents() { return next_ec_id_; }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Overriding the EventPublisher constructor is not recommended.
|
|
|
|
EventPublisher() : next_ec_id_(0) {};
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Return a string identifier associated with this EventPublisher.
|
|
|
|
virtual EventPublisherID type() const = 0;
|
2014-09-19 08:54:33 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Return a string identifier for the given EventPublisher symbol.
|
2014-09-25 17:17:32 +00:00
|
|
|
template <typename T>
|
2014-10-03 15:14:36 +00:00
|
|
|
static EventPublisherID type() {
|
|
|
|
const auto& event_pub = new T();
|
|
|
|
auto type_id = event_pub->type();
|
|
|
|
delete event_pub;
|
2014-09-25 17:17:32 +00:00
|
|
|
return type_id;
|
|
|
|
}
|
|
|
|
|
2014-09-30 20:17:54 +00:00
|
|
|
public:
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
|
|
|
* @brief The generic check loop to call MonitorContext callback methods.
|
|
|
|
*
|
|
|
|
* It is NOT recommended to override `fire`. The simple logic of enumerating
|
|
|
|
* the Monitor%s and using `shouldFire` is more appropraite.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* @param ec The EventContext created and fired by the EventPublisher.
|
2014-09-25 17:17:32 +00:00
|
|
|
* @param time The most accurate time associated with the event.
|
2014-09-24 15:03:16 +00:00
|
|
|
*/
|
2014-09-25 17:17:32 +00:00
|
|
|
void fire(const EventContextRef ec, EventTime time = 0);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-09-25 17:17:32 +00:00
|
|
|
protected:
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
|
|
|
* @brief The generic `fire` will call `shouldFire` for each Monitor.
|
|
|
|
*
|
|
|
|
* @param mc A MonitorContext with optional specifications for events details.
|
|
|
|
* @param ec The event fired with event details.
|
|
|
|
*
|
|
|
|
* @return should the Monitor%'s EventCallback be called for this event.
|
|
|
|
*/
|
2014-09-23 01:35:12 +00:00
|
|
|
virtual bool shouldFire(const MonitorContextRef mc, const EventContextRef ec);
|
2014-09-19 08:54:33 +00:00
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
protected:
|
2014-10-03 15:14:36 +00:00
|
|
|
/// The EventPublisher will keep track of Monitor%s that contain callins.
|
2014-09-19 08:54:33 +00:00
|
|
|
MonitorVector monitors_;
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// An Event ID is assigned by the EventPublisher within the EventContext.
|
2014-09-24 15:03:16 +00:00
|
|
|
/// This is not used to store event date in the backing store.
|
2014-09-19 08:54:33 +00:00
|
|
|
EventContextID next_ec_id_;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-24 15:03:16 +00:00
|
|
|
/// A lock for incrementing the next EventContextID.
|
2014-09-19 08:54:33 +00:00
|
|
|
boost::mutex ec_id_lock_;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
FRIEND_TEST(EventsTests, test_fire_event);
|
2014-09-18 04:20:30 +00:00
|
|
|
};
|
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
/**
|
2014-09-24 15:03:16 +00:00
|
|
|
* @brief An interface binding Monitors, event response, and table generation.
|
2014-09-19 08:54:33 +00:00
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* Use the EventSubscriber interface when adding event monitors and defining callin
|
|
|
|
* functions. The EventCallback is usually a member function for an EventSubscriber.
|
|
|
|
* The EventSubscriber interface includes a very important `add` method
|
2014-09-22 21:35:07 +00:00
|
|
|
* that abstracts the needed event to backing store interaction.
|
2014-09-19 08:54:33 +00:00
|
|
|
*
|
|
|
|
* Storing event data in the backing store must match a table spec for queries.
|
|
|
|
* Small overheads exist that help query-time indexing and lookups.
|
|
|
|
*/
|
2014-10-03 15:08:06 +00:00
|
|
|
class EventSubscriber {
|
2014-09-24 15:03:16 +00:00
|
|
|
public:
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Called after EventPublisher `setUp`. Add all Monitor%s here.
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief Add Monitor%s to the EventPublisher this module will act on.
|
2014-09-30 19:50:14 +00:00
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* When the EventSubscriber%'s `init` method is called you are assured the
|
2014-10-03 15:14:36 +00:00
|
|
|
* EventPublisher has `setUp` and is ready to monitor for events.
|
2014-09-30 19:50:14 +00:00
|
|
|
*/
|
2014-09-24 15:03:16 +00:00
|
|
|
virtual void init() {}
|
|
|
|
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
|
|
|
* @brief Suggested entrypoint for table generation.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* The EventSubscriber is a convention that removes a lot of boilerplate event
|
2014-09-30 19:50:14 +00:00
|
|
|
* monitoring and acting. The `genTable` static entrypoint is the suggested
|
|
|
|
* method for table specs.
|
|
|
|
*
|
|
|
|
* @return The query-time table data, retrieved from a backing store.
|
|
|
|
*/
|
2014-09-25 17:17:32 +00:00
|
|
|
static QueryData genTable();
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
protected:
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
|
|
|
* @brief Store parsed event data from an EventCallback in a backing store.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* Within a EventCallback the EventSubscriber has an opprotunity to create
|
|
|
|
* an osquery Row element, add the relevant table data for the EventSubscriber
|
2014-09-30 19:50:14 +00:00
|
|
|
* and store that element in the osquery backing store. At query-time
|
|
|
|
* the added data will apply selection criteria and return these elements.
|
2014-09-30 20:17:54 +00:00
|
|
|
* The backing store data retrieval is optimized by time-based indexes. It
|
2014-09-30 19:50:14 +00:00
|
|
|
* is important to added EventTime as it relates to "when the event occured".
|
|
|
|
*
|
|
|
|
* @param r An osquery Row element.
|
|
|
|
* @param time The time the added event occured.
|
|
|
|
*
|
|
|
|
* @return Was the element added to the backing store.
|
|
|
|
*/
|
2014-09-25 17:17:32 +00:00
|
|
|
virtual Status add(const osquery::Row& r, EventTime time) final;
|
|
|
|
|
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief Return all events added by this EventSubscriber within start, stop.
|
2014-09-25 17:17:32 +00:00
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* This is used internally (for the most part) by EventSubscriber::genTable.
|
2014-09-25 17:17:32 +00:00
|
|
|
*
|
|
|
|
* @param start Inclusive lower bound time limit.
|
|
|
|
* @param stop Inclusive upper bound time limit.
|
|
|
|
* @return Set of event rows matching time limits.
|
|
|
|
*/
|
|
|
|
virtual QueryData get(EventTime start, EventTime stop);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief When `get`ting event results, return EventID%s from time indexes.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* Used by EventSubscriber::get to retrieve EventID, EventTime indexes. This
|
2014-09-25 17:17:32 +00:00
|
|
|
* applies the lookup-efficiency checks for time list appropriate bins.
|
|
|
|
* If the time range in 24 hours and there is a 24-hour list bin it will
|
|
|
|
* be queried using a single backing store `Get` followed by two `Get`s of
|
|
|
|
* the most-specific boundary lists.
|
|
|
|
*
|
|
|
|
* @return List of EventID, EventTime%s
|
|
|
|
*/
|
|
|
|
std::vector<EventRecord> getRecords(EventTime start, EventTime stop);
|
2014-09-19 08:54:33 +00:00
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
|
|
|
* @brief Get a unique storage-related EventID.
|
|
|
|
*
|
|
|
|
* An EventID is an index/element-identifier for the backing store.
|
2014-10-03 15:14:36 +00:00
|
|
|
* Each EventPublisher maintains a fired EventContextID to identify the many
|
2014-09-30 19:50:14 +00:00
|
|
|
* events that may or may not be fired to monitoring criteria for this
|
2014-10-03 15:08:06 +00:00
|
|
|
* EventSubscriber. This EventContextID is NOT the same as an EventID.
|
|
|
|
* EventSubscriber development should not require use of EventID%s, if this
|
|
|
|
* indexing is required within-EventCallback consider an EventSubscriber%-unique
|
2014-09-30 19:50:14 +00:00
|
|
|
* indexing, counting mechanic.
|
|
|
|
*
|
|
|
|
* @return A unique ID for backing storage.
|
|
|
|
*/
|
2014-09-19 08:54:33 +00:00
|
|
|
EventID getEventID();
|
|
|
|
|
2014-09-25 17:17:32 +00:00
|
|
|
/*
|
|
|
|
* @brief Add an EventID, EventTime pair to all matching list types.
|
|
|
|
*
|
|
|
|
* The list types are defined by time size. Based on the EventTime this pair
|
|
|
|
* is added to the list bin for each list type. If there are two list types:
|
|
|
|
* 60 seconds and 3600 seconds and `time` is 92, this pair will be added to
|
|
|
|
* list type 1 bin 4 and list type 2 bin 1.
|
2014-09-30 19:50:14 +00:00
|
|
|
*
|
|
|
|
* @param eid A unique EventID.
|
|
|
|
* @param time The time when this EventID%'s event occured.
|
|
|
|
*
|
|
|
|
* @return Were the indexes recorded.
|
2014-09-25 17:17:32 +00:00
|
|
|
*/
|
|
|
|
Status recordEvent(EventID eid, EventTime time);
|
2014-09-19 08:54:33 +00:00
|
|
|
|
2014-09-23 03:33:58 +00:00
|
|
|
protected:
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
|
|
|
* @brief A single instance requirement for static callback facilities.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* The EventSubscriber constructor is NOT responsible for adding Monitor%s.
|
2014-10-03 15:14:36 +00:00
|
|
|
* Please use `init` for adding Monitor%s as all EventPublisher instances will
|
2014-09-24 15:03:16 +00:00
|
|
|
* have run `setUp` and initialized their run loops.
|
|
|
|
*/
|
2014-10-03 15:08:06 +00:00
|
|
|
EventSubscriber() {}
|
2014-09-23 03:33:58 +00:00
|
|
|
|
2014-09-30 19:50:14 +00:00
|
|
|
/// Backing storage indexing namespace definition methods.
|
2014-10-03 15:14:36 +00:00
|
|
|
EventPublisherID dbNamespace() { return type() + "." + name(); }
|
|
|
|
/// The string EventPublisher identifying this EventSubscriber.
|
|
|
|
virtual EventPublisherID type() const = 0;
|
2014-10-03 15:08:06 +00:00
|
|
|
/// The string name identifying this EventSubscriber.
|
2014-10-03 15:14:36 +00:00
|
|
|
virtual EventPublisherID name() const = 0;
|
2014-09-19 08:54:33 +00:00
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-24 15:03:16 +00:00
|
|
|
/// Lock used when incrementing the EventID database index.
|
2014-09-19 08:54:33 +00:00
|
|
|
boost::mutex event_id_lock_;
|
2014-09-24 15:03:16 +00:00
|
|
|
|
|
|
|
/// Lock used when recording an EventID and time into search bins.
|
2014-09-19 08:54:33 +00:00
|
|
|
boost::mutex event_record_lock_;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-19 08:54:33 +00:00
|
|
|
FRIEND_TEST(EventsDatabaseTests, test_event_module_id);
|
|
|
|
FRIEND_TEST(EventsDatabaseTests, test_unique_event_module_id);
|
|
|
|
};
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief A factory for associating event generators to EventPublisherID%s.
|
2014-09-18 04:20:30 +00:00
|
|
|
*
|
|
|
|
* This factory both registers new event types and the monitors that use them.
|
2014-10-03 15:14:36 +00:00
|
|
|
* An EventPublisher is also a factory, the single event factory arbitates Monitor
|
|
|
|
* creatating and management for each associated EventPublisher.
|
2014-09-18 04:20:30 +00:00
|
|
|
*
|
|
|
|
* Since event types may be plugins, they are created using the factory.
|
|
|
|
* Since monitors may be configured/disabled they are also factory-managed.
|
|
|
|
*/
|
|
|
|
class EventFactory {
|
2014-09-21 21:29:28 +00:00
|
|
|
public:
|
2014-09-24 15:03:16 +00:00
|
|
|
/// Access to the EventFactory instance.
|
2014-09-30 02:06:33 +00:00
|
|
|
static EventFactory& getInstance();
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief Add an EventPublisher to the factory.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* The registration is mostly abstracted using osquery's registery.
|
|
|
|
*/
|
2014-09-18 04:20:30 +00:00
|
|
|
template <typename T>
|
2014-10-03 15:14:36 +00:00
|
|
|
static Status registerEventPublisher() {
|
|
|
|
auto event_pub = std::make_shared<T>();
|
|
|
|
return EventFactory::registerEventPublisher(event_pub);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
2014-09-24 15:03:16 +00:00
|
|
|
|
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief Add an EventPublisher to the factory.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* The registration is mostly abstracted using osquery's registery.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* @param event_pub If for some reason the caller needs access to the
|
|
|
|
* EventPublisher instance they can register-by-instance.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* Access to the EventPublisher instance is not discouraged, but using the
|
|
|
|
* EventFactory `getEventPublisher` accessor is encouraged.
|
2014-09-24 15:03:16 +00:00
|
|
|
*/
|
2014-10-03 15:14:36 +00:00
|
|
|
static Status registerEventPublisher(const EventPublisherRef event_pub);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-24 18:25:05 +00:00
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief Add an EventSubscriber to the factory.
|
2014-09-24 18:25:05 +00:00
|
|
|
*
|
|
|
|
* The registration is mostly abstracted using osquery's registery.
|
|
|
|
*/
|
2014-09-24 15:03:16 +00:00
|
|
|
template <typename T>
|
2014-10-03 15:08:06 +00:00
|
|
|
static Status registerEventSubscriber() {
|
2014-09-25 17:17:32 +00:00
|
|
|
auto event_module = T::getInstance();
|
2014-10-03 15:08:06 +00:00
|
|
|
return EventFactory::registerEventSubscriber(event_module);
|
2014-09-24 15:03:16 +00:00
|
|
|
}
|
|
|
|
|
2014-09-24 18:25:05 +00:00
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief Add an EventSubscriber to the factory.
|
2014-09-24 18:25:05 +00:00
|
|
|
*
|
|
|
|
* The registration is mostly abstracted using osquery's registery.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* @param event_module If the caller must access the EventSubscriber instance
|
2014-09-24 18:25:05 +00:00
|
|
|
* control may be passed to the registry.
|
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* Access to the EventSubscriber instance outside of the within-instance
|
2014-09-24 18:25:05 +00:00
|
|
|
* table generation method and set of EventCallback%s is discouraged.
|
|
|
|
*/
|
2014-10-03 15:08:06 +00:00
|
|
|
static Status registerEventSubscriber(const EventSubscriberRef event_module);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief Add a MonitorContext and EventCallback Monitor to an EventPublisher.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* Create a Monitor from a given MonitorContext and EventCallback and
|
2014-10-03 15:14:36 +00:00
|
|
|
* add that Monitor to the EventPublisher assosicated identiter.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* @param type_id The string for an EventPublisher receiving the Monitor.
|
|
|
|
* @param mc A MonitorContext related to the EventPublisher.
|
|
|
|
* @param cb When the EventPublisher fires an event the MonitorContext will
|
2014-09-24 15:03:16 +00:00
|
|
|
* be evaluated, if the event matches optional specifics in the context this
|
|
|
|
* callback function will be called. It should belong to an EventMonitor.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* @return Was the MonitorContext appropriate for the EventPublisher.
|
2014-09-24 15:03:16 +00:00
|
|
|
*/
|
2014-10-03 15:14:36 +00:00
|
|
|
static Status addMonitor(EventPublisherID type_id,
|
2014-09-21 21:29:28 +00:00
|
|
|
const MonitorContextRef mc,
|
2014-09-25 17:17:32 +00:00
|
|
|
EventCallback cb = 0);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/// Add a Monitor using a caller Monitor instance.
|
2014-10-03 15:14:36 +00:00
|
|
|
static Status addMonitor(EventPublisherID type_id, const MonitorRef monitor);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Add a Monitor by templating the EventPublisher, using a MonitorContext.
|
2014-09-25 17:17:32 +00:00
|
|
|
template <typename T>
|
|
|
|
static Status addMonitor(const MonitorContextRef mc, EventCallback cb = 0) {
|
2014-10-03 15:14:36 +00:00
|
|
|
return addMonitor(EventPublisher::type<T>(), mc, cb);
|
2014-09-25 17:17:32 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Add a Monitor by templating the EventPublisher, using a Monitor instance.
|
2014-09-25 17:17:32 +00:00
|
|
|
template <typename T>
|
|
|
|
static Status addMonitor(const MonitorRef monitor) {
|
2014-10-03 15:14:36 +00:00
|
|
|
return addMonitor(EventPublisher::type<T>(), monitor);
|
2014-09-25 17:17:32 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Get the total number of Monitor%s across ALL EventPublisher%s.
|
|
|
|
static size_t numMonitors(EventPublisherID type_id);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Get the number of EventPublishers.
|
|
|
|
static size_t numEventPublishers() {
|
|
|
|
return EventFactory::getInstance().event_pubs_.size();
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief Halt the EventPublisher run loop and call its `tearDown`.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* Any EventSubscriber%s with Monitor%s for this EventPublisher will become useless.
|
2014-09-24 15:03:16 +00:00
|
|
|
* osquery instanciators MUST deregister events.
|
2014-10-03 15:14:36 +00:00
|
|
|
* EventPublisher%s assume they can hook/trampoline, which requires cleanup.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* @param event_pub The string label for the EventPublisher.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* @return Did the EventPublisher deregister cleanly.
|
2014-09-24 15:03:16 +00:00
|
|
|
*/
|
2014-10-03 15:14:36 +00:00
|
|
|
static Status deregisterEventPublisher(const EventPublisherRef event_pub);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Deregister an EventPublisher by EventPublisherID.
|
|
|
|
static Status deregisterEventPublisher(EventPublisherID type_id);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Deregister all EventPublisher%s.
|
|
|
|
static Status deregisterEventPublishers();
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Return an instance to a registered EventPublisher.
|
|
|
|
static EventPublisherRef getEventPublisher(EventPublisherID);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-23 01:35:12 +00:00
|
|
|
public:
|
|
|
|
/// The dispatched event thread's entrypoint (if needed).
|
2014-10-03 15:14:36 +00:00
|
|
|
static Status run(EventPublisherID type_id);
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-09-23 01:35:12 +00:00
|
|
|
/// An initializer's entrypoint for spawning all event type run loops.
|
|
|
|
static void delay();
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-09-30 20:17:54 +00:00
|
|
|
public:
|
2014-10-03 15:14:36 +00:00
|
|
|
/// If a static EventPublisher callback wants to fire
|
2014-09-30 20:17:54 +00:00
|
|
|
template <typename T>
|
|
|
|
static void fire(const EventContextRef ec) {
|
2014-10-03 15:14:36 +00:00
|
|
|
auto event_pub = getEventPublisher(EventPublisher::type<T>());
|
|
|
|
event_pub->fire(ec);
|
2014-09-30 20:17:54 +00:00
|
|
|
}
|
|
|
|
|
2014-09-24 15:03:16 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief End all EventPublisher run loops and call their `tearDown` methods.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
|
|
|
* End is NOT the same as deregistration.
|
|
|
|
*
|
|
|
|
* @param should_end Reset the "is ending" state if False.
|
|
|
|
*/
|
2014-09-23 03:33:58 +00:00
|
|
|
static void end(bool should_end = true);
|
2014-09-23 01:35:12 +00:00
|
|
|
|
2014-09-21 21:29:28 +00:00
|
|
|
private:
|
2014-09-30 19:50:14 +00:00
|
|
|
/// An EventFactory will exist for the lifetime of the application.
|
2014-09-23 01:35:12 +00:00
|
|
|
EventFactory() { ending_ = false; }
|
2014-09-30 02:06:33 +00:00
|
|
|
EventFactory(EventFactory const&);
|
|
|
|
void operator=(EventFactory const&);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-21 21:29:28 +00:00
|
|
|
private:
|
2014-09-24 15:03:16 +00:00
|
|
|
/// Set ending to True to cause event type run loops to finish.
|
2014-09-23 01:35:12 +00:00
|
|
|
bool ending_;
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Set of registered EventPublisher instances.
|
|
|
|
EventPublisherMap event_pubs_;
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Set of running EventPublisher run loop threads.
|
2014-09-24 17:20:58 +00:00
|
|
|
std::vector<std::shared_ptr<boost::thread>> threads_;
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:08:06 +00:00
|
|
|
/// Set of instanciated EventSubscriber Monitor sets (with callbacks and state).
|
|
|
|
std::vector<EventSubscriberRef> event_modules_;
|
2014-09-18 04:20:30 +00:00
|
|
|
};
|
|
|
|
}
|
2014-09-24 15:03:16 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
/// Expose a Plugin-like Registry for EventPublisher instances.
|
|
|
|
DECLARE_REGISTRY(EventPublishers, std::string, EventPublisherRef);
|
|
|
|
#define REGISTERED_EVENTTYPES REGISTRY(EventPublishers)
|
2014-09-25 17:17:32 +00:00
|
|
|
#define REGISTER_EVENTTYPE(decorator) \
|
2014-10-03 15:14:36 +00:00
|
|
|
REGISTER(EventPublishers, #decorator, std::make_shared<decorator>());
|
2014-09-24 15:03:16 +00:00
|
|
|
|
|
|
|
/**
|
2014-10-03 15:08:06 +00:00
|
|
|
* @brief Expose a Plugin-link Registry for EventSubscriber instances.
|
2014-09-24 15:03:16 +00:00
|
|
|
*
|
2014-10-03 15:08:06 +00:00
|
|
|
* In most cases the EventSubscriber class will organize itself to include
|
2014-09-24 15:03:16 +00:00
|
|
|
* an generator entry point for query-time table generation too.
|
|
|
|
*/
|
2014-10-03 15:08:06 +00:00
|
|
|
DECLARE_REGISTRY(EventSubscribers, std::string, EventSubscriberRef);
|
|
|
|
#define REGISTERED_EVENTMODULES REGISTRY(EventSubscribers)
|
2014-09-25 17:17:32 +00:00
|
|
|
#define REGISTER_EVENTMODULE(decorator) \
|
2014-10-03 15:08:06 +00:00
|
|
|
REGISTER(EventSubscribers, #decorator, decorator::getInstance());
|
2014-09-24 18:25:05 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
namespace registries {
|
2014-09-30 19:50:14 +00:00
|
|
|
/**
|
2014-10-03 15:14:36 +00:00
|
|
|
* @brief A utility method for moving EventPublisher%s and EventSubscriber%s (plugins)
|
2014-09-30 19:50:14 +00:00
|
|
|
* into the EventFactory.
|
|
|
|
*
|
2014-10-03 15:14:36 +00:00
|
|
|
* To handle run-time and compile-time EventPublisher and EventSubscriber additions
|
2014-09-30 19:50:14 +00:00
|
|
|
* as plugins or extensions, the osquery Registry workflow is used. During
|
|
|
|
* application launch (or within plugin load) the EventFactory faucet moves
|
2014-10-03 15:14:36 +00:00
|
|
|
* managed instances of these types to the EventFactory. The EventPublisher and
|
2014-10-03 15:08:06 +00:00
|
|
|
* EventSubscriber lifecycle/developer workflow is unknown to the Registry.
|
2014-09-30 19:50:14 +00:00
|
|
|
*/
|
2014-10-03 15:14:36 +00:00
|
|
|
void faucet(EventPublishers ets, EventSubscribers ems);
|
2014-09-24 18:25:05 +00:00
|
|
|
}
|
|
|
|
}
|