TEST_F(QueryTests, test_is_query_name_in_database) { auto query = getOsqueryScheduledQuery(); auto cf = Query("foobar", query); auto encoded_qd = getSerializedQueryDataJSON(); auto status = db_->Put(kQueries, "foobar", encoded_qd.first); EXPECT_TRUE(status.ok()); // Now test that the query name exists. EXPECT_TRUE(cf.isQueryNameInDatabase(db_)); }
TEST_F(QueryTests, test_is_query_name_in_database) { auto query = getOsqueryScheduledQuery(); auto cf = Query(query); auto hQR = getSerializedHistoricalQueryResultsJSON(); auto put_status = db->Put(kQueries, query.name, hQR.first); EXPECT_TRUE(put_status.ok()); EXPECT_EQ(put_status.toString(), "OK"); EXPECT_TRUE(cf.isQueryNameInDatabase(db)); }
Status Query::getPreviousQueryResults(QueryData& results, DBHandleRef db) { if (!isQueryNameInDatabase()) { return Status(0, "Query name not found in database"); } std::string raw; auto status = db->Get(kQueries, name_, raw); if (!status.ok()) { return status; } status = deserializeQueryDataJSON(raw, results); if (!status.ok()) { return status; } return Status(0, "OK"); }
Status Query::getHistoricalQueryResults(HistoricalQueryResults& hQR, std::shared_ptr<DBHandle> db) { if (isQueryNameInDatabase()) { std::string raw; auto get_status = db->Get(kQueries, query_.name, raw); if (get_status.ok()) { auto deserialize_status = deserializeHistoricalQueryResultsJSON(raw, hQR); if (!deserialize_status.ok()) { return deserialize_status; } } else { return get_status; } } else { return Status(1, kQueryNameNotFoundError); } return Status(0, "OK"); }
bool Query::isQueryNameInDatabase() { return isQueryNameInDatabase(DBHandle::getInstance()); }
Status Query::addNewResults(QueryData current_qd, const uint64_t current_epoch, uint64_t& counter, DiffResults& dr, bool calculate_diff) const { // The current results are 'fresh' when not calculating a differential. bool fresh_results = !calculate_diff; bool new_query = false; if (!isQueryNameInDatabase()) { // This is the first encounter of the scheduled query. fresh_results = true; LOG(INFO) << "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 " << 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_; saveQuery(name_, query_); } // Use a 'target' avoid copying the query data when serializing and saving. // If a differential is requested and needed the target remains the original // query data, otherwise the content is moved to the differential's added set. const auto* target_gd = ¤t_qd; bool update_db = true; if (!fresh_results && calculate_diff) { // Get the rows from the last run of this query name. QueryDataSet previous_qd; auto status = getPreviousQueryResults(previous_qd); if (!status.ok()) { return status; } // Calculate the differential between previous and current query results. dr = diff(previous_qd, current_qd); update_db = (!dr.added.empty() || !dr.removed.empty()); } else { dr.added = std::move(current_qd); target_gd = &dr.added; } counter = getQueryCounter(fresh_results || new_query); auto status = setDatabaseValue(kQueries, name_ + "counter", std::to_string(counter)); if (!status.ok()) { return status; } if (update_db) { // Replace the "previous" query data with the current. std::string json; status = serializeQueryDataJSON(*target_gd, json); if (!status.ok()) { return status; } status = setDatabaseValue(kQueries, name_, json); if (!status.ok()) { return status; } status = setDatabaseValue( kQueries, name_ + "epoch", std::to_string(current_epoch)); if (!status.ok()) { return status; } } return Status(0, "OK"); }