Mariadb MaxScale使って、MySQLで持ってる個人情報のマスキングやってみた

# なんでこんなことやったの？
- 担当プロジェクトにてセキュリティ面強化における開発要望となったため調査したら、権限周りと連動させての実装方法として意外と良さそうだったから :thinking: 
- アプリケーションで対応する方法もあるとは思うけど、運用で度々変更を求められることが想定されたので、設定値変更くらいで変えられる仕組みがよかった :thumbsup: 

# とりあえず試してみた
#### 使ったサーバが `Amazon Linux 1` だったのもあり、公式サイトのインストール手順にそって対応するとエラーが出てEC2にはインストールできず・・・ :cry: 

```
$ cat /etc/system-release
Amazon Linux AMI release 2018.03

$ curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
[error] Detected RHEL or compatible but version () is not supported.
[error] The MariaDB Repository supports these Linux OSs, on x86-64 only:
    * RHEL/CentOS 6, 7, & 8
    * Ubuntu 16.04 LTS (xenial), 18.04 LTS (bionic), & 20.04 LTS (focal)
    * Debian 8 (jessie), 9 (stretch), & 10 (buster)
    * SLES 12 & 15
[error] See https://mariadb.com/kb/en/mariadb/mariadb-package-repository-setup-and-usage/#platform-support
```

#### Dockerイメージなら用意されてるみたいだったので、それでトライ :thumbsup: 
とりあえずEC2にDockerインストールして、イメージ取ってきて、作ったconfigをコピーして `docker run` してSQL実行してみたらでけた :tada: :tada: :tada:

```
$ sudo yum update -y
$ sudo yum install -y docker
$ sudo service docker start
Starting cgconfig service:                                 [  OK  ]
Starting Docker:                                           [  OK  ]
$ sudo usermod -a -G docker ec2-user
$ docker pull mariadb/maxscale:latest
$ docker run -d -p 4008:4008 --name mxs -v /etc/maxscale.cnf:/etc/maxscale.cnf -v /etc/maxscale.cnf.d/masking_rules.json:/etc/maxscale.cnf.d/masking_rules.json mariadb/maxscale:latest
$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                    NAMES
XXXXXXXXXXXX        mariadb/maxscale:latest   "docker-entrypoint.s…"   7 minutes ago       Up 7 minutes        0.0.0.0:4008->4008/tcp   mxs

```

#### maxscale.cnfファイルは以下のような感じ :thumbsup: 

```bash:maxscale.cnf
# MaxScale documentation on GitHub:
# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Documentation-Contents.md
# Global parameters
#
# Complete list of configuration options:
# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Getting-Started/Configuration-Guide.md
[maxscale]
threads=auto

# Server definitions
#
# Set the address of the server to the network
# address of a MySQL server.
#
[server1]
type=server
address=XX.XX.XX.XXX
port=3306
protocol=MySQLBackend

# Monitor for the servers
#
# This will keep MaxScale aware of the state of the servers.
# MySQL Monitor documentation:
# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Monitors/MySQL-Monitor.md
[MySQL-Monitor]
type=monitor
module=mysqlmon
servers=server1
user=XXXXXXXXX
password=XXXXXXXXX
monitor_interval=10000
failcount=3

[Masking]
type=filter
module=masking
rules=/etc/maxscale.cnf.d/masking_rules.json　　←こいつにマスキング周りのルールを書く形でした
warn_type_mismatch=always
large_payload=ignore

# Service definitions
#
# Service Definition for a read-only service and
# a read/write splitting service.
#
# ReadConnRoute documentation:
# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Routers/ReadConnRoute.md
[Read-Only-Service]
type=service
router=readconnroute
servers=server1
user=XXXXXXXXX
password=XXXXXXXXX
router_options=slave
filters=Masking

# This service enables the use of the MaxAdmin interface
# MaxScale administration guide:
# https://github.com/mariadb-corporation/MaxScale/blob/2.1/Documentation/Reference/MaxAdmin.md
[MaxAdmin-Service]
type=service
router=cli
# Listener definitions for the services
#
# These listeners represent the ports the
# services will listen on.
#
[Read-Only-Listener]
type=listener
service=Read-Only-Service
protocol=MySQLClient
port=4008
address=0.0.0.0
[MaxAdmin-Listener]
type=listener
service=MaxAdmin-Service
protocol=maxscaled
socket=default
```

#### マスキングルール(`/etc/maxscale.cnf.d/masking_rules.json`) はとりあえずこう :point_down: 

