mongo_masker 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f217269ec66fb6a591ab9892b713668ef49cd761030f0f1daf3fb8f806c928f5
4
+ data.tar.gz: c3720d536bd94c8adc2c2a5fbd07446ebb54e9a192d34e93b0be7fea36ee34f3
5
+ SHA512:
6
+ metadata.gz: 16e4d2ca4b1b9ef37005beebe1bfb44431b8ba4bfdd93758c15f55178042da1f1ccee353cec9f70823ddc7928d6619b1c0c32a82a13f42ceb95824ef0e5c8e2a
7
+ data.tar.gz: cd977e2df4ecc121785d3c28158020883f895f0922b3973c21de401c54e0f6937f52d0655af6b26d3ccf6bc84d3641968b4a41972cbe22e98a30a20cb15da71e
data/.dockerignore ADDED
@@ -0,0 +1 @@
1
+ /data/
data/.gitignore ADDED
@@ -0,0 +1,53 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+
52
+ # import data
53
+ /data/
data/Dockerfile ADDED
@@ -0,0 +1,12 @@
1
+ FROM ruby:2.6
2
+
3
+ ENV LANG C.UTF-8
4
+
5
+ WORKDIR /masking
6
+
7
+ ADD Gemfile /masking/Gemfile
8
+ ADD Gemfile.lock /masking/Gemfile.lock
9
+
10
+ RUN bundle install
11
+
12
+ COPY . .
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'ffaker'
4
+ gem 'mongo'
5
+ gem 'irb'
6
+ gem 'thor'
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ bson (4.4.2)
5
+ ffaker (2.10.0)
6
+ irb (1.0.0)
7
+ mongo (2.7.0)
8
+ bson (>= 4.4.2, < 5.0.0)
9
+ thor (0.20.3)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ ffaker
16
+ irb
17
+ mongo
18
+ thor
19
+
20
+ BUNDLED WITH
21
+ 1.17.1
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Mongodb-data-masking
2
+ Masking your data in mongodb
3
+
4
+ # Usage
5
+ ```
6
+ bundle
7
+ ruby masker.rb mask mask.yml
8
+ ```
9
+
10
+ # Example mask.yml
11
+ ```yaml
12
+ version: 1
13
+ db_url: mongodb://mongodb:27017/development
14
+ models:
15
+ - name: users
16
+ condition:
17
+ email:
18
+ "$not": !ruby/regexp '/@basicinc\.jp$/'
19
+ fields:
20
+ email: FFaker::Internet.safe_email
21
+ - name: users
22
+ fields:
23
+ reset_password_token: String.new
24
+ confirmation_token: String.new
25
+ - name: sitesconta
26
+ fields:
27
+ title: FFaker::NameJA.name
28
+ description: FFaker::LoremJA.sentence
29
+ domain: FFaker::Internet.domain_name
30
+ external_service: :external_services
31
+ - name: external_services
32
+ fields:
33
+ _type: "'ExternalService'"
34
+ facebook: nil
35
+ google: nil
36
+ - name: contacts
37
+ condition:
38
+ site_id:
39
+ "$ne": BSON::ObjectId('12312345346456456456sdff')
40
+ delete: true
41
+ ```
data/bin/mongo_masker ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mongo_masker'
4
+ require 'thor'
5
+
6
+ class MongoMasker::Cli < Thor
7
+ include Thor::Actions
8
+
9
+ desc 'mask MASKER_FILE', 'Mask database'
10
+ def mask(masker_file)
11
+ masker = MongoMasker::Main.new(masker_file)
12
+ masker.mask
13
+ end
14
+ end
15
+
16
+ MongoMasker::Cli.start
@@ -0,0 +1,20 @@
1
+ version: '3'
2
+ services:
3
+ mongodb:
4
+ image: mongo:3.4.2
5
+ volumes:
6
+ - mongo-data:/data/db
7
+ - ./data:/tmp/data
8
+
9
+ app:
10
+ build: ./
11
+ links:
12
+ - mongodb
13
+ volumes:
14
+ - ./lib:/masking/lib
15
+ - ./bin:/masking/bin
16
+ stdin_open: true
17
+ tty: true
18
+
19
+ volumes:
20
+ mongo-data:
@@ -0,0 +1,141 @@
1
+ require 'yaml'
2
+ require 'ffaker'
3
+ require 'mongo'
4
+
5
+ Mongo::Logger.logger.level = Logger::FATAL
6
+
7
+ module MongoMasker
8
+ class Main
9
+ def initialize(config = nil)
10
+ configure config unless config.nil?
11
+ @sequence = 0
12
+ end
13
+
14
+ def db
15
+ @db ||= Mongo::Client.new(@config['db_url'] || 'mongodb://mongodb:27017/development')
16
+ end
17
+
18
+ def mask(config = nil)
19
+ configure config unless config.nil?
20
+ raise 'Please provide mask' if @config.nil?
21
+
22
+ track_time do
23
+ @config['models'].each do |model|
24
+ mask_document model
25
+ end
26
+ puts 'Done!' unless @config['silent']
27
+ end
28
+ end
29
+
30
+ def configure(config)
31
+ @config = config.is_a?(String) ? load_from_yaml(config) : config
32
+ end
33
+
34
+ def seq
35
+ @sequence += 1
36
+ end
37
+
38
+ private
39
+
40
+ def track_time
41
+ start_at = Time.now
42
+ yield
43
+ finish_at = Time.now
44
+ puts "Elapsed time: #{format_time_diff(start_at, finish_at)}" unless @config['silent']
45
+ end
46
+
47
+ def format_time_diff(start_at, finish_at)
48
+ output = Time.at(finish_at - start_at).strftime '%H hours %M minutes %S seconds'
49
+ output.gsub(/^0+ hours /, '').gsub(/^0+ minutes /, '')
50
+ end
51
+
52
+ def mask_document(model)
53
+ scope = prepair_scope model
54
+
55
+ if model['delete']
56
+ delete_documents scope, model
57
+ else
58
+ mask_each_document scope, model
59
+ end
60
+ rescue StandardError => e
61
+ puts "\nCan't mask #{model['name']}" unless @config['silent']
62
+ raise e
63
+ ensure
64
+ puts '' unless @config['silent']
65
+ end
66
+
67
+ def delete_documents(scope, model)
68
+ puts "Deleting #{model['name']}"
69
+ scope.delete_many
70
+ end
71
+
72
+ def mask_each_document(scope, model)
73
+ total = scope.count()
74
+
75
+ scope.each_with_index do |document, index|
76
+ print "Masking #{model['name']} (#{index + 1}/#{total})\r" unless @config['silent']
77
+ mask = create_mask model['fields']
78
+
79
+ apply_mask(document, mask)
80
+ db[model['name']].find({_id: document['_id']}).update_one(document)
81
+ end
82
+ end
83
+
84
+ def prepair_scope(model)
85
+ scope = db[model['name']]
86
+ scope.find(parse_condition(model['condition']))
87
+ end
88
+
89
+ def parse_condition condition
90
+ if condition.is_a?(String) && condition.match?(/^BSON::ObjectId\('[A-Za-z0-9]+'\)$/)
91
+ return eval(condition)
92
+ end
93
+
94
+ if condition.is_a?(Hash)
95
+ condition.each do |op, value|
96
+ condition[op] = parse_condition value
97
+ end
98
+ return condition
99
+ end
100
+
101
+ if condition.is_a?(Array)
102
+ return condition.map do |value|
103
+ parse_condition value
104
+ end
105
+ end
106
+
107
+ condition
108
+ end
109
+
110
+ def create_mask(fields)
111
+ mask = {}
112
+ fields.each do |field, value|
113
+ if value.is_a?(Symbol)
114
+ sub_mask = create_mask @config['models'].find{|model| model['name'] == value.to_s}['fields']
115
+ mask[field] = sub_mask
116
+ next
117
+ end
118
+
119
+ mask[field] = evalute_field_value(value)
120
+ end
121
+ mask
122
+ end
123
+
124
+ def apply_mask(document, mask)
125
+ mask = mask.reject do |field, _value|
126
+ document[field].nil?
127
+ end
128
+ document.update(mask)
129
+ end
130
+
131
+ def evalute_field_value(value)
132
+ eval(value)
133
+ rescue StandardError
134
+ raise "Can't eval `#{value}`"
135
+ end
136
+
137
+ def load_from_yaml(config_path)
138
+ YAML.load_file config_path
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'mongo_masker'
3
+ s.version = '1.0.0'
4
+ s.date = '2019-02-19'
5
+ s.summary = 'Mongo masker'
6
+ s.description = 'Masking production data mongodb for testing/development'
7
+ s.authors = ['Clicia Scarlet']
8
+ s.email = ['pnvduc@gmail.com']
9
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
10
+ s.bindir = 'bin'
11
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
12
+ s.require_paths = ['lib']
13
+ s.homepage = 'https://github.com/basicinc/Masker'
14
+ s.license = 'MIT'
15
+
16
+ s.add_runtime_dependency 'thor'
17
+ s.add_runtime_dependency 'mongo'
18
+ s.add_runtime_dependency 'ffaker'
19
+ s.add_runtime_dependency 'irb'
20
+
21
+ s.add_development_dependency 'bundler'
22
+ s.add_development_dependency 'rake'
23
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongo_masker
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Clicia Scarlet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mongo
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ffaker
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: irb
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Masking production data mongodb for testing/development
98
+ email:
99
+ - pnvduc@gmail.com
100
+ executables:
101
+ - mongo_masker
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".dockerignore"
106
+ - ".gitignore"
107
+ - Dockerfile
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - README.md
111
+ - bin/mongo_masker
112
+ - docker-compose.yml
113
+ - lib/mongo_masker.rb
114
+ - mongo_masker.gemspec
115
+ homepage: https://github.com/basicinc/Masker
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.7.6
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: Mongo masker
139
+ test_files: []