Add documentation for masking filter
MXS-910
This commit is contained in:
243
Documentation/Filters/Masking.md
Normal file
243
Documentation/Filters/Masking.md
Normal file
@ -0,0 +1,243 @@
|
||||
# Masking
|
||||
|
||||
## Overview
|
||||
With the _masking_ filter it is possible to obfuscate the returned
|
||||
value of a particular column.
|
||||
|
||||
For instance, suppose there is a table _person_ that, among other
|
||||
columns, contains the column _ssn_ where the social security number
|
||||
of a person is stored.
|
||||
|
||||
With the masking filter it is possible to specify that when the _ssn_
|
||||
field is queried, a masked value is returned unless the user making
|
||||
the query is a specific one. That is, when making the query
|
||||
```
|
||||
> SELECT name, ssn FROM person;
|
||||
```
|
||||
instead of getting the real result, as in
|
||||
```
|
||||
+-------+------------+
|
||||
+ name | ssn |
|
||||
+-------+------------+
|
||||
| Alice | 721-07-4426 |
|
||||
| Bob | 435-22-3267 |
|
||||
...
|
||||
```
|
||||
the _ssn_ would be masked, as in
|
||||
```
|
||||
+-------+-------------+
|
||||
+ name | ssn |
|
||||
+-------+-------------+
|
||||
| Alice | XXX-XX-XXXX |
|
||||
| Bob | XXX-XX-XXXX |
|
||||
...
|
||||
```
|
||||
|
||||
Note that he masking filter alone is *not* sufficient for preventing
|
||||
access to a particular column. As the masking filter works on the column
|
||||
name alone a query like
|
||||
```
|
||||
> SELECT name, concat(ssn) FROM person;
|
||||
```
|
||||
will reveal the value. Also, executing a query like
|
||||
```
|
||||
> SELECT name FROM person WHERE ssn = ...;
|
||||
```
|
||||
a sufficient number of times with different _ssn_ values, will, eventually,
|
||||
reveal the social security number of all persons in the database.
|
||||
|
||||
For a secure solution, the masking filter *must* be combined with the
|
||||
firewall filter to prevent the use of functions and the use of particular
|
||||
columns in where-clauses.
|
||||
|
||||
## Configuration
|
||||
|
||||
The masking filter is taken into use with the following kind of
|
||||
configuration setup.
|
||||
|
||||
```
|
||||
[Mask-SSN]
|
||||
type=filter
|
||||
module=masking
|
||||
rules_file=...
|
||||
|
||||
[SomeService]
|
||||
type=service
|
||||
...
|
||||
filters=Mask-SSN
|
||||
```
|
||||
|
||||
# Filter Parameter
|
||||
|
||||
The masking filter has one mandatory parameter - `rules_file`.
|
||||
|
||||
#### `rules_file`
|
||||
|
||||
Specifies the path of the file where the masking rules are stored.
|
||||
A relative path is interpreted relative to the _data directory_ of
|
||||
MariaDB MaxScale.
|
||||
|
||||
```
|
||||
rules_file=/path/to/rules-file
|
||||
```
|
||||
|
||||
# Rules
|
||||
|
||||
The masking rules are expressed as a JSON object.
|
||||
|
||||
The top-level object is expected to contain a key `rules` whose
|
||||
value is an array of rule objects.
|
||||
```
|
||||
{
|
||||
"rules": [ ... ]
|
||||
}
|
||||
```
|
||||
|
||||
## Rule
|
||||
|
||||
Each rule in the rules array is a JSON object, expected to
|
||||
contain the keys `replace`, `with`, `applies_to` and
|
||||
`exempted`. The two former ones are obligatory and the two
|
||||
latter ones optional.
|
||||
|
||||
```
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"replace": { ... },
|
||||
"with": { ... },
|
||||
"applies_to": [ ... ],
|
||||
"exempted": [ ... ]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `replace`
|
||||
|
||||
The value of this key is an object that specifies the column
|
||||
whose values should be masked. The object must contain the key
|
||||
`column` and may contain the keys `table` and `database`. The
|
||||
value of these keys must be a string.
|
||||
|
||||
If only `column` is specified, then a column with that name
|
||||
matches irrespective of the table and database. If `table`
|
||||
is specified, then the column matches only if it is in a table
|
||||
with the specified name, and if `database` is specified when
|
||||
the column matches only if it is in a database with the
|
||||
specified name.
|
||||
|
||||
```
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"replace": {
|
||||
"database": "db1",
|
||||
"table": "person",
|
||||
"column": "ssn"
|
||||
},
|
||||
"with": { ... },
|
||||
"applies_to": [ ... ],
|
||||
"exempted": [ ... ]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `with`
|
||||
|
||||
The value of this key is an object that specifies what the value
|
||||
of the matched column should be replaced with. Currently, the object
|
||||
is expected to contain either the key `value` or the key `fill`. The
|
||||
value of both must be a string. If both keys are specified, then
|
||||
`value` takes presedence.
|
||||
|
||||
If `value` is specified, then its value is used to replace the actual
|
||||
value verbatim and the length of the specified value must match the
|
||||
actual returned value (from the server) exactly. If the lengths do
|
||||
not match, then if `fill` is specified its value will be used to
|
||||
mask the actual value. Otherwise an error is logged and the value
|
||||
is *not* masked.
|
||||
|
||||
If `fill` is specified, then its value will be used for masking the
|
||||
value; as such if the lenghts match, by cutting it if the actual value
|
||||
is shorter, and by repeating it, fully or partially, the necessary
|
||||
amount of times, if the actual value is longer.
|
||||
```
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"replace": {
|
||||
"column": "ssn"
|
||||
},
|
||||
"with": {
|
||||
"value": "XXX-XX-XXXX"
|
||||
},
|
||||
"applies_to": [ ... ],
|
||||
"exempted": [ ... ]
|
||||
},
|
||||
{
|
||||
"replace": {
|
||||
"column": "age"
|
||||
},
|
||||
"with": {
|
||||
"fill": "*"
|
||||
},
|
||||
"applies_to": [ ... ],
|
||||
"exempted": [ ... ]
|
||||
},
|
||||
{
|
||||
"replace": {
|
||||
"column": "creditcard"
|
||||
},
|
||||
"with": {
|
||||
"value": "1234123412341234"
|
||||
"fill": "0"
|
||||
},
|
||||
"applies_to": [ ... ],
|
||||
"exempted": [ ... ]
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `applies_to`
|
||||
|
||||
With this _optional_ key, whose value must be an array of strings,
|
||||
it can be specified what users the rule is applied to. Each string
|
||||
should be a MariaDB account string, that is, `%` is a wildcard.
|
||||
|
||||
```
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"replace": { ... },
|
||||
"with": { ... },
|
||||
"applies_to": [ "'alice'@'host'", "'bob'@'%'" ],
|
||||
"exempted": [ ... ]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If this key is not specified, then the masking is performed for all
|
||||
users, except the ones exempted using the key `exempted`.
|
||||
|
||||
#### `exempted`
|
||||
|
||||
With this _optional_ key, whose value must be an array of strings,
|
||||
it can be specified what users the rule is *not* applied to. Each
|
||||
string should be a MariaDB account string, that is, `%` is a wildcard.
|
||||
|
||||
```
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"replace": { ... },
|
||||
"with": { ... },
|
||||
"applies_to": [ ... ],
|
||||
"exempted": [ "'admin'" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user