クレジットカード番号がログに残らないようにする fluent-plugin-pan-anonymizer をリリースしました
カンムでは業務でお客様のクレジットカード番号を扱っています。お客様の安全のため、PCIDSSの要件をクリアするため、コンプライアンス遵守のため、カード番号は安全に取り扱う必要があります。この記事では対象をログに定め、ログに不用意にカード番号が残らないような仕組みについて書きます。
fluent-plugin-pan-anonymizer
端的に言うと、こちらの fluent filter plugin を開発し、このプラグインを経由させることでカード番号がログに記録される前にマスクしています。
https://github.com/kanmu/fluent-plugin-pan-anonymizer
プラグイン名に入っている PAN は Primary Account Number の略で、いわゆるカード番号のことを示します。ログを秘匿化する fluent plugin としては https://github.com/y-ken/fluent-plugin-anonymizer がありますが、下記のようなモチベーションでカード番号のマスキングに特化したプラグインとして開発を行いました。
デフォルトで全フィールドをマスクの対象としたい
- 例えば、user_name など本来カード番号が入らないフィールドにも、お客様が誤って入力してしまうケースがあるため(※)
- 不意に出力されてしまった stack trace にカード番号が混入してしまう可能性があるため
フィールドすべてでなく、カード番号の箇所のみをマスクしたい
- すべてがマスクされてしまうと調査、分析に支障を来す可能性があるため
※ お客様には問い合わせの際にもカード番号はどこにも記載しないように案内しております
また、4000–1111–2222–3333 などという番号がヒットした際に、本当にカード番号として正しいかどうかの検証を行う機能も持たせています。実はクレジットカード番号には規則があり、最後の数字はチェックディジットになっています。カード番号と思しき数字列が見つかった場合に検査を行い、検査をパスした場合にのみマスクします。もちろん、検査を行わない設定 checksum_algorithm none
も可能です。
動作
README.md からの転載ですが、コンフィグと動作は下記のようになります。
NOTE: 下記 4019249331712145 は存在しない番号です
<source>
@type dummy
tag dummy
dummy [
{"time": 12345678901234567, "subject": "xxxxxx", "user_inquiry": "hi, my card number is 4019249331712145 !"},
{"time": 12345678901234568, "subject": "xxxxxx", "user_inquiry": "hello inquiry code is 4567890123456789"},
{"time": 12345678901234569, "subject": "I am 4019 2493 3171 2145", "user_inquiry": "4019-2493-3171-2145 is my number"},
{"time": 14019249331712145, "subject": "ユーザーです", "user_inquiry": "4019249331712145 のカードを使っています"}
]
</source><filter **>
@type pan_anonymizer
ignore_keys time
<pan>
formats /4\d{15}/, /4[0-9]{15}/
checksum_algorithm luhn
mask 9999999999999999
</pan>
<pan>
formats /4\d{3}-\d{4}-\d{4}-\d{4}/, /4\d{3}\s*\d{4}\s*\d{4}\s*\d{4}/
checksum_algorithm luhn
mask xxxx-xxxx-xxxx-xxxx
</pan>
</filter><match **>
@type stdout
</match>
上記コンフィグにて bundle exec fluentd -c fluent.conf -p lib/fluent/plugin
を実行すると下記のように対象の番号がマスクされます。
2018-11-13 22:01:35.074963000 +0900 dummy: {"time":12345678901234567,"subject":"xxxxxx","user_inquiry":"hi, my card number is 9999999999999999 !"}
2018-11-13 22:01:36.001053000 +0900 dummy: {"time":12345678901234568,"subject":"xxxxxx","user_inquiry":"hello inquiry code is 4567890123456789"}
2018-11-13 22:01:37.021032000 +0900 dummy: {"time":12345678901234569,"subject":"I am xxxx-xxxx-xxxx-xxxx","user_inquiry":"xxxx-xxxx-xxxx-xxxx is my number"}
2018-11-13 22:01:38.050578000 +0900 dummy: {"time":14019249331712145,"subject":"ユーザーです","user_inquiry":"9999999999999999 のカードを使っています"}
ignore_keys として指定した time: 14019249331712145 を除き、マスクされていることがわかります。また 4567890123456789は formats の正規表現にはヒットしますが、luhnアルゴリズムの検証をパスしないので、カード番号とみなされずマスクされません。
以上、この filter を経由させることでログに混入した PAN がマスクされることを示しました。
金融に関するエンジニアリングの情報はあまり表に出ていませんが、フィンテックを盛り上げるために発信していきたいと思います。