mirror of https://github.com/Icinga/icinga2.git
Cli: 'agent update-config' checks against black/whitelist filters on add/remove
fixes #7501 refs #7253
This commit is contained in:
parent
4fe486c4dd
commit
0ff5cf51b8
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue