class Fluent::Plugin::AnonymizerFilter
Constants
- MASK_METHODS
Public Class Methods
new()
click to toggle source
Calls superclass method
# File lib/fluent/plugin/filter_anonymizer.rb, line 99 def initialize super @salt_list = [] @salt_map = {} @conversions = [] end
Public Instance Methods
configure(conf)
click to toggle source
Calls superclass method
# File lib/fluent/plugin/filter_anonymizer.rb, line 106 def configure(conf) super salt_missing = false @salt_list << @salt @salt_list += @salts if @salts @masks = [] @mask_config_list.each do |c| unless c.salt || @salt_list.size > 0 salt_missing = true end conv = MASK_METHODS[c.method].call(c) [c.key || nil, *c.keys].compact.each do |key| @masks << masker_for_key(conv, key, c) end [c.key_chain || nil, *c.key_chains].compact.each do |key_chain| @masks << masker_for_key_chain(conv, key_chain.split('.'), c) end @masks << masker_for_key_pattern(conv, c.key_pattern, c) if c.key_pattern @masks << masker_for_value_pattern(conv, c.value_pattern, c) if c.value_pattern @masks << masker_for_value_in_subnet(conv, c.value_in_subnet, c) if c.value_in_subnet end # obsolete option handling [[@md5_keys,:md5],[@sha1_keys,:sha1],[@sha256_keys,:sha256],[@sha384_keys,:sha384],[@sha512_keys,:sha512]].each do |param,m| next unless param @salt_list << (@hash_salt || '') if @salt_list.empty? # to suppress ConfigError for salt missing conf = OpenStruct.new conf.salt = @hash_salt || '' conf.mask_array_elements = true conv = MASK_METHODS[m].call(conf) param.split(',').map(&:strip).each do |key| if key.include?('.') @masks << masker_for_key_chain(conv, key.split('.'), conf) else @masks << masker_for_key(conv, key, conf) end end end if @ipaddr_mask_keys @salt_list << (@hash_salt || '') if @salt_list.empty? # to suppress ConfigError for salt missing conf = OpenStruct.new conf.salt = @hash_salt || '' conf.mask_array_elements = true conf.ipv4_mask_bits = @ipv4_mask_subnet conf.ipv6_mask_bits = @ipv6_mask_subnet conv = MASK_METHODS[:network].call(conf) @ipaddr_mask_keys.split(',').map(&:strip).each do |key| if key.include?('.') @masks << masker_for_key_chain(conv, key.split('.'), conf) else @masks << masker_for_key(conv, key, conf) end end end if @masks.size < 1 raise Fluent::ConfigError, "no anonymizing operations configured" end if salt_missing raise Fluent::ConfigError, "salt (or salts) required, but missing" end end
filter(tag, time, record)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 173 def filter(tag, time, record) record.update(@masks.reduce(record){|r,mask| mask.call(r)}) end
mask_value(value, for_each) { |v| ... }
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 188 def mask_value(value, for_each) if for_each && value.is_a?(Array) value.map{|v| yield v } else yield value end end
masker_for_key(conv, key, opts)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 198 def masker_for_key(conv, key, opts) for_each = opts.mask_array_elements salt = opts.salt || salt_determine(key) if for_each ->(record){ begin if record.has_key?(key) record[key] = mask_value(record[key], for_each){|v| conv.call(v, salt) } end rescue => e log.error "unexpected error while masking value", error_class: e.class, error: e.message end record } else ->(record){ begin if record.has_key?(key) record[key] = conv.call(record[key], salt) end rescue => e log.error "unexpected error while masking value", error_class: e.class, error: e.message end record } end end
masker_for_key_chain(conv, key_chain, opts)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 226 def masker_for_key_chain(conv, key_chain, opts) for_each = opts.mask_array_elements heading = key_chain[0..-2] container_fetcher = ->(record){ heading.reduce(record){|r,c| r && r.has_key?(c) ? r[c] : nil } } tailing = key_chain[-1] ->(record){ begin container = container_fetcher.call(record) if container && container.has_key?(tailing) container[tailing] = mask_value(container[tailing], for_each){|v| conv.call(v, opts.salt || salt_determine(tailing)) } end rescue => e log.error "unexpected error while masking value", error_class: e.class, error: e.message end record } end
masker_for_key_pattern(conv, pattern, opts)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 244 def masker_for_key_pattern(conv, pattern, opts) for_each = opts.mask_array_elements regexp = Regexp.new(pattern) ->(record){ begin record.each_pair do |key, value| next unless (regexp =~ key.to_s rescue nil) record[key] = mask_value(record[key], for_each){|v| conv.call(v, opts.salt || salt_determine(key)) } end rescue => e log.error "unexpected error while masking value", error_class: e.class, error: e.message end record } end
masker_for_value_in_subnet(conv, network_str, opts)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 275 def masker_for_value_in_subnet(conv, network_str, opts) network = IPAddr.new(network_str) ->(record){ begin record.each_pair do |key, value| next unless (network.include?(value) rescue nil) record[key] = conv.call(value, opts.salt || salt_determine(key)) end rescue => e log.error "unexpected error while masking value", error_class: e.class, error: e.message end record } end
masker_for_value_pattern(conv, pattern, opts)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 260 def masker_for_value_pattern(conv, pattern, opts) regexp = Regexp.new(pattern) ->(record){ begin record.each_pair do |key, value| next unless (regexp =~ value.to_s rescue nil) record[key] = conv.call(value, opts.salt || salt_determine(key)) end rescue => e log.error "unexpected error while masking value", error_class: e.class, error: e.message end record } end
salt_determine(key)
click to toggle source
# File lib/fluent/plugin/filter_anonymizer.rb, line 177 def salt_determine(key) return @salt_map[key] if @salt_map.has_key?(key) keystr = key.to_s if keystr.empty? @salt_map[key] = @salt_list[0] else @salt_map[key] = @salt_list[(keystr[0].ord + keystr[-1].ord) % @salt_list.size] end @salt_map[key] end