Changing flag infra, reducing config testing, adding debug macro

This commit is contained in:
Teddy Reed 2014-10-27 09:34:13 -07:00
parent 16c1fa68ba
commit 6d50d762ce
12 changed files with 166 additions and 135 deletions

View File

@ -9,6 +9,10 @@ all:
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) && cmake ../.. && make --no-print-directory $(MAKEFLAGS)
debug:
mkdir -p $(BUILD_DIR)
cd $(BUILD_DIR) && cmake -DCMAKE_BUILD_TYPE=Debug ../../ && make --no-print-directory $(MAKEFLAGS)
deps:
./tools/provision.sh

View File

@ -15,6 +15,8 @@ namespace osquery {
* @brief The version of osquery
*/
extern const std::string kVersion;
/// Use a macro for the version literal, set the kVersion symbol in the library.
#define VERSION "0.0.2"
/**
* @brief Execute a query

79
include/osquery/flags.h Normal file
View File

@ -0,0 +1,79 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <boost/make_shared.hpp>
#include <gflags/gflags.h>
#include "osquery/registry.h"
namespace osquery {
typedef std::pair<std::string, std::string> FlagDetail;
/**
* @brief A small tracking wrapper for options, binary flags.
*
* The osquery-specific gflags-like options define macro `DEFINE_osquery_flag`
* uses a Flag instance to track the options data.
*/
class Flag {
public:
/*
* @brief the instance accessor, but also can register flag data.
*
* @param name The 'name' or the options switch data.
* @param value The default value for this flag.
* @param desc The description printed to the screen during help.
*/
static Flag& get(const std::string& name = "",
const std::string& value = "",
const std::string& desc = "") {
static Flag f;
if (name != "") {
f.add(name, value, desc);
}
return f;
}
/*
* @brief Wrapper by the Flag::get.
*
* @param name The 'name' or the options switch data.
* @param value The default value for this flag.
* @param desc The description printed to the screen during help.
*/
void add(const std::string& name,
const std::string& value,
const std::string& desc) {
flags_.insert(std::make_pair(name, std::make_pair(value, desc)));
}
private:
/// Keep the ctor private, for accessing through `add` wrapper.
Flag() {}
public:
/// The public flags instance, usable when parsing `--help`.
std::map<std::string, FlagDetail> flags() { return flags_; }
private:
/// The private simple map of name to value/desc flag data.
std::map<std::string, FlagDetail> flags_;
};
}
/*
* @brief Replace gflags' `DEFINE_type` macros to track osquery flags.
*
* @param type The `_type` symbol portion of the gflags define.
* @param name The name symbol passed to gflags' `DEFINE_type`.
* @param value The default value, use a C++ literal.
* @param desc A string literal used for help display.
*/
#define DEFINE_osquery_flag(type, name, value, desc) \
DEFINE_##type(name, value, desc); \
namespace flag_##name { \
Flag flag = Flag::get(#name, #value, #desc); \
}

View File

@ -1,8 +1,5 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "osquery/config.h"
#include "osquery/config/plugin.h"
#include <algorithm>
#include <future>
#include <sstream>
@ -16,6 +13,9 @@
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "osquery/config.h"
#include "osquery/config/plugin.h"
#include "osquery/flags.h"
#include "osquery/status.h"
using osquery::Status;
@ -24,11 +24,10 @@ namespace pt = boost::property_tree;
namespace osquery {
const std::string kDefaultConfigRetriever = "filesystem";
DEFINE_string(config_retriever,
kDefaultConfigRetriever,
"The config mechanism to retrieve config content via.");
DEFINE_osquery_flag(string,
config_retriever,
"filesystem",
"The config mechanism to retrieve config content via.");
boost::shared_mutex rw_lock;

View File

@ -24,6 +24,9 @@ TEST_F(ConfigTests, test_queries_execute) {
int err;
auto r = query(i.query, err);
EXPECT_EQ(err, 0);
// At most query one shceduled query from the config.
break;
}
}

View File

