sqreen 1.15.0-java → 1.15.5-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|