Merge branch 'MXS-1302' into develop
This commit is contained in:
commit
8b5c6f7286
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user