sqreen 1.15.0-java → 1.15.5-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sqreen/actions.rb +114 -43
- data/lib/sqreen/callback_tree.rb +16 -3
- data/lib/sqreen/callbacks.rb +7 -34
- data/lib/sqreen/capped_queue.rb +5 -1
- data/lib/sqreen/configuration.rb +4 -0
- data/lib/sqreen/deliveries/batch.rb +7 -4
- data/lib/sqreen/event.rb +4 -0
- data/lib/sqreen/events/request_record.rb +40 -7
- data/lib/sqreen/frameworks/generic.rb +0 -2
- data/lib/sqreen/frameworks/request_recorder.rb +14 -1
- data/lib/sqreen/instrumentation.rb +57 -33
- data/lib/sqreen/js/mini_racer_adapter.rb +46 -8
- data/lib/sqreen/metrics/average.rb +1 -1
- data/lib/sqreen/metrics/base.rb +4 -2
- data/lib/sqreen/metrics/binning.rb +3 -2
- data/lib/sqreen/metrics/collect.rb +1 -1
- data/lib/sqreen/metrics/sum.rb +1 -1
- data/lib/sqreen/metrics_store.rb +10 -5
- data/lib/sqreen/mono_time.rb +18 -0
- data/lib/sqreen/performance_notifications.rb +13 -38
- data/lib/sqreen/performance_notifications/binned_metrics.rb +12 -14
- data/lib/sqreen/performance_notifications/log.rb +6 -1
- data/lib/sqreen/performance_notifications/log_performance.rb +3 -1
- data/lib/sqreen/performance_notifications/metrics.rb +6 -3
- data/lib/sqreen/performance_notifications/newrelic.rb +6 -2
- data/lib/sqreen/remote_command.rb +26 -0
- data/lib/sqreen/rule_attributes.rb +1 -0
- data/lib/sqreen/rule_callback.rb +38 -0
- data/lib/sqreen/rules_callbacks/binding_accessor_matcher.rb +3 -2
- data/lib/sqreen/rules_callbacks/blacklist_ips.rb +1 -1
- data/lib/sqreen/rules_callbacks/run_block_user_actions.rb +1 -1
- data/lib/sqreen/rules_callbacks/run_req_start_actions.rb +8 -2
- data/lib/sqreen/runner.rb +11 -8
- data/lib/sqreen/sdk.rb +7 -1
- data/lib/sqreen/session.rb +4 -0
- data/lib/sqreen/trie.rb +274 -0
- data/lib/sqreen/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb1cc783655676697b23d94b34643b1990d7ef8011d4304d1f8602ee39830e0e
|
4
|
+
data.tar.gz: d569d191c90467462c4b9431750e31df1eac0f2a7fd5f8b9f85707937b460da6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e415a37c0cccbb9776f1c46d39e7d6a2da002950cf1a97d680c777c636ebfd225aeaebc552d50b1bf92e934946ceaf5a04214efa74ccb2b51e9d4f8787851be
|
7
|
+
data.tar.gz: 624b68dbc3150ec7f9637c9926c2ee9f02134310ee69327d161ea45d1959846b97c0458fdadf69842e6042a2e59dbbbc6e27733e5e12eb85d8bca6982bc44e2f
|
data/lib/sqreen/actions.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
3
|
|
4
4
|
require 'ipaddr'
|
5
|
+
require 'sqreen/trie'
|
5
6
|
require 'sqreen/log'
|
6
7
|
require 'sqreen/exception'
|
7
8
|
require 'sqreen/sdk'
|
@@ -24,21 +25,17 @@ module Sqreen
|
|
24
25
|
class Repository
|
25
26
|
include Singleton
|
26
27
|
|
27
|
-
def
|
28
|
-
|
29
|
-
@actions.default_proc = proc { |h, k| h[k] = [] }
|
28
|
+
def add(params, action)
|
29
|
+
action.class.index(params || {}, action)
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def [](action_class)
|
37
|
-
@actions[action_class]
|
32
|
+
def get(action_class, key)
|
33
|
+
action_class = Base.get_type_class(action_class) unless action_class.class == Class
|
34
|
+
action_class.actions_matching key
|
38
35
|
end
|
39
36
|
|
40
37
|
def clear
|
41
|
-
|
38
|
+
Base.known_subclasses.each(&:clear)
|
42
39
|
end
|
43
40
|
end
|
44
41
|
|
@@ -68,6 +65,8 @@ module Sqreen
|
|
68
65
|
end
|
69
66
|
|
70
67
|
# Base class for actions
|
68
|
+
# subclasses must also implement some methods in their singleton classes
|
69
|
+
# (actions_matching, index and clear)
|
71
70
|
class Base
|
72
71
|
attr_reader :id, :expiry, :send_response
|
73
72
|
|
@@ -124,10 +123,27 @@ module Sqreen
|
|
124
123
|
@@subclasses[name]
|
125
124
|
end
|
126
125
|
|
126
|
+
def known_subclasses
|
127
|
+
@@subclasses.values
|
128
|
+
end
|
129
|
+
|
127
130
|
def known_types
|
128
131
|
@@subclasses.keys
|
129
132
|
end
|
130
133
|
|
134
|
+
# all actions matching, possibly already expired
|
135
|
+
def actions_matching(_key)
|
136
|
+
raise 'implement in singletons of subclasses'
|
137
|
+
end
|
138
|
+
|
139
|
+
def index(_params, _action)
|
140
|
+
raise 'implement in singletons of subclasses'
|
141
|
+
end
|
142
|
+
|
143
|
+
def clear
|
144
|
+
raise 'implement in singletons of subclasses'
|
145
|
+
end
|
146
|
+
|
131
147
|
def inherited(subclass)
|
132
148
|
class << subclass
|
133
149
|
public :new
|
@@ -143,43 +159,75 @@ module Sqreen
|
|
143
159
|
end
|
144
160
|
end
|
145
161
|
|
146
|
-
module
|
147
|
-
|
162
|
+
module IpRangesIndex
|
163
|
+
def add_prefix(prefix_str, data)
|
164
|
+
@trie_v4 ||= Sqreen::Trie.new
|
165
|
+
@trie_v6 ||= Sqreen::Trie.new(nil, nil, Socket::AF_INET6)
|
166
|
+
prefix = Sqreen::Prefix.from_str(prefix_str, data)
|
167
|
+
trie = prefix.family == Socket::AF_INET6 ? @trie_v6 : @trie_v4
|
168
|
+
trie.insert prefix
|
169
|
+
end
|
170
|
+
|
171
|
+
def matching_actions(client_ip)
|
172
|
+
parsed_ip = IPAddr.new(client_ip)
|
173
|
+
trie = parsed_ip.family == Socket::AF_INET6 ? @trie_v6 : @trie_v4
|
174
|
+
return [] unless trie
|
175
|
+
found = trie.search_matching(parsed_ip.to_i, parsed_ip.family)
|
176
|
+
return [] unless found.size > 0
|
177
|
+
|
178
|
+
Sqreen.log.debug("Client ip #{client_ip} matches #{found.inspect}")
|
179
|
+
found.map(&:data)
|
180
|
+
end
|
181
|
+
|
182
|
+
def clear
|
183
|
+
@trie_v4 = Sqreen::Trie.new
|
184
|
+
@trie_v6 = Sqreen::Trie.new(nil, nil, Socket::AF_INET6)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
module IpRangeIndexedActionClass
|
189
|
+
include IpRangesIndex
|
190
|
+
|
191
|
+
def actions_matching(client_ip)
|
192
|
+
matching_actions client_ip
|
193
|
+
end
|
194
|
+
|
195
|
+
def index(params, action)
|
196
|
+
ranges = parse_ip_ranges params
|
197
|
+
|
198
|
+
ranges.each do |r|
|
199
|
+
add_prefix r, action
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
148
204
|
|
205
|
+
# returns array of prefixes in string form
|
149
206
|
def parse_ip_ranges(params)
|
150
207
|
ranges = params['ip_cidr']
|
151
208
|
unless ranges && ranges.is_a?(Array) && !ranges.empty?
|
152
209
|
raise 'no non-empty ip_cidr array present'
|
153
210
|
end
|
154
211
|
|
155
|
-
|
156
|
-
end
|
157
|
-
|
158
|
-
def matches_ip?(client_ip)
|
159
|
-
parsed_ip = IPAddr.new client_ip
|
160
|
-
found = ranges.find { |r| r.include? parsed_ip }
|
161
|
-
return false unless found
|
162
|
-
|
163
|
-
Sqreen.log.debug("Client ip #{client_ip} matches #{found.inspect}")
|
164
|
-
true
|
212
|
+
ranges
|
165
213
|
end
|
166
214
|
end
|
167
215
|
|
168
216
|
# Block a list of IP address ranges. Standard "raise" behavior.
|
169
217
|
class BlockIp < Base
|
170
|
-
|
218
|
+
extend IpRangeIndexedActionClass
|
219
|
+
|
171
220
|
self.type_name = 'block_ip'
|
172
221
|
|
173
222
|
def initialize(id, opts, params = {})
|
223
|
+
# no need to store the ranges for this action, the index filter the class
|
174
224
|
super(id, opts)
|
175
|
-
parse_ip_ranges params
|
176
225
|
end
|
177
226
|
|
178
227
|
def do_run(client_ip)
|
179
|
-
return nil unless matches_ip? client_ip
|
180
228
|
e = Sqreen::AttackBlocked.new("Blocked client's IP #{client_ip} " \
|
181
|
-
"(action: #{id}
|
182
|
-
{ :status => :raise, :exception => e }
|
229
|
+
"(action: #{id}). No action is required")
|
230
|
+
{ :status => :raise, :exception => e, :skip_rem_cbs => true }
|
183
231
|
end
|
184
232
|
|
185
233
|
def event_properties(client_ip)
|
@@ -190,7 +238,8 @@ module Sqreen
|
|
190
238
|
# Block a list of IP address ranges by forcefully redirecting the user
|
191
239
|
# to a specific URL.
|
192
240
|
class RedirectIp < Base
|
193
|
-
|
241
|
+
extend IpRangeIndexedActionClass
|
242
|
+
|
194
243
|
self.type_name = 'redirect_ip'
|
195
244
|
|
196
245
|
attr_reader :redirect_url
|
@@ -199,16 +248,15 @@ module Sqreen
|
|
199
248
|
super(id, opts)
|
200
249
|
@redirect_url = params['url']
|
201
250
|
raise "no url provided for action #{id}" unless @redirect_url
|
202
|
-
parse_ip_ranges params
|
203
251
|
end
|
204
252
|
|
205
253
|
def do_run(client_ip)
|
206
|
-
return nil unless matches_ip? client_ip
|
207
254
|
Sqreen.log.info "Will request redirect for client with IP #{client_ip} " \
|
208
|
-
"(action: #{id}
|
255
|
+
"(action: #{id})."
|
209
256
|
{
|
210
257
|
:status => :skip,
|
211
258
|
:new_return_value => [303, { 'Location' => @redirect_url }, ['']],
|
259
|
+
:skip_rem_cbs => true,
|
212
260
|
}
|
213
261
|
end
|
214
262
|
|
@@ -222,15 +270,46 @@ module Sqreen
|
|
222
270
|
class BlockUser < Base
|
223
271
|
self.type_name = 'block_user'
|
224
272
|
|
273
|
+
class << self
|
274
|
+
def actions_matching(identity_params)
|
275
|
+
return [] unless @idx
|
276
|
+
key = stringify_keys(identity_params)
|
277
|
+
actions = @idx[key]
|
278
|
+
actions || []
|
279
|
+
end
|
280
|
+
|
281
|
+
def index(params, action)
|
282
|
+
@idx ||= {}
|
283
|
+
users = params['users']
|
284
|
+
raise ::Sqreen::Exception, 'nil "users" param for block_user action' if users.nil?
|
285
|
+
raise ::Sqreen::Exception, '"users" param must be an array' unless users.is_a? Array
|
286
|
+
|
287
|
+
users.each do |u|
|
288
|
+
@idx[u] ||= []
|
289
|
+
@idx[u] << action
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def clear
|
294
|
+
@idx = {}
|
295
|
+
end
|
296
|
+
|
297
|
+
private
|
298
|
+
|
299
|
+
def stringify_keys(hash)
|
300
|
+
Hash[
|
301
|
+
hash.map { |k, v| [k.to_s, v] }
|
302
|
+
]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# BlockUser proper definition continues
|
307
|
+
|
225
308
|
def initialize(id, opts, params = {})
|
226
309
|
super(id, opts)
|
227
|
-
@users = params['users']
|
228
|
-
raise ::Sqreen::Exception, 'nil "users" param for block_user action' if @users.nil?
|
229
|
-
raise ::Sqreen::Exception, '"users" param must be an array' unless @users.is_a? Array
|
230
310
|
end
|
231
311
|
|
232
312
|
def do_run(identity_params)
|
233
|
-
return unless @users.include? stringify_keys(identity_params)
|
234
313
|
Sqreen.log.info(
|
235
314
|
"Will raise due to user being blocked by action #{id}. " \
|
236
315
|
"Blocked user identity: #{identity_params}"
|
@@ -250,14 +329,6 @@ module Sqreen
|
|
250
329
|
def event_properties(identity_params)
|
251
330
|
{ 'user' => identity_params }
|
252
331
|
end
|
253
|
-
|
254
|
-
private
|
255
|
-
|
256
|
-
def stringify_keys(hash)
|
257
|
-
Hash[
|
258
|
-
hash.map { |k, v| [k.to_s, v] }
|
259
|
-
]
|
260
|
-
end
|
261
332
|
end
|
262
333
|
end
|
263
334
|
end
|
data/lib/sqreen/callback_tree.rb
CHANGED
@@ -25,15 +25,15 @@ module Sqreen
|
|
25
25
|
|
26
26
|
if cb.pre?
|
27
27
|
methods[0] ||= []
|
28
|
-
methods[0]
|
28
|
+
add_to_array(methods[0], cb)
|
29
29
|
end
|
30
30
|
if cb.post?
|
31
31
|
methods[1] ||= []
|
32
|
-
methods[1]
|
32
|
+
add_to_array(methods[1], cb)
|
33
33
|
end
|
34
34
|
if cb.failing?
|
35
35
|
methods[2] ||= []
|
36
|
-
methods[2]
|
36
|
+
add_to_array(methods[2], cb)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -88,5 +88,18 @@ module Sqreen
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def add_to_array(arr, cb)
|
95
|
+
# find last element with prio equal or smaller; insert after
|
96
|
+
pos = arr.size
|
97
|
+
arr.reverse_each do |arr_cb|
|
98
|
+
break if arr_cb.priority <= cb.priority
|
99
|
+
pos -= 1
|
100
|
+
end
|
101
|
+
|
102
|
+
arr.insert(pos, cb)
|
103
|
+
end
|
91
104
|
end
|
92
105
|
end
|
data/lib/sqreen/callbacks.rb
CHANGED
@@ -36,6 +36,8 @@ module Sqreen
|
|
36
36
|
#
|
37
37
|
# CB can also declare that they are whitelisted and should not be run at the moment.
|
38
38
|
|
39
|
+
DEFAULT_PRIORITY = 100
|
40
|
+
|
39
41
|
attr_reader :klass, :method
|
40
42
|
attr_reader :overtimeable
|
41
43
|
|
@@ -55,6 +57,11 @@ module Sqreen
|
|
55
57
|
false
|
56
58
|
end
|
57
59
|
|
60
|
+
# the lower, the closer to the beginning of the list
|
61
|
+
def priority
|
62
|
+
DEFAULT_PRIORITY
|
63
|
+
end
|
64
|
+
|
58
65
|
def pre?
|
59
66
|
@has_pre
|
60
67
|
end
|
@@ -120,23 +127,6 @@ module Sqreen
|
|
120
127
|
framework && !framework.whitelisted_match.nil?
|
121
128
|
end
|
122
129
|
|
123
|
-
# Record an attack event into Sqreen system
|
124
|
-
# @param infos [Hash] Additional information about request
|
125
|
-
def record_event(infos, at = Time.now.utc)
|
126
|
-
return unless framework
|
127
|
-
payload = {
|
128
|
-
:infos => infos,
|
129
|
-
:rulespack_id => rulespack_id,
|
130
|
-
:rule_name => rule_name,
|
131
|
-
:test => test,
|
132
|
-
:time => at,
|
133
|
-
}
|
134
|
-
if payload_tpl.include?('context')
|
135
|
-
payload[:backtrace] = Sqreen::Context.new.bt
|
136
|
-
end
|
137
|
-
framework.observe(:attacks, payload, payload_tpl)
|
138
|
-
end
|
139
|
-
|
140
130
|
# Record a metric observation
|
141
131
|
# @param category [String] Name of the metric observed
|
142
132
|
# @param key [String] aggregation key
|
@@ -146,22 +136,5 @@ module Sqreen
|
|
146
136
|
return unless framework
|
147
137
|
framework.observe(:observations, [category, key, observation, at], [], false)
|
148
138
|
end
|
149
|
-
|
150
|
-
# Record an exception that just occurred
|
151
|
-
# @param exception [Exception] Exception to send over
|
152
|
-
# @param infos [Hash] Additional contextual information
|
153
|
-
def record_exception(exception, infos = {}, at = Time.now.utc)
|
154
|
-
return unless framework
|
155
|
-
payload = {
|
156
|
-
:exception => exception,
|
157
|
-
:infos => infos,
|
158
|
-
:rulespack_id => rulespack_id,
|
159
|
-
:rule_name => rule_name,
|
160
|
-
:test => test,
|
161
|
-
:time => at,
|
162
|
-
:backtrace => exception.backtrace || Sqreen::Context.bt,
|
163
|
-
}
|
164
|
-
framework.observe(:sqreen_exceptions, payload)
|
165
|
-
end
|
166
139
|
end
|
167
140
|
end
|
data/lib/sqreen/capped_queue.rb
CHANGED
@@ -15,7 +15,11 @@ module Sqreen
|
|
15
15
|
alias original_push push
|
16
16
|
|
17
17
|
def push(value)
|
18
|
-
|
18
|
+
until size < @capacity
|
19
|
+
discarded = pop
|
20
|
+
Sqreen.log.debug { "Discarded from queue: #{discarded}" }
|
21
|
+
end
|
22
|
+
Sqreen.log.debug { "Pushed to the queue: #{value}" }
|
19
23
|
original_push(value)
|
20
24
|
end
|
21
25
|
end
|
data/lib/sqreen/configuration.rb
CHANGED
@@ -53,6 +53,10 @@ module Sqreen
|
|
53
53
|
:default => nil },
|
54
54
|
{ :env => :SQREEN_STRIP_SENSITIVE_DATA, :name => :strip_sensitive_data,
|
55
55
|
:default => true, :convert => :to_bool },
|
56
|
+
{ :env => :SQREEN_STRIP_SENSITIVE_KEYS, :name => :strip_sensitive_keys,
|
57
|
+
:default => nil },
|
58
|
+
{ :env => :SQREEN_STRIP_SENSITIVE_REGEX, :name => :strip_sensitive_regex,
|
59
|
+
:default => nil },
|
56
60
|
|
57
61
|
].freeze
|
58
62
|
|
@@ -3,6 +3,8 @@
|
|
3
3
|
|
4
4
|
require 'sqreen/deliveries/simple'
|
5
5
|
require 'sqreen/events/remote_exception'
|
6
|
+
require 'sqreen/mono_time'
|
7
|
+
|
6
8
|
module Sqreen
|
7
9
|
module Deliveries
|
8
10
|
# Simple delivery method that batch event already seen in a batch
|
@@ -41,22 +43,23 @@ module Sqreen
|
|
41
43
|
def stale?
|
42
44
|
min = @first_seen.values.min
|
43
45
|
return false if min.nil?
|
44
|
-
(min + max_staleness) <
|
46
|
+
(min + max_staleness) < Sqreen.time
|
45
47
|
end
|
46
48
|
|
47
49
|
def post_batch_needed?(event)
|
48
|
-
now =
|
50
|
+
now = Sqreen.time
|
51
|
+
# do not use any? {} due to side effects inside block
|
49
52
|
event_keys(event).map do |key|
|
50
53
|
was = @first_seen[key]
|
51
54
|
@first_seen[key] ||= now
|
52
|
-
was.nil? || current_batch.size > max_batch || (was + max_staleness)
|
55
|
+
was.nil? || current_batch.size > max_batch || now > (was + max_staleness)
|
53
56
|
end.any?
|
54
57
|
end
|
55
58
|
|
56
59
|
def post_batch
|
57
60
|
session.post_batch(current_batch)
|
58
61
|
current_batch.clear
|
59
|
-
now =
|
62
|
+
now = Sqreen.time
|
60
63
|
@first_seen.each_key do |key|
|
61
64
|
@first_seen[key] = now
|
62
65
|
end
|
data/lib/sqreen/event.rb
CHANGED
@@ -7,6 +7,11 @@ require 'sqreen/event'
|
|
7
7
|
module Sqreen
|
8
8
|
# When a request is deeemed worthy of being sent to the backend
|
9
9
|
class RequestRecord < Sqreen::Event
|
10
|
+
def initialize(payload, redactor = nil)
|
11
|
+
@redactor = redactor
|
12
|
+
super(payload)
|
13
|
+
end
|
14
|
+
|
10
15
|
def observed
|
11
16
|
(payload && payload[:observed]) || {}
|
12
17
|
end
|
@@ -56,8 +61,8 @@ module Sqreen
|
|
56
61
|
res[:request][:parameters] = payload['params'] if payload['params']
|
57
62
|
res[:request][:headers] = payload['headers'] if payload['headers']
|
58
63
|
|
59
|
-
if
|
60
|
-
res[:request] =
|
64
|
+
if @redactor
|
65
|
+
res[:request] = @redactor.redact(res[:request])
|
61
66
|
end
|
62
67
|
|
63
68
|
res
|
@@ -105,14 +110,42 @@ module Sqreen
|
|
105
110
|
|
106
111
|
# For redacting sensitive data and avoid having it sent to our servers
|
107
112
|
class SensitiveDataRedactor
|
108
|
-
|
113
|
+
DEFAULT_SENSITIVE_KEYS = Set.new(%w[password secret passwd authorization api_key apikey access_token]).freeze
|
114
|
+
DEFAULT_REGEX = /\A(?:\d[ -]*?){13,16}\z/
|
109
115
|
MASK = '<Redacted by Sqreen>'.freeze
|
110
|
-
REGEX = /\A(?:\d[ -]*?){13,16}\z/
|
111
116
|
|
112
|
-
def self.
|
117
|
+
def self.from_config
|
118
|
+
keys = Sqreen.config_get(:strip_sensitive_keys)
|
119
|
+
if keys && keys.is_a?(String)
|
120
|
+
keys = keys.split(',')
|
121
|
+
else
|
122
|
+
keys = nil
|
123
|
+
end
|
124
|
+
|
125
|
+
regex = Sqreen.config_get(:strip_sensitive_regex)
|
126
|
+
if regex && regex.is_a?(String)
|
127
|
+
begin
|
128
|
+
regex = Regexp.compile(regex)
|
129
|
+
rescue RegexpError
|
130
|
+
Sqreen.log.warn("Invalid regular expression given in strip_sensitive_keys: #{regex}")
|
131
|
+
regex = nil
|
132
|
+
end
|
133
|
+
else
|
134
|
+
regex = nil
|
135
|
+
end
|
136
|
+
|
137
|
+
new(keys: keys, regex: regex)
|
138
|
+
end
|
139
|
+
|
140
|
+
def initialize(params = {})
|
141
|
+
@regex = params[:regex] || DEFAULT_REGEX
|
142
|
+
@keys = params[:keys] || DEFAULT_SENSITIVE_KEYS
|
143
|
+
end
|
144
|
+
|
145
|
+
def redact(obj)
|
113
146
|
case obj
|
114
147
|
when String
|
115
|
-
return MASK if obj =~
|
148
|
+
return MASK if obj =~ @regex
|
116
149
|
|
117
150
|
when Array
|
118
151
|
return obj.map(&method(:redact))
|
@@ -121,7 +154,7 @@ module Sqreen
|
|
121
154
|
return Hash[
|
122
155
|
obj.map do |k, v|
|
123
156
|
ck = k.is_a?(String) ? k.downcase : k
|
124
|
-
[k,
|
157
|
+
[k, @keys.include?(ck) ? MASK : redact(v)]
|
125
158
|
end
|
126
159
|
]
|
127
160
|
end
|