ADD_OSQUERY_LIBRARY(osquery_core tables.cpp
query.cpp
- plugins/logger.cpp
plugins/plugin.cpp
plugins/sql.cpp
sql/column.cpp
FILE(GLOB OSQUERY_CORE_TESTS "tests/*.cpp")
FILE(GLOB OSQUERY_CORE_POSIX_TESTS "tests/posix/*.cpp")
ADD_OSQUERY_TEST(${OSQUERY_SQL_TESTS}
- ${OSQUERY_CORE_POSIX_TESTS}
- ${OSQUERY_CORE_PLUGINS_TESTS})
+ ${OSQUERY_CORE_POSIX_TESTS})
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include "logger.h"
-
-#include <osquery/utils/json/json.h>
-
-namespace rj = rapidjson;
-
-namespace osquery {
-
-namespace {
-
-void deserializeIntermediateLog(const PluginRequest& request,
- std::vector<StatusLogLine>& log) {
- if (request.count("log") == 0) {
- return;
- }
-
- rj::Document doc;
- if (doc.Parse(request.at("log").c_str()).HasParseError()) {
- return;
- }
-
- for (auto& line : doc.GetArray()) {
- log.push_back({
- static_cast<StatusLogSeverity>(line["s"].GetInt()),
- line["f"].GetString(),
- line["i"].GetUint64(),
- line["m"].GetString(),
- line["c"].GetString(),
- line["u"].GetUint64(),
- line["h"].GetString(),
- });
- }
-}
-
-}
-
-Status LoggerPlugin::call(const PluginRequest& request,
- PluginResponse& response) {
- std::vector<StatusLogLine> intermediate_logs;
- if (request.count("string") > 0) {
- return this->logString(request.at("string"));
- } else if (request.count("snapshot") > 0) {
- return this->logSnapshot(request.at("snapshot"));
- } else if (request.count("init") > 0) {
- deserializeIntermediateLog(request, intermediate_logs);
- this->setProcessName(request.at("init"));
- this->init(this->name(), intermediate_logs);
- return Status(0);
- } else if (request.count("status") > 0) {
- deserializeIntermediateLog(request, intermediate_logs);
- return this->logStatus(intermediate_logs);
- } else if (request.count("event") > 0) {
- return this->logEvent(request.at("event"));
- } else if (request.count("action") && request.at("action") == "features") {
- size_t features = 0;
- features |= (usesLogStatus()) ? LOGGER_FEATURE_LOGSTATUS : 0;
- features |= (usesLogEvent()) ? LOGGER_FEATURE_LOGEVENT : 0;
- return Status(static_cast<int>(features));
- } else {
- return Status(1, "Unsupported call to logger plugin");
- }
-}
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <string>
-
-#include <osquery/plugins/plugin.h>
-#include <osquery/utils/status/status.h>
-
-namespace osquery {
-
-/**
- * @brief Logger plugin feature bits for complicated loggers.
- *
- * Logger plugins may opt-in to additional features like explicitly handling
- * Glog status events or requesting event subscribers to forward each event
- * directly to the logger. This enumeration tracks, and corresponds to, each
- * of the feature methods defined in a logger plugin.
- *
- * A specific registry call action can be used to retrieve an overloaded Status
- * object containing all of the opt-in features.
- */
-enum LoggerFeatures {
- LOGGER_FEATURE_BLANK = 0,
- LOGGER_FEATURE_LOGSTATUS = 1,
- LOGGER_FEATURE_LOGEVENT = 2,
-};
-
-/**
- * @brief An internal severity set mapping to Glog's LogSeverity levels.
- */
-enum StatusLogSeverity {
- O_INFO = 0,
- O_WARNING = 1,
- O_ERROR = 2,
- O_FATAL = 3,
-};
-
-/// An intermediate status log line.
-struct StatusLogLine {
- public:
- /// An integer severity level mimicking Glog's.
- StatusLogSeverity severity;
-
- /// The name of the file emitting the status log.
- std::string filename;
-
- /// The line of the file emitting the status log.
- size_t line;
-
- /// The string-formatted status message.
- std::string message;
-
- /// The ASCII time stamp for when the status message was emitted
- std::string calendar_time;
-
- /// The UNIX time for when the status message was emitted
- size_t time;
-
- /**
- * @brief The host identifier at the time when logs are flushed.
- *
- * There is occasionally a delay between logging a status and decorating
- * with the host identifier. In most cases the identifier is static so this
- * does not matter. In some cases the host identifier causes database lookups.
- */
- std::string identifier;
-};
-
-/**
- * @brief Superclass for the pluggable logging facilities.
- *
- * In order to make the logging of osquery results and inline debug, warning,
- * error status 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 at least implement the
- * LoggerPlugin::logString method.
- *
- * Consider the following example:
- *
- * @code{.cpp}
- * class TestLoggerPlugin : public LoggerPlugin {
- * public:
- * 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(TestLoggerPlugin, "logger", "test");
- * @endcode
- */
-class LoggerPlugin : public Plugin {
- public:
- /// The LoggerPlugin PluginRequest action router.
- Status call(const PluginRequest& request, PluginResponse& response) override;
-
- /**
- * @brief A feature method to decide if Glog should stop handling statuses.
- *
- * Return true if this logger plugin's #logStatus method should handle Glog
- * statuses exclusively. If true then Glog will stop writing status lines
- * to the configured log path.
- *
- * @return false if this logger plugin should NOT handle Glog statuses.
- */
- virtual bool usesLogStatus() {
- return false;
- }
-
- /**
- * @brief A feature method to decide if events should be forwarded.
- *
- * See the optional logEvent method.
- *
- * @return false if this logger plugin should NOT handle events directly.
- */
- virtual bool usesLogEvent() {
- return false;
- }
-
- /**
- * @brief Set the process name.
- */
- void setProcessName(const std::string& name) {
- process_name_ = name;
- }
-
- /**
- * @brief Get the process name.
- */
- const std::string& name() const {
- return process_name_;
- }
-
- /** @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 Status logString(const std::string& s) = 0;
-
- /**
- * @brief See the usesLogStatus method, log a Glog status.
- *
- * @param log A vector of parsed Glog log lines.
- * @return Status non-op indicating success or failure.
- */
- virtual Status logStatus(const std::vector<StatusLogLine>& log) {
- (void)log;
- return Status(1, "Not enabled");
- }
-
- /**
- * @brief Optionally handle snapshot query results separately from events.
- *
- * If a logger plugin wants to write snapshot query results (potentially
- * large amounts of data) to a specific sink it should implement logSnapshot.
- * Otherwise the serialized log item data will be forwarded to logString.
- *
- * @param s A special log item will complete results from a query.
- * @return log status
- */
- virtual Status logSnapshot(const std::string& s) {
- return logString(s);
- }
-
- /**
- * @brief Optionally handle each published event via the logger.
- *
- * It is possible to skip the database representation of event subscribers
- * and instead forward each added event to the active logger plugin.
- */
- virtual Status logEvent(const std::string& /*s*/) {
- return Status(1, "Not enabled");
- }
-
- protected:
- /**
- * @brief Initialize the logger with the name of the binary and any status
- * logs generated between program launch and logger start.
- *
- * The logger initialization is called once CLI flags have been parsed, the
- * registry items are constructed, extension routes broadcasted and extension
- * plugins discovered (as a logger may be an extension plugin) and the config
- * has been loaded (which may include additional CLI flag-options).
- *
- * All of these actions may have generated VERBOSE, INFO, WARNING, or ERROR
- * logs. The internal logging facility, Glog, collects these intermediate
- * status logs and a customized log sink buffers them until the active
- * osquery logger's `init` method is called.
- *
- * @param binary_name The string name of the process (argv[0]).
- * @param log The set of status (INFO, WARNING, ERROR) logs generated before
- * the logger's `init` method was called.
- */
- virtual void init(const std::string& binary_name,
- const std::vector<StatusLogLine>& log) = 0;
-
- private:
- std::string process_name_;
-};
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2018-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <gtest/gtest.h>
-
-#include <osquery/core/database/in_memory_database.h>
-#include <osquery/database.h>
-
-namespace osquery {
-
-GTEST_TEST(InMemoryDatabaseTest, test_open) {
- auto db = std::make_unique<InMemoryDatabase>("test");
- auto result = db->open();
- EXPECT_TRUE(result);
- db->close();
-}
-
-GTEST_TEST(InMemoryDatabaseTest, test_destroy) {
- auto db = std::make_unique<InMemoryDatabase>("test");
- ASSERT_FALSE(db->open().isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "key", 10).isError());
- db->close();
- // In memory db should be destroyed on close
- // but we want to test that destroy is not failing for no reason
- auto result = db->destroyDB();
- EXPECT_TRUE(result);
- ASSERT_FALSE(db->open().isError());
- auto get_result = db->getInt32(kPersistentSettings, "key");
- EXPECT_FALSE(get_result);
- EXPECT_EQ(get_result.getError(), DatabaseError::KeyNotFound);
-}
-
-GTEST_TEST(InMemoryDatabaseTest, test_put) {
- auto db = std::make_unique<InMemoryDatabase>("test");
-#ifdef NDEBUG
- auto result = db->putInt32("test", "test", 23);
- EXPECT_FALSE(result);
- EXPECT_EQ(result.getError(), DatabaseError::DbIsNotOpen);
-#endif
- EXPECT_TRUE(db->open());
- EXPECT_TRUE(db->putInt32(kPersistentSettings, "test_key_int", 12));
- auto int_value = db->getInt32(kPersistentSettings, "test_key_int");
- EXPECT_TRUE(int_value);
- EXPECT_EQ(int_value.take(), 12);
-
- EXPECT_TRUE(db->putString(kPersistentSettings, "test_key_string", "string"));
- auto string_value = db->getString(kPersistentSettings, "test_key_string");
- EXPECT_TRUE(string_value);
- EXPECT_EQ(string_value.take(), "string");
-}
-
-GTEST_TEST(InMemoryDatabaseTest, test_domain_error) {
- auto db = std::make_unique<InMemoryDatabase>("test");
- ASSERT_FALSE(db->open().isError());
- auto result = db->putInt32("bad_domain", "key", 12);
- EXPECT_FALSE(result);
- EXPECT_EQ(result.takeError(), DatabaseError::DomainNotFound);
-}
-
-GTEST_TEST(InMemoryDatabaseTest, test_unknown_key) {
- auto db = std::make_unique<InMemoryDatabase>("test");
- ASSERT_FALSE(db->open().isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "key", 12).isError());
- auto result = db->getInt32(kPersistentSettings, "key_");
- EXPECT_FALSE(result);
- EXPECT_EQ(result.takeError(), DatabaseError::KeyNotFound);
-}
-
-GTEST_TEST(InMemoryDatabaseTest, test_keys_search) {
- auto db = std::make_unique<InMemoryDatabase>("test");
- ASSERT_FALSE(db->open().isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "key_1", 1).isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "key_2", 2).isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "key_3", 3).isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "kEy_1", 4).isError());
- ASSERT_FALSE(db->putInt32(kPersistentSettings, "kEy_2", 5).isError());
- auto result_all = db->getKeys(kPersistentSettings);
- EXPECT_TRUE(result_all);
- EXPECT_EQ((*result_all).size(), 5);
- auto result_some = db->getKeys(kPersistentSettings, "key");
- EXPECT_TRUE(result_some);
- EXPECT_EQ((*result_some).size(), 3);
-}
-
-} // namespace osquery
#include <string>
#include <vector>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/query.h>
#include <osquery/utils/json/json.h>
if (!isQueryNameInDatabase()) {
// This is the first encounter of the scheduled query.
fresh_results = true;
- LOG(INFO) << "Storing initial results for new scheduled query: " << name_;
+ INFO(OSQUERY) << "Storing initial results for new scheduled query: " << name_;
saveQuery(name_, query_);
} else if (getPreviousEpoch() != current_epoch) {
fresh_results = true;
- LOG(INFO) << "New Epoch " << current_epoch << " for scheduled query "
+ INFO(OSQUERY) << "New Epoch " << current_epoch << " for scheduled query "
<< name_;
} else if (isNewQuery()) {
// This query is 'new' in that the previous results may be invalid.
new_query = true;
- LOG(INFO) << "Scheduled query has been updated: " + name_;
+ INFO(OSQUERY) << "Scheduled query has been updated: " + name_;
saveQuery(name_, query_);
}
#include <osquery/utils/json/json.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry_factory.h>
#include <osquery/tables.h>
#include <osquery/utils/conversions/tryto.h>
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <string>
-#include <vector>
-
-#include <boost/noncopyable.hpp>
-
-#include <osquery/core.h>
-#include <osquery/logger.h>
-#include <osquery/plugins/plugin.h>
-#include <osquery/query.h>
-
-namespace osquery {
-
-/// Set the verbose mode, changes Glog's sinking logic and will affect plugins.
-void setVerboseLevel();
-
-/**
- * @brief Start status logging to a buffer until the logger plugin is online.
- *
- * This will also call google::InitGoogleLogging. Use the default init_glog
- * to control this in tests to protect against calling the API twice.
- */
-void initStatusLogger(const std::string& name, bool init_glog = true);
-
-/**
- * @brief Initialize the osquery Logger facility by dumping the buffered status
- * logs and configurating status log forwarding.
- *
- * initLogger will disable the `BufferedLogSink` facility, dump any status logs
- * emitted between process start and this init call, then configure the new
- * logger facility to receive status logs.
- *
- * The `forward_all` control is used when buffering logs in extensions.
- * It is fine if the logger facility in the core app does not want to receive
- * status logs, but this is NOT an option in extensions/modules. All status
- * logs must be forwarded to the core.
- *
- * @param name The process name.
- */
-void initLogger(const std::string& name);
-
-/**
- * @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 message the string to log
- * @param category a category/metadata key
- *
- * @return Status indicating the success or failure of the operation
- */
-Status logString(const std::string& message, const std::string& category);
-
-/**
- * @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 message the string to log
- * @param category a category/metadata key
- * @param receiver a string representing the log receiver to use
- *
- * @return Status indicating the success or failure of the operation
- */
-Status logString(const std::string& message,
- const std::string& category,
- const std::string& receiver);
-
-/**
- * @brief Log results of scheduled queries to the default receiver
- *
- * @param item a struct representing the results of a scheduled query
- *
- * @return Status indicating the success or failure of the operation
- */
-Status logQueryLogItem(const QueryLogItem& item);
-
-/**
- * @brief 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 Status indicating the success or failure of the operation
- */
-Status logQueryLogItem(const QueryLogItem& item, const std::string& receiver);
-
-/**
- * @brief Log raw results from a query (or a snapshot scheduled query).
- *
- * @param item the unmangled results from the query planner.
- *
- * @return Status indicating the success or failure of the operation
- */
-Status logSnapshotQuery(const QueryLogItem& item);
-
-/**
- * @brief Sink a set of buffered status logs.
- *
- * When the osquery daemon uses a watcher/worker set, the watcher's status logs
- * are accumulated in a buffered log sink. Well-performing workers should have
- * the set of watcher status logs relayed and sent to the configured logger
- * plugin.
- *
- * Status logs from extensions will be forwarded to the extension manager (core)
- * normally, but the watcher does not receive or send registry requests.
- * Extensions, the registry, configuration, and optional config/logger plugins
- * are all protected as a monitored worker.
- */
-void relayStatusLogs(bool async = false);
-
-/// Inspect the number of internal-buffered status log lines.
-size_t queuedStatuses();
-
-/// Inspect the number of active internal status log sender threads.
-size_t queuedSenders();
-
-/**
- * @brief Write a log line to the OS system log.
- *
- * There are occasional needs to log independently of the osquery logging
- * facilities. This allows a feature (not a table) to bypass all osquery
- * configuration and log to the OS system log.
- *
- * Linux/Darwin: this uses syslog's LOG_NOTICE.
- * Windows: This will end up inside the Facebook/osquery in the Windows
- * Event Log.
- */
-void systemLog(const std::string& line);
-} // namespace osquery
+++ /dev/null
-../../logger/logger.h
\ No newline at end of file
+++ /dev/null
-# Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License
-
-ADD_OSQUERY_LIBRARY(osquery_logger logger.cpp)
-
-FILE(GLOB OSQUERY_LOGGER_TESTS "tests/*.cpp")
-ADD_OSQUERY_TEST(${OSQUERY_LOGGER_TESTS})
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#ifndef WIN32
-#include <syslog.h>
-#endif
-
-#include <algorithm>
-#include <future>
-#include <queue>
-#include <thread>
-
-#include <boost/noncopyable.hpp>
-
-#include <osquery/data_logger.h>
-#include <osquery/plugins/logger.h>
-#include <osquery/registry_factory.h>
-
-#include <osquery/utils/conversions/split.h>
-#include <osquery/utils/json/json.h>
-#include <osquery/utils/system/time.h>
-
-namespace rj = rapidjson;
-
-namespace osquery {
-
-CREATE_REGISTRY(LoggerPlugin, "logger");
-
-/**
- * @brief A custom Glog log sink for forwarding or buffering status logs.
- *
- * This log sink has two modes, it can buffer Glog status logs until an osquery
- * logger is initialized or forward Glog status logs to an initialized and
- * appropriate logger. The appropriateness is determined by the logger when its
- * LoggerPlugin::init method is called. If the `init` method returns success
- * then a BufferedLogSink will start forwarding status logs to
- * LoggerPlugin::logStatus.
- *
- * This facility will start buffering when first used and stop buffering
- * (aka remove itself as a Glog sink) using the exposed APIs. It will live
- * throughout the life of the process for two reasons: (1) It makes sense when
- * the active logger plugin is handling Glog status logs and (2) it must remove
- * itself as a Glog target.
- */
-class BufferedLogSink : public google::LogSink, private boost::noncopyable {
- public:
- /// We create this as a Singleton for proper disable/shutdown.
- static BufferedLogSink& get();
-
- /// The Glog-API LogSink call-in method.
- void send(google::LogSeverity severity,
- const char* full_filename,
- const char* base_filename,
- int line,
- const struct ::tm* tm_time,
- const char* message,
- size_t message_len) override;
-
- /// Pop from the aync sender queue and wait for one send to complete.
- void WaitTillSent() override;
-
- public:
- /// Accessor/mutator to dump all of the buffered logs.
- std::vector<StatusLogLine>& dump();
-
- /// Add the buffered log sink to Glog.
- void enable();
-
- /// Start the Buffered Sink, without enabling forwarding to loggers.
- void setUp();
-
- /**
- * @brief Add a logger plugin that should receive status updates.
- *
- * Since the logger may support multiple active logger plugins the sink
- * will keep track of those plugins that returned success after ::init.
- * This list of plugins will received forwarded messages from the sink.
- *
- * This list is important because sending logs to plugins that also use
- * and active Glog Sink (supports multiple) will create a logging loop.
- */
- void addPlugin(const std::string& name);
-
- /// Clear the sinks list, clear the named plugins added by addPlugin.s
- void resetPlugins();
-
- /// Retrieve the list of enabled plugins that should have logs forwarded.
- const std::vector<std::string>& enabledPlugins() const;
-
- public:
- /// Queue of sender functions that relay status logs to all plugins.
- std::queue<std::future<void>> senders;
-
- public:
- BufferedLogSink(BufferedLogSink const&) = delete;
- void operator=(BufferedLogSink const&) = delete;
-
- private:
- /// Create the log sink as buffering or forwarding.
- BufferedLogSink() = default;
-
- /// Stop the log sink.
- ~BufferedLogSink();
-
- private:
- /// Intermediate log storage until an osquery logger is initialized.
- std::vector<StatusLogLine> logs_;
-
- /**
- * @Brief Is the logger temporarily disabled.
- *
- * The Google Log Sink will still be active, but the send method also checks
- * enabled and drops log lines to the flood if the forwarder is not enabled.
- */
- std::atomic<bool> enabled_{false};
-
- /// Track multiple loggers that should receive sinks from the send forwarder.
- std::vector<std::string> sinks_;
-};
-
-/// Mutex protecting accesses to buffered status logs.
-Mutex kBufferedLogSinkLogs;
-
-/// Mutex protecting queued status log futures.
-Mutex kBufferedLogSinkSenders;
-
-static void serializeIntermediateLog(const std::vector<StatusLogLine>& log,
- PluginRequest& request) {
- auto doc = JSON::newArray();
- for (const auto& i : log) {
- auto line = doc.getObject();
- doc.add("s", static_cast<int>(i.severity), line);
- doc.addRef("f", i.filename, line);
- doc.add("i", i.line, line);
- doc.addRef("m", i.message, line);
- doc.addRef("h", i.identifier, line);
- doc.addRef("c", i.calendar_time, line);
- doc.add("u", i.time, line);
- doc.push(line);
- }
-
- doc.toString(request["log"]);
-}
-
-void initStatusLogger(const std::string& name, bool init_glog) {
- // Start the logging, and announce the daemon is starting.
- if (init_glog) {
- google::InitGoogleLogging(name.c_str());
- }
-}
-
-void initLogger(const std::string& name) {
- BufferedLogSink::get().resetPlugins();
-
- bool forward = false;
- PluginRequest init_request = {{"init", name}};
- PluginRequest features_request = {{"action", "features"}};
- auto logger_plugin = RegistryFactory::get().getActive("logger");
- // Allow multiple loggers, make sure each is accessible.
- for (const auto& logger : osquery::split(logger_plugin, ",")) {
- if (!RegistryFactory::get().exists("logger", logger)) {
- continue;
- }
-
- Registry::call("logger", logger, init_request);
- auto status = Registry::call("logger", logger, features_request);
- if ((status.getCode() & LOGGER_FEATURE_LOGSTATUS) > 0) {
- // Glog status logs are forwarded to logStatus.
- forward = true;
- // To support multiple plugins we only add the names of plugins that
- // return a success status after initialization.
- BufferedLogSink::get().addPlugin(logger);
- }
- }
-
- if (forward) {
- // Begin forwarding after all plugins have been set up.
- BufferedLogSink::get().enable();
- relayStatusLogs(true);
- }
-}
-
-BufferedLogSink& BufferedLogSink::get() {
- static BufferedLogSink sink;
- return sink;
-}
-
-void BufferedLogSink::setUp() {
- google::AddLogSink(&get());
-}
-
-void BufferedLogSink::enable() {
- enabled_ = true;
-}
-
-void BufferedLogSink::send(google::LogSeverity severity,
- const char* full_filename,
- const char* base_filename,
- int line,
- const struct ::tm* tm_time,
- const char* message,
- size_t message_len) {
- // WARNING, be extremely careful when accessing data here.
- // This should not cause any persistent storage or logging actions.
- {
- WriteLock lock(kBufferedLogSinkLogs);
- logs_.push_back({(StatusLogSeverity)severity,
- std::string(base_filename),
- static_cast<size_t>(line),
- std::string(message, message_len),
- toAsciiTimeUTC(tm_time),
- toUnixTime(tm_time),
- std::string()});
- }
-}
-
-void BufferedLogSink::WaitTillSent() {
- std::future<void> first;
-
- {
- WriteLock lock(kBufferedLogSinkSenders);
- if (senders.empty()) {
- return;
- }
- first = std::move(senders.back());
- senders.pop();
- }
-
- first.wait();
-}
-
-std::vector<StatusLogLine>& BufferedLogSink::dump() {
- return logs_;
-}
-
-void BufferedLogSink::addPlugin(const std::string& name) {
- sinks_.push_back(name);
-}
-
-void BufferedLogSink::resetPlugins() {
- sinks_.clear();
-}
-
-const std::vector<std::string>& BufferedLogSink::enabledPlugins() const {
- return sinks_;
-}
-
-BufferedLogSink::~BufferedLogSink() {
- enabled_ = false;
-}
-
-Status logString(const std::string& message, const std::string& category) {
- return logString(
- message, category, RegistryFactory::get().getActive("logger"));
-}
-
-Status logString(const std::string& message,
- const std::string& category,
- const std::string& receiver) {
- Status status;
- for (const auto& logger : osquery::split(receiver, ",")) {
- if (Registry::get().exists("logger", logger, true)) {
- auto plugin = Registry::get().plugin("logger", logger);
- auto logger_plugin = std::dynamic_pointer_cast<LoggerPlugin>(plugin);
- status = logger_plugin->logString(message);
- } else {
- status = Registry::call(
- "logger", logger, {{"string", message}, {"category", category}});
- }
- }
- return status;
-}
-
-namespace {
-const std::string kTotalQueryCounterMonitorPath("query.total.count");
-}
-
-Status logQueryLogItem(const QueryLogItem& results) {
- return logQueryLogItem(results, RegistryFactory::get().getActive("logger"));
-}
-
-Status logQueryLogItem(const QueryLogItem& results,
- const std::string& receiver) {
- std::vector<std::string> json_items;
- Status status;
- std::string json;
- status = serializeQueryLogItemJSON(results, json);
- json_items.emplace_back(json);
-
- if (!status.ok()) {
- return status;
- }
-
- for (const auto& json : json_items) {
- status = logString(json, "event", receiver);
- }
- return status;
-}
-
-Status logSnapshotQuery(const QueryLogItem& item) {
- std::vector<std::string> json_items;
- Status status;
- std::string json;
- status = serializeQueryLogItemJSON(item, json);
- json_items.emplace_back(json);
-
- if (!status.ok()) {
- return status;
- }
-
- for (const auto& json : json_items) {
- auto receiver = RegistryFactory::get().getActive("logger");
- for (const auto& logger : osquery::split(receiver, ",")) {
- if (Registry::get().exists("logger", logger, true)) {
- auto plugin = Registry::get().plugin("logger", logger);
- auto logger_plugin = std::dynamic_pointer_cast<LoggerPlugin>(plugin);
- status = logger_plugin->logSnapshot(json);
- } else {
- status = Registry::call("logger", logger, {{"snapshot", json}});
- }
- }
- }
-
- return status;
-}
-
-size_t queuedStatuses() {
- ReadLock lock(kBufferedLogSinkLogs);
- return BufferedLogSink::get().dump().size();
-}
-
-size_t queuedSenders() {
- ReadLock lock(kBufferedLogSinkSenders);
- return BufferedLogSink::get().senders.size();
-}
-
-void relayStatusLogs(bool async) {
- {
- ReadLock lock(kBufferedLogSinkLogs);
- if (BufferedLogSink::get().dump().size() == 0) {
- return;
- }
- }
-
- auto sender = ([]() {
- auto identifier = getHostIdentifier();
-
- // Construct a status log plugin request.
- PluginRequest request = {{"status", "true"}};
- {
- WriteLock lock(kBufferedLogSinkLogs);
- auto& status_logs = BufferedLogSink::get().dump();
- for (auto& log : status_logs) {
- // Copy the host identifier into each status log.
- log.identifier = identifier;
- }
-
- serializeIntermediateLog(status_logs, request);
-
- // Flush the buffered status logs.
- status_logs.clear();
- }
-
- auto logger_plugin = RegistryFactory::get().getActive("logger");
- for (const auto& logger : osquery::split(logger_plugin, ",")) {
- auto& enabled = BufferedLogSink::get().enabledPlugins();
- if (std::find(enabled.begin(), enabled.end(), logger) != enabled.end()) {
- // Skip the registry's logic, and send directly to the core's logger.
- PluginResponse response;
- Registry::call("logger", logger, request, response);
- }
- }
- });
-
- if (async) {
- sender();
- } else {
- std::packaged_task<void()> task(std::move(sender));
- auto result = task.get_future();
- std::thread(std::move(task)).detach();
-
- // Lock accesses to the sender queue.
- WriteLock lock(kBufferedLogSinkSenders);
- BufferedLogSink::get().senders.push(std::move(result));
- }
-}
-
-void systemLog(const std::string& line) {
-#ifndef WIN32
- syslog(LOG_NOTICE, "%s", line.c_str());
-#endif
-}
-}
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#ifdef WIN32
-#define GLOG_NO_ABBREVIATED_SEVERITIES
-#define GOOGLE_GLOG_DLL_DECL
-#endif
-
-#include <glog/logging.h>
-
-namespace osquery {
-
-/**
- * @brief Helper logging macro for table-generated verbose log lines.
- *
- * Since logging in tables does not always mean a critical warning or error
- * but more likely a parsing or expected edge-case, we provide a TLOG.
- *
- * The tool user can set within config or via the CLI what level of logging
- * to tolerate. It's the table developer's job to assume consistency in logging.
- */
-#define TLOG VLOG(1)
-
-/**
- * @brief Prepend a reference number to the log line.
- *
- * A reference number is an external-search helper for somewhat confusing or
- * seeminly-critical log lines.
- */
-#define RLOG(n) "[Ref #" #n "] "
-
-} // namespace osquery
#include <cstdlib>
#include <sstream>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry.h>
#include <osquery/utils/conversions/split.h>
#include <osquery/utils/json/json.h>
}
return get().registry(registry_name)->call(item_name, request, response);
} catch (const std::exception& e) {
- LOG(ERROR) << registry_name << " registry " << item_name
+ ERROR(OSQUERY) << registry_name << " registry " << item_name
<< " plugin caused exception: " << e.what();
return Status(1, e.what());
} catch (...) {
- LOG(ERROR) << registry_name << " registry " << item_name
+ ERROR(OSQUERY) << registry_name << " registry " << item_name
<< " plugin caused unknown exception";
return Status(2, "Unknown exception");
}
#include <gtest/gtest.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry.h>
namespace osquery {
#include "dynamic_table_row.h"
#include "virtual_table.h"
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/utils/conversions/tryto.h>
namespace rj = rapidjson;
auto exp = tryTo<long long>(rowid_text_field, 10);
if (exp.isError()) {
- VLOG(1) << "Invalid rowid value returned " << exp.getError();
+ DEBUG(OSQUERY) << "Invalid rowid value returned " << exp.getError();
return SQLITE_ERROR;
}
*pRowid = exp.take();
const auto& value = row[column_name];
if (this->row.count(column_name) == 0) {
// Missing content.
- VLOG(1) << "Error " << column_name << " is empty";
+ DEBUG(OSQUERY) << "Error " << column_name << " is empty";
sqlite3_result_null(ctx);
} else if (type == TEXT_TYPE || type == BLOB_TYPE) {
sqlite3_result_text(
} else if (type == INTEGER_TYPE) {
auto afinite = tryTo<long>(value, 0);
if (afinite.isError()) {
- VLOG(1) << "Error casting " << column_name << " (" << value
+ DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
<< ") to INTEGER";
sqlite3_result_null(ctx);
} else {
} else if (type == BIGINT_TYPE || type == UNSIGNED_BIGINT_TYPE) {
auto afinite = tryTo<long long>(value, 0);
if (afinite.isError()) {
- VLOG(1) << "Error casting " << column_name << " (" << value
+ DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
<< ") to BIGINT";
sqlite3_result_null(ctx);
} else {
char* end = nullptr;
double afinite = strtod(value.c_str(), &end);
if (end == nullptr || end == value.c_str() || *end != '\0') {
- VLOG(1) << "Error casting " << column_name << " (" << value
+ DEBUG(OSQUERY) << "Error casting " << column_name << " (" << value
<< ") to DOUBLE";
sqlite3_result_null(ctx);
} else {
sqlite3_result_double(ctx, afinite);
}
} else {
- LOG(ERROR) << "Error unknown column type " << column_name;
+ ERROR(OSQUERY) << "Error unknown column type " << column_name;
}
return SQLITE_OK;
#include <sstream>
#include <osquery/core.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry.h>
#include <osquery/sql.h>
#include <osquery/tables.h>
#include <osquery/utils/conversions/castvariant.h>
#include <osquery/core.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry_factory.h>
#include <osquery/sql.h>
primary_ = true;
} else {
db_ = nullptr;
- VLOG(1) << "DBManager contention: opening transient SQLite database";
+ DEBUG(OSQUERY) << "DBManager contention: opening transient SQLite database";
init();
}
}
#include <gtest/gtest.h>
#include <osquery/core.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry.h>
#include <osquery/sql.h>
#include <osquery/sql/dynamic_table_row.h>
*/
#include <osquery/core.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/sql.h>
#include "osquery/sql/dynamic_table_row.h"
}
}
if (r.count("path") > 0) {
- LOG(WARNING) << "Row contains a path key, refusing to overwrite";
+ WARN(OSQUERY) << "Row contains a path key, refusing to overwrite";
} else {
r["path"] = sqlite_db.string();
}
(SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE | SQLITE_OPEN_NOMUTEX),
getSystemVFS(respect_locking));
if (rc != SQLITE_OK || db == nullptr) {
- VLOG(1) << "Cannot open specified database: "
+ DEBUG(OSQUERY) << "Cannot open specified database: "
<< getStringForSQLiteReturnCode(rc);
if (db != nullptr) {
sqlite3_close(db);
rc = sqlite3_prepare_v2(db, sqlite_query.c_str(), -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
sqlite3_close(db);
- VLOG(1) << "Could not prepare database at path: " << sqlite_db;
+ DEBUG(OSQUERY) << "Could not prepare database at path: " << sqlite_db;
return Status(rc, "Could not prepare database");
}
#include <unordered_set>
#include <osquery/core.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry_factory.h>
#include <osquery/sql/dynamic_table_row.h>
#include <osquery/sql/virtual_table.h>
#include <osquery/utils/conversions/tryto.h>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
namespace osquery {
}
default: {
- LOG(ERROR) << "Invalid column type returned by sqlite";
+ ERROR(OSQUERY) << "Invalid column type returned by sqlite";
return false;
}
}
VirtualTable* pVtab) {
auto content = pVtab->content;
if (content->constraints.size() <= 0) {
- LOG(ERROR) << "Invalid constraints arguments";
+ ERROR(OSQUERY) << "Invalid constraints arguments";
return SQLITE_ERROR;
}
sqlite3_value** argv,
const TableColumns& columnDescriptors) {
if (columnDescriptors.size() != argc - 2U) {
- VLOG(1) << "Wrong column count: " << argc - 2U
+ DEBUG(OSQUERY) << "Wrong column count: " << argc - 2U
<< ". Expected: " << columnDescriptors.size();
return SQLITE_RANGE;
}
}
default: {
- LOG(ERROR) << "Invalid column type returned by sqlite";
+ ERROR(OSQUERY) << "Invalid column type returned by sqlite";
return SQLITE_MISMATCH;
}
}
auto serializerError = serializeUpdateParameters(
json_value_array, argument_count, argv, columnDescriptors);
if (serializerError != SQLITE_OK) {
- VLOG(1) << "Failed to serialize the INSERT request";
+ DEBUG(OSQUERY) << "Failed to serialize the INSERT request";
return serializerError;
}
std::string auto_generated_rowid;
if (!getColumnValue(auto_generated_rowid, 1U, argument_count, argv)) {
- VLOG(1) << "Failed to retrieve the column value";
+ DEBUG(OSQUERY) << "Failed to retrieve the column value";
return SQLITE_ERROR;
}
std::string current_rowid;
if (!getColumnValue(current_rowid, 0U, argument_count, argv)) {
- VLOG(1) << "Failed to retrieve the column value";
+ DEBUG(OSQUERY) << "Failed to retrieve the column value";
return SQLITE_ERROR;
}
if (sqlite3_value_type(argv[1]) == SQLITE_INTEGER) {
std::string new_rowid;
if (!getColumnValue(new_rowid, 1U, argument_count, argv)) {
- VLOG(1) << "Failed to retrieve the column value";
+ DEBUG(OSQUERY) << "Failed to retrieve the column value";
return SQLITE_ERROR;
}
auto serializerError = serializeUpdateParameters(
json_value_array, argument_count, argv, columnDescriptors);
if (serializerError != SQLITE_OK) {
- VLOG(1) << "Failed to serialize the UPDATE request";
+ DEBUG(OSQUERY) << "Failed to serialize the UPDATE request";
return serializerError;
}
plugin_request.insert({"json_value_array", json_value_array});
} else {
- VLOG(1) << "Invalid xUpdate call";
+ DEBUG(OSQUERY) << "Invalid xUpdate call";
return SQLITE_ERROR;
}
// Validate the response
if (response_list.size() != 1) {
- VLOG(1) << "Invalid response from the extension table";
+ DEBUG(OSQUERY) << "Invalid response from the extension table";
return SQLITE_ERROR;
}
const auto& response = response_list.at(0);
if (response.count("status") == 0) {
- VLOG(1) << "Invalid response from the extension table; the status field is "
+ DEBUG(OSQUERY) << "Invalid response from the extension table; the status field is "
"missing";
return SQLITE_ERROR;
return SQLITE_CONSTRAINT;
} else if (status_value != "success") {
- VLOG(1) << "Invalid response from the extension table; the status field "
+ DEBUG(OSQUERY) << "Invalid response from the extension table; the status field "
"could not be recognized";
return SQLITE_ERROR;
if (plugin_request.at("auto_rowid") == "true") {
if (!getColumnValue(rowid, 1U, argument_count, argv)) {
- VLOG(1) << "Failed to retrieve the rowid value";
+ DEBUG(OSQUERY) << "Failed to retrieve the rowid value";
return SQLITE_ERROR;
}
} else {
auto id_it = response.find("id");
if (id_it == response.end()) {
- VLOG(1) << "The plugin did not return a row id";
+ DEBUG(OSQUERY) << "The plugin did not return a row id";
return SQLITE_ERROR;
}
auto exp = tryTo<long long>(rowid);
if (exp.isError()) {
- VLOG(1) << "The plugin did not return a valid row id";
+ DEBUG(OSQUERY) << "The plugin did not return a valid row id";
return SQLITE_ERROR;
}
*pRowid = exp.take();
int rc = sqlite3_declare_vtab(db, statement.c_str());
if (rc != SQLITE_OK || !status.ok() || response.size() == 0) {
- LOG(ERROR) << "Error creating virtual table: " << name << " (" << rc
+ ERROR(OSQUERY) << "Error creating virtual table: " << name << " (" << rc
<< "): " << getStringForSQLiteReturnCode(rc);
- VLOG(1) << "Cannot create virtual table using: " << statement;
+ DEBUG(OSQUERY) << "Cannot create virtual table using: " << statement;
delete pVtab;
return (rc != SQLITE_OK) ? rc : SQLITE_ERROR;
}
}
if (!user_based_satisfied) {
- LOG(WARNING) << "The " << pVtab->content->name
+ WARN(OSQUERY) << "The " << pVtab->content->name
<< " table returns data based on the current user by default, "
"consider JOINing against the users table";
} else if (!required_satisfied) {
- LOG(WARNING)
+ WARN(OSQUERY)
<< "Table " << pVtab->content->name
<< " was queried without a required column in the WHERE clause";
} else if (!events_satisfied) {
- LOG(WARNING) << "Table " << pVtab->content->name
+ WARN(OSQUERY) << "Table " << pVtab->content->name
<< " is event-based but events are disabled";
}
const SQLiteDBInstanceRef& instance,
bool is_extension) {
if (SQLiteDBManager::isDisabled(name)) {
- VLOG(1) << "Table " << name << " is disabled, not attaching";
+ DEBUG(OSQUERY) << "Table " << name << " is disabled, not attaching";
return Status(0, getStringForSQLiteReturnCode(0));
}
struct sqlite3_module* module =
tables::sqlite::getVirtualTableModule(name, is_extension);
if (module == nullptr) {
- VLOG(1) << "Failed to retrieve the virtual table module for \"" << name
+ DEBUG(OSQUERY) << "Failed to retrieve the virtual table module for \"" << name
<< "\"";
return Status(1);
}
sqlite3_exec(instance->db(), format.c_str(), nullptr, nullptr, nullptr);
} else {
- LOG(ERROR) << "Error attaching table: " << name << " (" << rc << ")";
+ ERROR(OSQUERY) << "Error attaching table: " << name << " (" << rc << ")";
}
return Status(rc, getStringForSQLiteReturnCode(rc));
auto format = "DROP TABLE IF EXISTS temp." + name;
int rc = sqlite3_exec(instance->db(), format.c_str(), nullptr, nullptr, 0);
if (rc != SQLITE_OK) {
- LOG(ERROR) << "Error detaching table: " << name << " (" << rc << ")";
+ ERROR(OSQUERY) << "Error detaching table: " << name << " (" << rc << ")";
}
return Status(rc, getStringForSQLiteReturnCode(rc));
#include <boost/filesystem/operations.hpp>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/registry_factory.h>
#include <osquery/sql.h>
#include <osquery/utils/system/time.h>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
namespace bai = boost::archive::iterators;
return std::string(base64_dec(encoded.data()),
base64_dec(encoded.data() + encoded.size()));
} catch (const boost::archive::iterators::dataflow_exception& e) {
- LOG(INFO) << "Could not base64 decode string: " << e.what();
+ INFO(OSQUERY) << "Could not base64 decode string: " << e.what();
return "";
}
}
encoded.append(std::string(writePaddChars, '='));
return encoded;
} catch (const boost::archive::iterators::dataflow_exception& e) {
- LOG(INFO) << "Could not base64 decode string: " << e.what();
+ INFO(OSQUERY) << "Could not base64 decode string: " << e.what();
return "";
}
}
#include <string>
#include <cstddef>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
#include <osquery/utils/chars.h>
#include <osquery/utils/conversions/tryto.h>
// Assume 2-byte wide unicode.
auto const exp = tryTo<long>(escaped.substr(i + 2, 4), 16);
if (exp.isError()) {
- LOG(WARNING) << "Unescaping a string with length: " << escaped.size()
+ WARN(OSQUERY) << "Unescaping a string with length: " << escaped.size()
<< " failed at: " << i;
return "";
}
#include <mutex>
-#include <osquery/logger.h>
+#include <vist/logger.hpp>
namespace {
std::mutex mutex;
if (table.empty())
return Status(1, "Wrong table name");
- LOG(INFO) << "Add NotifyCallback to:" << table;
+ INFO(VIST) << "Add NotifyCallback to:" << table;
{
std::lock_guard<std::mutex> lock(mutex);
this->callbacks.insert(std::make_pair(table, callback));
if (iter == this->callbacks.end())
return Status(1, "Registered callback not found");
- LOG(INFO) << "Emit notification about:" << table;
+ INFO(VIST) << "Emit notification about:" << table;
{
std::lock_guard<std::mutex> lock(mutex);
while (iter != this->callbacks.end()) {
#include <gtest/gtest.h>
+#include <vist/logger.hpp>
#include <vist/notification/notification.hpp>
-#include <osquery/logger.h>
-
using namespace vist;
class NotificationTests : public testing::Test {};
auto& notifier = Notification::instance();
auto callback = [](const Row& row) {
- LOG(INFO) << "NotifyCallback called:";
+ INFO(VIST) << "NotifyCallback called:";
for (const auto& r : row)
- LOG(INFO) << "\t" << r.first << " : " << r.second;
+ INFO(VIST) << "\t" << r.first << " : " << r.second;
};
auto s = notifier.add("test", std::move(callback));
auto& notifier = Notification::instance();
auto callback = [](const Row& row) {
- LOG(INFO) << "NotifyCallback called:";
+ INFO(VIST) << "NotifyCallback called:";
for (const auto& r : row)
- LOG(INFO) << "\t" << r.first << " : " << r.second;
+ INFO(VIST) << "\t" << r.first << " : " << r.second;
};
auto s = notifier.add("", std::move(callback));
int called = 0;
auto callback = [&](const Row& row) {
- LOG(INFO) << "NotifyCallback called:";
+ INFO(VIST) << "NotifyCallback called:";
for (const auto& r : row)
- LOG(INFO) << "\t" << r.first << " : " << r.second;
+ INFO(VIST) << "\t" << r.first << " : " << r.second;
called++;
};
** This file is generated. Do not modify it manually!
*/
-#include <osquery/logger.h>
#include <osquery/sql/dynamic_table_row.h>
#include <osquery/tables.h>
#include <osquery/registry_factory.h>
** This file is generated. Do not modify it manually!
*/
-#include <osquery/logger.h>
#include <osquery/tables.h>
#include <osquery/registry_factory.h>
** This file is generated. Do not modify it manually!
*/
-#include <osquery/logger.h>
#include <osquery/tables.h>
#include <osquery/registry_factory.h>