```bash:/etc/maxscale.cnf.d/masking_rules.json
{
    "rules": [
        {
            "replace": {
                "database": "sample",
                "table": "user",
                "column": "user_name"
            },
            "with": {
                "fill": "X"
            }
        },
        {
            "replace": {
                "database": "sample",
                "table": "user",
                "column": "mail_address"
            },
            "with": {
                "fill": "@"
            }
        }
    ]
}
```

# 実際の結果
## 直接接続
```
$ mysql -u XXXXXXXX -p -h XX.XX.XX.XXX
Enter password: 
mysql> use sample
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed

mysql> select id,user_name,mail_address from user limit 3;
+----+---------------------+-----------------+
| id | user_name           | mail_address    |
+----+---------------------+-----------------+
|  1 | 山田太郎１            | yamada@test.com |
|  2 | スズキ 一太郎         | suzuki@test.com |
|  3 | 佐藤 二郎            | sato@test.com   |
+----+---------------------+-----------------+
3 rows in set (0.00 sec)
```

## MaxScale経由で接続
```
$ mysql -u XXXXXXXX -p -h 172.17.0.2 -P 4008
Enter password: 
mysql> use sample
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed

mysql> select id,user_name,mail_address from user limit 3;
+----+---------------------+-----------------+
| id | user_name           | mail_address    |
+----+---------------------+-----------------+
|  1 | XXXXXXXXXXXXXXX     | @@@@@@@@@@@@@@@ |
|  2 | XXXXXXXXXXXXXXXX    | @@@@@@@@@@@@@@@ |
|  3 | XXXXXXXXXXXXXXXXXXX | @@@@@@@@@@@@@@@ |
+----+---------------------+-----------------+
3 rows in set (0.00 sec)
```

# 使ってみた感想
フルマスキングができたので、次は複数のマスキングルール試したらやれそう :thinking: 
電話番号のマスキングやら住所も正規表現でやればマスキング自体はできそうですね :smile:
 「対象文字列の一部はそのままがいい」とかワガママ案件でなければｗ :sweat_smile: 

# 参考サイト
## Mariadb MaxScale周り
- [MariaDB MaxScale を使ってデータベース内の個人情報をリアルタイムにマスクする - LiBz Tech Blog](https://tech.libinc.co.jp/entry/2019/08/23/111941)
- [Setting up MariaDB MaxScale - MariaDB Knowledge Base](https://mariadb.com/kb/en/mariadb-maxscale-24-setting-up-mariadb-maxscale/)
- [MariaDB Memory Allocation - MariaDB Knowledge Base](https://mariadb.com/kb/en/mariadb-memory-allocation/)
- [MariaDB MaxScale masking フィルタによるデータ保護 | スマートスタイル TECH BLOG｜データベース＆クラウドの最新技術情報を配信](https://www.s-style.co.jp/blog/2019/02/3453/)
- [MariaDB MaxScale を CentOS 7 にインストール | スマートスタイル TECH BLOG｜データベース＆クラウドの最新技術情報を配信](https://www.s-style.co.jp/blog/2019/07/4547/)
- [mariadb/maxscale - Docker Hub](https://hub.docker.com/r/mariadb/maxscale)

## その他のマスキング対応ツール
- [Dynamic Data Masking Solution | DataSunrise Data & DB Security](https://www.datasunrise.com/dynamic-data-masking/)
- [DataSunrise Security を使用して Amazon Redshift の PII データを保護および監査する | Amazon Web Services ブログ](https://aws.amazon.com/jp/blogs/news/protect-and-audit-pii-data-in-amazon-redshift-with-datasunrise-security/)
- [ユーザーローカル 個人情報匿名化フィルター](https://privacy-masking.userlocal.jp/documents/result)
[mysqlデータマスキング - mysql - Program QA](https://ja.programqa.com/question/5058611/)

## マスキングの正規表現周り
- [Laravel 6のデータマスキング - php - Program QA](https://ja.programqa.com/question/60619692/)
- [PHPの正規表現で住所を分けるには？ - PHP 解決済み| 【OKWAVE】](https://okwave.jp/qa/q7544726.html)
- [住所を分ける正規表現をチェックするやつ](https://gist.github.com/zakuroishikuro/826f1be2840509d470fa)
- [なるべく短い正規表現で住所を「都道府県/市区町村/それ以降」に分けるエクストリームスポーツ - Qiita](https://qiita.com/zakuroishikuro/items/066421bce820e3c73ce9)
- [日本の住所かどうか判定する正規表現メモ - Qiita](https://qiita.com/wildspin/items/590d59bc18160bcbf699)