osquery-1/include/osquery/events.h

227 lines
7.3 KiB
C
Raw Normal View History

// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <functional>
#include <memory>
#include <map>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
2014-09-19 08:54:33 +00:00
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include "osquery/status.h"
2014-09-19 08:54:33 +00:00
#include "osquery/database.h"
namespace osquery {
struct Monitor;
class EventType;
typedef const std::string EventTypeID;
2014-09-19 08:54:33 +00:00
typedef const std::string EventID;
typedef uint32_t EventContextID;
typedef uint32_t EventTime;
struct MonitorContext {};
struct EventContext {};
typedef boost::shared_ptr<Monitor> MonitorRef;
typedef boost::shared_ptr<EventType> EventTypeRef;
typedef boost::shared_ptr<MonitorContext> MonitorContextRef;
typedef boost::shared_ptr<EventContext> EventContextRef;
2014-09-19 08:54:33 +00:00
typedef std::function<Status(EventContextID, EventTime, EventContextRef)>
2014-09-21 21:29:28 +00:00
EventCallback;
2014-09-19 08:54:33 +00:00
/// An EventType must track every monitor added.
typedef std::vector<MonitorRef> MonitorVector;
2014-09-19 08:54:33 +00:00
/// The EventFactory tracks every EventType and the name it specifies.
typedef std::map<EventTypeID, EventTypeRef> EventTypeMap;
2014-09-19 08:54:33 +00:00
/// The set of search-time binned lookup tables.
extern const std::vector<size_t> kEventTimeLists;
// Instead of attempting fancy RTTI limitations, each derived EventType may
// choose to macro-define a getter for a custom EventContext/MonitorContext.
// This assumes each event will implement custom fields for monitoring
// and custom fields holding event-related data.
#define DECLARE_EVENTTYPE(TYPE, MONITOR, EVENT) \
public: \
EventTypeID type() const { return TYPE; } \
static boost::shared_ptr<EVENT> getEventContext(EventContextRef context) { \
return boost::static_pointer_cast<EVENT>(context); \
} \
static boost::shared_ptr<MONITOR> getMonitorContext( \
MonitorContextRef context) { \
return boost::static_pointer_cast<MONITOR>(context); \
} \
static boost::shared_ptr<EVENT> createEventContext() { \
auto ec = boost::make_shared<EVENT>(); \
return ec; \
}
2014-09-19 08:54:33 +00:00
/// Helper define for binding EventModule to an EventType.
#define DECLARE_EVENTMODULE(NAME, TYPE) \
private: \
2014-09-19 08:54:33 +00:00
EventTypeID name() const { return NAME; } \
EventTypeID type() const { return TYPE; }
/**
* @brief An implementation monitor context used to configure/create a monitor.
*
* The monitor stuct is a helper/boiler-plate constructor for a context and
* the caller's callback.
*/
struct Monitor {
2014-09-21 21:29:28 +00:00
public:
MonitorContextRef context;
EventCallback callback;
2014-09-21 21:29:28 +00:00
static MonitorRef create() { return boost::make_shared<Monitor>(); }
static MonitorRef create(const MonitorContextRef mc, EventCallback ec = 0) {
auto monitor = boost::make_shared<Monitor>();
monitor->context = mc;
monitor->callback = ec;
return monitor;
}
};
/**
* @brief Generate OS events of a type (FS, Network, Syscall, ioctl).
*
2014-09-21 21:29:28 +00:00
* A class of OS Events is abstracted into a type-class responsible for
* remaining as agile as possible given a known-set of monitors using the
* events.
*
* There are four actions an event generator will take, start, configure, stop,
* and generate event. THe configure is a pseudo-start that may occur during
2014-09-21 21:29:28 +00:00
* runtime.
*/
class EventType {
2014-09-21 21:29:28 +00:00
public:
virtual void configure() {}
virtual void setUp() {}
virtual void tearDown() {}
2014-09-19 08:54:33 +00:00
virtual Status run();
Status addMonitor(const MonitorRef monitor) {
2014-09-19 08:54:33 +00:00
monitors_.push_back(monitor);
return Status(0, "OK");
}
size_t numMonitors() { return monitors_.size(); }
2014-09-21 21:29:28 +00:00
EventType(){};
2014-09-19 08:54:33 +00:00
virtual EventTypeID type() const = 0;
protected:
2014-09-19 08:54:33 +00:00
void fire(EventContextRef ec, EventTime event_time = 0);
protected:
2014-09-19 08:54:33 +00:00
/// The EventType will keep track of Monitors that contain associated callins.
MonitorVector monitors_;
2014-09-19 08:54:33 +00:00
/// An Event ID is assigned by the EventType within the EventContext.
/// This is not used to store EventData in the backing store.
EventContextID next_ec_id_;
private:
2014-09-19 08:54:33 +00:00
boost::mutex ec_id_lock_;
private:
2014-09-19 08:54:33 +00:00
FRIEND_TEST(EventsTests, test_fire_event);
};
2014-09-19 08:54:33 +00:00
/**
* @brief An interface binding monitors, event response, and table generation.
*
* Use the EventModule interface when adding event monitors and defining callin
* functions. The EventCallback typedef is usually a member function for an
2014-09-19 08:54:33 +00:00
* EventModule. The EventModule interface includes a very important 'Add' method
* 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.
*/
class EventModule {
protected:
2014-09-19 08:54:33 +00:00
/// Store an event for Table-access into the underlying backing store.
Status Add(const osquery::Row& r, int event_time);
private:
2014-09-19 08:54:33 +00:00
/// Returns a new Event ID for this module, increments to the current EID.
EventID getEventID();
/// Records an added EventID/Event data.
Status recordEvent(EventID eid, int event_time);
private:
2014-09-19 08:54:33 +00:00
virtual EventTypeID type() const = 0;
virtual EventTypeID name() const = 0;
private:
2014-09-19 08:54:33 +00:00
boost::mutex event_id_lock_;
boost::mutex event_record_lock_;
private:
2014-09-19 08:54:33 +00:00
FRIEND_TEST(EventsDatabaseTests, test_event_module_id);
FRIEND_TEST(EventsDatabaseTests, test_unique_event_module_id);
};
/**
* @brief A factory for associating event generators to event type IDs.
*
* This factory both registers new event types and the monitors that use them.
* An event type is also a factor, the single event factory arbitates monitor
* creatating and management for each associated event type.
*
* 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:
static boost::shared_ptr<EventFactory> get();
template <typename T>
static Status registerEventType() {
auto event_type = boost::make_shared<T>();
return EventFactory::registerEventType(event_type);
}
static Status registerEventType(const EventTypeRef event_type);
2014-09-19 08:54:33 +00:00
// The dispatched event thread's entrypoint (if needed).
static Status run(EventTypeID type_id);
static Status addMonitor(EventTypeID type_id, const MonitorRef monitor);
2014-09-21 21:29:28 +00:00
static Status addMonitor(EventTypeID type_id,
const MonitorContextRef mc,
EventCallback callback = 0);
2014-09-19 08:54:33 +00:00
static size_t numMonitors(EventTypeID type_id);
static size_t numEventTypes() {
return EventFactory::get()->event_types_.size();
}
// A watching context MUST deregister events.
// EventType's assume they can hook/trampoline, which requires cleanup.
static Status deregisterEventType(const EventTypeRef event_type);
static Status deregisterEventType(EventTypeID type_id);
static Status deregisterEventTypes();
static EventTypeRef getEventType(EventTypeID);
2014-09-21 21:29:28 +00:00
private:
EventFactory() {}
2014-09-21 21:29:28 +00:00
private:
EventTypeMap event_types_;
};
}