Cli: 'agent update-config' checks against black/whitelist filters on add/remove

fixes #7501
refs #7253
This commit is contained in:
Michael Friedrich 2014-10-30 00:29:09 +01:00
parent 4fe486c4dd
commit 0ff5cf51b8
3 changed files with 122 additions and 33 deletions

View File

@ -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 << "'.";
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);
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";
}
if (!RepositoryUtility::AddObject(zone, "Host", host_attrs)) {
Log(LogCritical, "cli")
<< "Cannot add agent host '" << zone << "' to the config repository!\n";
}
ObjectLock olock(repository);
@ -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;
}
@ -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>();
@ -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;
@ -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.";
@ -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

View File

@ -385,9 +385,14 @@ 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)
{
String list_path = AgentUtility::GetRepositoryPath() + "/" + type + ".list";
return AgentUtility::GetRepositoryPath() + "/" + type + ".list";
}
Dictionary::Ptr AgentUtility::GetBlackAndWhiteList(const String& type)
{
String list_path = GetBlackAndWhiteListPath(type);
Dictionary::Ptr lists = make_shared<Dictionary>();
@ -395,6 +400,13 @@ int AgentUtility::UpdateBlackAndWhiteList(const String& type, const String& agen
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);
@ -420,6 +432,7 @@ 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;
@ -427,13 +440,7 @@ int AgentUtility::UpdateBlackAndWhiteList(const String& type, const String& agen
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);
@ -456,6 +463,7 @@ int AgentUtility::RemoveBlackAndWhiteList(const String& type, const String& agen
return 1;
}
String list_path = GetBlackAndWhiteListPath(type);
Utility::SaveJsonFile(list_path, lists);
return 0;
@ -463,13 +471,7 @@ int AgentUtility::RemoveBlackAndWhiteList(const String& type, const String& agen
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";
@ -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
*/

View File

@ -61,12 +61,16 @@ public:
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);