Skip to content

Commit

Permalink
Cli: 'agent update-config' checks against black/whitelist filters on …
Browse files Browse the repository at this point in the history
…add/remove

fixes #7501
refs #7253
  • Loading branch information
Michael Friedrich committed Oct 29, 2014
1 parent 4fe486c commit 0ff5cf5
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 35 deletions.
74 changes: 55 additions & 19 deletions lib/cli/agentupdateconfigcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,30 +89,28 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
Dictionary::Ptr repository = agent->Get("repository");
String zone = agent->Get("zone");
String endpoint = agent->Get("endpoint");
String agent_name = endpoint;

/* store existing structure in index */
inventory->Set(endpoint, agent);

Dictionary::Ptr host_services = make_shared<Dictionary>();

/* if there is no health check host for this agent zone, create one */
if (!repository->Contains(zone)) {
Log(LogInformation, "cli")
<< "Repository for agent '" << endpoint << "' does not contain a health check host. Adding host '" << zone << "'.";

Dictionary::Ptr host_attrs = make_shared<Dictionary>();
host_attrs->Set("__name", zone);
host_attrs->Set("name", zone);
host_attrs->Set("check_command", "cluster-zone");
host_attrs->Set("zone", zone);
Array::Ptr host_imports = make_shared<Array>();
host_imports->Add("agent-host"); //default host agent template
host_attrs->Set("import", host_imports);

if (!RepositoryUtility::AddObject(zone, "Host", host_attrs)) {
Log(LogCritical, "cli")
<< "Cannot add agent host '" << zone << "' to the config repository!\n";
}
Log(LogInformation, "cli")
<< "Repository for agent '" << endpoint << "' does not contain a health check host. Adding host '" << zone << "'.";

Dictionary::Ptr host_attrs = make_shared<Dictionary>();
host_attrs->Set("__name", zone);
host_attrs->Set("name", zone);
host_attrs->Set("check_command", "cluster-zone");
host_attrs->Set("zone", zone);
Array::Ptr host_imports = make_shared<Array>();
host_imports->Add("agent-host"); //default host agent template
host_attrs->Set("import", host_imports);

if (!RepositoryUtility::AddObject(zone, "Host", host_attrs)) {
Log(LogCritical, "cli")
<< "Cannot add agent host '" << zone << "' to the config repository!\n";
}

ObjectLock olock(repository);
Expand All @@ -123,7 +121,7 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v

if (host == "localhost") {
Log(LogWarning, "cli")
<< "Ignoring host '" << host << "'. Please make sure to configure a unique name on your agent '" << endpoint << "'.";
<< "Ignoring host '" << host << "'. Please make sure to configure a unique name on your agent '" << agent_name << "'.";
continue;
}

Expand All @@ -136,6 +134,18 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
}
}

/* host has already been created above */
if (host == zone)
skip_host = true;

/* check against black/whitelist before trying to add host */
if (AgentUtility::CheckAgainstBlackAndWhiteList("blacklist", agent_name, host, Empty) &&
!AgentUtility::CheckAgainstBlackAndWhiteList("whitelist", agent_name, host, Empty)) {
Log(LogWarning, "cli")
<< "Host '" << host << "' on agent '" << agent_name << "' is blacklisted, but not whitelisted. Skipping.";
skip_host = true;
}

if (!skip_host) {
/* add a new host to the config repository */
Dictionary::Ptr host_attrs = make_shared<Dictionary>();
Expand Down Expand Up @@ -182,6 +192,15 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
}
}

/* check against black/whitelist before trying to add service */
if (AgentUtility::CheckAgainstBlackAndWhiteList("blacklist", endpoint, host, service) &&
!AgentUtility::CheckAgainstBlackAndWhiteList("whitelist", endpoint, host, service)) {
Log(LogWarning, "cli")
<< "Service '" << service << "' on host '" << host << "' on agent '"
<< agent_name << "' is blacklisted, but not whitelisted. Skipping.";
skip_service = true;
}

if (skip_service)
continue;

Expand Down Expand Up @@ -309,6 +328,14 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v
continue;
}

/* check against black/whitelist before trying to remove host */
if (AgentUtility::CheckAgainstBlackAndWhiteList("blacklist", old_agent_name, old_host, Empty) &&
!AgentUtility::CheckAgainstBlackAndWhiteList("whitelist", old_agent_name, old_host, Empty)) {
Log(LogWarning, "cli")
<< "Host '" << old_agent << "' on agent '" << old_agent << "' is blacklisted, but not whitelisted. Skipping.";
continue;
}

