Merge branch 'MXS-1302' into develop

This commit is contained in:
MassimilianoPinto 2017-07-07 17:37:16 +02:00
commit 8b5c6f7286
2 changed files with 314 additions and 49 deletions

View File

@ -42,6 +42,7 @@ static const char KEY_RULES[] = "rules";
static const char KEY_TABLE[] = "table";
static const char KEY_VALUE[] = "value";
static const char KEY_WITH[] = "with";
static const char KEY_OBFUSCATE[] = "obfuscate";
/**
* @class AccountVerbatim
@ -330,13 +331,13 @@ bool get_accounts(const char* zName,
*
* @return A Rule instance or NULL in case of error.
*/
auto_ptr<MaskingRules::Rule> create_rule_from_elements(json_t* pColumn,
json_t* pTable,
json_t* pDatabase,
json_t* pValue,
json_t* pFill,
json_t* pApplies_to,
json_t* pExempted)
auto_ptr<MaskingRules::ReplaceRule> create_rule_from_elements(json_t* pColumn,
json_t* pTable,
json_t* pDatabase,
json_t* pValue,
json_t* pFill,
json_t* pApplies_to,
json_t* pExempted)
{
ss_dassert(pColumn && json_is_string(pColumn));
ss_dassert(!pTable || json_is_string(pTable));
@ -347,7 +348,7 @@ auto_ptr<MaskingRules::Rule> create_rule_from_elements(json_t* pColumn,
ss_dassert(!pApplies_to || json_is_array(pApplies_to));
ss_dassert(!pExempted || json_is_array(pExempted));
auto_ptr<MaskingRules::Rule> sRule;
auto_ptr<MaskingRules::ReplaceRule> sRule;
string column(json_string_value(pColumn));
string table(pTable ? json_string_value(pTable) : "");
@ -371,9 +372,9 @@ auto_ptr<MaskingRules::Rule> create_rule_from_elements(json_t* pColumn,
if (ok)
{
sRule = auto_ptr<MaskingRules::Rule>(new MaskingRules::Rule(column, table, database,
value, fill,
applies_to, exempted));
sRule = auto_ptr<MaskingRules::ReplaceRule>(new MaskingRules::ReplaceRule(column, table, database,
applies_to, exempted,
value, fill));
}
return sRule;
@ -389,17 +390,17 @@ auto_ptr<MaskingRules::Rule> create_rule_from_elements(json_t* pColumn,
*
* @return A Rule instance or NULL in case of error.
*/
auto_ptr<MaskingRules::Rule> create_rule_from_elements(json_t* pReplace,
json_t* pWith,
json_t* pApplies_to,
json_t* pExempted)
auto_ptr<MaskingRules::ReplaceRule> create_rule_from_elements(json_t* pReplace,
json_t* pWith,
json_t* pApplies_to,
json_t* pExempted)
{
ss_dassert(pReplace && json_is_object(pReplace));
ss_dassert(pWith && json_is_object(pWith));
ss_dassert(!pApplies_to || json_is_array(pApplies_to));
ss_dassert(!pExempted || json_is_array(pExempted));
auto_ptr<MaskingRules::Rule> sRule;
auto_ptr<MaskingRules::ReplaceRule> sRule;
json_t* pDatabase = json_object_get(pReplace, KEY_DATABASE);
json_t* pTable = json_object_get(pReplace, KEY_TABLE);
@ -478,7 +479,18 @@ bool create_rules_from_array(json_t* pRules, vector<shared_ptr<MaskingRules::Rul
if (json_is_object(pRule))
{
auto_ptr<MaskingRules::Rule> sRule = MaskingRules::Rule::create_from(pRule);
auto_ptr<MaskingRules::Rule> sRule;
json_t* pObfuscate = json_object_get(pRule, KEY_OBFUSCATE);
json_t* pReplace = json_object_get(pRule, KEY_REPLACE);
if (pObfuscate)
{
sRule = MaskingRules::ObfuscateRule::create_from(pRule);
}
else
{
sRule = MaskingRules::ReplaceRule::create_from(pRule);
}
if (sRule.get())
{
@ -550,26 +562,84 @@ MaskingRules::Rule::Account::~Account()
MaskingRules::Rule::Rule(const std::string& column,
const std::string& table,
const std::string& database,
const std::string& value,
const std::string& fill,
const std::vector<SAccount>& applies_to,
const std::vector<SAccount>& exempted)
: m_column(column)
, m_table(table)
, m_database(database)
, m_value(value)
, m_fill(fill)
, m_applies_to(applies_to)
, m_exempted(exempted)
{
}
MaskingRules::ReplaceRule::ReplaceRule(const std::string& column,
const std::string& table,
const std::string& database,
const std::vector<SAccount>& applies_to,
const std::vector<SAccount>& exempted,
const std::string& value,
const std::string& fill)
: MaskingRules::Rule::Rule(column, table, database, applies_to, exempted)
, m_value(value)
, m_fill(fill)
{
}
MaskingRules::ObfuscateRule::ObfuscateRule(const std::string& column,
const std::string& table,
const std::string& database,
const std::vector<SAccount>& applies_to,
const std::vector<SAccount>& exempted)
: MaskingRules::Rule::Rule(column, table, database, applies_to, exempted)
{
}
MaskingRules::Rule::~Rule()
{
}
MaskingRules::ReplaceRule::~ReplaceRule()
{
}
MaskingRules::ObfuscateRule::~ObfuscateRule()
{
}
/** Check the Json array for user rules
*
* @param pApplies_to The array of users the rule is applied to
* @param pExempted The array of users the rule is NOT applied to
*
* @return False on errors, True otherwise
*/
static bool validate_user_rules(json_t* pApplies_to, json_t* pExempted)
{
const char *err = NULL;
// Check for pApplies_to and pExempted
if (pApplies_to && !json_is_array(pApplies_to))
{
err = KEY_APPLIES_TO;
}
if (pExempted && !json_is_array(pExempted))
{
err = KEY_EXEMPTED;
}
if (err)
{
MXS_ERROR("A masking rule contains a '%s' key, "
"but the value is not an array.",
err);
return false;
}
return true;
}
//static
auto_ptr<MaskingRules::Rule> MaskingRules::Rule::create_from(json_t* pRule)
auto_ptr<MaskingRules::Rule> MaskingRules::ReplaceRule::create_from(json_t* pRule)
{
ss_dassert(json_is_object(pRule));
@ -625,6 +695,81 @@ auto_ptr<MaskingRules::Rule> MaskingRules::Rule::create_from(json_t* pRule)
return sRule;
}
//static
auto_ptr<MaskingRules::Rule> MaskingRules::ObfuscateRule::create_from(json_t* pRule)
{
ss_dassert(json_is_object(pRule));
auto_ptr<MaskingRules::Rule> sRule;
// Get obfuscate
json_t* pObfuscate = json_object_get(pRule, KEY_OBFUSCATE);
// Get applies_to
json_t* pApplies_to = json_object_get(pRule, KEY_APPLIES_TO);
// Get applies_to
json_t* pExempted = json_object_get(pRule, KEY_EXEMPTED);
// Check the pObfuscate object
if (pObfuscate && !json_is_object(pObfuscate))
{
MXS_ERROR("A masking rule contains a '%s' key, "
"but the value is not an object.",
KEY_OBFUSCATE);
return sRule;
}
// Check for pApplies_to and pExempted
if (!validate_user_rules(pApplies_to, pExempted))
{
return sRule;
}
vector<shared_ptr<MaskingRules::Rule::Account> > applies_to;
vector<shared_ptr<MaskingRules::Rule::Account> > exempted;
// Set the account rules
if (pApplies_to && pExempted &&
(!get_accounts(KEY_APPLIES_TO, pApplies_to, applies_to) ||
(!get_accounts(KEY_EXEMPTED, pExempted, exempted))))
{
return sRule;
}
// Get database, table and column from obfuscate object
json_t* pDatabase = json_object_get(pObfuscate, KEY_DATABASE);
json_t* pTable = json_object_get(pObfuscate, KEY_TABLE);
json_t* pColumn = json_object_get(pObfuscate, KEY_COLUMN);
// A column is mandatory; both table and database are optional.
if ((pColumn && json_is_string(pColumn)) &&
(!pTable || json_is_string(pTable)) &&
(!pDatabase || json_is_string(pDatabase)))
{
// Instantiate the ObfuscateRule class
string column(json_string_value(pColumn));
string table(pTable ? json_string_value(pTable) : "");
string database(pDatabase ? json_string_value(pDatabase) : "");
sRule = auto_ptr<MaskingRules::Rule>(new MaskingRules::ObfuscateRule(column,
table,
database,
applies_to,
exempted));
}
else
{
MXS_ERROR("The '%s' object of a masking rule does not have a '%s' key, or "
"the values of that key and/or possible '%s' and '%s' keys are "
"not strings.",
KEY_OBFUSCATE,
KEY_COLUMN,
KEY_TABLE,
KEY_DATABASE);
}
return sRule;
}
string MaskingRules::Rule::match() const
{
string s;
@ -704,7 +849,42 @@ bool MaskingRules::Rule::matches(const ComQueryResponse::ColumnDef& column_def,
return match;
}
void MaskingRules::Rule::rewrite(LEncString& s) const
/**
* Basic obfuscation routine
*
* @param c The bye to obfuscate
*
* @return The obfuscated byte
*/
static inline char maxscale_basic_obfuscation(const char c)
{
if (c >= 'a' && c <= 'z')
{
return (c - 'a' + 13) % 26 + 'a';
}
else if (c >= 'A' && c <= 'Z')
{
return (c - 'A' + 13) % 26 + 'A';
}
else
{
char d = c + 32;
d = d > 127 ? 127 : d;
return d;
}
return c;
}
void MaskingRules::ObfuscateRule::rewrite(LEncString& s) const
{
// Basic Obfuscation routine
std::transform(s.begin(),
s.end(),
s.begin(),
maxscale_basic_obfuscation);
}
void MaskingRules::ReplaceRule::rewrite(LEncString& s) const
{
bool rewritten = false;

View File

@ -67,13 +67,11 @@ public:
typedef std::tr1::shared_ptr<Account> SAccount;
/**
* Constructor
* Constructor of base Rule class
*
* @param column The column value from the json file.
* @param table The table value from the json file.
* @param database The database value from the json file.
* @param value The value value from the json file.
* @param fill The file value from the json file.
* @param applies_to Account instances corresponding to the
* accounts listed in 'applies_to' in the json file.
* @param exempted Account instances corresponding to the
@ -82,8 +80,6 @@ public:
Rule(const std::string& column,
const std::string& table,
const std::string& database,
const std::string& value,
const std::string& fill,
const std::vector<SAccount>& applies_to,
const std::vector<SAccount>& exempted);
~Rule();
@ -102,14 +98,6 @@ public:
{
return m_database;
}
const std::string& value() const
{
return m_value;
}
const std::string& fill() const
{
return m_fill;
}
const std::vector<SAccount>& applies_to() const
{
return m_applies_to;
@ -119,16 +107,6 @@ public:
return m_exempted;
}
/**
* Create a Rule instance
*
* @param pRule A json object corresponding to a single
* rule in the rules json file.
*
* @return A Rule instance or NULL.
*/
static std::auto_ptr<Rule> create_from(json_t* pRule);
/**
* Establish whether a rule matches a column definition and user/host.
*
@ -142,7 +120,12 @@ public:
const char* zUser,
const char* zHost) const;
void rewrite(LEncString& s) const;
/**
* Mask the column content with value or fill.
*
* @param s The current value to be rewritten.
*/
virtual void rewrite(LEncString& s) const = 0;
private:
Rule(const Rule&);
@ -152,12 +135,114 @@ public:
std::string m_column;
std::string m_table;
std::string m_database;
std::string m_value;
std::string m_fill;
std::vector<SAccount> m_applies_to;
std::vector<SAccount> m_exempted;
};
class ReplaceRule : public Rule
{
public:
/**
* Constructor of ReplaceRule
*
* @param column The column value from the json file.
* @param table The table value from the json file.
* @param database The database value from the json file.
* @param applies_to Account instances corresponding to the
* accounts listed in 'applies_to' in the json file.
* @param exempted Account instances corresponding to the
* accounts listed in 'exempted' in the json file.
* @param value The replace value from the json file.
* @param fill The fill value from the json file.
*/
ReplaceRule(const std::string& column,
const std::string& table,
const std::string& database,
const std::vector<SAccount>& applies_to,
const std::vector<SAccount>& exempted,
const std::string& value,
const std::string& fill);
~ReplaceRule();
const std::string& value() const
{
return m_value;
}
const std::string& fill() const
{
return m_fill;
}
/**
* Create a ReplaceRule instance
*
* @param pRule A json object corresponding to a single
* rule in the rules json file.
*
* @return A Rule instance or NULL.
*/
static std::auto_ptr<Rule> create_from(json_t* pRule);
/**
* Rewrite the column value based on rules
*
* @param s The column value to rewrite.
*/
void rewrite(LEncString& s) const;
private:
std::string m_value;
std::string m_fill;
private:
ReplaceRule(const ReplaceRule&);
ReplaceRule& operator = (const ReplaceRule&);
};
class ObfuscateRule : public Rule
{
public:
/**
* Constructor of ObfuscateRule
*
* @param column The column value from the json file.
* @param table The table value from the json file.
* @param database The database value from the json file.
* @param applies_to Account instances corresponding to the
* accounts listed in 'applies_to' in the json file.
* @param exempted Account instances corresponding to the
* accounts listed in 'exempted' in the json file.
*/
ObfuscateRule(const std::string& column,
const std::string& table,
const std::string& database,
const std::vector<SAccount>& applies_to,
const std::vector<SAccount>& exempted);
~ObfuscateRule();
/**
* Create a ObfuscateRule instance
*
* @param pRule A json object corresponding to a single
* rule in the rules json file.
*
* @return A Rule instance or NULL.
*/
static std::auto_ptr<Rule> create_from(json_t* pRule);
/**
* Obfuscate the column value based on rules
*
* @param s The column value to obfuscate.
*/
void rewrite(LEncString& s) const;
private:
ObfuscateRule(const ObfuscateRule&);
ObfuscateRule& operator = (const ObfuscateRule&);
};
~MaskingRules();
/**