Nginxのアクセスログに機密情報を残したくない方のためのlua-resty-querymask

最近Facebookがパスワードを平文で保存しているというニュースがありましたね。

jp.techcrunch.com

またシステム的に保持していなくても、意図せずアクセスログに情報が残ってしまうことも考えられます。
その対策として安全にアクセスログのマスク処理を行う 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_stringmask_part_length の値に準じ処理を行います。
    • ex) 設定が mask_part_string=%, mask_part_length=5 で、指定パラメータ値が abcdefghijklmn の時
      • 出力値=abcde%%%%%%%%%
  • fill
    • 項目の値が設定した固定値でマスクされます。 mask_fill_string の値に準じ処理を行います
  • hash
    • 項目の値をhashingします。 mask_hash_seed の値に準じ処理を行います。

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もまとめて処理しているので、同じインタフェースで同じ変数に簡単に突っ込めるのが割と便利!


まとめ

昨今、セキュリティ関連の話題が尽きません。お手軽かつハイパフォーマンスにマスク処理を行いたいときには検討してみてください。

ECSサービスで「MemberOf placement constraint unsatisfied」が表示されたときの原因

placement constraintsで条件を指定しているサービスで以下のようなメッセージが表示されたとき…

service xxxxxxxxxxxxx was unable to place a task because no container instance met all of its requirements. The closest matching container-instance zzzzzz-zzzzzzzzz-zzzzzzz-zzzzzzzz encountered error "MemberOf placement constraint unsatisfied.". For more information, see the Troubleshooting section.

もしかしたら、インスタンスのリソースが足りていないのかも?

2018年振り返りと2019年

2018年

総括

いつにも増してあっという間でした。濃い一年でしたね。

本厄

でした😇
仕事では特に厄年っぽいことはありませんでしたが、親戚関連ではいろいろありました…

仕事

総評

2018年は大きめの案件がいくつかあったのでそれに注力してました。
また去年くらいまで会社として「やりたい(やっていくべき)ところ」がなかなか進まなかったんだけど、やっとこさ楔を打てたのではないかと思う。
そのあたりのお手伝いもしていて特に大きな問題なく進められたので良かった。割と本気で2019年の動向は楽しみだったりしています。
また、実は去年に引き続き今年も病欠なしでした 😁
別エントリで病気にならない秘訣的なの書こうかなw

ロール

正式に技術チームのマネージャーに任命されたっぽいです。
ただ、自分的にはまだまだマネージメント出来てないので来年はもう少し頑張らねば。
チームメンバーはみなさん優秀なので技術的には全く心配はしてないのですが「チームとしてうまく動ける/会社にコミットできる/エンジニアとして幸せな環境である」といったところを重視してチームビルディングしていければ良いなーと思っています。

家族

娘が小学生に上がりました。息子も順調に体がでかくなってます…すぐ追い越されそう。
ただ、心配は尽きず。
やっぱり小学生にもなると、幼児期と少し悩みの軸が変わってきましたね。
最近の子供達見ていると、もう少しきちんと将来のことを考えて教育していかないとなぁと思っています。
あと家族というか家の中がわちゃわちゃしちゃってきているので、お金を使ってでも解決しようと模索中…
許容範囲を超えてきてて、子供の教育にもよろしくない :(


あと最近忙しくて奥さんとデートできていないのでデートしたい。


2019年

後厄です😇
仕事は今年ターニングポイントだと思ってるので引き続き手を抜かずにがんばります。一発当てて社員全員給料上げてくぞ! 💰

iTerm2から素のTerminalに戻ったら思いの外快適だった件

先日iTermアップデートしたらタブが全く追加されなくなるという現象に陥りました(※最新版は解消している様子)

タブ使いまくる自分としてはだいぶ困るので、仕方がなくMac標準のTerminalに戻ってみました。
すると割と不便なく普通に使えてしまいました :) 1
そんな自分がTermnalに移って最初に設定・確認したことをメモしてみます。


Terminalでやったこと

テーマ変更

標準のテーマがイケてなさすぎるのでいの一番に変えました。調べた結果 iceberg というテーマが良さそうだったので導入してみました。
Iceberg - dark blue color scheme for Vim / Neovim

導入方法

上記サイトの一番下のリンクからファイルをダウンロードし、Terminalの「環境設定」>「プロファイル」>「ギアアイコン」>「読み込み」でファイルを読み込めば設定がimportされます。

f:id:toritori0318:20181111033440p:plain

イメージ

f:id:toritori0318:20181111035840p:plain

だいぶ良い感じになります! 2


ショートカット

リンクジャンプでブラウザ表示

GitLabではgit pushしたあと自動的にマージリクエストへのURLが表示されます。そしてターミナル上でそのままリンクジャンプしてマージリクエストを確認するのはよく利用しています。
こちらの機能に関してはリンクっぽい文字列上で command+ダブルクリック で実現できました。

ダブルクリックで単語っぽいのを文字列選択

Terminalだとダブルクリック時の文字列選択がデフォルトだと微妙です。
たとえば hoge-fuga-piyo という文字列上で fuga にフォーカスあててダブルクリックすると fuga のみ選択されてしまいます。
こちらに関しては shift+command+ダブルクリック で問題なく hoge-fuga-piyo を文字列選択することができます。3

ドキュメント

実はAppleの公式サポートページに出来ること一覧が掲載されています。こちらを見るといろんな発見があるかも。

support.apple.com


Terminalにしてよかったこと

