2015-12-07 19:58:53 +00:00
|
|
|
/*
|
2016-02-11 19:48:58 +00:00
|
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
2015-12-07 19:58:53 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
2016-03-27 08:01:20 +00:00
|
|
|
#include <osquery/logger.h>
|
2016-07-07 22:16:28 +00:00
|
|
|
#include <osquery/system.h>
|
2016-03-27 08:01:20 +00:00
|
|
|
|
2015-12-07 19:58:53 +00:00
|
|
|
#include "osquery/dispatcher/scheduler.h"
|
2016-09-12 16:46:52 +00:00
|
|
|
#include "osquery/sql/sqlite_util.h"
|
|
|
|
#include "osquery/tests/test_util.h"
|
2015-12-07 19:58:53 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
2016-03-27 08:01:20 +00:00
|
|
|
DECLARE_bool(disable_logging);
|
2017-01-26 01:48:33 +00:00
|
|
|
DECLARE_uint64(schedule_reload);
|
2016-03-27 08:01:20 +00:00
|
|
|
|
|
|
|
class SchedulerTests : public testing::Test {
|
|
|
|
void SetUp() override {
|
|
|
|
logging_ = FLAGS_disable_logging;
|
|
|
|
FLAGS_disable_logging = true;
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().reset();
|
2016-03-27 08:01:20 +00:00
|
|
|
}
|
|
|
|
|
2016-04-12 20:06:02 +00:00
|
|
|
void TearDown() override {
|
|
|
|
FLAGS_disable_logging = logging_;
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().reset();
|
2016-04-12 20:06:02 +00:00
|
|
|
}
|
2016-03-27 08:01:20 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool logging_{false};
|
|
|
|
};
|
2015-12-07 19:58:53 +00:00
|
|
|
|
|
|
|
TEST_F(SchedulerTests, test_monitor) {
|
|
|
|
std::string name = "pack_test_test_query";
|
|
|
|
|
|
|
|
// This query has never run so it will not have a timestamp.
|
|
|
|
std::string timestamp;
|
|
|
|
getDatabaseValue(kPersistentSettings, "timestamp." + name, timestamp);
|
|
|
|
ASSERT_TRUE(timestamp.empty());
|
|
|
|
|
|
|
|
// Fill in a scheduled query and execute it via the query monitor wrapper.
|
|
|
|
ScheduledQuery query;
|
|
|
|
query.interval = 10;
|
|
|
|
query.splayed_interval = 11;
|
|
|
|
query.query = "select * from time";
|
|
|
|
auto results = monitor(name, query);
|
|
|
|
EXPECT_EQ(results.rows().size(), 1U);
|
|
|
|
|
|
|
|
// Ask the config instance for the monitored performance.
|
|
|
|
QueryPerformance perf;
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().getPerformanceStats(
|
2015-12-07 19:58:53 +00:00
|
|
|
name, ([&perf](const QueryPerformance& r) { perf = r; }));
|
|
|
|
// Make sure it was recorded query ran.
|
|
|
|
// There is no pack for this query within the config, that is fine as these
|
|
|
|
// performance stats are tracked independently.
|
|
|
|
EXPECT_EQ(perf.executions, 1U);
|
|
|
|
EXPECT_GT(perf.output_size, 0U);
|
|
|
|
|
|
|
|
// A bit more testing, potentially redundant, check the database results.
|
|
|
|
// Since we are only monitoring, no 'actual' results are stored.
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kQueries, name, content);
|
|
|
|
EXPECT_TRUE(content.empty());
|
|
|
|
|
|
|
|
// Finally, make sure there is a recorded timestamp for the execution.
|
|
|
|
// We are not concerned with the APPROX value, only that it was recorded.
|
|
|
|
getDatabaseValue(kPersistentSettings, "timestamp." + name, timestamp);
|
|
|
|
EXPECT_FALSE(timestamp.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SchedulerTests, test_config_results_purge) {
|
|
|
|
// Set a query time for now (time is only important relative to a week ago).
|
|
|
|
auto query_time = osquery::getUnixTime();
|
2016-08-31 22:32:20 +00:00
|
|
|
setDatabaseValue(
|
|
|
|
kPersistentSettings, "timestamp.test_query", std::to_string(query_time));
|
2015-12-07 19:58:53 +00:00
|
|
|
// Store a meaningless saved query interval splay.
|
|
|
|
setDatabaseValue(kPersistentSettings, "interval.test_query", "11");
|
|
|
|
// Store meaningless query differential results.
|
|
|
|
setDatabaseValue(kQueries, "test_query", "{}");
|
|
|
|
|
|
|
|
// We do not need "THE" config instance.
|
|
|
|
// We only need to trigger a 'purge' event, this occurs when configuration
|
|
|
|
// content is updated by a plugin or on load.
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().purge();
|
2015-12-07 19:58:53 +00:00
|
|
|
|
|
|
|
// Nothing should have been purged.
|
|
|
|
{
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kPersistentSettings, "timestamp.test_query", content);
|
|
|
|
EXPECT_FALSE(content.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kPersistentSettings, "interval.test_query", content);
|
|
|
|
EXPECT_FALSE(content.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kQueries, "test_query", content);
|
|
|
|
EXPECT_FALSE(content.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the timestamp to have run a week and a day ago.
|
|
|
|
query_time -= (84600 * (7 + 1));
|
2016-08-31 22:32:20 +00:00
|
|
|
setDatabaseValue(
|
|
|
|
kPersistentSettings, "timestamp.test_query", std::to_string(query_time));
|
2015-12-07 19:58:53 +00:00
|
|
|
|
|
|
|
// Trigger another purge.
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().purge();
|
2015-12-07 19:58:53 +00:00
|
|
|
// Now ALL 'test_query' related storage will have been purged.
|
|
|
|
{
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kPersistentSettings, "timestamp.test_query", content);
|
|
|
|
EXPECT_TRUE(content.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kPersistentSettings, "interval.test_query", content);
|
|
|
|
EXPECT_TRUE(content.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kQueries, "test_query", content);
|
|
|
|
EXPECT_TRUE(content.empty());
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 08:01:20 +00:00
|
|
|
|
|
|
|
TEST_F(SchedulerTests, test_scheduler) {
|
2016-08-01 07:38:43 +00:00
|
|
|
auto backup_step = TablePlugin::kCacheStep;
|
|
|
|
auto backup_interval = TablePlugin::kCacheInterval;
|
|
|
|
|
2016-03-27 08:01:20 +00:00
|
|
|
// Start the scheduler now.
|
|
|
|
auto now = osquery::getUnixTime();
|
|
|
|
TablePlugin::kCacheStep = now;
|
|
|
|
|
|
|
|
// Update the config with a pack/schedule that contains several queries.
|
|
|
|
std::string config =
|
|
|
|
"{"
|
|
|
|
"\"packs\": {"
|
|
|
|
"\"scheduler\": {"
|
|
|
|
"\"queries\": {"
|
|
|
|
"\"1\": {\"query\": \"select * from osquery_schedule\", \"interval\": 1},"
|
|
|
|
"\"2\": {\"query\": \"select * from osquery_info\", \"interval\": 1},"
|
|
|
|
"\"3\": {\"query\": \"select * from processes\", \"interval\": 1},"
|
|
|
|
"\"4\": {\"query\": \"select * from osquery_packs\", \"interval\": 1}"
|
|
|
|
"}"
|
|
|
|
"}"
|
|
|
|
"}"
|
|
|
|
"}";
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().update({{"data", config}});
|
2016-03-27 08:01:20 +00:00
|
|
|
|
|
|
|
// Run the scheduler for 1 second with a second interval.
|
2016-09-12 16:46:52 +00:00
|
|
|
SchedulerRunner runner(static_cast<unsigned long int>(now + 1), 1);
|
2016-03-27 08:01:20 +00:00
|
|
|
runner.start();
|
|
|
|
|
|
|
|
// If a query was executed the cache step will have been advanced.
|
|
|
|
EXPECT_GT(TablePlugin::kCacheStep, now);
|
2016-08-01 07:38:43 +00:00
|
|
|
|
|
|
|
// Restore plugin settings.
|
|
|
|
TablePlugin::kCacheStep = backup_step;
|
|
|
|
TablePlugin::kCacheInterval = backup_interval;
|
2016-03-27 08:01:20 +00:00
|
|
|
}
|
2017-01-26 01:48:33 +00:00
|
|
|
|
|
|
|
TEST_F(SchedulerTests, test_scheduler_reload) {
|
|
|
|
std::string config =
|
|
|
|
"{\"schedule\":{\"1\":{"
|
|
|
|
"\"query\":\"select * from processes\", \"interval\":1}}}";
|
|
|
|
auto backup_reload = FLAGS_schedule_reload;
|
|
|
|
|
|
|
|
// Start the scheduler;
|
|
|
|
auto expire = static_cast<unsigned long int>(getUnixTime() + 1);
|
|
|
|
FLAGS_schedule_reload = 1;
|
|
|
|
SchedulerRunner runner(expire, 1);
|
|
|
|
FLAGS_schedule_reload = backup_reload;
|
|
|
|
}
|
2015-12-07 19:58:53 +00:00
|
|
|
}
|