TEST_F(DecoratorsConfigParserPluginTests, test_decorators_run_interval) { // Prevent loads from executing. FLAGS_disable_decorators = true; Config::getInstance().update(config_data_); // Mimic the schedule's execution. FLAGS_disable_decorators = false; runDecorators(DECORATE_INTERVAL, 60); QueryLogItem item; getDecorations(item.decorations); ASSERT_EQ(item.decorations.size(), 2U); EXPECT_EQ(item.decorations.at("internal_60_test"), "test"); std::string log_line; serializeQueryLogItemJSON(item, log_line); std::string expected = "{\"snapshot\":\"\",\"action\":\"snapshot\",\"decorations\":{\"internal_" "60_test\":\"test\",\"one\":\"1\"},\"name\":\"\",\"hostIdentifier\":\"\"," "\"calendarTime\":\"\",\"unixTime\":\"0\"}\n"; EXPECT_EQ(log_line, expected); // Now clear and run again. clearDecorations("awesome"); runDecorators(DECORATE_INTERVAL, 60 * 60); QueryLogItem second_item; getDecorations(second_item.decorations); ASSERT_EQ(second_item.decorations.size(), 2U); }
void SchedulerRunner::start() { // Start the counter at the second. auto i = osquery::getUnixTime(); for (; (timeout_ == 0) || (i <= timeout_); ++i) { Config::get().scheduledQueries( ([&i](const std::string& name, const ScheduledQuery& query) { if (query.splayed_interval > 0 && i % query.splayed_interval == 0) { TablePlugin::kCacheInterval = query.splayed_interval; TablePlugin::kCacheStep = i; launchQuery(name, query); } })); // Configuration decorators run on 60 second intervals only. if ((i % 60) == 0) { runDecorators(DECORATE_INTERVAL, i); } if (FLAGS_schedule_reload > 0 && (i % FLAGS_schedule_reload) == 0) { if (FLAGS_schedule_reload_sql) { SQLiteDBManager::resetPrimary(); } resetDatabase(); } // GLog is not re-entrant, so logs must be flushed in a dedicated thread. if ((i % 3) == 0) { relayStatusLogs(true); } // Put the thread into an interruptible sleep without a config instance. pauseMilli(interval_ * 1000); if (interrupted()) { break; } } }
void runDecorators(DecorationPoint point, size_t time, const std::string& source) { if (FLAGS_disable_decorators) { return; } auto parser = Config::getParser(PARSER_NAME); if (parser == nullptr) { // The decorators parser does not exist. return; } // Abstract the use of the decorator parser API. auto dp = std::dynamic_pointer_cast<DecoratorsConfigParserPlugin>(parser); WriteLock lock(DecoratorsConfigParserPlugin::kDecorationsMutex); if (point == DECORATE_LOAD) { for (const auto& target_source : dp->load_) { if (source.empty() || target_source.first == source) { runDecorators(target_source.first, target_source.second); } } } else if (point == DECORATE_ALWAYS) { for (const auto& target_source : dp->always_) { if (source.empty() || target_source.first == source) { runDecorators(target_source.first, target_source.second); } } } else if (point == DECORATE_INTERVAL) { for (const auto& target_source : dp->intervals_) { for (const auto& interval : target_source.second) { if (time % interval.first == 0) { if (source.empty() || target_source.first == source) { runDecorators(target_source.first, interval.second); } } } } } }
void SchedulerRunner::start() { // Start the counter at the second. auto i = osquery::getUnixTime(); for (; (timeout_ == 0) || (i <= timeout_); ++i) { Config::getInstance().scheduledQueries( ([&i](const std::string& name, const ScheduledQuery& query) { if (query.splayed_interval > 0 && i % query.splayed_interval == 0) { TablePlugin::kCacheInterval = query.splayed_interval; TablePlugin::kCacheStep = i; launchQuery(name, query); } })); // Configuration decorators run on 60 second intervals only. if (i % 60 == 0) { runDecorators(DECORATE_INTERVAL, i); } // Put the thread into an interruptible sleep without a config instance. pauseMilli(interval_ * 1000); if (interrupted()) { break; } } }
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); } }