Merge pull request #25 from draios/configuration

Configuration
This commit is contained in:
Henri DF 2016-04-12 16:15:30 -07:00
commit 4eef8c9647
7 changed files with 252 additions and 6 deletions

View File

@ -84,6 +84,19 @@ ExternalProject_Add(b64
BUILD_IN_SOURCE 1 BUILD_IN_SOURCE 1
INSTALL_COMMAND "") INSTALL_COMMAND "")
set(YAMLCPP_SRC "${PROJECT_BINARY_DIR}/yamlcpp-prefix/src/yamlcpp")
message(STATUS "Using bundled yaml-cpp in '${YAMLCPP_SRC}'")
set(YAMLCPP_LIB "${YAMLCPP_SRC}/libyaml-cpp.a")
set(YAMLCPP_INCLUDE_DIR "${YAMLCPP_SRC}/include")
# Once the next version of yaml-cpp is released (first version not requiring
# boost), we can switch to that and no longer pull from github.
ExternalProject_Add(yamlcpp
GIT_REPOSITORY "https://github.com/jbeder/yaml-cpp.git"
GIT_TAG "7d2873ce9f2202ea21b6a8c5ecbc9fe38032c229"
BUILD_IN_SOURCE 1
INSTALL_COMMAND "")
set(OPENSSL_BUNDLE_DIR "${PROJECT_BINARY_DIR}/openssl-prefix/src/openssl") set(OPENSSL_BUNDLE_DIR "${PROJECT_BINARY_DIR}/openssl-prefix/src/openssl")
set(OPENSSL_INSTALL_DIR "${OPENSSL_BUNDLE_DIR}/target") set(OPENSSL_INSTALL_DIR "${OPENSSL_BUNDLE_DIR}/target")
set(OPENSSL_LIBRARY_SSL "${OPENSSL_INSTALL_DIR}/lib/libssl.a") set(OPENSSL_LIBRARY_SSL "${OPENSSL_INSTALL_DIR}/lib/libssl.a")

16
digwatch.yaml Normal file
View File

@ -0,0 +1,16 @@
rules_file: /etc/digwatch.conf
# Priority level
# Any rule with priority lower than this level will be discarded
priority_level: warning
syslog_output:
enabled: true
file_output:
enabled: true
filename: "bla.bla"
stdout_output:
enabled: false

View File

@ -5,12 +5,16 @@ include_directories(${PROJECT_SOURCE_DIR}/../sysdig/userspace/libscap)
include_directories(${PROJECT_SOURCE_DIR}/../sysdig/userspace/libsinsp) include_directories(${PROJECT_SOURCE_DIR}/../sysdig/userspace/libsinsp)
include_directories("${PROJECT_BINARY_DIR}/userspace/digwatch") include_directories("${PROJECT_BINARY_DIR}/userspace/digwatch")
include_directories("${CURL_INCLUDE_DIR}") include_directories("${CURL_INCLUDE_DIR}")
include_directories("${YAMLCPP_INCLUDE_DIR}")
include_directories("${LPEG_SRC}") include_directories("${LPEG_SRC}")
include_directories(${DRAIOS_DEPENDENCIES_DIR}/yaml-${DRAIOS_YAML_VERSION}/target/include)
add_executable(digwatch formats.cpp fields.cpp rules.cpp syslog.cpp digwatch.cpp) add_executable(digwatch configuration.cpp formats.cpp fields.cpp rules.cpp syslog.cpp digwatch.cpp)
target_link_libraries(digwatch sinsp) target_link_libraries(digwatch sinsp)
target_link_libraries(digwatch "${LPEG_SRC}/lpeg.a") target_link_libraries(digwatch
"${LPEG_SRC}/lpeg.a"
"${YAMLCPP_LIB}")
set(DIGWATCH_LUA_MAIN "rule_loader.lua") set(DIGWATCH_LUA_MAIN "rule_loader.lua")

View File

