Class: MyObfuscate
- Inherits:
-
Object
- Object
- MyObfuscate
- Defined in:
- lib/my_obfuscate.rb,
lib/my_obfuscate/mysql.rb,
lib/my_obfuscate/version.rb,
lib/my_obfuscate/sql_server.rb
Overview
Class for obfuscating MySQL dumps. This can parse mysqldump outputs when using the -c option, which includes column names in the insert statements.
Defined Under Namespace
Constant Summary collapse
- NUMBER_CHARS =
"1234567890"
- USERNAME_CHARS =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" + NUMBER_CHARS
- SENSIBLE_CHARS =
USERNAME_CHARS + '+-=[{]}/?|!@#$%^&*()`~'
- VERSION =
"0.3.6"
Instance Attribute Summary collapse
-
#config ⇒ Object
Returns the value of attribute config.
-
#database_type ⇒ Object
Returns the value of attribute database_type.
-
#fail_on_unspecified_columns ⇒ Object
Returns the value of attribute fail_on_unspecified_columns.
-
#globally_kept_columns ⇒ Object
Returns the value of attribute globally_kept_columns.
Class Method Summary collapse
- .apply_table_config(row, table_config, columns) ⇒ Object
- .make_conditional_method(conditional_method, index, row) ⇒ Object
- .random_integer(between) ⇒ Object
- .random_string(length_or_range, chars) ⇒ Object
- .row_as_hash(row, columns) ⇒ Object
Instance Method Summary collapse
- #check_for_defined_columns_not_in_table(table_name, columns) ⇒ Object
- #check_for_table_columns_not_in_definition(table_name, columns) ⇒ Object
- #database_helper ⇒ Object
- #fail_on_unspecified_columns? ⇒ Boolean
-
#initialize(configuration = {}) ⇒ MyObfuscate
constructor
Make a new MyObfuscate object.
-
#obfuscate(input_io, output_io) ⇒ Object
Read an input stream and dump out an obfuscated output stream.
- #obfuscate_bulk_insert_line(line, table_name, columns) ⇒ Object
- #reassembling_each_insert(line, table_name, columns) ⇒ Object
Constructor Details
#initialize(configuration = {}) ⇒ MyObfuscate
Make a new MyObfuscate object. Pass in a configuration structure to define how the obfuscation should be performed. See the README.rdoc file for more information.
15 16 17 |
# File 'lib/my_obfuscate.rb', line 15 def initialize(configuration = {}) @config = configuration end |
Instance Attribute Details
#config ⇒ Object
Returns the value of attribute config.
7 8 9 |
# File 'lib/my_obfuscate.rb', line 7 def config @config end |
#database_type ⇒ Object
Returns the value of attribute database_type.
7 8 9 |
# File 'lib/my_obfuscate.rb', line 7 def database_type @database_type end |
#fail_on_unspecified_columns ⇒ Object
Returns the value of attribute fail_on_unspecified_columns.
7 8 9 |
# File 'lib/my_obfuscate.rb', line 7 def fail_on_unspecified_columns @fail_on_unspecified_columns end |
#globally_kept_columns ⇒ Object
Returns the value of attribute globally_kept_columns.
7 8 9 |
# File 'lib/my_obfuscate.rb', line 7 def globally_kept_columns @globally_kept_columns end |
Class Method Details
.apply_table_config(row, table_config, columns) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/my_obfuscate.rb', line 83 def self.apply_table_config(row, table_config, columns) return row unless table_config.is_a?(Hash) row_hash = row_as_hash(row, columns) table_config.each do |column, definition| index = columns.index(column) definition = { :type => definition } if definition.is_a?(Symbol) if definition.has_key?(:unless) unless_check = make_conditional_method(definition[:unless], index, row) next if unless_check.call(row_hash) end if definition.has_key?(:if) if_check = make_conditional_method(definition[:if], index, row) next unless if_check.call(row_hash) end if definition[:skip_regexes] next if definition[:skip_regexes].any? {|regex| row[index] =~ regex} end row[index.to_i] = case definition[:type] when :email clean_quotes(Faker::Internet.email) when :string random_string(definition[:length] || 30, definition[:chars] || SENSIBLE_CHARS) when :lorem clean_bad_whitespace(clean_quotes(Faker::Lorem.sentences(definition[:number] || 1).join(". "))) when :name clean_quotes(Faker::Name.name) when :first_name clean_quotes(Faker::Name.first_name) when :last_name clean_quotes(Faker::Name.last_name) when :address clean_quotes("#{Faker::Address.street_address}\\n#{Faker::Address.city}, #{Faker::Address.state_abbr} #{Faker::Address.zip_code}") when :street_address clean_bad_whitespace(clean_quotes(Faker::Address.street_address)) when :city clean_quotes(Faker::Address.city) when :state Faker::Address.state_abbr when :zip_code Faker::Address.zip_code when :phone Faker::PhoneNumber.phone_number when :company clean_bad_whitespace(clean_quotes(Faker::Company.name)) when :ipv4 Faker::Internet.ip_v4_address when :ipv6 Faker::Internet.ip_v6_address when :url clean_bad_whitespace(Faker::Internet.url) when :integer random_integer(definition[:between] || (0..1000)).to_s when :fixed if definition[:one_of] definition[:one_of][(rand * definition[:one_of].length).to_i] else definition[:string].is_a?(Proc) ? definition[:string].call(row_hash) : definition[:string] end when :null nil when :keep row[index] else $stderr.puts "Keeping a column value by providing an unknown type (#{definition[:type]}) is deprecated. Use :keep instead." row[index] end end row end |
.make_conditional_method(conditional_method, index, row) ⇒ Object
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/my_obfuscate.rb', line 72 def self.make_conditional_method(conditional_method, index, row) if conditional_method.is_a?(Symbol) if conditional_method == :blank conditional_method = lambda { |row_hash| row[index].nil? || row[index] == '' } elsif conditional_method == :nil conditional_method = lambda { |row_hash| row[index].nil? } end end conditional_method end |
.random_integer(between) ⇒ Object
162 163 164 |
# File 'lib/my_obfuscate.rb', line 162 def self.random_integer(between) (between.min + (between.max - between.min) * rand).round end |
.random_string(length_or_range, chars) ⇒ Object
166 167 168 169 170 171 172 |
# File 'lib/my_obfuscate.rb', line 166 def self.random_string(length_or_range, chars) length_or_range = (length_or_range..length_or_range) if length_or_range.is_a?(Fixnum) times = random_integer(length_or_range) out = "" times.times { out << chars[rand * chars.length] } out end |
.row_as_hash(row, columns) ⇒ Object
68 69 70 |
# File 'lib/my_obfuscate.rb', line 68 def self.row_as_hash(row, columns) columns.zip(row).inject({}) {|m, (name, value)| m[name] = value; m} end |
Instance Method Details
#check_for_defined_columns_not_in_table(table_name, columns) ⇒ Object
174 175 176 177 178 179 180 181 182 |
# File 'lib/my_obfuscate.rb', line 174 def check_for_defined_columns_not_in_table(table_name, columns) missing_columns = config[table_name].keys - columns unless missing_columns.length == 0 = missing_columns.map do |missing_column| "Column '#{missing_column}' could not be found in table '#{table_name}', please fix your obfuscator config." end.join("\n") raise RuntimeError.new() end end |
#check_for_table_columns_not_in_definition(table_name, columns) ⇒ Object
184 185 186 187 188 189 190 191 192 |
# File 'lib/my_obfuscate.rb', line 184 def check_for_table_columns_not_in_definition(table_name, columns) missing_columns = columns - (config[table_name].keys + (globally_kept_columns || []).map {|i| i.to_sym}).uniq unless missing_columns.length == 0 = missing_columns.map do |missing_column| "Column '#{missing_column}' defined in table '#{table_name}', but not found in table definition, please fix your obfuscator config." end.join("\n") raise RuntimeError.new() end end |
#database_helper ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/my_obfuscate.rb', line 23 def database_helper if @database_helper.nil? if @database_type == :sql_server @database_helper = SqlServer.new else @database_helper = Mysql.new end end @database_helper end |
#fail_on_unspecified_columns? ⇒ Boolean
19 20 21 |
# File 'lib/my_obfuscate.rb', line 19 def fail_on_unspecified_columns? @fail_on_unspecified_columns end |
#obfuscate(input_io, output_io) ⇒ Object
Read an input stream and dump out an obfuscated output stream. These streams could be StringIO objects, Files, or STDIN and STDOUT.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/my_obfuscate.rb', line 37 def obfuscate(input_io, output_io) # We assume that every INSERT INTO line occupies one line in the file, with no internal linebreaks. input_io.each do |line| if table_data = database_helper.parse_insert_statement(line) table_name = table_data[:table_name] columns = table_data[:column_names] if config[table_name] output_io.puts obfuscate_bulk_insert_line(line, table_name, columns) else $stderr.puts "Deprecated: #{table_name} was not specified in the config. A future release will cause this to be an error. Please specify the table definition or set it to :keep." output_io.write line end else output_io.write line end end end |
#obfuscate_bulk_insert_line(line, table_name, columns) ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/my_obfuscate.rb', line 194 def obfuscate_bulk_insert_line(line, table_name, columns) table_config = config[table_name] if table_config == :truncate "" elsif table_config == :keep line else check_for_defined_columns_not_in_table(table_name, columns) check_for_table_columns_not_in_definition(table_name, columns) if fail_on_unspecified_columns? # Note: Remember to SQL escape strings in what you pass back. reassembling_each_insert(line, table_name, columns) do |row| MyObfuscate.apply_table_config(row, table_config, columns) end end end |
#reassembling_each_insert(line, table_name, columns) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/my_obfuscate.rb', line 56 def reassembling_each_insert(line, table_name, columns) output = database_helper.rows_to_be_inserted(line).map do |sub_insert| result = yield(sub_insert) result = result.map do |i| database_helper.make_valid_value_string(i) end result = result.join(",") "(" + result + ")" end.join(",") database_helper.make_insert_statement(table_name, columns, output) end |