はじめに
- この記事は以前導入したDatasunriseの動的マスキング機能を試すという内容です
- 導入編はこちら
マスキングの仕様
プリセットのマスキング機能は公式ドキュメントの5.10.2 Masking Methods
に記載されています。
対象のカラムの型によって適用可能なプリセットフィルタが決まっているようです。(数字置換系ルールはINTやVARCHAR、文字列置換系のルールはVARCHARといった具合)
ちなみにTEXT型はDefault
かUnstructured
、またはFunction call
のみ適用可能らしい(困った)
- マスキングの仕組み
DataSunrise_Database_Security_Suite_User_Guideの5.1 execution order of DataSunrise Rulues
より、
If the query was not blocked at the previous stage, it is examined for matching conditions defined by existing Masking Rules. If a Masking Rule matches, DataSunrise modifies the query's code according to the Rule's settings and redirects the modified query to the target DB. Having received the modified query, the target DB edits its response and outputs obfuscated ("masked") values instead of actual DB contents.
ルールが一致するとDataSunriseはSQLコードを変更し、それをターゲットDBにリダイレクトして難読化した結果を得る、みたいなところでしょうか。
試してみた
1.環境について
構成イメージは上記の通りです。DBはAurora MySQLです。
今回はDataSunriseを導入したインスタンスにSSMでアクセスし、mysql -h [DataSunriseインスタンスのhost名] -u [ユーザ名] -p -P [proxyのポート番号]
でDataSunrise経由でDBにアクセスします。その後Sunriseでプリセットされているマスキング機能を試していきます。
ちなみに、上記DBの接続を保ったままGUIでのマスキング設定を行った場合、DBに再接続することなくマスキングが適用されます。これはマスキングを試す際地味に便利な仕様です。
設定自体はDataSunriseのGUIから実施します。(CLIも可)
※DB名/カラム名等はQiita記事作成の際に手動マスキングしています。
2.1 Fixed String
対象文字列を任意の文字列で置き換えるというもの。
1つのルールごとに置き換え先の文字列はひとつしか入力できません。
黒塗りしていますが、マスキング対象のDB/テーブル/カラムを選択可能です。
MySQL [*****]> select ***** from ***** limit 10;
+--------------+
| ***** |
+--------------+
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
| 見本太郎 |
+--------------+
対象カラムをselectすると入力した文字列に変換されています。
2.2 Credit card masking
- 入力文字列内の数字をXで置き換えるルール。
- ハイフン区切りを認識し、最後の数字はマスキングしないようです。
- 1234-5678-9012-3456ならXXXX-XXXX-XXXX-3456みたいな
- 今回はこれを電話番号のマスキングに活用できるか試してみました。
MySQL [*****]> select distinct ***** from ***** limit 10;
+--------------+
| ***** |
+--------------+
| XX-XXXX-2555 |
| XX-XXXX-1234 |
| XX-XXXX-0241 |
| XX-XXXX-1235 |
| XX-XXXX-3838 |
| XXX-XXX-6610 |
| XX-XXXX-4871 |
| XXX-XXX-5750 |
| XXXX-XX-5368 |
| XX-XXXX-6216 |
+--------------+
10 rows in set (0.00 sec)
市外局番も含めよしなにマスキングしてくれています。
MySQL [*****]> select a.ct from (select ***** as test from *****) as a limit 10;
+--------------+
| test |
+--------------+
| XX-XXXX-2555 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
| XX-XXXX-1234 |
+--------------+
10 rows in set (0.00 sec)
対象カラムをサブクエリ内で呼び、エイリアスをつけるパターンでもマスキングされています。
これはうれしいですね。
2.3 Regexp replace
正規表現を用いた文字列置き換えが可能のようです。
正規表現のパターンと何で置き換えたいを入力します。
電話番号や金額系に活用できるでしょうか。
MySQL [*****]> select ***** from ***** limit 10;
ERROR 1305 (42000): FUNCTION mysql.regexp_replace does not exist
実行したところ怒られました。今回のTargetDBはAurora MySQLなのですが、そもそもREGEX_REPLACE関数はPostgreSQLの関数なのでした。
MySQLでもバージョン8.0.4でREGEX_REPLACE関数がサポートされるらしいのですが、Aurora MySQLでは・・・。
2.4 Mask first chars
入力文字列の頭からn文字目までを任意の文字で置換するルールです。
頭から6文字目までを0で置き換える設定にしてみました。
MySQL [*****]> select distinct ***** from ***** limit 10;
+------------------------------------------------------------------------------+
| ***** |
+------------------------------------------------------------------------------+
| NULL |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
| 000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= |
+------------------------------------------------------------------------------+
10 rows in set (0.07 sec)
0で置換できています。
2.5 Random value like current
数値の置き換えに関するルールで、入力値と同じ桁数でランダムな数値を返します。
ちなみに数値系のルールは単純な置換のFixed number
や最大最小値を定めてその間のランダムな値を返すRandom from interval
がありますが、今回は試していません。なお、当然対象のカラムはINT等である必要があります。
MySQL [*****]> select ***** from ***** limit 10;
+-------------------+
| ***** |
+-------------------+
| 4262299 |
| 1 |
| 3039358 |
| 8 |
| 1387122 |
| 4432493 |
| 7 |
| 7708035 |
| 4 |
| 7560250 |
+-------------------+
10 rows in set (0.01 sec)
1桁と7桁が混在するカラムで試したところ、ランダムな値に置き換わっているのが確認できました。
ちなみに、数値系のカラムと文字列系のカラムを同時に選択すると、Masking Methodは基本的なもの(全て空白にするもの等)しか選べなくなります。
2.6 Email masking
メールアドレスに関するルールです。これは文字列の最初と最後以外を*で置き換えるというものですが、他にもトップレベルのドメインだけを残すEmail masking full
や@の前だけを置き換えるMask username of Email
ルールが用意されています。
- Email masking
MySQL [*****]> select distinct ***** from ***** limit 10;
+---------------------------+
| ***** |
+---------------------------+
| |
| n***********@******.**m |
| m***@******.**m |
| k************@******.**m |
| o**********@******.**m |
| o***********@******.**m |
| o************@******.**m |
| o*************@******.**m |
+---------------------------+
8 rows in set (0.01 sec)
- Email masking full
MySQL [*****]> select distinct ***** from ***** limit 10;
+---------------------------+
| ***** |
+---------------------------+
| |
| ************@******.com |
| ****@******.com |
| *************@******.com |
| ***********@******.com |
| **************@******.com |
+---------------------------+
6 rows in set (0.01 sec)
- Mask username of Email
MySQL [*****]> select distinct ***** from ***** limit 10;
+---------------------------+
| ***** |
+---------------------------+
| |
| ************@XXXXX.com |
| ****@XXXXX.com |
| *************@XXXXX.com |
| ***********@XXXXX.com |
| **************@XXXXX.com |
+---------------------------+
※プロバイダ名は記事化に伴い"XXXXX"に手動マスキングしていますが、実際には表示されます。
ちなみにカウントもよしなにやってくれます。
MySQL [*****]> select count(*****) from ***** limit 10;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| count(case when LENGTH(trim(*****)) <= 1 then ***** else CONCAT( LEFT(trim(*****), 1) , INSERT(INSERT( REPEAT('*', LENGTH(trim(*****))-2), INSTR(trim(*****), '@') - 1, 1, '@' ), INSTR(trim(*****), '.')-1, 1, '.' ) , RIGH |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 3084 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set, 3077 warnings (0.01 sec)
- 直接DBに繋いで試した場合
MySQL [*****]> select count(*****) from ***** limit 10;
+--------------------+
| count(*****) |
+--------------------+
| 3084 |
+--------------------+
1 row in set (0.01 sec)
カウント数が一致しているのが確認できます。
2.7 おまけ TEXT型について
2.1-2.6で試したルールはVARCHAR型やINT型等のカラムでしたが、当社にてマスキングしたいカラムにTEXT型のものがあります。しかしながら、TEXT型カラムを選んだ場合、選択できるMasking MethodはDefault
かFunction call
、unstructured masking
ルールのみです。
TEXT型はEmpty Spaceで置き換えるか事前に仕込んだFUNCTIONを呼び出すしか選択肢がないことを表しています。
unstructured masking
はReplacing potentially sensitive values with the "*" character
とのことですが、試したところ日本語には対応していませんでした。(何もマスキングされませんでした)
- Defaultを試す
MySQL [*****]> select ***** from ***** limit 10;
+----------+
| ***** |
+----------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+----------+
10 rows in set (0.00 sec)
- unstructured maskingを試す
ySQL [*****]> select ***** from ***** limit 1;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| contents |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| XXXXXXXXXXXXXXXXXXXXXXXXXXX
※記事化に伴い手動でXで置換しましたが、マスキングされていませんでした。
まとめ
簡単な設定だけでこれだけのマスキングができるというのは、かなりありがたいのではないかと思います。
マスキング以外の機能も試してみたいところですね。
Reference