From 886ad6e928ef064966b8d7f8a7f27d9eec106065 Mon Sep 17 00:00:00 2001 From: Javier Marcos Date: Thu, 21 May 2015 13:42:45 -0700 Subject: [PATCH] Added table for the packs and check for already scheduled queries --- include/osquery/config.h | 6 ++ osquery/config/CMakeLists.txt | 3 + osquery/config/config.cpp | 13 +++ osquery/config/parsers/query_packs.cpp | 13 +-- .../config/parsers}/query_packs.h | 2 - .../parsers/tests/query_packs_tests.cpp | 11 ++- osquery/tables/utility/osquery.cpp | 86 +++++++++++-------- 7 files changed, 89 insertions(+), 45 deletions(-) rename {include/osquery => osquery/config/parsers}/query_packs.h (96%) diff --git a/include/osquery/config.h b/include/osquery/config.h index 93fcf67b..a3fd85f6 100644 --- a/include/osquery/config.h +++ b/include/osquery/config.h @@ -105,6 +105,12 @@ class Config : private boost::noncopyable { */ static void addScheduledQuery(const std::string name, const std::string query, const int interval); + /** + * @brief Checks if the query is already added to the schedule + * + */ + static bool checkScheduledQuery(const std::string query); + /** * @brief Check to ensure that the config is accessible and properly * formatted diff --git a/osquery/config/CMakeLists.txt b/osquery/config/CMakeLists.txt index 33ac48e6..fb26a011 100644 --- a/osquery/config/CMakeLists.txt +++ b/osquery/config/CMakeLists.txt @@ -18,6 +18,9 @@ file(GLOB OSQUERY_CONFIG_PARSERS "parsers/*.cpp") ADD_OSQUERY_LIBRARY(FALSE osquery_config_plugins ${OSQUERY_CONFIG_PLUGINS} +) + +ADD_OSQUERY_LIBRARY(TRUE osquery_config_parsers ${OSQUERY_CONFIG_PARSERS} ) diff --git a/osquery/config/config.cpp b/osquery/config/config.cpp index 814e92b6..b3203c41 100644 --- a/osquery/config/config.cpp +++ b/osquery/config/config.cpp @@ -307,6 +307,19 @@ Status Config::checkConfig() { return load(); } +bool Config::checkScheduledQuery(const std::string query) { + bool result = false; + ConfigDataInstance config; + + for (const auto& scheduled_query : config.schedule()) { + if (scheduled_query.second.query == query) { + result = true; + } + } + + return result; +} + void Config::recordQueryPerformance(const std::string& name, size_t delay, size_t size, diff --git a/osquery/config/parsers/query_packs.cpp b/osquery/config/parsers/query_packs.cpp index f3baa95e..8e302b95 100644 --- a/osquery/config/parsers/query_packs.cpp +++ b/osquery/config/parsers/query_packs.cpp @@ -15,12 +15,11 @@ #include #include #include -#include +#include "query_packs.h" namespace pt = boost::property_tree; namespace osquery { -namespace tables { pt::ptree QueryPackSingleEntry(const pt::ptree& pack_data) { // Extract all the pack fields @@ -92,7 +91,7 @@ bool versionChecker(const std::string& pack_version) { return false; } -std::map QueryPackParsePacks(const pt::ptree& raw_packs, bool check_platform, bool check_version) { +std::map QueryPackConfigParserPlugin::QueryPackParsePacks(const pt::ptree& raw_packs, bool check_platform, bool check_version) { std::map result; // Iterate through all the pack elements @@ -128,9 +127,13 @@ std::map QueryPackParsePacks(const pt::ptree& raw_packs, Status QueryPackConfigParserPlugin::update(const std::map& config) { Status status; + const auto& pack_config = config.at("packs"); + + data_.add_child("packs", pack_config); + + // Iterate through all the packs to get the configuration for(auto const &pack_element : pack_config) { - // Iterate through all the packs to get the configuration auto pack_name = std::string(pack_element.first.data()); auto pack_path = std::string(pack_element.second.data()); @@ -169,6 +172,7 @@ Status QueryPackConfigParserPlugin::update(const std::map namespace osquery { -namespace tables { /** * @brief A simple ConfigParserPlugin for a "packs" dictionary key. @@ -21,4 +20,3 @@ class QueryPackConfigParserPlugin : public ConfigParserPlugin { }; } -} diff --git a/osquery/config/parsers/tests/query_packs_tests.cpp b/osquery/config/parsers/tests/query_packs_tests.cpp index ad160e24..eb997913 100644 --- a/osquery/config/parsers/tests/query_packs_tests.cpp +++ b/osquery/config/parsers/tests/query_packs_tests.cpp @@ -13,12 +13,12 @@ #include #include +#include "osquery/config/parsers/query_packs.h" #include "osquery/core/test_util.h" namespace pt = boost::property_tree; namespace osquery { -namespace tables { std::map QueryPackParsePacks(const pt::ptree& raw_packs, bool check_platform, bool check_version); @@ -29,7 +29,13 @@ std::map getQueryPacksContent() { Status status = osquery::parseJSON(pack_path, pack_tree); pt::ptree pack_file_element = pack_tree.get_child("test_pack_test"); - result = QueryPackParsePacks(pack_file_element, false, true); + ConfigDataInstance config; + const auto& pack_parser = config.getParser("packs"); + if (pack_parser == nullptr) { + return result; + } + const auto& queryPackParser = std::static_pointer_cast(pack_parser); + result = queryPackParser->QueryPackParsePacks(pack_file_element, false, true); return result; } @@ -69,4 +75,3 @@ TEST_F(QueryPacksConfigTests, test_query_packs_configuration) { EXPECT_EQ(expected["launchd"].get("value"), data["launchd"].get("value")); } } -} diff --git a/osquery/tables/utility/osquery.cpp b/osquery/tables/utility/osquery.cpp index 45185ddf..cb0d9561 100644 --- a/osquery/tables/utility/osquery.cpp +++ b/osquery/tables/utility/osquery.cpp @@ -9,7 +9,6 @@ */ #include -#include #include #include #include @@ -19,6 +18,8 @@ #include #include +#include "osquery/config/parsers/query_packs.h" + namespace osquery { namespace tables { @@ -163,10 +164,11 @@ QueryData genOsquerySchedule(QueryContext& context) { } QueryData genOsqueryPacks(QueryContext& context) { + Row r; QueryData results; ConfigDataInstance config; - const auto& pack_config = config.getParsedData("packs"); + // Get the instance for the parser const auto& pack_parser = config.getParser("packs"); if (pack_parser == nullptr) { return results; @@ -176,48 +178,62 @@ QueryData genOsqueryPacks(QueryContext& context) { return results; } - for(auto const &pack_element : pack_config) { - Row r; + // Get the loaded data tree from global JSON configuration + const auto& packs_parsed_data = config.getParsedData("packs"); + if (packs_parsed_data.count("packs") == 0) { + return results; + } - // Iterate through all the packs to get the configuration - auto pack_name = std::string(pack_element.first.data()); - auto pack_path = std::string(pack_element.second.data()); - - r["name"] = TEXT(pack_name); - r["path"] = TEXT(pack_path); - - // Read each pack configuration in JSON - pt::ptree pack_tree; - Status status = osquery::parseJSON(pack_path, pack_tree); - - // Get all the parsed elements from the pack JSON file - if (pack_tree.count(pack_name) == 0) { + // Iterate through all the packs to get the configuration + for(auto const &pack_element : packs_parsed_data) { + // Make sure the element has items + if (pack_element.second.size() == 0) { continue; } - pt::ptree pack_file_element = pack_tree.get_child(pack_name); + std::string pack_name; + std::string pack_path; - // Get all the valid packs and return them in a map + // Find all the packs from loaded configuration + for (auto const &conf_element : pack_element.second) { + pack_name = std::string(conf_element.first.data()); + pack_path = std::string(conf_element.second.data()); - std::map clean_packs = queryPackParser->QueryPackParsePacks(pack_file_element, false, false); + // Read each pack configuration in JSON + pt::ptree pack_tree; + Status status = osquery::parseJSON(pack_path, pack_tree); - // Iterate through the already parsed and valid packs - std::map::iterator pk = clean_packs.begin(); - for(pk=clean_packs.begin(); pk!=clean_packs.end(); ++pk) { - // Adding a prefix to the pack queries, to be easily found in the scheduled queries - std::string pk_name = "pack_" + pack_name + "_" + pk->first; - pt::ptree pk_data = pk->second; + // Get all the parsed elements from the pack JSON file + if (pack_tree.count(pack_name) == 0) { + continue; + } + pt::ptree pack_file_element = pack_tree.get_child(pack_name); - r["query_name"] = TEXT(pk->first); + // Get all the valid packs and return them in a map + std::map clean_packs = queryPackParser->QueryPackParsePacks(pack_file_element, false, false); - // Query data to return as Row - r["query"] = TEXT(pk_data.get("query")); - r["interval"] = INTEGER(pk_data.get("interval")); - r["platform"] = TEXT(pk_data.get("platform")); - r["version"] = TEXT(pk_data.get("version")); - r["description"] = TEXT(pk_data.get("description")); - r["value"] = TEXT(pk_data.get("value")); + // Iterate through the already parsed and valid packs + std::map::iterator pk = clean_packs.begin(); + for(pk=clean_packs.begin(); pk!=clean_packs.end(); ++pk) { + // Adding a prefix to the pack queries, to be easily found in the scheduled queries + std::string pk_name = "pack_" + pack_name + "_" + pk->first; + pt::ptree pk_data = pk->second; - results.push_back(r); + // Query data to return as Row + r["query_name"] = TEXT(pk->first); + r["name"] = TEXT(pack_name); + r["path"] = TEXT(pack_path); + r["query"] = TEXT(pk_data.get("query")); + r["interval"] = INTEGER(pk_data.get("interval")); + r["platform"] = TEXT(pk_data.get("platform")); + r["version"] = TEXT(pk_data.get("version")); + r["description"] = TEXT(pk_data.get("description")); + r["value"] = TEXT(pk_data.get("value")); + r["scheduled_name"] = TEXT(pk_name); + int scheduled = Config::checkScheduledQuery(r["query"]) ? 1 : 0; + r["scheduled"] = INTEGER(scheduled); + + results.push_back(r); + } } }