@ -1,17 +1,21 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "osquery/config/plugin.h"
#include <fstream>
#include <boost/filesystem/operations.hpp>
#include "osquery/config/plugin.h"
#include "osquery/flags.h"
namespace fs = boost::filesystem;
using osquery::Status;
namespace osquery {
DEFINE_string(config_path, "/var/osquery/osquery.conf", "Path to config file");
DEFINE_osquery_flag(string,
config_path,
"/var/osquery/osquery.conf",
"Path to config file");
class FilesystemConfigPlugin : public ConfigPlugin {
public:

View File

@ -1,116 +1,46 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "osquery/core.h"
#include <iostream>
#include <unistd.h>
#include <boost/algorithm/string/predicate.hpp>
#include "osquery/flags.h"
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "osquery/core.h"
#include "osquery/database.h"
#include "osquery/registry.h"
using namespace boost::algorithm;
namespace osquery {
const std::string kDefaultHelp = R"(
osquery
--help, -h print help message
)";
const std::string kOsquerydHelp = R"(
osqueryd
--help, -h Print help and usage information
--config_retriever The config plugin to use (ex: filesystem, http)
Default: filesystem
--config_path If using the filesystem config plugin, the path where
your osquery JSON config file can be found
Default: /var/osquery/osquery.conf
--log_receiver The logger plugin to use (ex: filesystem, scribe)
Default: filesystem
--log_dir The directory which you would like to store your
output logs
Default: /var/log/osquery/
-v Increase output verbosity
Example: -v=3
)";
const std::map<std::string, std::string> kHelpMessages = {
{"osqueryd", kOsquerydHelp},
};
const std::string kDefaultLogDir = "/var/log/osquery/";
const std::string kDescription = "your operating system as a high-performance "
"relational database";
const std::string kEpilog = "osquery project page <http://osquery.io>.";
char *stringToChar(const std::string &s) {
char *pc = new char[s.size() + 1];
std::strcpy(pc, s.c_str());
return pc;
}
void printHelp(char *argv0) {
auto bits = split(std::string(argv0), "/");
auto program_name = bits[bits.size() - 1];
for (const auto &it : kHelpMessages) {
if (it.first == program_name) {
std::cout << it.second << std::endl;
return;
}
}
// this should only be reached if the binary name didn't match any of the
// presets
std::cout << kDefaultHelp << std::endl;
}
void printHelpAndExit(char *argv0, int code) {
printHelp(argv0);
exit(code);
}
// gflags help is pretty ugly, so let's intercept calls to "--help" and the
// like so that we can proactively print prettier help messages
std::pair<int, char **> parseCommandLineFlags(int argc, char **argv) {
std::vector<std::string> new_args;
for (int i = 0; i < argc; ++i) {
std::string arg(argv[i]);
if (contains(arg, "help")) {
// this will match "--help", "-help", "help" and pretty much every string
// that has the word "help" in it. beware of this if you try to create
// and argument called something like "--foo-help"
printHelpAndExit(argv[0], 0);
} else if (starts_with(arg, "-") && ends_with(arg, "-h")) {
// this will match "-h" and "--h", but be aware that it was also match
// args like "--foo-h"
printHelpAndExit(argv[0], 0);
} else {
// the argument wasn't a flag that we want to intercept, so pass it to
// glog
new_args.push_back(arg);
}
}
int new_argc = (int)new_args.size();
std::vector<char *> char_vector;
std::transform(new_args.begin(),
new_args.end(),
std::back_inserter(char_vector),
stringToChar);
char **new_argv = (char **)new char(new_argc + 1);
for (int i = 0; i < char_vector.size(); ++i) {
new_argv[i] = char_vector[i];
}
return std::make_pair(new_argc, new_argv);
static const char* basename(const char* filename) {
const char* sep = strrchr(filename, '/');
return sep ? sep + 1 : filename;
}
void initOsquery(int argc, char *argv[]) {
if (argc > 1 && (std::string(argv[1]) == "--help" ||
std::string(argv[1]) == "-h")) {
// Parse help options before gflags. Only display osquery-related options.
fprintf(stdout, "osquery " VERSION ", %s\n", kDescription.c_str());
fprintf(stdout, "%s: [OPTION]...\n\n", basename(argv[0]));
fprintf(stdout, "The following options control the osquery "
"daemon and shell.\n\n");
auto flags = Flag::get().flags();
for (auto& flag : flags) {
fprintf(stdout, " --%s, --%s=VALUE\n %s (default: %s)\n",
flag.first.c_str(), flag.first.c_str(), flag.second.second.c_str(),
flag.second.first.c_str());
}
fprintf(stdout, "\n%s\n", kEpilog.c_str());
::exit(0);
}
FLAGS_alsologtostderr = true;
FLAGS_logbufsecs = 0; // flush the log buffer immediately
FLAGS_stop_logging_if_full_disk = true;
@ -121,8 +51,6 @@ void initOsquery(int argc, char *argv[]) {
google::InitGoogleLogging(argv[0]);
osquery::InitRegistry::get().run();
auto new_args = osquery::parseCommandLineFlags(argc, argv);
google::ParseCommandLineFlags(&new_args.first, &new_args.second, true);
try {
DBHandle::getInstance();
@ -130,5 +58,8 @@ void initOsquery(int argc, char *argv[]) {
LOG(ERROR) << "osquery failed to start: " << e.what();
::exit(1);
}
// Let gflags parse the non-help options/flags.
google::ParseCommandLineNonHelpFlags(&argc, &argv, true);
}
}

View File

@ -1,21 +1,21 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "osquery/dispatcher.h"
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "osquery/core/conversions.h"
#include "osquery/dispatcher.h"
#include "osquery/flags.h"
using namespace apache::thrift::concurrency;
namespace osquery {
const int kDefaultThreadPoolSize = 4;
DEFINE_int32(worker_threads,
kDefaultThreadPoolSize,
"The number of threads to use for the work dispatcher");
/// The worker_threads define the default thread pool size.
DEFINE_osquery_flag(int32,
worker_threads,
4,
"The number of threads to use for the work dispatcher");
Dispatcher& Dispatcher::getInstance() {
static Dispatcher d;

View File

@ -2,12 +2,12 @@
#include "osquery/filesystem.h"
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "osquery/core.h"
#include "osquery/core/darwin/test_util.h"
#include "osquery/flags.h"
using namespace osquery::core;
namespace pt = boost::property_tree;
@ -15,7 +15,7 @@ namespace pt = boost::property_tree;
namespace osquery {
// run this benchmark with --iterations=9001 to parse over 9000 property lists
DEFINE_int32(iterations, 100, "Iterations to execute");
DEFINE_osquery_flag(int32, iterations, 100, "Iterations to execute.");
class PlistBenchmark : public testing::Test {};

View File

@ -3,9 +3,9 @@
#include <algorithm>
#include <thread>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "osquery/flags.h"
#include "osquery/logger.h"
#include "osquery/logger/plugin.h"
@ -13,13 +13,16 @@ using osquery::Status;
namespace osquery {
const std::string kDefaultLogReceiverName = "filesystem";
/// `log_receiver` defines the default log receiver plugin name.
DEFINE_osquery_flag(string,
log_receiver,
"filesystem",
"The upstream log receiver to log messages to.");
DEFINE_string(log_receiver,
kDefaultLogReceiverName,
"The upstream log receiver to log messages to.");
DEFINE_bool(log_result_events, true, "Log scheduled results as events.");
DEFINE_osquery_flag(bool,
log_result_events,
true,
"Log scheduled results as events.");
Status logString(const std::string& s) {
return logString(s, FLAGS_log_receiver);

View File

@ -1,25 +1,29 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "osquery/logger/plugin.h"
#include <algorithm>
#include <thread>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <scribe/client/ScribeClient.h>
#include "osquery/flags.h"
#include "osquery/logger/plugin.h"
using osquery::Status;
namespace osquery {
DEFINE_string(
active_scribe_category,
"osquery",
"The path of the scribe category to be used if scribe logging is enabled.");
DEFINE_osquery_flag(string,
active_scribe_category,
"osquery",
"The path of the scribe category to be used if scribe "
"logging is enabled.");
DEFINE_bool(dev_machine, false, "Set to true if the machine is a dev machine.");
DEFINE_osquery_flag(bool,
dev_machine,
false,
"Set to true if the machine is a dev machine.");
class ScribeLoggerPlugin : public LoggerPlugin {
public:

View File

@ -2,7 +2,9 @@
#include <string>
#include "osquery/core.h"
namespace osquery {
const std::string kVersion = "0.0.1";
const std::string kVersion = VERSION;
}