TEST_F(LoggerTests, test_logger_scheduled_query) { RegistryFactory::get().setActive("logger", "test"); initLogger("scheduled_query"); QueryLogItem item; item.name = "test_query"; item.identifier = "unknown_test_host"; item.time = 0; item.calendar_time = "no_time"; item.epoch = 0L; item.results.added.push_back({{"test_column", "test_value"}}); logQueryLogItem(item); EXPECT_EQ(1U, LoggerTests::log_lines.size()); item.results.removed.push_back({{"test_column", "test_new_value\n"}}); logQueryLogItem(item); ASSERT_EQ(3U, LoggerTests::log_lines.size()); // Make sure the JSON output does not have a newline. std::string expected = "{\"name\":\"test_query\",\"hostIdentifier\":\"unknown_test_host\"," "\"calendarTime\":\"no_time\",\"unixTime\":\"0\",\"epoch\":\"0\"," "\"columns\":{\"test_column\":\"test_value\"},\"action\":\"added\"}"; EXPECT_EQ(LoggerTests::log_lines.back(), expected); }
TEST_F(LoggerTests, test_logger_scheduled_query) { RegistryFactory::get().setActive("logger", "test"); initLogger("scheduled_query"); QueryLogItem item; item.name = "test_query"; item.identifier = "unknown_test_host"; item.time = 0; item.calendar_time = "no_time"; item.epoch = 0L; item.counter = 0L; item.results.added.push_back({{"test_column", "test_value"}}); logQueryLogItem(item); EXPECT_EQ(1U, LoggerTests::log_lines.size()); // The entire removed/added is one event when result events is false. FLAGS_logger_event_type = false; item.results.removed.push_back({{"test_column", "test_new_value\n"}}); logQueryLogItem(item); EXPECT_EQ(2U, LoggerTests::log_lines.size()); FLAGS_logger_event_type = true; // Now the two removed will be individual events. logQueryLogItem(item); ASSERT_EQ(4U, LoggerTests::log_lines.size()); // Make sure the JSON output does not have a newline. std::string expected = "{\"name\":\"test_query\",\"hostIdentifier\":\"unknown_test_host\"," "\"calendarTime\":\"no_time\",\"unixTime\":0,\"epoch\":0," "\"counter\":0,\"columns\":{\"test_column\":\"test_value\"}," "\"action\":\"added\"}"; EXPECT_EQ(LoggerTests::log_lines.back(), expected); }
TEST_F(LoggerTests, test_logger_scheduled_query) { QueryLogItem item; item.name = "test_query"; item.identifier = "unknown_test_host"; item.time = 0; item.calendar_time = "no_time"; item.results.added.push_back({{"test_column", "test_value"}}); logQueryLogItem(item); EXPECT_EQ(LoggerTests::log_lines.size(), 1U); item.results.removed.push_back({{"test_column", "test_new_value\n"}}); logQueryLogItem(item); EXPECT_EQ(LoggerTests::log_lines.size(), 3U); }
void launchQuery(const std::string& name, const ScheduledQuery& query) { // Execute the scheduled query and create a named query object. VLOG(1) << "Executing query: " << query.query; auto sql = (FLAGS_enable_monitor) ? monitor(name, query) : SQL(query.query); if (!sql.ok()) { LOG(ERROR) << "Error executing query (" << query.query << "): " << sql.getMessageString(); return; } // Fill in a host identifier fields based on configuration or availability. std::string ident; auto status = getHostIdentifier(ident); if (!status.ok() || ident.empty()) { ident = "<unknown>"; } // A query log item contains an optional set of differential results or // a copy of the most-recent execution alongside some query metadata. QueryLogItem item; item.name = name; item.identifier = ident; item.time = osquery::getUnixTime(); item.calendar_time = osquery::getAsciiTime(); if (query.options.count("snapshot") && query.options.at("snapshot")) { // This is a snapshot query, emit results with a differential or state. item.snapshot_results = std::move(sql.rows()); logSnapshotQuery(item); return; } // Create a database-backed set of query results. auto dbQuery = Query(name, query); DiffResults diff_results; // Add this execution's set of results to the database-tracked named query. // We can then ask for a differential from the last time this named query // was executed by exact matching each row. status = dbQuery.addNewResults(sql.rows(), diff_results); if (!status.ok()) { LOG(ERROR) << "Error adding new results to database: " << status.what(); return; } if (diff_results.added.size() == 0 && diff_results.removed.size() == 0) { // No diff results or events to emit. return; } VLOG(1) << "Found results for query (" << name << ") for host: " << ident; item.results = diff_results; status = logQueryLogItem(item); if (!status.ok()) { LOG(ERROR) << "Error logging the results of query (" << query.query << "): " << status.toString(); } }
TEST_F(LoggerTests, test_logger_scheduled_query) { QueryLogItem item; item.name = "test_query"; item.identifier = "unknown_test_host"; item.time = 0; item.calendar_time = "no_time"; item.results.added.push_back({{"test_column", "test_value"}}); logQueryLogItem(item); EXPECT_EQ(LoggerTests::log_lines.size(), 1U); item.results.removed.push_back({{"test_column", "test_new_value\n"}}); logQueryLogItem(item); ASSERT_EQ(LoggerTests::log_lines.size(), 3U); // Make sure the JSON output does not have a newline. std::string expected = "{\"name\":\"test_query\",\"hostIdentifier\":\"unknown_test_host\"," "\"calendarTime\":\"no_time\",\"unixTime\":\"0\",\"columns\":{\"test_" "column\":\"test_new_value\\n\"},\"action\":\"removed\"}"; EXPECT_EQ(LoggerTests::log_lines.back(), expected); }
Status logQueryLogItem(const QueryLogItem& results) { return logQueryLogItem(results, Registry::getActive("logger")); }
inline void launchQuery(const std::string& name, const ScheduledQuery& query) { // Execute the scheduled query and create a named query object. LOG(INFO) << "Executing scheduled query " << name << ": " << query.query; runDecorators(DECORATE_ALWAYS); auto sql = monitor(name, query); if (!sql.ok()) { LOG(ERROR) << "Error executing scheduled query " << name << ": " << sql.getMessageString(); return; } // Fill in a host identifier fields based on configuration or availability. std::string ident = getHostIdentifier(); // A query log item contains an optional set of differential results or // a copy of the most-recent execution alongside some query metadata. QueryLogItem item; item.name = name; item.identifier = ident; item.time = osquery::getUnixTime(); item.epoch = FLAGS_schedule_epoch; item.calendar_time = osquery::getAsciiTime(); getDecorations(item.decorations); if (query.options.count("snapshot") && query.options.at("snapshot")) { // This is a snapshot query, emit results with a differential or state. item.snapshot_results = std::move(sql.rows()); logSnapshotQuery(item); return; } // Create a database-backed set of query results. auto dbQuery = Query(name, query); // Comparisons and stores must include escaped data. sql.escapeResults(); Status status; DiffResults diff_results; // Add this execution's set of results to the database-tracked named query. // We can then ask for a differential from the last time this named query // was executed by exact matching each row. if (!FLAGS_events_optimize || !sql.eventBased()) { status = dbQuery.addNewResults( sql.rows(), item.epoch, item.counter, diff_results); if (!status.ok()) { std::string line = "Error adding new results to database: " + status.what(); LOG(ERROR) << line; // If the database is not available then the daemon cannot continue. Initializer::requestShutdown(EXIT_CATASTROPHIC, line); } } else { diff_results.added = std::move(sql.rows()); } if (diff_results.added.empty() && diff_results.removed.empty()) { // No diff results or events to emit. return; } VLOG(1) << "Found results for query: " << name; item.results = diff_results; if (query.options.count("removed") && !query.options.at("removed")) { item.results.removed.clear(); } status = logQueryLogItem(item); if (!status.ok()) { // If log directory is not available, then the daemon shouldn't continue. std::string error = "Error logging the results of query: " + name + ": " + status.toString(); LOG(ERROR) << error; Initializer::requestShutdown(EXIT_CATASTROPHIC, error); } }