MXS-1519 Use fw instance specific rules and users

The rules and users need to be distinct not only for each thread
but for each instance and thread.
This commit is contained in:
Johan Wikman 2017-11-15 11:38:59 +02:00
parent b63c6504a3
commit 11a240cb15

View File

@ -67,6 +67,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include <map>
#include <maxscale/atomic.h> #include <maxscale/atomic.h>
#include <maxscale/modulecmd.h> #include <maxscale/modulecmd.h>
@ -97,16 +98,27 @@ namespace
{ {
/** The rules and users for each thread */ /** The rules and users for each thread */
struct DbfwThread class DbfwThread
{ {
DbfwThread(): public:
rule_version(0) int& rule_version(const Dbfw* d) { return m_instance_data[d].rule_version; }
{ RuleList& rules(const Dbfw* d) { return m_instance_data[d].rules; }
} UserMap& users(const Dbfw* d) { return m_instance_data[d].users; }
int rule_version; private:
RuleList rules; class Data
UserMap users; {
public:
Data()
: rule_version(0)
{}
int rule_version;
RuleList rules;
UserMap users;
};
std::map<const Dbfw*, Data> m_instance_data;
}; };
thread_local DbfwThread* this_thread = NULL; thread_local DbfwThread* this_thread = NULL;
@ -140,7 +152,7 @@ static json_t* rules_to_json(const RuleList& rules)
{ {
json_t* rval = json_array(); json_t* rval = json_array();
for (RuleList::const_iterator it = this_thread->rules.begin(); it != this_thread->rules.end(); it++) for (RuleList::const_iterator it = rules.begin(); it != rules.end(); it++)
{ {
const SRule& rule = *it; const SRule& rule = *it;
json_array_append_new(rval, rule_to_json(rule)); json_array_append_new(rval, rule_to_json(rule));
@ -410,7 +422,10 @@ bool dbfw_show_rules(const MODULECMD_ARG *argv, json_t** output)
dcb_printf(dcb, "Rule, Type, Times Matched\n"); dcb_printf(dcb, "Rule, Type, Times Matched\n");
if (this_thread->rules.empty() || this_thread->users.empty()) RuleList& rules = this_thread->rules(inst);
UserMap& users = this_thread->users(inst);
if (rules.empty() || users.empty())
{ {
if (!replace_rules(inst)) if (!replace_rules(inst))
{ {
@ -418,7 +433,7 @@ bool dbfw_show_rules(const MODULECMD_ARG *argv, json_t** output)
} }
} }
for (RuleList::const_iterator it = this_thread->rules.begin(); it != this_thread->rules.end(); it++) for (RuleList::const_iterator it = rules.begin(); it != rules.end(); it++)
{ {
const SRule& rule = *it; const SRule& rule = *it;
char buf[rule->name().length() + 200]; // Some extra space char buf[rule->name().length() + 200]; // Some extra space
@ -436,7 +451,10 @@ bool dbfw_show_rules_json(const MODULECMD_ARG *argv, json_t** output)
json_t* arr = json_array(); json_t* arr = json_array();
if (this_thread->rules.empty() || this_thread->users.empty()) RuleList& rules = this_thread->rules(inst);
UserMap& users = this_thread->users(inst);
if (rules.empty() || users.empty())
{ {
if (!replace_rules(inst)) if (!replace_rules(inst))
{ {
@ -444,7 +462,7 @@ bool dbfw_show_rules_json(const MODULECMD_ARG *argv, json_t** output)
} }
} }
for (RuleList::const_iterator it = this_thread->rules.begin(); it != this_thread->rules.end(); it++) for (RuleList::const_iterator it = rules.begin(); it != rules.end(); it++)
{ {
const SRule& rule = *it; const SRule& rule = *it;
json_array_append_new(arr, rule_to_json(rule)); json_array_append_new(arr, rule_to_json(rule));
@ -1092,11 +1110,11 @@ bool replace_rules(Dbfw* instance)
if (process_rule_file(filename, &rules, &users)) if (process_rule_file(filename, &rules, &users))
{ {
this_thread->rules.swap(rules); this_thread->rules(instance).swap(rules);
this_thread->users.swap(users); this_thread->users(instance).swap(users);
rval = true; rval = true;
} }
else if (!this_thread->rules.empty() && !this_thread->users.empty()) else if (!this_thread->rules(instance).empty() && !this_thread->users(instance).empty())
{ {
MXS_ERROR("Failed to parse rules at '%s'. Old rules are still used.", MXS_ERROR("Failed to parse rules at '%s'. Old rules are still used.",
filename.c_str()); filename.c_str());
@ -1116,14 +1134,14 @@ static bool update_rules(Dbfw* my_instance)
bool rval = true; bool rval = true;
int rule_version = my_instance->get_rule_version(); int rule_version = my_instance->get_rule_version();
if (this_thread->rule_version < rule_version) if (this_thread->rule_version(my_instance) < rule_version)
{ {
if (!replace_rules(my_instance)) if (!replace_rules(my_instance))
{ {
rval = false; rval = false;
} }
this_thread->rule_version = rule_version; this_thread->rule_version(my_instance) = rule_version;
} }
return rval; return rval;
@ -1409,7 +1427,7 @@ int DbfwSession::routeQuery(GWBUF* buffer)
ss_dassert(analyzed_queue); ss_dassert(analyzed_queue);
} }
SUser suser = find_user_data(this_thread->users, user(), remote()); SUser suser = find_user_data(this_thread->users(m_instance), user(), remote());
bool query_ok = false; bool query_ok = false;
if (command_is_mandatory(buffer)) if (command_is_mandatory(buffer))
@ -1673,7 +1691,9 @@ void Dbfw::diagnostics(DCB *dcb) const
dcb_printf(dcb, "Firewall Filter\n"); dcb_printf(dcb, "Firewall Filter\n");
dcb_printf(dcb, "Rule, Type, Times Matched\n"); dcb_printf(dcb, "Rule, Type, Times Matched\n");
for (RuleList::const_iterator it = this_thread->rules.begin(); it != this_thread->rules.end(); it++) RuleList& rules = this_thread->rules(this);
for (RuleList::const_iterator it = rules.begin(); it != rules.end(); it++)
{ {
const SRule& rule = *it; const SRule& rule = *it;
char buf[rule->name().length() + 200]; char buf[rule->name().length() + 200];
@ -1694,5 +1714,5 @@ void Dbfw::diagnostics(DCB *dcb) const
*/ */
json_t* Dbfw::diagnostics_json() const json_t* Dbfw::diagnostics_json() const
{ {
return rules_to_json(this_thread->rules); return rules_to_json(this_thread->rules(this));
} }