Example #1
0
TEST_F(LoggerTests, test_recursion) {
  // Stop the internal Glog facilities.
  google::ShutdownGoogleLogging();

  auto& rf = RegistryFactory::get();
  auto plugin = std::make_shared<RecursiveLoggerPlugin>();
  rf.registry("logger")->add("recurse", plugin);
  EXPECT_TRUE(rf.exists("logger", "recurse"));
  EXPECT_TRUE(rf.setActive("logger", "recurse").ok());

  FLAGS_logtostderr = true;
  initStatusLogger("logger_test");
  initLogger("logger_test");
  LOG(WARNING) << "Log to the recursive logger";
  EXPECT_EQ(1U, plugin->statuses);

  FLAGS_logger_status_sync = false;
  LOG(WARNING) << "recurse";
  if (isPlatform(PlatformType::TYPE_WINDOWS)) {
    for (size_t i = 0; i < 100; i++) {
      std::this_thread::sleep_for(std::chrono::microseconds(10));
      if (plugin->statuses == 3U) {
        break;
      }
    }
  }
  EXPECT_EQ(3U, plugin->statuses);

  // Try again with the tool type as a daemon.
  auto tool_type = kToolType;
  kToolType = ToolType::DAEMON;
  LOG(WARNING) << "recurse";

  // The daemon calls the status relay within the scheduler.
  EXPECT_EQ(3U, plugin->statuses);

  // All of recursive log lines will sink during the next call.
  relayStatusLogs(true);
  EXPECT_EQ(4U, plugin->statuses);
  relayStatusLogs(true);
  EXPECT_EQ(5U, plugin->statuses);
  kToolType = tool_type;

  EXPECT_EQ(0U, queuedStatuses());
  EXPECT_EQ(0U, queuedSenders());

  // Make sure the test file does not create a filesystem log.
  // This will happen if the logtostderr is not set.
  EXPECT_FALSE(pathExists("logger_test.INFO"));

  FLAGS_logtostderr = false;
}
Example #2
0
TEST_F(LoggerTests, test_logger_init) {
  auto& rf = RegistryFactory::get();
  // Expect the logger to have been registered from the first test.
  EXPECT_TRUE(rf.exists("logger", "test"));
  EXPECT_TRUE(rf.setActive("logger", "test").ok());

  initStatusLogger("logger_test");
  // This will be printed to stdout.
  LOG(WARNING) << "Logger test is generating a warning status (1)";
  initLogger("logger_test");

  // The warning message will have been buffered and sent to the active logger
  // which is test.
  EXPECT_EQ(1U, LoggerTests::status_messages.size());
  EXPECT_EQ(1U, LoggerTests::statuses_logged);
}
Example #3
0
TEST_F(LoggerTests, test_logger_init) {
  // Expect the logger to have been registered from the first test.
  EXPECT_TRUE(Registry::exists("logger", "test"));
  EXPECT_TRUE(Registry::setActive("logger", "test").ok());

  initStatusLogger("logger_test");
  // This will be printed to stdout.
  LOG(WARNING) << "Logger test is generating a warning status (1)";
  initLogger("logger_test");

  // The warning message will have been buffered and sent to the active logger
  // which is test.
  EXPECT_EQ(LoggerTests::status_messages.size(), 1U);

  // The logStatus API should NOT have been called. It will only be used if
  // (1) The active logger's init returns success within initLogger and
  // (2) for status logs generated after initLogger is called.
  EXPECT_EQ(LoggerTests::statuses_logged, 0);
}
TEST_F(FilesystemLoggerTests, test_log_status) {
  if (isPlatform(PlatformType::TYPE_WINDOWS)) {
    // Cannot test status deterministically on windows.
    return;
  }

  initStatusLogger("osqueryd");
  initLogger("osqueryd");

  LOG(WARNING) << "Filesystem logger test is generating a warning status (1/3)";

  auto status_path = fs::path(FLAGS_logger_path) / "osqueryd.INFO";
  EXPECT_TRUE(osquery::pathExists(status_path));

  std::string content;
  EXPECT_TRUE(readFile(status_path, content));
  auto lines = osquery::split(content, "\n").size();
  EXPECT_EQ(4U, lines);

  LOG(WARNING) << "Filesystem logger test is generating a warning status (2/3)";
  content.clear();
  readFile(status_path, content);
  lines = osquery::split(content, "\n").size();
  EXPECT_EQ(5U, lines);

  auto& rf = RegistryFactory::get();
  auto filesystem_test = std::make_shared<FilesystemTestLoggerPlugin>();
  rf.registry("logger")->add("filesystem_test", filesystem_test);
  EXPECT_TRUE(rf.setActive("logger", "filesystem,filesystem_test").ok());

  LOG(WARNING) << "Filesystem logger test is generating a warning status (3/3)";
  content.clear();
  readFile(status_path, content);
  lines = osquery::split(content, "\n").size();
  EXPECT_EQ(6U, lines);

  relayStatusLogs(true);
  content.clear();
  readFile(status_path, content);
  lines = osquery::split(content, "\n").size();
  EXPECT_EQ(6U, lines);
}
Example #5
0
Initializer::Initializer(int& argc, char**& argv, ToolType tool)
    : argc_(&argc),
      argv_(&argv),
      tool_(tool),
      binary_((tool == OSQUERY_TOOL_DAEMON) ? "osqueryd" : "osqueryi") {
  std::srand(chrono_clock::now().time_since_epoch().count());
  // The 'main' thread is that which executes the initializer.
  kMainThreadId = std::this_thread::get_id();

  // Handled boost filesystem locale problems fixes in 1.56.
  // See issue #1559 for the discussion and upstream boost patch.
  try {
    boost::filesystem::path::codecvt();
  } catch (const std::runtime_error& e) {
    setenv("LC_ALL", "C", 1);
  }

  // osquery implements a custom help/usage output.
  for (int i = 1; i < *argc_; i++) {
    auto help = std::string((*argv_)[i]);
    if ((help == "--help" || help == "-help" || help == "--h" ||
         help == "-h") &&
        tool != OSQUERY_TOOL_TEST) {
      printUsage(binary_, tool_);
      shutdown();
    }
  }

// To change the default config plugin, compile osquery with
// -DOSQUERY_DEFAULT_CONFIG_PLUGIN=<new_default_plugin>
#ifdef OSQUERY_DEFAULT_CONFIG_PLUGIN
  FLAGS_config_plugin = STR(OSQUERY_DEFAULT_CONFIG_PLUGIN);
#endif

// To change the default logger plugin, compile osquery with
// -DOSQUERY_DEFAULT_LOGGER_PLUGIN=<new_default_plugin>
#ifdef OSQUERY_DEFAULT_LOGGER_PLUGIN
  FLAGS_logger_plugin = STR(OSQUERY_DEFAULT_LOGGER_PLUGIN);
#endif

  // Set version string from CMake build
  GFLAGS_NAMESPACE::SetVersionString(kVersion.c_str());

  // Let gflags parse the non-help options/flags.
  GFLAGS_NAMESPACE::ParseCommandLineFlags(
      argc_, argv_, (tool == OSQUERY_TOOL_SHELL));

  // Set the tool type to allow runtime decisions based on daemon, shell, etc.
  kToolType = tool;
  if (tool == OSQUERY_TOOL_SHELL) {
    // The shell is transient, rewrite config-loaded paths.
    FLAGS_disable_logging = true;
    // The shell never will not fork a worker.
    FLAGS_disable_watchdog = true;
    // Get the caller's home dir for temporary storage/state management.
    auto homedir = osqueryHomeDirectory();
    boost::system::error_code ec;
    if (osquery::pathExists(homedir).ok() ||
        boost::filesystem::create_directory(homedir, ec)) {
      // Only apply user/shell-specific paths if not overridden by CLI flag.
      if (Flag::isDefault("database_path")) {
        osquery::FLAGS_database_path = homedir + "/shell.db";
      }
      if (Flag::isDefault("extensions_socket")) {
        osquery::FLAGS_extensions_socket = homedir + "/shell.em";
      }
    } else {
      LOG(INFO) << "Cannot access or create osquery home directory";
      FLAGS_disable_extensions = true;
      FLAGS_database_path = "/dev/null";
    }
  }

  // All tools handle the same set of signals.
  // If a daemon process is a watchdog the signal is passed to the worker,
  // unless the worker has not yet started.
  std::signal(SIGTERM, signalHandler);
  std::signal(SIGABRT, signalHandler);
  std::signal(SIGINT, signalHandler);
  std::signal(SIGHUP, signalHandler);
  std::signal(SIGALRM, signalHandler);
  std::signal(SIGUSR1, signalHandler);

  // If the caller is checking configuration, disable the watchdog/worker.
  if (FLAGS_config_check) {
    FLAGS_disable_watchdog = true;
  }

  // Initialize the status and results logger.
  initStatusLogger(binary_);
  if (tool != OSQUERY_EXTENSION) {
    if (isWorker()) {
      VLOG(1) << "osquery worker initialized [watcher=" << getppid() << "]";
    } else {
      VLOG(1) << "osquery initialized [version=" << kVersion << "]";
    }
  } else {
    VLOG(1) << "osquery extension initialized [sdk=" << kSDKVersion << "]";
  }
}
Example #6
0
Initializer::Initializer(int& argc, char**& argv, ToolType tool)
    : argc_(&argc),
      argv_(&argv),
      tool_(tool),
      binary_((tool == ToolType::DAEMON) ? "osqueryd" : "osqueryi") {
  std::srand(static_cast<unsigned int>(
      chrono_clock::now().time_since_epoch().count()));

  // Initialize registries and plugins
  registryAndPluginInit();

  // The 'main' thread is that which executes the initializer.
  kMainThreadId = std::this_thread::get_id();
  // Set the tool type to allow runtime decisions based on daemon, shell, etc.
  kToolType = tool;

  // Handled boost filesystem locale problems fixes in 1.56.
  // See issue #1559 for the discussion and upstream boost patch.
  try {
    boost::filesystem::path::codecvt();
  } catch (const std::runtime_error& /* e */) {
#ifdef WIN32
    setlocale(LC_ALL, "C");
#else
    setenv("LC_ALL", "C", 1);
#endif
  }

  Flag::create("logtostderr",
               {"Log messages to stderr in addition to the logger plugin(s)",
                false,
                false,
                true,
                false});
  Flag::create("stderrthreshold",
               {"Stderr log level threshold", false, false, true, false});

  // osquery implements a custom help/usage output.
  for (int i = 1; i < *argc_; i++) {
    auto help = std::string((*argv_)[i]);
    if ((help == "--help" || help == "-help" || help == "--h" ||
         help == "-h") &&
        tool != ToolType::TEST) {
      printUsage(binary_, tool_);
      shutdown();
    }
  }

  if (tool == ToolType::SHELL) {
    // The shell is transient, rewrite config-loaded paths.
    FLAGS_disable_logging = true;
    // The shell never will not fork a worker.
    FLAGS_disable_watchdog = true;
    FLAGS_disable_events = true;
  }

  bool default_flags = false;
  if (FLAGS_flagfile.empty() && isReadable(kDefaultFlagfile)) {
    // No flagfile was set (daemons and services always set a flagfile).
    default_flags = true;
    FLAGS_flagfile = kDefaultFlagfile;
  }

  // Set version string from CMake build
  GFLAGS_NAMESPACE::SetVersionString(kVersion.c_str());

  // Let gflags parse the non-help options/flags.
  GFLAGS_NAMESPACE::ParseCommandLineFlags(
      argc_, argv_, (tool == ToolType::SHELL));

  if (tool == ToolType::SHELL) {
    if (Flag::isDefault("database_path") &&
        Flag::isDefault("disable_database")) {
      // The shell should not use a database by default, but should use the DB
      // specified by database_path if it is set
      FLAGS_disable_database = true;
    }
    // Initialize the shell after setting modified defaults and parsing flags.
    initShell();
  } else {
    // The daemon will only output ERROR logs to stderr.
    if (Flag::isDefault("stderrthreshold")) {
      Flag::updateValue("stderrthreshold", "2");
    }
  }

#ifndef WIN32
  // All tools handle the same set of signals.
  // If a daemon process is a watchdog the signal is passed to the worker,
  // unless the worker has not yet started.
  std::signal(SIGTERM, signalHandler);
  std::signal(SIGINT, signalHandler);
  std::signal(SIGHUP, signalHandler);
  std::signal(SIGALRM, signalHandler);
  std::signal(SIGCHLD, SIG_IGN);
#endif

  std::signal(SIGABRT, signalHandler);
  std::signal(SIGUSR1, signalHandler);

  // If the caller is checking configuration, disable the watchdog/worker.
  if (FLAGS_config_check) {
    FLAGS_disable_watchdog = true;
  }

  // Initialize the status and results logger.
  initStatusLogger(binary_);
  if (tool != ToolType::EXTENSION) {
    if (isWorker()) {
      VLOG(1) << "osquery worker initialized [watcher="
              << PlatformProcess::getLauncherProcess()->pid() << "]";
    } else {
      VLOG(1) << "osquery initialized [version=" << kVersion << "]";
    }
  } else {
    VLOG(1) << "osquery extension initialized [sdk=" << kSDKVersion << "]";
  }

  if (default_flags) {
    VLOG(1) << "Using default flagfile: " << kDefaultFlagfile;
  }

  // Initialize the COM libs
  platformSetup();
}
Example #7
0
Initializer::Initializer(int& argc, char**& argv, ToolType tool)
    : argc_(&argc),
      argv_(&argv),
      tool_(tool),
      binary_(fs::path(std::string(argv[0])).filename().string()) {
  std::srand(time(nullptr));

  // osquery implements a custom help/usage output.
  std::string first_arg = (*argc_ > 1) ? std::string((*argv_)[1]) : "";
  if ((first_arg == "--help" || first_arg == "-help" || first_arg == "--h" ||
       first_arg == "-h") &&
      tool != OSQUERY_TOOL_TEST) {
    printUsage(binary_, tool_);
    ::exit(0);
  }

// To change the default config plugin, compile osquery with
// -DOSQUERY_DEFAULT_CONFIG_PLUGIN=<new_default_plugin>
#ifdef OSQUERY_DEFAULT_CONFIG_PLUGIN
  FLAGS_config_plugin = STR(OSQUERY_DEFAULT_CONFIG_PLUGIN);
#endif

// To change the default logger plugin, compile osquery with
// -DOSQUERY_DEFAULT_LOGGER_PLUGIN=<new_default_plugin>
#ifdef OSQUERY_DEFAULT_LOGGER_PLUGIN
  FLAGS_logger_plugin = STR(OSQUERY_DEFAULT_LOGGER_PLUGIN);
#endif

  // Set version string from CMake build
  GFLAGS_NAMESPACE::SetVersionString(OSQUERY_VERSION);

  // Let gflags parse the non-help options/flags.
  GFLAGS_NAMESPACE::ParseCommandLineFlags(
      argc_, argv_, (tool == OSQUERY_TOOL_SHELL));

  if (tool == OSQUERY_TOOL_SHELL) {
    // The shell is transient, rewrite config-loaded paths.
    FLAGS_disable_logging = true;
    // Get the caller's home dir for temporary storage/state management.
    auto homedir = osqueryHomeDirectory();
    if (osquery::pathExists(homedir).ok() ||
        boost::filesystem::create_directory(homedir)) {
      osquery::FLAGS_database_path = homedir + "/shell.db";
      osquery::FLAGS_extensions_socket = homedir + "/shell.em";
    }
  }

  // If the caller is checking configuration, disable the watchdog/worker.
  if (FLAGS_config_check) {
    FLAGS_disable_watchdog = true;
  }

  // Initialize the status and results logger.
  initStatusLogger(binary_);
  if (tool != OSQUERY_EXTENSION) {
    VLOG(1) << "osquery initialized [version=" << OSQUERY_VERSION << "]";
  } else {
    VLOG(1) << "osquery extension initialized [sdk=" << OSQUERY_SDK_VERSION
            << "]";
  }
}
Example #8
0
Initializer::Initializer(int& argc, char**& argv, ToolType tool)
    : argc_(&argc),
      argv_(&argv),
      tool_(tool),
      binary_(fs::path(std::string(argv[0])).filename().string()) {
  std::srand(chrono_clock::now().time_since_epoch().count());

  // osquery implements a custom help/usage output.
  for (int i = 1; i < *argc_; i++) {
    auto help = std::string((*argv_)[i]);
    if ((help == "--help" || help == "-help" || help == "--h" ||
         help == "-h") &&
        tool != OSQUERY_TOOL_TEST) {
      printUsage(binary_, tool_);
      ::exit(0);
    }
  }

// To change the default config plugin, compile osquery with
// -DOSQUERY_DEFAULT_CONFIG_PLUGIN=<new_default_plugin>
#ifdef OSQUERY_DEFAULT_CONFIG_PLUGIN
  FLAGS_config_plugin = STR(OSQUERY_DEFAULT_CONFIG_PLUGIN);
#endif

// To change the default logger plugin, compile osquery with
// -DOSQUERY_DEFAULT_LOGGER_PLUGIN=<new_default_plugin>
#ifdef OSQUERY_DEFAULT_LOGGER_PLUGIN
  FLAGS_logger_plugin = STR(OSQUERY_DEFAULT_LOGGER_PLUGIN);
#endif

  // Set version string from CMake build
  GFLAGS_NAMESPACE::SetVersionString(kVersion.c_str());

  // Let gflags parse the non-help options/flags.
  GFLAGS_NAMESPACE::ParseCommandLineFlags(
      argc_, argv_, (tool == OSQUERY_TOOL_SHELL));

  if (tool == OSQUERY_TOOL_SHELL) {
    // The shell is transient, rewrite config-loaded paths.
    FLAGS_disable_logging = true;
    // Get the caller's home dir for temporary storage/state management.
    auto homedir = osqueryHomeDirectory();
    if (osquery::pathExists(homedir).ok() ||
        boost::filesystem::create_directory(homedir)) {
      // Only apply user/shell-specific paths if not overridden by CLI flag.
      if (Flag::isDefault("database_path")) {
        osquery::FLAGS_database_path = homedir + "/shell.db";
      }
      if (Flag::isDefault("extensions_socket")) {
        osquery::FLAGS_extensions_socket = homedir + "/shell.em";
      }
    }
  }

  // If the caller is checking configuration, disable the watchdog/worker.
  if (FLAGS_config_check) {
    FLAGS_disable_watchdog = true;
  }

  // Initialize the status and results logger.
  initStatusLogger(binary_);
  if (tool != OSQUERY_EXTENSION) {
    if (isWorker()) {
      VLOG(1) << "osquery worker initialized [watcher="
              << getenv("OSQUERY_WORKER") << "]";
    } else {
      VLOG(1) << "osquery initialized [version=" << kVersion << "]";
    }
  } else {
    VLOG(1) << "osquery extension initialized [sdk=" << kSDKVersion << "]";
  }
}