読者です 読者をやめる 読者になる 読者になる

べにやまぶろぐ

技術寄りの話を書くつもり

Embulk で任意のカラムをマスクする embulk-filter-mask プラグインを公開しました

Embulk OSS

久しぶりの投稿ですが生きております。

ふと Embulk のプラグインを見よう見まねで作ってみました。

github.com

Embulk で転送かけるデータのカラムを指定して * で置換を行うフィルタープラグインです。

センシティブな情報なのでマスクしたい、がカラムごと削ってしまうと入力有無がわからなくて困る…あるいは JSON の一部分だけ不要なんだけど他は連携する必要がある…などの時に使えるかなと思い作りました。

README にもある通り、例えば

first_name last_name gender age contact
Benjamin Bell male 30 bell.benjamin_dummy@example.com
Lucas Duncan male 20 lucas.duncan_dummy@example.com
Elizabeth May female 25 elizabeth.may_dummy@example.com
Christian Reid male 15 christian.reid_dummy@example.com
Amy Avery female 40 amy.avercy_dummy@example.com

というデータを input に食わせた時、

filters:
  - type: mask
    columns:
      - { name: last_name}
      - { name: age}
      - { name: contact, pattern: email, length: 5}

という設定を embulk の config に記述しておくと

first_name last_name gender age contact
Benjamin **** male ** *****@example.com
Lucas ****** male ** *****@example.com
Elizabeth *** female ** *****@example.com
Christian **** male ** *****@example.com
Amy ***** female ** *****@example.com

このようなデータが output に渡されます。

カラム名を指定しただけの状態では単純に文字数分の * に置換されますが、例えばlength オプションで5文字と指定することで一律 ***** とすることも可能です。文字長に意味を持たせたくないときなどによろしいかと思います。

あとは、pattern: email とするとメールアドレスのドメイン部分(@ 以降)は残したままでマスクを行います(デフォルトは pattern: all の全文字置換)。

JSON 型のサポートもしており、

{
  "full_name": {
    "first_name": "Benjamin",
    "last_name": "Bell"
  },
  "gender": "male",
  "age": 30,
  "email": "test_mail@example.com"
}

という構造のデータが入っている user というカラムがあった時、

filters:
  - type: mask
    columns:
      - { name: user, paths: [{key: $.full_name.first_name}, {key: $.email, pattern: email}]}    

などとすると $.full_name.first_name$.email の二つの JSONPath に合致するノードをマスクします。

またこの時、前述の patternlength オプションも個別に指定が可能なので、上記の例の出力は

{
  "full_name": {
    "first_name": "********",
    "last_name": "Bell"
  },
  "gender": "male",
  "age": 30,
  "email": "*********@example.com"
}

のようになります。

指定されたカラムの value が文字列以外の型だった場合は一回文字列に変換したものを置換します。例えば [0, 1, 2, 3] のような配列は ********* になります。

あるいは上の例で $.full_name などと指定すると

  {
    "first_name": "Benjamin",
    "last_name": "Bell"
  }

の部分が単なる文字列として解釈されてまるっと * になります。

だいぶ乱暴というか投げやりなのでこの辺は今後直して各ノードの value 部分だけをマスクして

  {
    "first_name": "********",
    "last_name": "****"
  }

などとできるようにしたいところです。

JSONPath については

github.com

を内部で使っていますので、そこで解釈できるパスであれば基本的に動作すると思います。

また今回プラグインの作り方、特にテストの書き方や JSON の扱い方などは

qiita.com

や、その中でも題材にされている embulk-filter-expand_json プラグイン

github.com

を参考にさせていただきました。ありがとうございました!