@ -3,6 +3,9 @@
#define DIGWATCH_VERSION "${DIGWATCH_VERSION}" #define DIGWATCH_VERSION "${DIGWATCH_VERSION}"
#define DIGWATCH_LUA_DIR "/usr/share/digwatch/lua/" #define DIGWATCH_LUA_DIR "/usr/share/digwatch/lua/"
#define DIGWATCH_SOURCE_DIR "${PROJECT_SOURCE_DIR}"
#define DIGWATCH_SOURCE_CONF_FILE "${PROJECT_SOURCE_DIR}/digwatch.yaml"
#define DIGWATCH_INSTALL_CONF_FILE "/etc/digwatch.yaml"
#define DIGWATCH_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/digwatch/lua/" #define DIGWATCH_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/digwatch/lua/"

View File

@ -0,0 +1,56 @@
#include "configuration.h"
#include "config_digwatch.h"
#include "sinsp.h"
using namespace std;
// If we don't have a configuration file, we just use stdout output and all other defaults
void digwatch_configuration::init()
{
output_config stdout_output;
stdout_output.name = "stdout";
m_outputs.push_back(stdout_output);
}
void digwatch_configuration::init(string conf_filename)
{
string m_config_file = conf_filename;
m_config = new yaml_configuration(m_config_file);
m_rules_file = m_config->get_scalar<string>("rules_file", "/etc/digwatch.conf");
m_priority_level = m_config->get_scalar<string>("priority_level", "warning");
output_config file_output;
file_output.name = "file";
if (m_config->get_scalar<bool>("file_output", "enabled", false))
{
string filename;
filename = m_config->get_scalar<string>("file_output", "filename", "");
if (filename == string(""))
{
throw sinsp_exception("Error reading config file (" + m_config_file + "): file output enabled but no filename in configuration block");
}
file_output.options["filename"] = filename;
m_outputs.push_back(file_output);
}
output_config stdout_output;
stdout_output.name = "stdout";
if (m_config->get_scalar<bool>("stdout_output", "enabled", false))
{
m_outputs.push_back(stdout_output);
}
output_config syslog_output;
syslog_output.name = "syslog";
if (m_config->get_scalar<bool>("syslog_output", "enabled", false))
{
m_outputs.push_back(syslog_output);
}
if (m_outputs.size() == 0)
{
throw sinsp_exception("Error reading config file (" + m_config_file + "): No outputs configured. Please configure at least one output file output enabled but no filename in configuration block");
}
}

View File

@ -0,0 +1,103 @@
#pragma once
#include <yaml-cpp/yaml.h>
#include <iostream>
struct output_config
{
std::string name;
std::map<std::string, std::string> options;
};
class yaml_configuration
{
public:
std::string m_path;
yaml_configuration(const std::string& path)
{
m_path = path;
YAML::Node config;
std::vector<output_config> outputs;
try
{
m_root = YAML::LoadFile(path);
}
catch (const YAML::BadFile& ex)
{
std::cerr << "Error reading config file (" + path + "): " + ex.what() + "\n";
throw;
}
catch (const YAML::ParserException& ex)
{
std::cerr << "Cannot read config file (" + path + "): " + ex.what() + "\n";
throw;
}
}
/**
* Get a scalar value defined at the top level of the config
*/
template<typename T>
const T get_scalar(const std::string& key, const T& default_value)
{
try
{
auto node = m_root[key];
if (node.IsDefined())
{
return node.as<T>();
}
} catch (const YAML::BadConversion& ex)
{
std::cerr << "Cannot read config file (" + m_path + "): wrong type at key " + key + "\n";
throw;
}
return default_value;
}
/**
* Get a scalar value defined inside a 2 level nested structure like:
* file_output:
* enabled: true
* filename: output_file.txt
*
* get_scalar<bool>("file_output", "enabled", false)
*/
template<typename T>
const T get_scalar(const std::string& key, const std::string& subkey, const T& default_value)
{
try
{
auto node = m_root[key][subkey];
if (node.IsDefined())
{
return node.as<T>();
}
}
catch (const YAML::BadConversion& ex)
{
std::cerr << "Cannot read config file (" + m_path + "): wrong type at key " + key + "\n";
throw;
}
return default_value;
}
private:
YAML::Node m_root;
};
class digwatch_configuration
{
public:
void init(std::string conf_filename);
void init();
std::string m_rules_file;
std::string m_priority_level;
std::vector<output_config> m_outputs;
private:
yaml_configuration* m_config;
};

