MXS-591 Add filter for injecting comments

Comments specified in the cnf file will be injected as a comment before
every sql statement.
This commit is contained in:
Marko 2018-06-12 15:21:35 +03:00
parent 69b19d1473
commit de1f95028b
7 changed files with 347 additions and 0 deletions

View File

@ -0,0 +1,70 @@
# Comment Filter
## Overview
With the _comment_ filter it is possible to define comments that are
injected before the actual statements. These comments appear as sql
comments when they are received by the server.
```
[MyComment]
type=filter
module=comment
inject=Comment to be injected
[MyService]
type=service
router=readwritesplit
servers=server1
user=myuser
passwd=mypasswd
filters=MyComment
```
## Filter Parameters
The Comment filter requires one mandatory parameter to be defined.
### `inject`
A parameter that contains the comment injected before the statements.
There is also defined variable $IP that can be used to comment the
IP address of the client in the injected comment.
Variables must be written in all caps.
## Examples
### Example 1 - Inject IP address of the connected client into statements
as comment.
You want to see the IP addresses of the clients with the server so you
define filter to comment the into the statements they send.
```
[IPComment]
type=filter
module=comment
inject=IP=$IP
[MyService]
type=service
router=readwritesplit
servers=server1
user=myuser
passwd=mypasswd
filters=IPComment
```
In this example when MaxScale receives statement like:
```
SELECT user FROM people;
```
It would look like
```
/* IP=::ffff:127.0.0.1 */SELECT user FROM people;
```
when received by server.

View File

@ -16,3 +16,4 @@ add_subdirectory(tee)
add_subdirectory(throttlefilter)
add_subdirectory(topfilter)
add_subdirectory(tpmfilter)
add_subdirectory(comment)

View File

@ -0,0 +1,4 @@
add_library(comment SHARED commentfilter.cc commentfiltersession.cc)
set_target_properties(comment PROPERTIES VERSION "1.0.0")
install_module(comment core)

View File

@ -0,0 +1,91 @@
/*
* 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/bsl11.
*
* Change Date: 2020-01-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.
*/
// All log messages from this module are prefixed with this
#define MXS_MODULE_NAME "commentfilter"
#include "commentfilter.hh"
#include <string>
#include <cstring>
namespace
{
const char CN_INJECT[] = "inject";
}
// This declares a module in MaxScale
extern "C" MXS_MODULE* MXS_CREATE_MODULE()
{
static MXS_MODULE info =
{
MXS_MODULE_API_FILTER,
MXS_MODULE_IN_DEVELOPMENT,
MXS_FILTER_VERSION,
"A comment filter that can inject comments in sql queries",
"V1.0.0",
RCAP_TYPE_NONE,
&CommentFilter::s_object, // This is defined in the MaxScale filter template
NULL, /* Process init. */
NULL, /* Process finish. */
NULL, /* Thread init. */
NULL, /* Thread finish. */
{
{ CN_INJECT, MXS_MODULE_PARAM_STRING, NULL, MXS_MODULE_OPT_REQUIRED },
{ MXS_END_MODULE_PARAMS }
}
};
return &info;
}
CommentFilter::CommentFilter(std::string comment) : m_comment(comment)
{
MXS_INFO("Comment filter with comment [%s] created.", m_comment.c_str());
}
CommentFilter::~CommentFilter()
{
}
// static
CommentFilter* CommentFilter::create(const char* zName, char** pzOptions, MXS_CONFIG_PARAMETER* pParams)
{
return new CommentFilter(config_get_string(pParams, CN_INJECT));
}
CommentFilterSession* CommentFilter::newSession(MXS_SESSION* pSession)
{
return CommentFilterSession::create(pSession, this);
}
// static
void CommentFilter::diagnostics(DCB* pDcb) const
{
dcb_printf(pDcb, "Comment filter with comment: %s", m_comment.c_str());
}
// static
json_t* CommentFilter::diagnostics_json() const
{
json_t* rval = json_object();
json_object_set_new(rval, "Comment", json_string(m_comment.c_str()));
return rval;
}
// static
uint64_t CommentFilter::getCapabilities()
{
return RCAP_TYPE_NONE;
}

View File