こちらは副作用ですがiTermよりも動作が軽快な気がします。
特に大きなファイルをvimで編集すると割と動作重い時があったのですが、Terminalでは今の所全く気になりません(気持ちの問題かもw)


まとめ

今までiTermを利用していた筆者がTerminalに戻ったお話でした。
Terminalでもそこそこ戦えそうなのでしばらくこのまま利用してみようと思います 🙂



  1. たんに自分がTerminalのことを知らなかっただけというお話w

  2. すみません、vimはmorokaiです😅

  3. 仕様上は「URL文字列として選択」という機能みたいです

redash-dynamic-query v1.0.4をリリースしました

github.com

pypi.org

今回のリリースで以下の改善が行われています。

1.datasource_idを指定しなくても自動で設定するように

今まではdatasource_idが必須だったのですが、これ自動で取得するMRをいただいたので基本指定しなくても良くなりました。わいわい

2.cliコマンド追加

rdq というコマンドが利用できるようになりました。
これにより、今まではpython前提だったのですが、shellからも気軽に利用できるようになっています。

helpはREADME に記載されているので詳細はそちらをご参照ください。

フォーマットは csv / tsv / json が指定できるので様々な用途でご利用いただけるかと思います。 shellだとjsonフォーマット+jqでゴニョゴニョできそうですね!

Nginxで「pread() read only xxxx of xxxx from xxxx」 エラーが表示されたときの対応と、open_file_cacheとの関連

OpenRestyで動的生成されたコンフィグファイルをLuaで読み込んで云々、という処理を行っているのですが、
その際Nginx側で表題の「pread() read only xxxx of xxxx from xxxx」といったエラーが表示される事案がありました。

状況まとめ

  • 特定の環境のみ表示
  • 突然エラーが出始めた
    • 同じロジックで、過去にエラー表示されたことはない
  • しばらく(1分くらい)するとエラーでなくなる

ググる

以下の2つのリンクが引っかかりました。

引用ですが

Investigating my Nginx configuration I found this may be related to the files cached using open_file_cache option on Nginx. According to Igor Sysoev (creator of Nginx) on this forum it was caused because the file was not updated atomically.

Temporary disabling open_file_cache fixed the issue.

とありますね。
どうやら「Nginxでopen_file_cacheを利用していて、かつそのキャッシュの対象ファイルがアトミックに処理されないとエラーになる」ようです。
open_file_cacheを無効にすれば解消しそうですが、無効にはしたくないですし原因不明のまま対応するのも気持ち悪いのでもう少し調べてみます。

コンフィグ生成コード

言われてみれば、その辺りコンフィグファイルを動的生成するときにはあまり気にしていませんでした。
Consulでイベント受信して生成しているのですが、ファイルを出力する現状のコードは以下のような感じです。

def write_file(self, file, data):
        directory = "/path/to/config"
        if not os.path.exists(directory):
            os.makedirs(directory)

        fname = directory + file    
        with open(fname, mode = 'w') as fh:
            fh.write(data)

そこで、以下のようにアトミックにファイルを生成するように変更してみました。

import tempfile
from stat import S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH

def write_file(self, file, data):
      directory = "/path/to/config"
      if not os.path.exists(directory):
          os.makedirs(directory)

      fname = directory + file
      with tempfile.NamedTemporaryFile(delete=False) as tfh:
           tfh.write(data)
           temp_fname = tfh.name

      # 新しくファイル作っているので、適切なパーミッション付与しとく
      os.chmod(temp_fname, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
      # move
      os.rename(temp_fname, fname)

この対応でエラー無く処理されるようになりました! 🙆‍

急にエラーが発生した原因

単純に、いままではファイルバッファ内に収まっていて問題にはならなかったのですが、
コンフィグファイル肥大化によりバッファが溢れてアトミックに処理されなくなっただけでしょう。

まとめ

あんまり見たことがないエラーだったので久々に記事にしてみました。
この問題はLuaに限らず普通のファイルアップロードなどでも発生するので、open_file_cacheを利用する際には気をつけましょう!

2017年振り返りと2018年

2017年

いろんなことがあったけど、振り返ってみると自分にとっては総じてあまり良い年ではなかったなーと思う。

前厄

でした😇

仕事

総評

言い訳にはなるのだけど、運用しながら新しいことをやるというのはとても難儀だった。
会社としてもとにかく動きが激しくなりはじめ、こなすことで精一杯。
自分としてやりたかったことが全然出来なかったのが悔やまれる。
あっ、あと昨年は病欠しなかったみたいです。小学生か!

ロール

なんとなくチームリーダー的なことをしてたんだけど、 中旬あたりからid:muddydixon がJoinしてくれてからは自分のロールも変わったこともあり現在はほぼおまかせ。
マネージメントやチームビルディングに関してはもともと得意分野ではなかったのだけど
「どうすればチームとしてプロダクトに貢献できるか/エンジニアがやりやすい環境をつくれるか」
を考えるのは体験としてはなかなか面白かった。
上手く行ってたかどうかは不明だけど、悪くはなかったとは思っている。

家族

息子も娘も順調に育ってくれているのでありがたい。
息子は友達少なそうなのが心配…
娘はマイクラ動画とオデッセイ動画を見すぎなので控えましょう。
奥さんは最近やさしくしてくれます。ありがとう〜


2018年

本厄です😇
仕事はとにかく面白くなりそうなんだけど、リソースが本当厳しい。
今まで以上に頑張らないといけないのだけど、完全にこれはチャンスでもあるので手を抜かずにやっていきたい 💪