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; }
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); }
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); }
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 << "]"; } }
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(); }
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 << "]"; } }
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 << "]"; } }