--- /dev/null
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#pragma once
+
+#include <future>
+#include <string>
+#include <vector>
+
+#include "osquery/status.h"
+#include "osquery/database.h"
+
+namespace osquery {
+
+/**
+ * @brief A string which represents the default logger receiver
+ *
+ * The logger plugin that you use to define your config receiver can be
+ * defined via a command-line flag, however, if you don't define a logger
+ * plugin to use via the command-line, then the logger receiver which is
+ * represented by the string stored kDefaultLogReceiverName will be used.
+ */
+extern const std::string kDefaultLogReceiverName;
+
+/**
+ * @brief Log a string using the default logger receiver.
+ *
+ * Note that this method should only be used to log results. If you'd like to
+ * log normal osquery operations, use Google Logging.
+ *
+ * @param s the string to log
+ *
+ * @return an instance of osquery::Status, indicating the success or failure
+ * of the operation.
+ */
+osquery::Status logString(const std::string& s);
+
+/**
+ * @brief Log a string using a specific logger receiver.
+ *
+ * Note that this method should only be used to log results. If you'd like to
+ * log normal osquery operations, use Google Logging.
+ *
+ * @param s the string to log
+ * @param receiver a string representing the log receiver to use
+ *
+ * @return an instance of osquery::Status, indicating the success or failure
+ * of the operation.
+ */
+osquery::Status logString(const std::string& s, const std::string& receiver);
+
+/**
+ * @brief Directly log results of scheduled queries to the default receiver
+ *
+ * @param item a struct representing the results of a scheduled query
+ *
+ * @return an instance of osquery::Status, indicating the success or failure
+ * of the operation.
+ */
+osquery::Status logScheduledQueryLogItem(
+ const osquery::ScheduledQueryLogItem& item);
+
+/**
+ * @brief Directly log results of scheduled queries to a specified receiver
+ *
+ * @param item a struct representing the results of a scheduled query
+ * @param receiver a string representing the log receiver to use
+ *
+ * @return an instance of osquery::Status, indicating the success or failure
+ * of the operation.
+ */
+osquery::Status logScheduledQueryLogItem(
+ const osquery::ScheduledQueryLogItem& item, const std::string& receiver);
+}
--- /dev/null
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#pragma once
+
+#include <memory>
+
+#include "osquery/registry.h"
+#include "osquery/status.h"
+
+namespace osquery {
+
+/**
+ * @brief Superclass for the pluggable config component.
+ *
+ * In order to make the logging of osquery results easy to integrate into your
+ * environment, we take advantage of a plugin interface which allows you to
+ * integrate osquery with your internal large-scale logging infrastructure.
+ * You may use flume, splunk, syslog, scribe, etc. In order to use your
+ * specific upstream logging systems, one simply needs to create a custom
+ * subclass of LoggerPlugin. That subclass should implement the
+ * LoggerPlugin::logString method.
+ *
+ * Consider the following example:
+ *
+ * @code{.cpp}
+ * class TestLoggerPlugin : public ConfigPlugin {
+ * public:
+ * virtual osquery::Status logString(const std::string& s) {
+ * int i = 0;
+ * internal::logStringToFlume(s, i);
+ * std::string message;
+ * if (i == 0) {
+ * message = "OK";
+ * } else {
+ * message = "Failed";
+ * }
+ * return osquery::Status(i, message);
+ * }
+ * };
+ *
+ * REGISTER_LOGGER_PLUGIN(
+ * "test", std::make_shared<osquery::TestLoggerPlugin>());
+ * @endcode
+ */
+class LoggerPlugin {
+ public:
+ /** @brief Virtual method which should implement custom logging.
+ *
+ * LoggerPlugin::logString should be implemented by a subclass of
+ * LoggerPlugin which needs to log a string in a custom way.
+ *
+ * @return an instance of osquery::Status which indicates the success or
+ * failure of the operation.
+ */
+ virtual osquery::Status logString(const std::string& s) = 0;
+
+ /// Virtual destructor
+ virtual ~LoggerPlugin() {}
+};
+}
+
+DECLARE_REGISTRY(LoggerPlugins,
+ std::string,
+ std::shared_ptr<osquery::LoggerPlugin>)
+
+#define REGISTERED_LOGGER_PLUGINS REGISTRY(LoggerPlugins)
+
+#define REGISTER_LOGGER_PLUGIN(name, decorator) \
+ REGISTER(LoggerPlugins, name, decorator)
ADD_SUBDIRECTORY(database)
ADD_SUBDIRECTORY(registry)
ADD_SUBDIRECTORY(filesystem)
+ADD_SUBDIRECTORY(logger)
ADD_LIBRARY(${TARGET_OSQUERY_LIB} STATIC main/lib.cpp ${${TARGET_OSQUERY_LIB}_SRCS})
TARGET_LINK_LIBRARIES(${TARGET_OSQUERY_LIB} ${${TARGET_OSQUERY_LIB}_DEP})
--- /dev/null
+ADD_OSQUERY_LIBRARY(osquery_logger logger.cpp
+ plugins/filesystem.cpp)
+
+ADD_OSQUERY_TEST(osquery_logger_tests logger_tests.cpp)
--- /dev/null
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#include "osquery/logger.h"
+#include "osquery/logger/plugin.h"
+
+#include <algorithm>
+#include <thread>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+
+using osquery::Status;
+
+namespace osquery {
+
+const std::string kDefaultLogReceiverName = "filesystem";
+
+DEFINE_string(log_receiver,
+ kDefaultLogReceiverName,
+ "The upstream log receiver to log messages to.");
+
+Status logString(const std::string& s) {
+ return logString(s, FLAGS_log_receiver);
+}
+
+Status logString(const std::string& s, const std::string& receiver) {
+ if (REGISTERED_LOGGER_PLUGINS.find(receiver) ==
+ REGISTERED_LOGGER_PLUGINS.end()) {
+ LOG(ERROR) << "Logger receiver " << receiver << " not found";
+ return Status(1, "Logger receiver not found");
+ }
+ auto log_status = REGISTERED_LOGGER_PLUGINS.at(receiver)->logString(s);
+ if (!log_status.ok()) {
+ return log_status;
+ }
+ return Status(0, "OK");
+}
+
+Status logScheduledQueryLogItem(const osquery::ScheduledQueryLogItem& results) {
+ return logScheduledQueryLogItem(results, FLAGS_log_receiver);
+}
+
+Status logScheduledQueryLogItem(const osquery::ScheduledQueryLogItem& results,
+ const std::string& receiver) {
+ std::string json;
+ auto s = osquery::serializeScheduledQueryLogItemJSON(results, json);
+ if (!s.ok()) {
+ return s;
+ }
+ return logString(json, receiver);
+}
+}
--- /dev/null
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#include "osquery/logger.h"
+#include "osquery/logger/plugin.h"
+
+#include <gtest/gtest.h>
+#include <glog/logging.h>
+
+#include "osquery/core.h"
+
+using osquery::Status;
+
+namespace osquery {
+
+class LoggerTests : public testing::Test {
+ public:
+ LoggerTests() { osquery::InitRegistry::get().run(); }
+};
+
+class TestLoggerPlugin : public LoggerPlugin {
+ public:
+ TestLoggerPlugin() {}
+
+ Status logString(const std::string& s) { return Status(0, s); }
+
+ virtual ~TestLoggerPlugin() {}
+};
+
+REGISTER_LOGGER_PLUGIN("test", std::make_shared<osquery::TestLoggerPlugin>())
+
+TEST_F(LoggerTests, test_plugin) {
+ auto s = REGISTERED_LOGGER_PLUGINS.at("test")->logString("foobar");
+ EXPECT_EQ(s.ok(), true);
+ EXPECT_EQ(s.toString(), "foobar");
+}
+}
+
+int main(int argc, char* argv[]) {
+ testing::InitGoogleTest(&argc, argv);
+ osquery::initOsquery(argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#include "osquery/logger/plugin.h"
+
+#include <algorithm>
+#include <exception>
+#include <ios>
+#include <fstream>
+#include <mutex>
+#include <thread>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+
+using osquery::Status;
+
+namespace osquery {
+
+std::mutex filesystemLoggerPluginMutex;
+
+class FilesystemLoggerPlugin : public LoggerPlugin {
+ public:
+ std::string log_path;
+ FilesystemLoggerPlugin() {
+ log_path = FLAGS_log_dir + "osqueryd.results.log";
+ }
+
+ virtual Status logString(const std::string& s) {
+ std::lock_guard<std::mutex> lock(filesystemLoggerPluginMutex);
+ try {
+ VLOG(3) << "filesystem logger plugin: logging to " << log_path;
+ std::ofstream log_stream(log_path,
+ std::ios_base::app | std::ios_base::out);
+ if (log_stream.fail()) {
+ return Status(1, "error opening file: " + log_path);
+ }
+ log_stream << s << std::endl;
+ } catch (const std::exception& e) {
+ return Status(1, e.what());
+ }
+ return Status(0, "OK");
+ }
+};
+
+REGISTER_LOGGER_PLUGIN("filesystem",
+ std::make_shared<osquery::FilesystemLoggerPlugin>())
+}
%{_bindir}/osquery_sqlite_util_tests
%{_bindir}/osquery_test_util_tests
%{_bindir}/osquery_text_tests
+%{_bindir}/osquery_logger_tests