Gem Version Build Status

Mask ActiveRecord/Mongoid data with ease!

Introduction

This gem is intended to mask sensitive data so that production database dumps can be used in staging or test environments. It works with Rails 4+ and modern Rubies. It supports Active Record and Mongoid models.

Getting started

Installation

Add attr_masker to your gemfile:

  gem "attr_masker", github: "riboseinc/attr_masker"

Then install the gem:

  bundle install

Basic usage

In your models, define attributes which should be masked:

  class User
    attr_masker :email, :first_name, :last_name
  end

Then, when you want to mask the data, run the db:mask Rake task in some Rails environment other than production, for example:

  bundle exec rake db:mask RAILS_ENV=staging
Warning
Data are destructively overwritten. Run rake db:mask with care!

Masking records selectively

You can use :if and :unless options to prevent some records from being altered.

# evaluates given proc for each record, and the record is passed as a proc's
# argument
attr_masker :email :unless => ->(record) { ! record.tester_user? }

# calls #tester_user? method on each record
attr_masker :first_name, :if => :tester_user?

The ActiveRecord’s ::default_scope method has no effect on masking. All table records are updated, provided that :if and :unless filters allow that. For example, if you’re using a Paranoia[https://github.com/rubysherpas/paranoia] gem to soft-delete your data, records marked as deleted will be masked as well.

Using custom maskers

By default, data is maksed with AttrMasker::Maskers::Simple masker which always returns "(redacted)" string. But anything what responds to #call can be used instead: a lambda, Method instance, and more. You can specify it by setting the :masker option.

For instance, you may want to use ffaker or Well Read Faker to generate random replacement values:

require "ffaker"

attr_masker :first_name, :masker => ->(_hash) { FFaker::Name.first_name }

A hash is passed as an argument, which includes some information about the record being masked and the attribute value. It can be used to further customize masker’s behaviour.

Built-in maskers

Attr Masker comes with several built-in maskers.

AttrMasker::Maskers::Simple

Simply replaces any value with the "(redacted)". Only useful for columns containing textual data.

This is a default masker. It is used when :masker option is unspecified.

Example:

attr_masker :first_name
attr_masker :last_name, :masker => AttrMasker::Maskers::Simple.new

Would set both first_name and last_name attributes to "(redacted)".

AttrMasker::Maskers::Replacing

Replaces characters with some masker string (single asterisk by default). Can be initialized with options.

Name Default Description

replacement

"*"

Replacement string, can be empty.

alphanum_only

false

When true, only alphanumeric charaters are replaced.

Example:

rm = AttrMasker::Maskers::Replacing.new(character: "X", alphanum_only: true)
attr_masker :phone, :masker => rm

Would mask "123-456-7890" as "XXX-XXX-XXXX".

Roadmap & TODOs

  • documentation

  • spec tests

  • Make the Rails.env (in which db:mask could be run) configurable

    • maybe by passing ENV vars

  • more masking options!

    • default scrambling algorithms?

    • structured text preserving algorithms

      • e.g., keeping an HTML snippet valid HTML, but with masked inner text

    • structured Object preserving algorithms

      • i.e. generalization of the above HTML scenario

  • I18n of the default "(redacted)" phrase

Acknowledgements

attr_encrypted for the initial code structure