Nginxのアクセスログに機密情報を残したくない方のためのlua-resty-querymask
最近Facebookがパスワードを平文で保存しているというニュースがありましたね。
またシステム的に保持していなくても、意図せずアクセスログに情報が残ってしまうことも考えられます。
その対策として安全にアクセスログのマスク処理を行う lua-resty-querymaskというモジュールをご紹介いたします。
使い方
OpenResty のモジュールとして動作します。 以下、README のSYNOPSIS のママです。
local querymask = require "resty.querymask" local q = querymask:new({ mode = "writelist", mask_part_string = "*", mask_part_length = 3, mask_fill_string = "*MASK*", mask_hash_seed = "hogefugapiyo", max_field_length = 512, fields = { origin = {"attr1", "attr2"}, part = {"attr3"}, fill = {"attr4"}, hash = {"attr5"}, } }) print(q:mask_query_string()) -- (example) -- curl 'http://localhost/mask?attr1=hogeeee&attr2=fugaaaa&attr3=piyoooo&attr4=fooooo&attr5=barrrrr' -- -- attr1=hogeeee&attr2=fugaaaa&attr3=piy****&attr4=*MASK*&attr5=eoroiaweuroajejrfalwjreoaijrejwaerwaer'
モード
whitelist
モード と blacklist
モードがあります。
そのままなのですがホワイトリストモードは「fieldsに指定したパラメータのみを対象とし、マスク処理を行う」モードで、ブラックリストモードは「基本的には全パラメータを出力対象とし、fieldsに指定された項目のみマスク処理を行う」モードです。
ターゲット・マスク処理
以下の4種類があります。
- origin
- 処理対象をそのまま出力します(ホワイトリストモードで利用)
- part
- 項目の一部のみをマスクします。
mask_part_string
とmask_part_length
の値に準じ処理を行います。 - ex) 設定が mask_part_string=%, mask_part_length=5 で、指定パラメータ値が
abcdefghijklmn
の時- 出力値=
abcde%%%%%%%%%
- 出力値=
- 項目の一部のみをマスクします。
- fill
- 項目の値が設定した固定値でマスクされます。
mask_fill_string
の値に準じ処理を行います
- 項目の値が設定した固定値でマスクされます。
- hash
- 項目の値をhashingします。
mask_hash_seed
の値に準じ処理を行います。
- 項目の値をhashingします。
hashingされた値の表示
メールアドレスをハッシュ化したいことはよくあることでしょう。
たとえばメールアドレスをハッシュ化していて、 hogehoge@gmail.com
のメールアドレスを検索したい時のハッシュ値を知りたいときは、以下のようなエンドポイントを用意し
curl 'http://xxxxxxxxx/get_hash?data=hogehoge@gmail.com'
といったリクエストを実行するとお手軽にハッシュ値を得ることが出来ます。
(こちらも同様にREADMEに例が載っています)
location /get_hash { # なんらかの制限をしておくと良いですね allow xxx.xxx.xxx.xxx; deny all; content_by_lua_block { local data = ngx.req.get_uri_args().data local querymask = require "resty.querymask" local q = querymask:new({ mode = "writelist", mask_part_string = "*", mask_part_length = 3, mask_fill_string = "*MASK*", mask_hash_seed = "hogefugapiyo", max_field_length = 512, fields = { origin = {"attr1", "attr2"}, part = {"attr3"}, fill = {"attr4"}, hash = {"attr5"}, } }) -- get hash local data_hash = q:get_hash(data) ngx.header.content_type = "text/plain" ngx.say(data_hash) } }
設定インタフェースについて
自分でもイマイチだと思っているのですが、モジュールの設定インタフェースどうにかしたい気持ち…
ホワイトリストとブラックリストを両方包括しているので仕方なくこうしているのもあるのですが、もっとイイ感じの設定方法があればPRくださいませ!
その他便利なところ
クエリパラメータもbodyもまとめて処理しているので、同じインタフェースで同じ変数に簡単に突っ込めるのが割と便利!
まとめ
昨今、セキュリティ関連の話題が尽きません。お手軽かつハイパフォーマンスにマスク処理を行いたいときには検討してみてください。