View File

@ -18,12 +18,14 @@ extern "C" {
} }
#include <sinsp.h> #include <sinsp.h>
#include <config_digwatch.h> #include "config_digwatch.h"
#include "configuration.h"
#include "rules.h" #include "rules.h"
#include "formats.h" #include "formats.h"
#include "fields.h" #include "fields.h"
#include "syslog.h" #include "syslog.h"
#include "utils.h" #include "utils.h"
#include <yaml-cpp/yaml.h>
static bool g_terminate = false; static bool g_terminate = false;
@ -155,6 +157,8 @@ void add_lua_path(lua_State *ls, string path)
lua_pop(ls, 1); lua_pop(ls, 1);
} }
// //
// ARGUMENT PARSING AND PROGRAM SETUP // ARGUMENT PARSING AND PROGRAM SETUP
// //
@ -169,6 +173,7 @@ int digwatch_init(int argc, char **argv)
string lua_main_filename; string lua_main_filename;
string output_name = "stdout"; string output_name = "stdout";
string infile; string infile;
string conf_filename;
string lua_dir = DIGWATCH_LUA_DIR; string lua_dir = DIGWATCH_LUA_DIR;
lua_State* ls = NULL; lua_State* ls = NULL;
@ -188,7 +193,7 @@ int digwatch_init(int argc, char **argv)
// Parse the args // Parse the args
// //
while((op = getopt_long(argc, argv, while((op = getopt_long(argc, argv,
"ho:r:", "c:ho:R:",
long_options, &long_index)) != -1) long_options, &long_index)) != -1)
{ {
switch(op) switch(op)
@ -196,6 +201,9 @@ int digwatch_init(int argc, char **argv)
case 'h': case 'h':
usage(); usage();
goto exit; goto exit;
case 'c':
conf_filename = optarg;
break;
case 'o': case 'o':
valid = std::find(valid_output_names.begin(), valid_output_names.end(), optarg) != valid_output_names.end(); valid = std::find(valid_output_names.begin(), valid_output_names.end(), optarg) != valid_output_names.end();
if (!valid) if (!valid)
@ -246,6 +254,50 @@ int digwatch_init(int argc, char **argv)
} }
ifstream* conf_stream;
if (conf_filename.size())
{
conf_stream = new ifstream(conf_filename);
if (!conf_stream->good())
{
fprintf(stderr, "Could not find configuration file at %s \n", conf_filename.c_str());
result = EXIT_FAILURE;
goto exit;
}
}
else
{
conf_stream = new ifstream(DIGWATCH_SOURCE_CONF_FILE);
if (conf_stream->good())
{
conf_filename = DIGWATCH_SOURCE_CONF_FILE;
}
else
{
conf_stream = new ifstream(DIGWATCH_INSTALL_CONF_FILE);
if (conf_stream->good())
{
conf_filename = DIGWATCH_INSTALL_CONF_FILE;
}
else
{
conf_filename = "";
}
}
}
digwatch_configuration config;
if (conf_filename.size())
{
cout << "Using configuration file " + conf_filename + "\n";
config.init(conf_filename);
}
else
{
cout << "No configuration file found, proceeding with defaults\n";
config.init();
}
if(signal(SIGINT, signal_callback) == SIG_ERR) if(signal(SIGINT, signal_callback) == SIG_ERR)
{ {
fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n"); fprintf(stderr, "An error occurred while setting SIGINT signal handler.\n");
@ -275,7 +327,6 @@ int digwatch_init(int argc, char **argv)
} }
} }
// Initialize Lua interpreter // Initialize Lua interpreter
ls = lua_open(); ls = lua_open();
luaL_openlibs(ls); luaL_openlibs(ls);
@ -327,7 +378,7 @@ int digwatch_init(int argc, char **argv)
} }
catch(...) catch(...)
{ {
printf("Exception\n"); printf("Error, exiting.\n");
result = EXIT_FAILURE; result = EXIT_FAILURE;
} }