2017-12-19 00:04:06 +00:00
|
|
|
/**
|
2016-02-11 19:48:58 +00:00
|
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
2014-12-18 18:50:47 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2017-12-19 00:04:06 +00:00
|
|
|
* This source code is licensed under both the Apache 2.0 license (found in the
|
|
|
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
|
|
* in the COPYING file in the root directory of this source tree).
|
|
|
|
* You may select, at your option, one of the above-listed licenses.
|
2014-12-18 18:50:47 +00:00
|
|
|
*/
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2017-08-20 09:44:38 +00:00
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2015-10-26 08:14:51 +00:00
|
|
|
|
2016-11-19 23:01:40 +00:00
|
|
|
#include <boost/algorithm/string/replace.hpp>
|
2015-12-04 18:07:38 +00:00
|
|
|
#include <boost/algorithm/string/trim.hpp>
|
2017-07-17 18:38:21 +00:00
|
|
|
#include <boost/iterator/filter_iterator.hpp>
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/config.h>
|
2015-09-17 06:31:07 +00:00
|
|
|
#include <osquery/database.h>
|
2017-03-21 05:03:09 +00:00
|
|
|
#include <osquery/events.h>
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/flags.h>
|
2015-01-21 21:36:55 +00:00
|
|
|
#include <osquery/logger.h>
|
2015-12-09 23:01:20 +00:00
|
|
|
#include <osquery/packs.h>
|
2015-03-30 06:51:52 +00:00
|
|
|
#include <osquery/registry.h>
|
2015-06-12 21:09:42 +00:00
|
|
|
#include <osquery/tables.h>
|
2014-12-11 01:35:21 +00:00
|
|
|
|
2015-11-03 23:36:46 +00:00
|
|
|
#include "osquery/core/conversions.h"
|
|
|
|
|
2018-01-21 01:58:01 +00:00
|
|
|
namespace rj = rapidjson;
|
2015-03-13 23:05:20 +00:00
|
|
|
|
2015-06-04 01:09:32 +00:00
|
|
|
namespace osquery {
|
|
|
|
|
2016-07-14 21:19:33 +00:00
|
|
|
/**
|
|
|
|
* @brief Config plugin registry.
|
|
|
|
*
|
|
|
|
* This creates an osquery registry for "config" which may implement
|
|
|
|
* ConfigPlugin. A ConfigPlugin's call API should make use of a genConfig
|
|
|
|
* after reading JSON data in the plugin implementation.
|
|
|
|
*/
|
|
|
|
CREATE_REGISTRY(ConfigPlugin, "config");
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief ConfigParser plugin registry.
|
|
|
|
*
|
|
|
|
* This creates an osquery registry for "config_parser" which may implement
|
|
|
|
* ConfigParserPlugin. A ConfigParserPlugin should not export any call actions
|
|
|
|
* but rather have a simple property tree-accessor API through Config.
|
|
|
|
*/
|
|
|
|
CREATE_LAZY_REGISTRY(ConfigParserPlugin, "config_parser");
|
|
|
|
|
2015-07-18 22:08:51 +00:00
|
|
|
/// The config plugin must be known before reading options.
|
2015-03-03 23:03:14 +00:00
|
|
|
CLI_FLAG(string, config_plugin, "filesystem", "Config plugin name");
|
2014-07-31 00:35:19 +00:00
|
|
|
|
2015-12-04 23:41:40 +00:00
|
|
|
CLI_FLAG(bool,
|
|
|
|
config_check,
|
|
|
|
false,
|
|
|
|
"Check the format of an osquery config and exit");
|
|
|
|
|
|
|
|
CLI_FLAG(bool, config_dump, false, "Dump the contents of the configuration");
|
|
|
|
|
2017-02-27 01:45:06 +00:00
|
|
|
CLI_FLAG(uint64,
|
|
|
|
config_refresh,
|
|
|
|
0,
|
|
|
|
"Optional interval in seconds to re-read configuration");
|
2017-05-29 21:09:44 +00:00
|
|
|
FLAG_ALIAS(google::uint64, config_tls_refresh, config_refresh);
|
|
|
|
|
|
|
|
/// How long to wait when config update fails
|
|
|
|
CLI_FLAG(uint64,
|
|
|
|
config_accelerated_refresh,
|
|
|
|
300,
|
|
|
|
"Interval to wait if reading a configuration fails");
|
|
|
|
FLAG_ALIAS(google::uint64,
|
|
|
|
config_tls_accelerated_refresh,
|
|
|
|
config_accelerated_refresh);
|
2017-02-27 01:45:06 +00:00
|
|
|
|
2015-12-04 23:41:40 +00:00
|
|
|
DECLARE_string(config_plugin);
|
2015-11-03 02:05:46 +00:00
|
|
|
DECLARE_string(pack_delimiter);
|
|
|
|
|
2015-11-02 08:23:11 +00:00
|
|
|
/**
|
|
|
|
* @brief The backing store key name for the executing query.
|
|
|
|
*
|
|
|
|
* The config maintains schedule statistics and tracks failed executions.
|
|
|
|
* On process or worker resume an initializer or config may check if the
|
|
|
|
* resume was the result of a failure during an executing query.
|
|
|
|
*/
|
2016-11-19 23:01:40 +00:00
|
|
|
const std::string kExecutingQuery{"executing_query"};
|
|
|
|
const std::string kFailedQueries{"failed_queries"};
|
2015-09-17 06:31:07 +00:00
|
|
|
|
2017-06-14 00:26:34 +00:00
|
|
|
/// The time osquery was started.
|
|
|
|
std::atomic<size_t> kStartTime;
|
|
|
|
|
2015-09-17 06:31:07 +00:00
|
|
|
// The config may be accessed and updated asynchronously; use mutexes.
|
2016-03-11 08:30:20 +00:00
|
|
|
Mutex config_hash_mutex_;
|
|
|
|
Mutex config_valid_mutex_;
|
2017-05-31 02:22:41 +00:00
|
|
|
Mutex config_refresh_mutex_;
|
2015-03-04 02:40:24 +00:00
|
|
|
|
2016-03-27 04:52:22 +00:00
|
|
|
/// Several config methods require enumeration via predicate lambdas.
|
|
|
|
RecursiveMutex config_schedule_mutex_;
|
|
|
|
RecursiveMutex config_files_mutex_;
|
|
|
|
RecursiveMutex config_performance_mutex_;
|
|
|
|
|
2016-02-06 01:10:35 +00:00
|
|
|
using PackRef = std::shared_ptr<Pack>;
|
|
|
|
|
2015-12-09 23:01:20 +00:00
|
|
|
/**
|
|
|
|
* The schedule is an iterable collection of Packs. When you iterate through
|
|
|
|
* a schedule, you only get the packs that should be running on the host that
|
|
|
|
* you're currently operating on.
|
|
|
|
*/
|
|
|
|
class Schedule : private boost::noncopyable {
|
|
|
|
public:
|
|
|
|
/// Under the hood, the schedule is just a list of the Pack objects
|
2016-02-06 01:10:35 +00:00
|
|
|
using container = std::list<PackRef>;
|
2015-12-09 23:01:20 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create a schedule maintained by the configuration.
|
|
|
|
*
|
|
|
|
* This will check for previously executing queries. If any query was
|
|
|
|
* executing it is considered in a 'dirty' state and should generate logs.
|
|
|
|
* The schedule may also choose to blacklist this query.
|
|
|
|
*/
|
|
|
|
Schedule();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This class' iteration function
|
|
|
|
*
|
|
|
|
* Our step operation will be called on each element in packs_. It is
|
|
|
|
* responsible for determining if that element should be returned as the
|
|
|
|
* next iterator element or skipped.
|
|
|
|
*/
|
|
|
|
struct Step {
|
2017-12-18 16:42:00 +00:00
|
|
|
bool operator()(PackRef& pack);
|
2015-12-09 23:01:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Add a pack to the schedule
|
2017-12-18 16:42:00 +00:00
|
|
|
void add(PackRef&& pack);
|
2015-12-09 23:01:20 +00:00
|
|
|
|
|
|
|
/// Remove a pack, by name.
|
2017-12-18 16:42:00 +00:00
|
|
|
void remove(const std::string& pack);
|
2015-12-09 23:01:20 +00:00
|
|
|
|
2016-01-09 00:45:51 +00:00
|
|
|
/// Remove a pack by name and source.
|
2017-12-18 16:42:00 +00:00
|
|
|
void remove(const std::string& pack, const std::string& source);
|
2015-12-09 23:01:20 +00:00
|
|
|
|
2016-01-09 00:45:51 +00:00
|
|
|
/// Remove all packs by source.
|
2017-12-18 16:42:00 +00:00
|
|
|
void removeAll(const std::string& source);
|
2016-01-09 00:45:51 +00:00
|
|
|
|
2015-12-09 23:01:20 +00:00
|
|
|
/// Boost gives us a nice template for maintaining the state of the iterator
|
|
|
|
using iterator = boost::filter_iterator<Step, container::iterator>;
|
|
|
|
|
2017-12-18 16:42:00 +00:00
|
|
|
iterator begin();
|
2016-11-19 23:01:40 +00:00
|
|
|
|
2017-12-18 16:42:00 +00:00
|
|
|
iterator end();
|
2015-12-09 23:01:20 +00:00
|
|
|
|
2017-12-18 16:42:00 +00:00
|
|
|
PackRef& last();
|
2016-02-06 01:10:35 +00:00
|
|
|
|
2015-12-09 23:01:20 +00:00
|
|
|
private:
|
|
|
|
/// Underlying storage for the packs
|
|
|
|
container packs_;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The schedule will check and record previously executing queries.
|
|
|
|
*
|
|
|
|
* If a query is found on initialization, the name will be recorded, it is
|
|
|
|
* possible to skip previously failed queries.
|
|
|
|
*/
|
|
|
|
std::string failed_query_;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief List of blacklisted queries.
|
|
|
|
*
|
|
|
|
* A list of queries that are blacklisted from executing due to prior
|
|
|
|
* failures. If a query caused a worker to fail it will be recorded during
|
|
|
|
* the next execution and saved to the blacklist.
|
|
|
|
*/
|
|
|
|
std::map<std::string, size_t> blacklist_;
|
|
|
|
|
|
|
|
private:
|
|
|
|
friend class Config;
|
|
|
|
};
|
|
|
|
|
2017-12-18 16:42:00 +00:00
|
|
|
bool Schedule::Step::operator()(PackRef& pack) {
|
|
|
|
return pack->shouldPackExecute();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Schedule::add(PackRef&& pack) {
|
|
|
|
remove(pack->getName(), pack->getSource());
|
|
|
|
packs_.push_back(pack);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Schedule::remove(const std::string& pack) {
|
|
|
|
remove(pack, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Schedule::remove(const std::string& pack, const std::string& source) {
|
|
|
|
packs_.remove_if([pack, source](PackRef& p) {
|
|
|
|
if (p->getName() == pack && (p->getSource() == source || source == "")) {
|
|
|
|
Config::get().removeFiles(source + FLAGS_pack_delimiter + p->getName());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void Schedule::removeAll(const std::string& source) {
|
|
|
|
packs_.remove_if(([source](PackRef& p) {
|
|
|
|
if (p->getSource() == source) {
|
|
|
|
Config::get().removeFiles(source + FLAGS_pack_delimiter + p->getName());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
Schedule::iterator Schedule::begin() {
|
|
|
|
return Schedule::iterator(packs_.begin(), packs_.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
Schedule::iterator Schedule::end() {
|
|
|
|
return Schedule::iterator(packs_.end(), packs_.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
PackRef& Schedule::last() {
|
|
|
|
return packs_.back();
|
|
|
|
}
|
|
|
|
|
2017-07-17 18:38:21 +00:00
|
|
|
/**
|
|
|
|
* @brief A thread that periodically reloads configuration state.
|
|
|
|
*
|
|
|
|
* This refresh runner thread can refresh any configuration plugin.
|
|
|
|
* It may accelerate the time between checks if the configuration fails to load.
|
|
|
|
* For configurations pulled from the network this assures that configuration
|
|
|
|
* is fresh when re-attaching.
|
|
|
|
*/
|
|
|
|
class ConfigRefreshRunner : public InternalRunnable {
|
|
|
|
public:
|
2017-10-25 02:55:05 +00:00
|
|
|
ConfigRefreshRunner() : InternalRunnable("ConfigRefreshRunner") {}
|
|
|
|
|
2017-07-17 18:38:21 +00:00
|
|
|
/// A simple wait/interruptible lock.
|
2018-05-02 02:47:01 +00:00
|
|
|
void start() override;
|
2017-07-17 18:38:21 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
/// The current refresh rate in seconds.
|
|
|
|
std::atomic<size_t> refresh_{0};
|
|
|
|
std::atomic<size_t> mod_{1000};
|
|
|
|
|
|
|
|
private:
|
|
|
|
friend class Config;
|
|
|
|
};
|
|
|
|
|
2015-11-03 23:36:46 +00:00
|
|
|
void restoreScheduleBlacklist(std::map<std::string, size_t>& blacklist) {
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kPersistentSettings, kFailedQueries, content);
|
|
|
|
auto blacklist_pairs = osquery::split(content, ":");
|
|
|
|
if (blacklist_pairs.size() == 0 || blacklist_pairs.size() % 2 != 0) {
|
|
|
|
// Nothing in the blacklist, or malformed data.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t current_time = getUnixTime();
|
|
|
|
for (size_t i = 0; i < blacklist_pairs.size() / 2; i++) {
|
|
|
|
// Fill in a mapping of query name to time the blacklist expires.
|
2016-09-12 16:46:52 +00:00
|
|
|
long long expire = 0;
|
|
|
|
safeStrtoll(blacklist_pairs[(i * 2) + 1], 10, expire);
|
2015-11-03 23:36:46 +00:00
|
|
|
if (expire > 0 && current_time < (size_t)expire) {
|
|
|
|
blacklist[blacklist_pairs[(i * 2)]] = (size_t)expire;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void saveScheduleBlacklist(const std::map<std::string, size_t>& blacklist) {
|
|
|
|
std::string content;
|
|
|
|
for (const auto& query : blacklist) {
|
|
|
|
if (!content.empty()) {
|
|
|
|
content += ":";
|
|
|
|
}
|
|
|
|
content += query.first + ":" + std::to_string(query.second);
|
|
|
|
}
|
|
|
|
setDatabaseValue(kPersistentSettings, kFailedQueries, content);
|
|
|
|
}
|
|
|
|
|
2015-11-02 08:23:11 +00:00
|
|
|
Schedule::Schedule() {
|
2017-01-07 20:21:35 +00:00
|
|
|
if (RegistryFactory::get().external()) {
|
2015-11-06 17:52:10 +00:00
|
|
|
// Extensions should not restore or save schedule details.
|
|
|
|
return;
|
|
|
|
}
|
2015-11-03 23:36:46 +00:00
|
|
|
// Parse the schedule's query blacklist from backing storage.
|
|
|
|
restoreScheduleBlacklist(blacklist_);
|
|
|
|
|
2015-11-02 08:23:11 +00:00
|
|
|
// Check if any queries were executing when the tool last stopped.
|
|
|
|
getDatabaseValue(kPersistentSettings, kExecutingQuery, failed_query_);
|
|
|
|
if (!failed_query_.empty()) {
|
|
|
|
LOG(WARNING) << "Scheduled query may have failed: " << failed_query_;
|
|
|
|
setDatabaseValue(kPersistentSettings, kExecutingQuery, "");
|
2015-11-03 23:36:46 +00:00
|
|
|
// Add this query name to the blacklist and save the blacklist.
|
|
|
|
blacklist_[failed_query_] = getUnixTime() + 86400;
|
|
|
|
saveScheduleBlacklist(blacklist_);
|
2015-11-02 08:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-09 23:01:20 +00:00
|
|
|
Config::Config()
|
|
|
|
: schedule_(std::make_shared<Schedule>()),
|
|
|
|
valid_(false),
|
2017-05-29 21:09:44 +00:00
|
|
|
refresh_runner_(std::make_shared<ConfigRefreshRunner>()) {}
|
2015-12-09 23:01:20 +00:00
|
|
|
|
2018-05-01 18:56:51 +00:00
|
|
|
Config& Config::get() {
|
|
|
|
static Config instance;
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
2015-10-26 08:14:51 +00:00
|
|
|
void Config::addPack(const std::string& name,
|
|
|
|
const std::string& source,
|
2018-01-21 01:58:01 +00:00
|
|
|
const rj::Value& obj) {
|
|
|
|
assert(obj.IsObject());
|
|
|
|
|
2016-11-22 17:35:03 +00:00
|
|
|
auto addSinglePack = ([this, &source](const std::string pack_name,
|
2018-01-21 01:58:01 +00:00
|
|
|
const rj::Value& pack_obj) {
|
2016-11-22 17:35:03 +00:00
|
|
|
RecursiveLock wlock(config_schedule_mutex_);
|
|
|
|
try {
|
2018-01-21 01:58:01 +00:00
|
|
|
schedule_->add(std::make_shared<Pack>(pack_name, source, pack_obj));
|
2016-11-22 17:35:03 +00:00
|
|
|
if (schedule_->last()->shouldPackExecute()) {
|
2018-01-21 01:58:01 +00:00
|
|
|
applyParsers(source + FLAGS_pack_delimiter + pack_name, pack_obj, true);
|
2016-11-22 17:35:03 +00:00
|
|
|
}
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
LOG(WARNING) << "Error adding pack: " << pack_name << ": " << e.what();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (name == "*") {
|
|
|
|
// This is a multi-pack, expect the config plugin to have generated a
|
|
|
|
// "name": {pack-content} response similar to embedded pack content
|
|
|
|
// within the configuration.
|
2018-01-21 01:58:01 +00:00
|
|
|
for (const auto& pack : obj.GetObject()) {
|
|
|
|
addSinglePack(pack.name.GetString(), pack.value);
|
2016-02-06 01:10:35 +00:00
|
|
|
}
|
2016-11-22 17:35:03 +00:00
|
|
|
} else {
|
2018-01-21 01:58:01 +00:00
|
|
|
addSinglePack(name, obj);
|
2015-10-26 08:14:51 +00:00
|
|
|
}
|
2015-03-20 17:34:36 +00:00
|
|
|
}
|
|
|
|
|
2017-06-14 00:26:34 +00:00
|
|
|
size_t Config::getStartTime() {
|
|
|
|
return kStartTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::setStartTime(size_t st) {
|
|
|
|
kStartTime = st;
|
|
|
|
}
|
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
void Config::removePack(const std::string& pack) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock wlock(config_schedule_mutex_);
|
2015-12-09 23:01:20 +00:00
|
|
|
return schedule_->remove(pack);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
2015-07-18 22:08:51 +00:00
|
|
|
|
2015-12-08 07:08:00 +00:00
|
|
|
void Config::addFile(const std::string& source,
|
|
|
|
const std::string& category,
|
|
|
|
const std::string& path) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock wlock(config_files_mutex_);
|
2015-12-08 07:08:00 +00:00
|
|
|
files_[source][category].push_back(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::removeFiles(const std::string& source) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock wlock(config_files_mutex_);
|
2015-12-08 07:08:00 +00:00
|
|
|
if (files_.count(source)) {
|
|
|
|
FileCategories().swap(files_[source]);
|
|
|
|
}
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
2014-12-01 09:05:46 +00:00
|
|
|
|
2017-12-18 16:42:00 +00:00
|
|
|
/**
|
|
|
|
* @brief Return true if the failed query is no longer blacklisted.
|
|
|
|
*
|
|
|
|
* There are two scenarios where a blacklisted query becomes 'unblacklisted'.
|
|
|
|
* The first is simple, the amount of time it was blacklisted for has expired.
|
|
|
|
* The second is more complex, the query failed but the schedule has requested
|
|
|
|
* that the query should not be blacklisted.
|
|
|
|
*
|
|
|
|
* @param blt The time the query was originally blacklisted.
|
|
|
|
* @param query The scheduled query and its options.
|
|
|
|
*/
|
|
|
|
static inline bool blacklistExpired(size_t blt, const ScheduledQuery& query) {
|
|
|
|
if (getUnixTime() > blt) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto blo = query.options.find("blacklist");
|
|
|
|
if (blo != query.options.end() && blo->second == false) {
|
|
|
|
// The schedule requested that we do not blacklist this query.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-03-05 17:29:51 +00:00
|
|
|
void Config::scheduledQueries(
|
|
|
|
std::function<void(const std::string& name, const ScheduledQuery& query)>
|
2017-12-18 03:25:42 +00:00
|
|
|
predicate,
|
|
|
|
bool blacklisted) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock lock(config_schedule_mutex_);
|
2017-12-18 03:25:42 +00:00
|
|
|
for (PackRef& pack : *schedule_) {
|
|
|
|
for (auto& it : pack->getSchedule()) {
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
std::string name = it.first;
|
2015-11-03 23:36:46 +00:00
|
|
|
// The query name may be synthetic.
|
2016-02-06 01:10:35 +00:00
|
|
|
if (pack->getName() != "main" && pack->getName() != "legacy_main") {
|
|
|
|
name = "pack" + FLAGS_pack_delimiter + pack->getName() +
|
2015-11-03 02:05:46 +00:00
|
|
|
FLAGS_pack_delimiter + it.first;
|
2015-07-18 22:08:51 +00:00
|
|
|
}
|
2017-12-18 16:42:00 +00:00
|
|
|
|
2015-11-03 23:36:46 +00:00
|
|
|
// They query may have failed and been added to the schedule's blacklist.
|
2017-12-18 03:25:42 +00:00
|
|
|
auto blacklisted_query = schedule_->blacklist_.find(name);
|
|
|
|
if (blacklisted_query != schedule_->blacklist_.end()) {
|
2017-12-18 16:42:00 +00:00
|
|
|
if (blacklistExpired(blacklisted_query->second, it.second)) {
|
2015-11-03 23:36:46 +00:00
|
|
|
// The blacklisted query passed the expiration time (remove).
|
2015-12-09 23:01:20 +00:00
|
|
|
schedule_->blacklist_.erase(blacklisted_query);
|
|
|
|
saveScheduleBlacklist(schedule_->blacklist_);
|
2017-12-18 03:25:42 +00:00
|
|
|
it.second.blacklisted = false;
|
2015-11-03 23:36:46 +00:00
|
|
|
} else {
|
|
|
|
// The query is still blacklisted.
|
2017-12-18 03:25:42 +00:00
|
|
|
it.second.blacklisted = true;
|
|
|
|
if (!blacklisted) {
|
|
|
|
// The caller does not want blacklisted queries.
|
|
|
|
continue;
|
|
|
|
}
|
2015-11-03 23:36:46 +00:00
|
|
|
}
|
|
|
|
}
|
2017-12-18 03:25:42 +00:00
|
|
|
|
2015-11-03 23:36:46 +00:00
|
|
|
// Call the predicate.
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
predicate(name, it.second);
|
2015-05-11 08:21:57 +00:00
|
|
|
}
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
2015-03-22 03:51:42 +00:00
|
|
|
|
2016-02-06 01:10:35 +00:00
|
|
|
void Config::packs(std::function<void(PackRef& pack)> predicate) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock lock(config_schedule_mutex_);
|
2016-02-06 01:10:35 +00:00
|
|
|
for (PackRef& pack : schedule_->packs_) {
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
predicate(pack);
|
|
|
|
}
|
|
|
|
}
|
2015-04-14 07:57:22 +00:00
|
|
|
|
2017-02-27 01:45:06 +00:00
|
|
|
Status Config::refresh() {
|
2015-01-30 18:44:25 +00:00
|
|
|
PluginResponse response;
|
2015-03-08 21:52:13 +00:00
|
|
|
auto status = Registry::call("config", {{"action", "genConfig"}}, response);
|
2017-05-31 02:22:41 +00:00
|
|
|
|
|
|
|
WriteLock lock(config_refresh_mutex_);
|
2015-01-30 18:44:25 +00:00
|
|
|
if (!status.ok()) {
|
2017-07-17 18:38:21 +00:00
|
|
|
if (FLAGS_config_refresh > 0 && getRefresh() == FLAGS_config_refresh) {
|
2017-05-29 21:09:44 +00:00
|
|
|
VLOG(1) << "Using accelerated configuration delay";
|
2017-07-17 18:38:21 +00:00
|
|
|
setRefresh(FLAGS_config_accelerated_refresh);
|
2017-05-29 21:09:44 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 05:34:03 +00:00
|
|
|
loaded_ = true;
|
2015-01-30 18:44:25 +00:00
|
|
|
return status;
|
2017-07-17 18:38:21 +00:00
|
|
|
} else if (getRefresh() != FLAGS_config_refresh) {
|
2017-05-29 21:09:44 +00:00
|
|
|
VLOG(1) << "Normal configuration delay restored";
|
2017-07-17 18:38:21 +00:00
|
|
|
setRefresh(FLAGS_config_refresh);
|
2014-07-31 00:35:19 +00:00
|
|
|
}
|
2015-01-04 07:12:28 +00:00
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
// if there was a response, parse it and update internal state
|
2015-12-03 05:01:41 +00:00
|
|
|
valid_ = true;
|
2015-03-13 23:05:20 +00:00
|
|
|
if (response.size() > 0) {
|
2015-12-04 23:41:40 +00:00
|
|
|
if (FLAGS_config_dump) {
|
|
|
|
// If config checking is enabled, debug-write the raw config data.
|
|
|
|
for (const auto& content : response[0]) {
|
|
|
|
fprintf(stdout,
|
|
|
|
"{\"%s\": %s}\n",
|
|
|
|
content.first.c_str(),
|
|
|
|
content.second.c_str());
|
|
|
|
}
|
2017-02-27 01:45:06 +00:00
|
|
|
// Don't force because the config plugin may have started services.
|
2016-03-19 02:37:11 +00:00
|
|
|
Initializer::requestShutdown();
|
2017-05-31 02:22:41 +00:00
|
|
|
return Status();
|
2015-12-04 23:41:40 +00:00
|
|
|
}
|
2015-12-08 07:08:00 +00:00
|
|
|
status = update(response[0]);
|
2015-03-13 23:05:20 +00:00
|
|
|
}
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
|
2015-12-08 07:08:00 +00:00
|
|
|
loaded_ = true;
|
|
|
|
return status;
|
2014-12-11 01:35:21 +00:00
|
|
|
}
|
|
|
|
|
2017-07-17 18:38:21 +00:00
|
|
|
void Config::setRefresh(size_t refresh, size_t mod) {
|
|
|
|
refresh_runner_->refresh_ = refresh;
|
|
|
|
if (mod > 0) {
|
|
|
|
refresh_runner_->mod_ = mod;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Config::getRefresh() const {
|
|
|
|
return refresh_runner_->refresh_;
|
|
|
|
}
|
|
|
|
|
2017-02-27 01:45:06 +00:00
|
|
|
Status Config::load() {
|
|
|
|
valid_ = false;
|
|
|
|
auto config_plugin = RegistryFactory::get().getActive("config");
|
|
|
|
if (!RegistryFactory::get().exists("config", config_plugin)) {
|
|
|
|
return Status(1, "Missing config plugin " + config_plugin);
|
|
|
|
}
|
|
|
|
|
2017-05-29 21:09:44 +00:00
|
|
|
// Set the initial and optional refresh value.
|
2017-07-17 18:38:21 +00:00
|
|
|
setRefresh(FLAGS_config_refresh);
|
2017-07-18 05:28:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the initial configuration includes a non-0 refresh, start an
|
|
|
|
* additional service that sleeps and periodically regenerates the
|
|
|
|
* configuration.
|
|
|
|
*/
|
|
|
|
if (!FLAGS_config_check && !started_thread_ && getRefresh() > 0) {
|
|
|
|
Dispatcher::addService(refresh_runner_);
|
|
|
|
started_thread_ = true;
|
|
|
|
}
|
|
|
|
|
2017-02-27 01:45:06 +00:00
|
|
|
return refresh();
|
|
|
|
}
|
|
|
|
|
2016-11-22 17:35:03 +00:00
|
|
|
void stripConfigComments(std::string& json) {
|
2015-12-04 18:07:38 +00:00
|
|
|
std::string sink;
|
2016-11-19 23:01:40 +00:00
|
|
|
|
|
|
|
boost::replace_all(json, "\\\n", "");
|
2015-12-04 18:07:38 +00:00
|
|
|
for (auto& line : osquery::split(json, "\n")) {
|
|
|
|
boost::trim(line);
|
|
|
|
if (line.size() > 0 && line[0] == '#') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (line.size() > 1 && line[0] == '/' && line[1] == '/') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sink += line + '\n';
|
|
|
|
}
|
|
|
|
json = sink;
|
|
|
|
}
|
|
|
|
|
2016-02-11 04:08:34 +00:00
|
|
|
Status Config::updateSource(const std::string& source,
|
|
|
|
const std::string& json) {
|
2015-12-04 23:41:40 +00:00
|
|
|
// Compute a 'synthesized' hash using the content before it is parsed.
|
2017-05-31 02:22:41 +00:00
|
|
|
if (!hashSource(source, json)) {
|
|
|
|
// This source did not change, the returned status allows the caller to
|
|
|
|
// choose to reconfigure if any sources had changed.
|
|
|
|
return Status(2);
|
|
|
|
}
|
2015-10-26 08:14:51 +00:00
|
|
|
|
2017-01-11 08:05:01 +00:00
|
|
|
{
|
|
|
|
RecursiveLock lock(config_schedule_mutex_);
|
|
|
|
// Remove all packs from this source.
|
|
|
|
schedule_->removeAll(source);
|
|
|
|
// Remove all files from this source.
|
|
|
|
removeFiles(source);
|
|
|
|
}
|
2016-01-09 00:45:51 +00:00
|
|
|
|
2018-01-21 01:58:01 +00:00
|
|
|
// load the config (source.second) into a JSON object.
|
|
|
|
auto doc = JSON::newObject();
|
|
|
|
auto clone = json;
|
|
|
|
stripConfigComments(clone);
|
|
|
|
|
|
|
|
if (!doc.fromString(clone) || !doc.doc().IsObject()) {
|
2015-10-26 08:14:51 +00:00
|
|
|
return Status(1, "Error parsing the config JSON");
|
|
|
|
}
|
|
|
|
|
|
|
|
// extract the "schedule" key and store it as the main pack
|
2017-01-07 20:21:35 +00:00
|
|
|
auto& rf = RegistryFactory::get();
|
2018-01-21 01:58:01 +00:00
|
|
|
if (doc.doc().HasMember("schedule") && !rf.external()) {
|
|
|
|
auto& schedule = doc.doc()["schedule"];
|
|
|
|
if (schedule.IsObject()) {
|
|
|
|
auto main_doc = JSON::newObject();
|
|
|
|
auto queries_obj = main_doc.getObject();
|
|
|
|
main_doc.copyFrom(schedule, queries_obj);
|
|
|
|
main_doc.add("queries", queries_obj);
|
|
|
|
addPack("main", source, main_doc.doc());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doc.doc().HasMember("scheduledQueries") && !rf.external()) {
|
|
|
|
auto& schedule = doc.doc()["scheduledQueries"];
|
|
|
|
if (schedule.IsArray()) {
|
|
|
|
auto queries_doc = JSON::newObject();
|
|
|
|
auto queries_obj = queries_doc.getObject();
|
|
|
|
|
|
|
|
for (auto& query : schedule.GetArray()) {
|
2018-04-13 14:10:53 +00:00
|
|
|
if (!query.IsObject()) {
|
|
|
|
// This is a legacy structure, and it is malformed.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string query_name;
|
|
|
|
if (query.HasMember("name") && query["name"].IsString()) {
|
|
|
|
query_name = query["name"].GetString();
|
|
|
|
}
|
2018-01-21 01:58:01 +00:00
|
|
|
if (query_name.empty()) {
|
|
|
|
return Status(1, "Error getting name from legacy scheduled query");
|
|
|
|
}
|
|
|
|
queries_doc.add(query_name, query, queries_obj);
|
2015-10-26 08:14:51 +00:00
|
|
|
}
|
2018-01-21 01:58:01 +00:00
|
|
|
|
|
|
|
queries_doc.add("queries", queries_obj);
|
|
|
|
addPack("legacy_main", source, queries_doc.doc());
|
2015-10-26 08:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// extract the "packs" key into additional pack objects
|
2018-01-21 01:58:01 +00:00
|
|
|
if (doc.doc().HasMember("packs") && !rf.external()) {
|
|
|
|
auto& packs = doc.doc()["packs"];
|
|
|
|
if (packs.IsObject()) {
|
|
|
|
for (const auto& pack : packs.GetObject()) {
|
|
|
|
std::string pack_name = pack.name.GetString();
|
|
|
|
if (pack.value.IsObject()) {
|
|
|
|
// The pack is a JSON object, treat the content as pack data.
|
|
|
|
addPack(pack_name, source, pack.value);
|
|
|
|
} else if (pack.value.IsString()) {
|
|
|
|
genPack(pack_name, source, pack.value.GetString());
|
|
|
|
}
|
2015-10-26 08:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-21 01:58:01 +00:00
|
|
|
applyParsers(source, doc.doc(), false);
|
|
|
|
return Status();
|
2016-01-09 00:45:51 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 04:08:34 +00:00
|
|
|
Status Config::genPack(const std::string& name,
|
|
|
|
const std::string& source,
|
|
|
|
const std::string& target) {
|
|
|
|
// If the pack value is a string (and not a JSON object) then it is a
|
|
|
|
// resource to be handled by the config plugin.
|
|
|
|
PluginResponse response;
|
|
|
|
PluginRequest request = {
|
|
|
|
{"action", "genPack"}, {"name", name}, {"value", target}};
|
|
|
|
Registry::call("config", request, response);
|
|
|
|
|
|
|
|
if (response.size() == 0 || response[0].count(name) == 0) {
|
|
|
|
return Status(1, "Invalid plugin response");
|
|
|
|
}
|
|
|
|
|
2018-01-21 01:58:01 +00:00
|
|
|
auto clone = response[0][name];
|
|
|
|
if (clone.empty()) {
|
|
|
|
LOG(WARNING) << "Error reading the query pack named: " << name;
|
|
|
|
return Status();
|
|
|
|
}
|
|
|
|
|
|
|
|
stripConfigComments(clone);
|
|
|
|
auto doc = JSON::newObject();
|
|
|
|
if (!doc.fromString(clone) || !doc.doc().IsObject()) {
|
|
|
|
LOG(WARNING) << "Error parsing the \"" << name << "\" pack JSON";
|
|
|
|
} else {
|
|
|
|
addPack(name, source, doc.doc());
|
2016-02-11 04:08:34 +00:00
|
|
|
}
|
2018-01-21 01:58:01 +00:00
|
|
|
|
|
|
|
return Status();
|
2016-02-11 04:08:34 +00:00
|
|
|
}
|
|
|
|
|
2016-01-09 00:45:51 +00:00
|
|
|
void Config::applyParsers(const std::string& source,
|
2018-01-21 01:58:01 +00:00
|
|
|
const rj::Value& obj,
|
2016-01-09 00:45:51 +00:00
|
|
|
bool pack) {
|
2018-01-21 01:58:01 +00:00
|
|
|
assert(obj.IsObject());
|
|
|
|
|
2015-12-08 07:08:00 +00:00
|
|
|
// Iterate each parser.
|
2017-01-11 08:05:01 +00:00
|
|
|
RecursiveLock lock(config_schedule_mutex_);
|
2017-01-07 20:21:35 +00:00
|
|
|
for (const auto& plugin : RegistryFactory::get().plugins("config_parser")) {
|
2015-12-04 23:41:40 +00:00
|
|
|
std::shared_ptr<ConfigParserPlugin> parser = nullptr;
|
2015-10-26 08:14:51 +00:00
|
|
|
try {
|
|
|
|
parser = std::dynamic_pointer_cast<ConfigParserPlugin>(plugin.second);
|
2016-09-02 22:04:03 +00:00
|
|
|
} catch (const std::bad_cast& /* e */) {
|
2015-10-26 08:14:51 +00:00
|
|
|
LOG(ERROR) << "Error casting config parser plugin: " << plugin.first;
|
|
|
|
}
|
|
|
|
if (parser == nullptr || parser.get() == nullptr) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For each key requested by the parser, add a property tree reference.
|
2018-01-21 01:58:01 +00:00
|
|
|
std::map<std::string, JSON> parser_config;
|
2015-10-26 08:14:51 +00:00
|
|
|
for (const auto& key : parser->keys()) {
|
2018-02-11 09:16:38 +00:00
|
|
|
if (obj.HasMember(key) && !obj[key].IsNull()) {
|
2018-04-13 14:10:53 +00:00
|
|
|
if (!obj[key].IsArray() && !obj[key].IsObject()) {
|
|
|
|
LOG(WARNING) << "Error config " << key
|
|
|
|
<< " should be an array or object";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-01-21 01:58:01 +00:00
|
|
|
auto doc = JSON::newFromValue(obj[key]);
|
|
|
|
parser_config.emplace(std::make_pair(key, std::move(doc)));
|
2015-10-26 08:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// The config parser plugin will receive a copy of each property tree for
|
|
|
|
// each top-level-config key. The parser may choose to update the config's
|
|
|
|
// internal state
|
2016-01-09 00:45:51 +00:00
|
|
|
parser->update(source, parser_config);
|
2015-10-26 08:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
Status Config::update(const std::map<std::string, std::string>& config) {
|
|
|
|
// A config plugin may call update from an extension. This will update
|
|
|
|
// the config instance within the extension process and the update must be
|
|
|
|
// reflected in the core.
|
2017-01-07 20:21:35 +00:00
|
|
|
if (RegistryFactory::get().external()) {
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
for (const auto& source : config) {
|
|
|
|
PluginRequest request = {
|
|
|
|
{"action", "update"},
|
|
|
|
{"source", source.first},
|
|
|
|
{"data", source.second},
|
|
|
|
};
|
|
|
|
// A "update" registry item within core should call the core's update
|
|
|
|
// method. The config plugin call action handling must also know to
|
|
|
|
// update.
|
|
|
|
Registry::call("config", "update", request);
|
2015-04-30 01:53:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-07 19:58:53 +00:00
|
|
|
// Iterate though each source and overwrite config data.
|
|
|
|
// This will add/overwrite pack data, append to the schedule, change watched
|
|
|
|
// files, set options, etc.
|
|
|
|
// Before this occurs, take an opportunity to purge stale state.
|
|
|
|
purge();
|
|
|
|
|
2017-05-31 02:22:41 +00:00
|
|
|
bool needs_reconfigure = false;
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
for (const auto& source : config) {
|
2015-10-26 08:14:51 +00:00
|
|
|
auto status = updateSource(source.first, source.second);
|
2017-05-31 02:22:41 +00:00
|
|
|
if (status.getCode() == 2) {
|
2017-07-17 18:38:21 +00:00
|
|
|
// The source content did not change.
|
2017-05-31 02:22:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-10-26 08:14:51 +00:00
|
|
|
if (!status.ok()) {
|
2017-07-17 18:38:21 +00:00
|
|
|
// The content was not parsed correctly.
|
2015-10-26 08:14:51 +00:00
|
|
|
return status;
|
2015-05-21 20:42:45 +00:00
|
|
|
}
|
2017-05-31 02:22:41 +00:00
|
|
|
// If a source was updated and the content has changed, then the registry
|
|
|
|
// should be reconfigured. File watches may have changed, etc.
|
|
|
|
needs_reconfigure = true;
|
2015-05-21 20:42:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-31 02:22:41 +00:00
|
|
|
if (loaded_ && needs_reconfigure) {
|
2015-12-08 07:08:00 +00:00
|
|
|
// The config has since been loaded.
|
|
|
|
// This update call is most likely a response to an async update request
|
|
|
|
// from a config plugin. This request should request all plugins to update.
|
2017-01-07 20:21:35 +00:00
|
|
|
for (const auto& registry : RegistryFactory::get().all()) {
|
2015-12-08 07:08:00 +00:00
|
|
|
if (registry.first == "event_publisher" ||
|
|
|
|
registry.first == "event_subscriber") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
registry.second->configure();
|
|
|
|
}
|
|
|
|
|
2017-03-21 05:03:09 +00:00
|
|
|
EventFactory::configUpdate();
|
2015-12-08 07:08:00 +00:00
|
|
|
}
|
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
return Status(0, "OK");
|
2015-05-21 20:42:45 +00:00
|
|
|
}
|
|
|
|
|
2015-12-07 19:58:53 +00:00
|
|
|
void Config::purge() {
|
|
|
|
// The first use of purge is removing expired query results.
|
|
|
|
std::vector<std::string> saved_queries;
|
|
|
|
scanDatabaseKeys(kQueries, saved_queries);
|
|
|
|
|
|
|
|
const auto& schedule = this->schedule_;
|
|
|
|
auto queryExists = [&schedule](const std::string& query_name) {
|
2015-12-09 23:01:20 +00:00
|
|
|
for (const auto& pack : schedule->packs_) {
|
2016-02-06 01:10:35 +00:00
|
|
|
const auto& pack_queries = pack->getSchedule();
|
2015-12-07 19:58:53 +00:00
|
|
|
if (pack_queries.count(query_name)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock lock(config_schedule_mutex_);
|
2015-12-07 19:58:53 +00:00
|
|
|
// Iterate over each result set in the database.
|
|
|
|
for (const auto& saved_query : saved_queries) {
|
|
|
|
if (queryExists(saved_query)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string content;
|
|
|
|
getDatabaseValue(kPersistentSettings, "timestamp." + saved_query, content);
|
|
|
|
if (content.empty()) {
|
|
|
|
// No timestamp is set for this query, perhaps this is the first time
|
|
|
|
// query results expiration is applied.
|
|
|
|
setDatabaseValue(kPersistentSettings,
|
|
|
|
"timestamp." + saved_query,
|
|
|
|
std::to_string(getUnixTime()));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the timestamp and compare.
|
|
|
|
size_t last_executed = 0;
|
|
|
|
try {
|
|
|
|
last_executed = boost::lexical_cast<size_t>(content);
|
2016-09-02 22:04:03 +00:00
|
|
|
} catch (const boost::bad_lexical_cast& /* e */) {
|
2015-12-07 19:58:53 +00:00
|
|
|
// Erase the timestamp as is it potentially corrupt.
|
|
|
|
deleteDatabaseValue(kPersistentSettings, "timestamp." + saved_query);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last_executed < getUnixTime() - 592200) {
|
|
|
|
// Query has not run in the last week, expire results and interval.
|
|
|
|
deleteDatabaseValue(kQueries, saved_query);
|
2017-07-08 00:56:03 +00:00
|
|
|
deleteDatabaseValue(kQueries, saved_query + "epoch");
|
2015-12-07 19:58:53 +00:00
|
|
|
deleteDatabaseValue(kPersistentSettings, "interval." + saved_query);
|
|
|
|
deleteDatabaseValue(kPersistentSettings, "timestamp." + saved_query);
|
|
|
|
VLOG(1) << "Expiring results for scheduled query: " << saved_query;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 04:08:34 +00:00
|
|
|
void Config::reset() {
|
2017-06-14 00:26:34 +00:00
|
|
|
setStartTime(getUnixTime());
|
|
|
|
|
2016-02-11 04:08:34 +00:00
|
|
|
schedule_ = std::make_shared<Schedule>();
|
|
|
|
std::map<std::string, QueryPerformance>().swap(performance_);
|
|
|
|
std::map<std::string, FileCategories>().swap(files_);
|
|
|
|
std::map<std::string, std::string>().swap(hash_);
|
|
|
|
valid_ = false;
|
|
|
|
loaded_ = false;
|
2016-04-12 20:06:02 +00:00
|
|
|
|
2017-07-18 05:28:11 +00:00
|
|
|
refresh_runner_ = std::make_shared<ConfigRefreshRunner>();
|
|
|
|
started_thread_ = false;
|
|
|
|
|
2016-04-12 20:06:02 +00:00
|
|
|
// Also request each parse to reset state.
|
2017-01-07 20:21:35 +00:00
|
|
|
for (const auto& plugin : RegistryFactory::get().plugins("config_parser")) {
|
2016-04-12 20:06:02 +00:00
|
|
|
std::shared_ptr<ConfigParserPlugin> parser = nullptr;
|
|
|
|
try {
|
|
|
|
parser = std::dynamic_pointer_cast<ConfigParserPlugin>(plugin.second);
|
2016-09-02 22:04:03 +00:00
|
|
|
} catch (const std::bad_cast& /* e */) {
|
2016-04-12 20:06:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (parser == nullptr || parser.get() == nullptr) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
parser->reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConfigParserPlugin::reset() {
|
|
|
|
// Resets will clear all top-level keys from the parser's data store.
|
2018-01-21 01:58:01 +00:00
|
|
|
for (auto& category : data_.doc().GetObject()) {
|
|
|
|
auto obj = data_.getObject();
|
|
|
|
data_.add(category.name.GetString(), obj, data_.doc());
|
2016-04-12 20:06:02 +00:00
|
|
|
}
|
2016-02-11 04:08:34 +00:00
|
|
|
}
|
|
|
|
|
2015-04-30 01:53:25 +00:00
|
|
|
void Config::recordQueryPerformance(const std::string& name,
|
|
|
|
size_t delay,
|
|
|
|
size_t size,
|
|
|
|
const Row& r0,
|
|
|
|
const Row& r1) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock lock(config_performance_mutex_);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
if (performance_.count(name) == 0) {
|
|
|
|
performance_[name] = QueryPerformance();
|
2015-04-30 01:53:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Grab access to the non-const schedule item.
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
auto& query = performance_.at(name);
|
2015-11-03 23:36:46 +00:00
|
|
|
BIGINT_LITERAL diff = 0;
|
|
|
|
if (!r1.at("user_time").empty() && !r0.at("user_time").empty()) {
|
|
|
|
diff = AS_LITERAL(BIGINT_LITERAL, r1.at("user_time")) -
|
|
|
|
AS_LITERAL(BIGINT_LITERAL, r0.at("user_time"));
|
|
|
|
if (diff > 0) {
|
|
|
|
query.user_time += diff;
|
|
|
|
}
|
2015-06-12 21:09:42 +00:00
|
|
|
}
|
|
|
|
|
2015-11-03 23:36:46 +00:00
|
|
|
if (!r1.at("system_time").empty() && !r0.at("system_time").empty()) {
|
|
|
|
diff = AS_LITERAL(BIGINT_LITERAL, r1.at("system_time")) -
|
|
|
|
AS_LITERAL(BIGINT_LITERAL, r0.at("system_time"));
|
|
|
|
if (diff > 0) {
|
|
|
|
query.system_time += diff;
|
|
|
|
}
|
2015-06-12 21:09:42 +00:00
|
|
|
}
|
|
|
|
|
2015-11-03 23:36:46 +00:00
|
|
|
if (!r1.at("resident_size").empty() && !r0.at("resident_size").empty()) {
|
|
|
|
diff = AS_LITERAL(BIGINT_LITERAL, r1.at("resident_size")) -
|
|
|
|
AS_LITERAL(BIGINT_LITERAL, r0.at("resident_size"));
|
|
|
|
if (diff > 0) {
|
|
|
|
// Memory is stored as an average of RSS changes between query executions.
|
|
|
|
query.average_memory = (query.average_memory * query.executions) + diff;
|
|
|
|
query.average_memory = (query.average_memory / (query.executions + 1));
|
|
|
|
}
|
2015-06-12 21:09:42 +00:00
|
|
|
}
|
|
|
|
|
2015-04-30 01:53:25 +00:00
|
|
|
query.wall_time += delay;
|
|
|
|
query.output_size += size;
|
|
|
|
query.executions += 1;
|
2015-11-02 18:33:20 +00:00
|
|
|
query.last_executed = getUnixTime();
|
2015-09-17 06:31:07 +00:00
|
|
|
|
|
|
|
// Clear the executing query (remove the dirty bit).
|
|
|
|
setDatabaseValue(kPersistentSettings, kExecutingQuery, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::recordQueryStart(const std::string& name) {
|
|
|
|
// There should only ever be a single executing query in the schedule.
|
|
|
|
setDatabaseValue(kPersistentSettings, kExecutingQuery, name);
|
2015-12-07 19:58:53 +00:00
|
|
|
// Store the time this query name last executed for later results eviction.
|
|
|
|
// When configuration updates occur the previous schedule is searched for
|
|
|
|
// 'stale' query names, aka those that have week-old or longer last execute
|
|
|
|
// timestamps. Offending queries have their database results purged.
|
|
|
|
setDatabaseValue(
|
|
|
|
kPersistentSettings, "timestamp." + name, std::to_string(getUnixTime()));
|
2015-04-30 01:53:25 +00:00
|
|
|
}
|
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
void Config::getPerformanceStats(
|
|
|
|
const std::string& name,
|
|
|
|
std::function<void(const QueryPerformance& query)> predicate) {
|
|
|
|
if (performance_.count(name) > 0) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock lock(config_performance_mutex_);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
predicate(performance_.at(name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-31 02:22:41 +00:00
|
|
|
bool Config::hashSource(const std::string& source, const std::string& content) {
|
|
|
|
auto new_hash = getBufferSHA1(content.c_str(), content.size());
|
|
|
|
|
2015-09-03 18:43:36 +00:00
|
|
|
WriteLock wlock(config_hash_mutex_);
|
2017-05-31 02:22:41 +00:00
|
|
|
if (hash_[source] == new_hash) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
hash_[source] = new_hash;
|
|
|
|
return true;
|
2015-09-03 18:43:36 +00:00
|
|
|
}
|
|
|
|
|
2016-12-22 08:37:59 +00:00
|
|
|
Status Config::genHash(std::string& hash) {
|
2017-05-29 09:06:57 +00:00
|
|
|
WriteLock lock(config_hash_mutex_);
|
2015-09-30 17:50:28 +00:00
|
|
|
if (!valid_) {
|
2015-09-03 18:43:36 +00:00
|
|
|
return Status(1, "Current config is not valid");
|
|
|
|
}
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
|
2015-09-03 18:43:36 +00:00
|
|
|
std::vector<char> buffer;
|
|
|
|
buffer.reserve(hash_.size() * 32);
|
|
|
|
auto add = [&buffer](const std::string& text) {
|
|
|
|
for (const auto& c : text) {
|
|
|
|
buffer.push_back(c);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
2015-09-03 18:43:36 +00:00
|
|
|
};
|
2015-12-07 19:58:53 +00:00
|
|
|
for (const auto& it : hash_) {
|
2015-09-03 18:43:36 +00:00
|
|
|
add(it.second);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
2016-12-22 08:37:59 +00:00
|
|
|
hash = getBufferSHA1(buffer.data(), buffer.size());
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
2017-07-17 18:38:21 +00:00
|
|
|
std::string Config::getHash(const std::string& source) const {
|
|
|
|
WriteLock lock(config_hash_mutex_);
|
|
|
|
if (!hash_.count(source)) {
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
return hash_.at(source);
|
|
|
|
}
|
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
const std::shared_ptr<ConfigParserPlugin> Config::getParser(
|
|
|
|
const std::string& parser) {
|
2017-01-07 20:21:35 +00:00
|
|
|
if (!RegistryFactory::get().exists("config_parser", parser, true)) {
|
2016-03-05 17:29:51 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-01-07 20:21:35 +00:00
|
|
|
auto plugin = RegistryFactory::get().plugin("config_parser", parser);
|
2017-05-29 21:09:44 +00:00
|
|
|
// This is an error, need to check for existence (and not nullptr).
|
2016-03-05 17:29:51 +00:00
|
|
|
return std::dynamic_pointer_cast<ConfigParserPlugin>(plugin);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Config::files(
|
|
|
|
std::function<void(const std::string& category,
|
|
|
|
const std::vector<std::string>& files)> predicate) {
|
2016-03-27 04:52:22 +00:00
|
|
|
RecursiveLock lock(config_files_mutex_);
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
for (const auto& it : files_) {
|
2015-12-08 07:08:00 +00:00
|
|
|
for (const auto& category : it.second) {
|
|
|
|
predicate(category.first, category.second);
|
|
|
|
}
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Status ConfigPlugin::genPack(const std::string& name,
|
|
|
|
const std::string& value,
|
|
|
|
std::string& pack) {
|
|
|
|
return Status(1, "Not implemented");
|
|
|
|
}
|
|
|
|
|
2015-01-30 18:44:25 +00:00
|
|
|
Status ConfigPlugin::call(const PluginRequest& request,
|
|
|
|
PluginResponse& response) {
|
2018-02-22 01:52:35 +00:00
|
|
|
auto action = request.find("action");
|
|
|
|
if (action == request.end()) {
|
|
|
|
return Status(1, "Config plugins require an action");
|
2015-01-30 18:44:25 +00:00
|
|
|
}
|
|
|
|
|
2018-02-22 01:52:35 +00:00
|
|
|
if (action->second == "genConfig") {
|
2015-03-13 23:05:20 +00:00
|
|
|
std::map<std::string, std::string> config;
|
|
|
|
auto stat = genConfig(config);
|
|
|
|
response.push_back(config);
|
|
|
|
return stat;
|
2018-02-22 01:52:35 +00:00
|
|
|
} else if (action->second == "genPack") {
|
|
|
|
auto name = request.find("name");
|
|
|
|
auto value = request.find("value");
|
|
|
|
if (name == request.end() || value == request.end()) {
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
return Status(1, "Missing name or value");
|
|
|
|
}
|
2018-02-22 01:52:35 +00:00
|
|
|
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
std::string pack;
|
2018-02-22 01:52:35 +00:00
|
|
|
auto stat = genPack(name->second, value->second, pack);
|
|
|
|
response.push_back({{name->second, pack}});
|
[fix #1390] query pack re-org
This commit contains the features specified in #1390 as well as a
refactoring of the general osquery configuration code.
The API for the config plugins hasn't changed, although now there's a
`genPack` method that config plugins can implement. If a plugin doesn't
implement `genPack`, then the map<string, string> format cannot be used.
The default config plugin, the filesystem plugin, now implements
`genPack`, so existing query packs code will continue to work as it
always has.
Now many other config plugins can implement custom pack handling for
what makes sense in their context. `genPacks` is not a pure virtual, so
it doesn't have to be implemented in your plugin if you don't want to
use it. Also, more importantly, all config plugins can use the standard
inline pack format if they want to use query packs. Which is awesome.
For more information, refer to #1390, the documentation and the doxygen
comments included with this pull requests, as well as the following
example config which is now supported, regardless of what config plugin
you're using:
```json
{
"options": {
"enable_monitor": "true"
},
"packs": {
"core_os_monitoring": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"kernel_modules": {
"query": "SELECT name, size FROM kernel_modules;",
"interval": 600
},
"system_controls": {
"query": "SELECT * FROM system_controls;",
"interval": 600,
"snapshot": true,
},
"usb_devices": {
"query": "SELECT * FROM usb_devices;",
"interval": 600
}
}
},
"osquery_internal_info": {
"version": "1.4.5",
"discovery": [
"select pid from processes where name like '%osqueryd%';"
],
"queries": {
"info": {
"query": "select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;",
"interval": 60,
"snapshot": true
},
"registry": {
"query": "SELECT * FROM osquery_registry;",
"interval": 600,
"snapshot": true
},
"schedule": {
"query": "select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory from osquery_schedule;",
"interval": 60,
"snapshot": true
}
}
}
}
}
```
The `osquery_packs` table was modified to remove the superfluous
columns which could already have been found in `osquery_schedule`. Two
more columns were added in their place, representing stats about pack's
discovery query execution history.
Notably, the internal API for the `osquery::Config` class has changed
rather dramatically as apart of the refactoring. We think this is an
improvement. While strictly adhering to the osquery config plugin
interface will have avoided any compatibility errors, advanced users may
notice compilation errors if they access config data directly. All
internal users of the config have obviously been updated. Yet another
reason to merge your code into mainline; we update it for you when we
refactor!
2015-08-19 20:27:49 +00:00
|
|
|
return stat;
|
2018-02-22 01:52:35 +00:00
|
|
|
} else if (action->second == "update") {
|
|
|
|
auto source = request.find("source");
|
|
|
|
auto data = request.find("data");
|
|
|
|
if (source == request.end() || data == request.end()) {
|
2015-03-25 03:59:28 +00:00
|
|
|
return Status(1, "Missing source or data");
|
|
|
|
}
|
2018-02-22 01:52:35 +00:00
|
|
|
|
|
|
|
return Config::get().update({{source->second, data->second}});
|
|
|
|
} else if (action->second == "option") {
|
|
|
|
auto name = request.find("name");
|
|
|
|
if (name == request.end()) {
|
|
|
|
return Status(1, "Missing option name");
|
|
|
|
}
|
|
|
|
|
|
|
|
response.push_back(
|
|
|
|
{{"name", name->second}, {"value", Flag::getValue(name->second)}});
|
|
|
|
return Status();
|
2015-01-30 18:44:25 +00:00
|
|
|
}
|
2018-02-22 01:52:35 +00:00
|
|
|
return Status(1, "Config plugin action unknown: " + action->second);
|
2015-01-30 18:44:25 +00:00
|
|
|
}
|
2015-03-22 21:58:00 +00:00
|
|
|
|
2015-04-14 07:57:22 +00:00
|
|
|
Status ConfigParserPlugin::setUp() {
|
|
|
|
for (const auto& key : keys()) {
|
2018-01-21 01:58:01 +00:00
|
|
|
auto obj = data_.getObject();
|
|
|
|
data_.add(key, obj);
|
2015-04-14 07:57:22 +00:00
|
|
|
}
|
2018-01-21 01:58:01 +00:00
|
|
|
return Status();
|
2015-04-14 07:57:22 +00:00
|
|
|
}
|
2017-02-27 01:45:06 +00:00
|
|
|
|
|
|
|
void ConfigRefreshRunner::start() {
|
|
|
|
while (!interrupted()) {
|
|
|
|
// Cool off and time wait the configured period.
|
|
|
|
// Apply this interruption initially as at t=0 the config was read.
|
2017-05-29 21:09:44 +00:00
|
|
|
pauseMilli(refresh_ * mod_);
|
2017-02-27 01:45:06 +00:00
|
|
|
// Since the pause occurs before the logic, we need to check for an
|
|
|
|
// interruption request.
|
|
|
|
if (interrupted()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VLOG(1) << "Refreshing configuration state";
|
2017-05-29 06:04:53 +00:00
|
|
|
Config::get().refresh();
|
2017-02-27 01:45:06 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-15 07:25:30 +00:00
|
|
|
}
|