diff --git a/Documentation/Filters/Masking.md b/Documentation/Filters/Masking.md index 558525ffb..3cdd6d4f0 100644 --- a/Documentation/Filters/Masking.md +++ b/Documentation/Filters/Masking.md @@ -76,7 +76,7 @@ type=service filters=Mask-SSN ``` -# Filter Parameter +## Filter Parameters The masking filter has one mandatory parameter - `rules_file`. @@ -90,6 +90,18 @@ MariaDB MaxScale. 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 The masking rules are expressed as a JSON object. diff --git a/server/modules/filter/masking/CMakeLists.txt b/server/modules/filter/masking/CMakeLists.txt index 85a0b2d05..fde8d9e7f 100644 --- a/server/modules/filter/masking/CMakeLists.txt +++ b/server/modules/filter/masking/CMakeLists.txt @@ -1,6 +1,7 @@ if (JANSSON_FOUND) add_library(masking SHARED maskingfilter.cc + maskingfilterconfig.cc maskingfiltersession.cc maskingrules.cc ) diff --git a/server/modules/filter/masking/maskingfilter.cc b/server/modules/filter/masking/maskingfilter.cc index a679a3326..1aa92e344 100644 --- a/server/modules/filter/masking/maskingfilter.cc +++ b/server/modules/filter/masking/maskingfilter.cc @@ -77,6 +77,8 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE() MXS_NOTICE("Masking module %s initialized.", VERSION_STRING); + typedef MaskingFilter::Config Config; + static MXS_MODULE info = { MXS_MODULE_API_FILTER, @@ -90,8 +92,11 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE() NULL, /* Thread init. */ NULL, /* Thread finish. */ { - {"rules_file", MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED}, - {MXS_END_MODULE_PARAMS} + { Config::rules_file_name, MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED }, + { 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 -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::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 sRules = MaskingRules::load(config.rules_file().c_str()); if (sRules.get()) diff --git a/server/modules/filter/masking/maskingfilter.hh b/server/modules/filter/masking/maskingfilter.hh index fbd7ad1dc..b3543e44c 100644 --- a/server/modules/filter/masking/maskingfilter.hh +++ b/server/modules/filter/masking/maskingfilter.hh @@ -39,6 +39,7 @@ public: void reload(DCB* pOut); + const Config& config() const { return m_config; } SMaskingRules rules() const; private: diff --git a/server/modules/filter/masking/maskingfilterconfig.cc b/server/modules/filter/masking/maskingfilterconfig.cc new file mode 100644 index 000000000..96a63c313 --- /dev/null +++ b/server/modules/filter/masking/maskingfilterconfig.cc @@ -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); +} diff --git a/server/modules/filter/masking/maskingfilterconfig.hh b/server/modules/filter/masking/maskingfilterconfig.hh index afccb2cbe..fe0999ce0 100644 --- a/server/modules/filter/masking/maskingfilterconfig.hh +++ b/server/modules/filter/masking/maskingfilterconfig.hh @@ -13,22 +13,42 @@ */ #include +#include +#include #include class MaskingFilterConfig { 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) : m_name(zName) + , m_warn_type_mismatch(WARN_NEVER) {} ~MaskingFilterConfig() {} - const std::string& name() const { return m_name; } - const std::string& rules_file() const { return m_rules_file; } + const std::string& name() const { return m_name; } + 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_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: - std::string m_name; - std::string m_rules_file; + std::string m_name; + std::string m_rules_file; + warn_type_mismatch_t m_warn_type_mismatch; }; diff --git a/server/modules/filter/masking/maskingfiltersession.cc b/server/modules/filter/masking/maskingfiltersession.cc index a9d2e409f..acda3a3a2 100644 --- a/server/modules/filter/masking/maskingfiltersession.cc +++ b/server/modules/filter/masking/maskingfiltersession.cc @@ -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) { MXS_NOTICE("handle_row"); @@ -213,7 +224,10 @@ void MaskingFilterSession::handle_row(GWBUF* pPacket) LEncString s = value.as_string(); pRule->rewrite(s); } - + else if (m_filter.config().warn_type_mismatch() == Config::WARN_ALWAYS) + { + warn_of_type_mismatch(*pRule); + } } ++i; } @@ -238,6 +252,10 @@ void MaskingFilterSession::handle_row(GWBUF* pPacket) LEncString s = value.as_string(); pRule->rewrite(s); } + else if (m_filter.config().warn_type_mismatch() == Config::WARN_ALWAYS) + { + warn_of_type_mismatch(*pRule); + } } ++i; } diff --git a/server/modules/filter/masking/maskingfiltersession.hh b/server/modules/filter/masking/maskingfiltersession.hh index fbd94bebb..7e7f59c22 100644 --- a/server/modules/filter/masking/maskingfiltersession.hh +++ b/server/modules/filter/masking/maskingfiltersession.hh @@ -20,10 +20,13 @@ #include "maskingrules.hh" class MaskingFilter; +class MaskingFilterConfig; class MaskingFilterSession : public maxscale::FilterSession { public: + typedef MaskingFilterConfig Config; + ~MaskingFilterSession(); static MaskingFilterSession* create(SESSION* pSession, const MaskingFilter* pFilter); diff --git a/server/modules/filter/masking/maskingrules.cc b/server/modules/filter/masking/maskingrules.cc index ea93e36df..7a75f715c 100644 --- a/server/modules/filter/masking/maskingrules.cc +++ b/server/modules/filter/masking/maskingrules.cc @@ -614,6 +614,19 @@ auto_ptr MaskingRules::Rule::create_from(json_t* pRule) 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 { diff --git a/server/modules/filter/masking/maskingrules.hh b/server/modules/filter/masking/maskingrules.hh index b3021d786..80e695718 100644 --- a/server/modules/filter/masking/maskingrules.hh +++ b/server/modules/filter/masking/maskingrules.hh @@ -88,6 +88,8 @@ public: const std::vector& exempted); ~Rule(); + std::string match() const; + const std::string& column() const { return m_column; } const std::string& table() const { return m_table; } const std::string& database() const { return m_database; }