if (!new_agent_repository->Contains(old_host)) {
Log(LogInformation, "cli")
<< "Agent update found old host '" << old_host << "' on agent '" << old_agent_name << "'. Removing it.";
Expand All @@ -323,6 +350,15 @@ int AgentUpdateConfigCommand::Run(const boost::program_options::variables_map& v

ObjectLock ylock(old_services);
BOOST_FOREACH(const String& old_service, old_services) {
/* check against black/whitelist before trying to remove service */
if (AgentUtility::CheckAgainstBlackAndWhiteList("blacklist", old_agent_name, old_host, old_service) &&
!AgentUtility::CheckAgainstBlackAndWhiteList("whitelist", old_agent_name, old_host, old_service)) {
Log(LogWarning, "cli")
<< "Service '" << old_service << "' on host '" << old_host << "' on agent '"
<< old_agent_name << "' is blacklisted, but not whitelisted. Skipping.";
skip_service = true;
}

if (!new_services->Contains(old_service)) {
Log(LogInformation, "cli")
<< "Agent update found old service '" << old_service << "' on host '" << old_host
Expand Down
81 changes: 65 additions & 16 deletions lib/cli/agentutility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,16 +385,28 @@ bool AgentUtility::WriteAgentConfigObjects(const String& filename, const Array::
/*
* Black/Whitelist helpers
*/
int AgentUtility::UpdateBlackAndWhiteList(const String& type, const String& agent_filter, const String& host_filter, const String& service_filter)
String AgentUtility::GetBlackAndWhiteListPath(const String& type)
{
return AgentUtility::GetRepositoryPath() + "/" + type + ".list";
}

Dictionary::Ptr AgentUtility::GetBlackAndWhiteList(const String& type)
{
String list_path = AgentUtility::GetRepositoryPath() + "/" + type + ".list";
String list_path = GetBlackAndWhiteListPath(type);

Dictionary::Ptr lists = make_shared<Dictionary>();

if (Utility::PathExists(list_path)) {
lists = Utility::LoadJsonFile(list_path);
}

return lists;
}

int AgentUtility::UpdateBlackAndWhiteList(const String& type, const String& agent_filter, const String& host_filter, const String& service_filter)
{
Dictionary::Ptr lists = GetBlackAndWhiteList(type);

Dictionary::Ptr host_service = make_shared<Dictionary>();

host_service->Set("host_filter", host_filter);
Expand All @@ -420,20 +432,15 @@ int AgentUtility::UpdateBlackAndWhiteList(const String& type, const String& agen

lists->Set(agent_filter, host_service);

String list_path = GetBlackAndWhiteListPath(type);
Utility::SaveJsonFile(list_path, lists);

return 0;
}

int AgentUtility::RemoveBlackAndWhiteList(const String& type, const String& agent_filter, const String& host_filter, const String& service_filter)
{
String list_path = AgentUtility::GetRepositoryPath() + "/" + type + ".list";

Dictionary::Ptr lists = make_shared<Dictionary>();

if (Utility::PathExists(list_path)) {
lists = Utility::LoadJsonFile(list_path);
}
Dictionary::Ptr lists = GetBlackAndWhiteList(type);

if (lists->Contains(agent_filter)) {
Dictionary::Ptr host_service = lists->Get(agent_filter);
Expand All @@ -456,20 +463,15 @@ int AgentUtility::RemoveBlackAndWhiteList(const String& type, const String& agen
return 1;
}

String list_path = GetBlackAndWhiteListPath(type);
Utility::SaveJsonFile(list_path, lists);

return 0;
}

int AgentUtility::PrintBlackAndWhiteList(std::ostream& fp, const String& type)
{
String list_path = AgentUtility::GetRepositoryPath() + "/" + type + ".list";

Dictionary::Ptr lists = make_shared<Dictionary>();

if (Utility::PathExists(list_path)) {
lists = Utility::LoadJsonFile(list_path);
}
Dictionary::Ptr lists = GetBlackAndWhiteList(type);

fp << "Listing all " << type << " entries:\n";

Expand All @@ -485,6 +487,53 @@ int AgentUtility::PrintBlackAndWhiteList(std::ostream& fp, const String& type)
return 0;
}

bool AgentUtility::CheckAgainstBlackAndWhiteList(const String& type, const String& agent, const String& host, const String& service)
{
Dictionary::Ptr lists = GetBlackAndWhiteList(type);

Log(LogInformation, "cli")
<< "Checking object against " << type << ".";

ObjectLock olock(lists);
BOOST_FOREACH(const Dictionary::Pair& kv, lists) {
String agent_filter = kv.first;
Dictionary::Ptr host_service = kv.second;
String host_filter = host_service->Get("host_filter");
String service_filter;

if (host_service->Contains("service_filter"))
service_filter = host_service->Get("service_filter");

Log(LogInformation, "cli")
<< "Checking Agent '" << agent << "' =~ '" << agent_filter << "', host '" << host << "' =~ '" << host_filter
<< "', service '" << service << "' =~ '" << service_filter << "'.";

if (Utility::Match(agent_filter, agent)) {
Log(LogNotice, "cli")
<< "Agent '" << agent << "' matches filter '" << agent_filter << "'";

if (Utility::Match(host_filter, host)) {
Log(LogNotice, "cli")
<< "Host '" << host << "' matches filter '" << host_filter << "'";

/* no service filter means host match */
if (service_filter.IsEmpty())
return true;

if (Utility::Match(service_filter, service)) {
Log(LogNotice, "cli")
<< "Host '" << service << "' matches filter '" << service_filter << "'";
return true;
}
}


}
}

return false;
}

/*
* We generally don't overwrite files without backup before
*/
Expand Down
4 changes: 4 additions & 0 deletions lib/cli/agentutility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,16 @@ class AgentUtility
static int GenerateAgentMasterIcingaConfig(const String& nodename);

/* black/whitelist */
static String GetBlackAndWhiteListPath(const String& type);
static Dictionary::Ptr GetBlackAndWhiteList(const String& type);
static int UpdateBlackAndWhiteList(const String& type, const String& agent_filter,
const String& host_filter, const String& service_filter);
static int RemoveBlackAndWhiteList(const String& type, const String& agent_filter,
const String& host_filter, const String& service_filter);
static int PrintBlackAndWhiteList(std::ostream& fp, const String& type);

static bool CheckAgainstBlackAndWhiteList(const String& type, const String& agent, const String& host, const String& service);

private:
AgentUtility(void);
static bool RemoveAgentFile(const String& path);
Expand Down

0 comments on commit 0ff5cf5

Please sign in to comment.