Masking: Add parameter for warnings
The masking filter can now be instructed to warn in case a masking rule matches a column of a type that is not masked.
This commit is contained in:
@ -76,7 +76,7 @@ type=service
|
|||||||
filters=Mask-SSN
|
filters=Mask-SSN
|
||||||
```
|
```
|
||||||
|
|
||||||
# Filter Parameter
|
## Filter Parameters
|
||||||
|
|
||||||
The masking filter has one mandatory parameter - `rules_file`.
|
The masking filter has one mandatory parameter - `rules_file`.
|
||||||
|
|
||||||
@ -90,6 +90,18 @@ MariaDB MaxScale.
|
|||||||
rules_file=/path/to/rules-file
|
rules_file=/path/to/rules-file
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `warn_type_mismatch`
|
||||||
|
|
||||||
|
With this optional parameter the masking filter can be instructed to log
|
||||||
|
a warning if a masking rule matches a column that is not of one of the
|
||||||
|
allowed types.
|
||||||
|
|
||||||
|
The values that can be used are `never` and `always`, with `never` being
|
||||||
|
the default.
|
||||||
|
```
|
||||||
|
warn_type_mismatch=always
|
||||||
|
```
|
||||||
|
|
||||||
# Rules
|
# Rules
|
||||||
|
|
||||||
The masking rules are expressed as a JSON object.
|
The masking rules are expressed as a JSON object.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
if (JANSSON_FOUND)
|
if (JANSSON_FOUND)
|
||||||
add_library(masking SHARED
|
add_library(masking SHARED
|
||||||
maskingfilter.cc
|
maskingfilter.cc
|
||||||
|
maskingfilterconfig.cc
|
||||||
maskingfiltersession.cc
|
maskingfiltersession.cc
|
||||||
maskingrules.cc
|
maskingrules.cc
|
||||||
)
|
)
|
||||||
|
@ -77,6 +77,8 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
|
|
||||||
MXS_NOTICE("Masking module %s initialized.", VERSION_STRING);
|
MXS_NOTICE("Masking module %s initialized.", VERSION_STRING);
|
||||||
|
|
||||||
|
typedef MaskingFilter::Config Config;
|
||||||
|
|
||||||
static MXS_MODULE info =
|
static MXS_MODULE info =
|
||||||
{
|
{
|
||||||
MXS_MODULE_API_FILTER,
|
MXS_MODULE_API_FILTER,
|
||||||
@ -90,8 +92,11 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
NULL, /* Thread init. */
|
NULL, /* Thread init. */
|
||||||
NULL, /* Thread finish. */
|
NULL, /* Thread finish. */
|
||||||
{
|
{
|
||||||
{"rules_file", MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED},
|
{ Config::rules_file_name, MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED },
|
||||||
{MXS_END_MODULE_PARAMS}
|
{ Config::warn_type_mismatch_name,
|
||||||
|
MXS_MODULE_PARAM_ENUM, Config::warn_type_mismatch_default,
|
||||||
|
MXS_MODULE_OPT_NONE, Config::warn_type_mismatch_values },
|
||||||
|
{ MXS_END_MODULE_PARAMS }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,12 +119,15 @@ MaskingFilter::~MaskingFilter()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
MaskingFilter* MaskingFilter::create(const char* zName, char** pzOptions, CONFIG_PARAMETER* ppParams)
|
MaskingFilter* MaskingFilter::create(const char* zName, char** pzOptions, CONFIG_PARAMETER* pParams)
|
||||||
{
|
{
|
||||||
MaskingFilter* pFilter = NULL;
|
MaskingFilter* pFilter = NULL;
|
||||||
|
|
||||||
MaskingFilter::Config config(zName);
|
MaskingFilter::Config config(zName);
|
||||||
process_params(pzOptions, ppParams, config);
|
|
||||||
|
config.set_warn_type_mismatch(Config::get_warn_type_mismatch(pParams));
|
||||||
|
process_params(pzOptions, pParams, config);
|
||||||
|
|
||||||
auto_ptr<MaskingRules> sRules = MaskingRules::load(config.rules_file().c_str());
|
auto_ptr<MaskingRules> sRules = MaskingRules::load(config.rules_file().c_str());
|
||||||
|
|
||||||
if (sRules.get())
|
if (sRules.get())
|
||||||
|
@ -39,6 +39,7 @@ public:
|
|||||||
|
|
||||||
void reload(DCB* pOut);
|
void reload(DCB* pOut);
|
||||||
|
|
||||||
|
const Config& config() const { return m_config; }
|
||||||
SMaskingRules rules() const;
|
SMaskingRules rules() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
52
server/modules/filter/masking/maskingfilterconfig.cc
Normal file
52
server/modules/filter/masking/maskingfilterconfig.cc
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||||
|
*
|
||||||
|
* Use of this software is governed by the Business Source License included
|
||||||
|
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||||
|
*
|
||||||
|
* Change Date: 2019-07-01
|
||||||
|
*
|
||||||
|
* On the date above, in accordance with the Business Source License, use
|
||||||
|
* of this software will be governed by version 2 or later of the General
|
||||||
|
* Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "maskingfilterconfig.hh"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
const char config_name_rules_file[] = "rules_file";
|
||||||
|
const char config_name_warn_type_mismatch[] = "warn_type_mismatch";
|
||||||
|
|
||||||
|
const char config_value_never[] = "never";
|
||||||
|
const char config_value_always[] = "always";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
const char* MaskingFilterConfig::rules_file_name = config_name_rules_file;
|
||||||
|
|
||||||
|
|
||||||
|
//static
|
||||||
|
const char* MaskingFilterConfig::warn_type_mismatch_name = config_name_warn_type_mismatch;
|
||||||
|
|
||||||
|
//static
|
||||||
|
const MXS_ENUM_VALUE MaskingFilterConfig::warn_type_mismatch_values[] =
|
||||||
|
{
|
||||||
|
{ config_value_never, MaskingFilterConfig::WARN_NEVER },
|
||||||
|
{ config_value_always, MaskingFilterConfig::WARN_ALWAYS },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
//static
|
||||||
|
const char* MaskingFilterConfig::warn_type_mismatch_default = config_value_never;
|
||||||
|
|
||||||
|
|
||||||
|
//static
|
||||||
|
MaskingFilterConfig::warn_type_mismatch_t
|
||||||
|
MaskingFilterConfig::get_warn_type_mismatch(const CONFIG_PARAMETER* pParams)
|
||||||
|
{
|
||||||
|
int warn = config_get_enum(pParams, warn_type_mismatch_name, warn_type_mismatch_values);
|
||||||
|
return static_cast<warn_type_mismatch_t>(warn);
|
||||||
|
}
|
@ -13,22 +13,42 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <maxscale/cppdefs.hh>
|
#include <maxscale/cppdefs.hh>
|
||||||
|
#include <maxscale/config.h>
|
||||||
|
#include <maxscale/modinfo.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class MaskingFilterConfig
|
class MaskingFilterConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum warn_type_mismatch_t
|
||||||
|
{
|
||||||
|
WARN_NEVER,
|
||||||
|
WARN_ALWAYS
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* rules_file_name;
|
||||||
|
|
||||||
|
static const char* warn_type_mismatch_name;
|
||||||
|
static const MXS_ENUM_VALUE warn_type_mismatch_values[];
|
||||||
|
static const char* warn_type_mismatch_default;
|
||||||
|
|
||||||
MaskingFilterConfig(const char* zName)
|
MaskingFilterConfig(const char* zName)
|
||||||
: m_name(zName)
|
: m_name(zName)
|
||||||
|
, m_warn_type_mismatch(WARN_NEVER)
|
||||||
{}
|
{}
|
||||||
~MaskingFilterConfig() {}
|
~MaskingFilterConfig() {}
|
||||||
|
|
||||||
const std::string& name() const { return m_name; }
|
const std::string& name() const { return m_name; }
|
||||||
const std::string& rules_file() const { return m_rules_file; }
|
const std::string& rules_file() const { return m_rules_file; }
|
||||||
|
warn_type_mismatch_t warn_type_mismatch() const { return m_warn_type_mismatch; }
|
||||||
|
|
||||||
void set_rules_file(const std::string& s) { m_rules_file = s; }
|
void set_rules_file(const std::string& s) { m_rules_file = s; }
|
||||||
|
void set_warn_type_mismatch(warn_type_mismatch_t w) { m_warn_type_mismatch = w; }
|
||||||
|
|
||||||
|
static warn_type_mismatch_t get_warn_type_mismatch(const CONFIG_PARAMETER* pParams);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::string m_rules_file;
|
std::string m_rules_file;
|
||||||
|
warn_type_mismatch_t m_warn_type_mismatch;
|
||||||
};
|
};
|
||||||
|
@ -178,6 +178,17 @@ void MaskingFilterSession::handle_eof(GWBUF* pPacket)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
void warn_of_type_mismatch(const MaskingRules::Rule& rule)
|
||||||
|
{
|
||||||
|
MXS_WARNING("The rule targeting \"%s\" matches a column "
|
||||||
|
"that is not of string type.", rule.match().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MaskingFilterSession::handle_row(GWBUF* pPacket)
|
void MaskingFilterSession::handle_row(GWBUF* pPacket)
|
||||||
{
|
{
|
||||||
MXS_NOTICE("handle_row");
|
MXS_NOTICE("handle_row");
|
||||||
@ -213,7 +224,10 @@ void MaskingFilterSession::handle_row(GWBUF* pPacket)
|
|||||||
LEncString s = value.as_string();
|
LEncString s = value.as_string();
|
||||||
pRule->rewrite(s);
|
pRule->rewrite(s);
|
||||||
}
|
}
|
||||||
|
else if (m_filter.config().warn_type_mismatch() == Config::WARN_ALWAYS)
|
||||||
|
{
|
||||||
|
warn_of_type_mismatch(*pRule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@ -238,6 +252,10 @@ void MaskingFilterSession::handle_row(GWBUF* pPacket)
|
|||||||
LEncString s = value.as_string();
|
LEncString s = value.as_string();
|
||||||
pRule->rewrite(s);
|
pRule->rewrite(s);
|
||||||
}
|
}
|
||||||
|
else if (m_filter.config().warn_type_mismatch() == Config::WARN_ALWAYS)
|
||||||
|
{
|
||||||
|
warn_of_type_mismatch(*pRule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,13 @@
|
|||||||
#include "maskingrules.hh"
|
#include "maskingrules.hh"
|
||||||
|
|
||||||
class MaskingFilter;
|
class MaskingFilter;
|
||||||
|
class MaskingFilterConfig;
|
||||||
|
|
||||||
class MaskingFilterSession : public maxscale::FilterSession
|
class MaskingFilterSession : public maxscale::FilterSession
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef MaskingFilterConfig Config;
|
||||||
|
|
||||||
~MaskingFilterSession();
|
~MaskingFilterSession();
|
||||||
|
|
||||||
static MaskingFilterSession* create(SESSION* pSession, const MaskingFilter* pFilter);
|
static MaskingFilterSession* create(SESSION* pSession, const MaskingFilter* pFilter);
|
||||||
|
@ -614,6 +614,19 @@ auto_ptr<MaskingRules::Rule> MaskingRules::Rule::create_from(json_t* pRule)
|
|||||||
return sRule;
|
return sRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string MaskingRules::Rule::match() const
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
|
||||||
|
s += m_database.empty() ? "*" : m_database;
|
||||||
|
s += ".";
|
||||||
|
s += m_table.empty() ? "*" : m_table;
|
||||||
|
s += ".";
|
||||||
|
s += m_column;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -88,6 +88,8 @@ public:
|
|||||||
const std::vector<SAccount>& exempted);
|
const std::vector<SAccount>& exempted);
|
||||||
~Rule();
|
~Rule();
|
||||||
|
|
||||||
|
std::string match() const;
|
||||||
|
|
||||||
const std::string& column() const { return m_column; }
|
const std::string& column() const { return m_column; }
|
||||||
const std::string& table() const { return m_table; }
|
const std::string& table() const { return m_table; }
|
||||||
const std::string& database() const { return m_database; }
|
const std::string& database() const { return m_database; }
|
||||||
|
Reference in New Issue
Block a user