@ -0,0 +1,53 @@
#pragma once
/*
* 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/bsl11.
*
* Change Date: 2020-01-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 <maxscale/cppdefs.hh>
#include <maxscale/filter.hh>
#include "commentfiltersession.hh"
#include <string>
class CommentFilter : public maxscale::Filter<CommentFilter, CommentFilterSession>
{
public:
// Prevent copy-constructor and assignment operator usage
CommentFilter(const CommentFilter&) = delete;
CommentFilter& operator = (const CommentFilter&) = delete;
~CommentFilter();
// Creates a new filter instance
static CommentFilter* create(const char* zName, char** pzOptions, MXS_CONFIG_PARAMETER* ppParams);
// Creates a new session for this filter
CommentFilterSession* newSession(MXS_SESSION* pSession);
// Print diagnostics to a DCB
void diagnostics(DCB* pDcb) const;
// Returns JSON form diagnostic data
json_t* diagnostics_json() const;
// Get filter capabilities
uint64_t getCapabilities();
std::string comment() const
{
return m_comment;
}
private:
std::string m_comment;
// Used in the create function
CommentFilter(std::string comment);
};

View File

@ -0,0 +1,80 @@
/*
* 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/bsl11.
*
* Change Date: 2020-01-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.
*/
// All log messages from this module are prefixed with this
#define MXS_MODULE_NAME "commentfilter"
#include "commentfiltersession.hh"
#include "commentfilter.hh"
#include <maxscale/modutil.hh>
#include <string>
#include <regex>
using namespace std;
CommentFilterSession::CommentFilterSession(MXS_SESSION* pSession, const CommentFilter* pFilter)
: maxscale::FilterSession(pSession),
m_filter(*pFilter)
{
}
CommentFilterSession::~CommentFilterSession()
{
}
//static
CommentFilterSession* CommentFilterSession::create(MXS_SESSION* pSession, const CommentFilter* pFilter)
{
return new CommentFilterSession(pSession, pFilter);
}
void CommentFilterSession::close()
{
}
int CommentFilterSession::routeQuery(GWBUF* pPacket)
{
if (modutil_is_SQL(pPacket))
{
string sql = mxs::extract_sql(pPacket);
string comment = parseComment(m_filter.comment());
string newsql = string("/* ").append(comment).append(" */").append(sql);
pPacket = modutil_replace_SQL(pPacket, (char*)newsql.c_str());
//maxscale expects contiguous memory to arrive from client so we must make the buffer contiguous
//after using modutil_replace_SQL.
GWBUF* pModified_packet = gwbuf_make_contiguous(pPacket);
if (pModified_packet)
{
pPacket = pModified_packet;
}
else
{
gwbuf_free(pPacket);
pPacket = NULL;
}
}
return pPacket ? mxs::FilterSession::routeQuery(pPacket) : 1;
}
int CommentFilterSession::clientReply(GWBUF* pPacket)
{
return mxs::FilterSession::clientReply(pPacket);
}
//TODO this probably should be refactored in some way in case we add more variables
string CommentFilterSession::parseComment(string comment)
{
string ip = m_pSession->client_dcb->remote;
string parsedComment = std::regex_replace(comment, std::regex("\\$IP"), ip);
return parsedComment;
}

View File

@ -0,0 +1,48 @@
#pragma once
/*
* 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/bsl11.
*
* Change Date: 2020-01-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 <maxscale/cppdefs.hh>
#include <maxscale/filter.hh>
#include <string>
class CommentFilter;
class CommentFilterSession : public maxscale::FilterSession
{
// Prevent copy-constructor and assignment operator usage
CommentFilterSession(const CommentFilterSession&);
CommentFilterSession& operator = (const CommentFilterSession&);
public:
~CommentFilterSession();
// Called when a client session has been closed
void close();
// Create a new filter session
static CommentFilterSession* create(MXS_SESSION* pSession, const CommentFilter* pFilter);
// Handle a query from the client
int routeQuery(GWBUF* pPacket);
// Handle a reply from server
int clientReply(GWBUF* pPacket);
private:
// Used in the create function
CommentFilterSession(MXS_SESSION* pSession, const CommentFilter* pFilter);
const CommentFilter& m_filter;
std::string parseComment(std::string comment);
};