logasm-jruby 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/logasm/preprocessors/blacklist'
3
+
4
+ describe Logasm::Preprocessors::Blacklist do
5
+ subject(:processed_data) { described_class.new(config).process(data) }
6
+
7
+ let(:config) {{
8
+ fields: [{ key: 'field', action: action }]
9
+ }}
10
+
11
+ let(:action) {}
12
+ let(:data) {{
13
+ field: value,
14
+ data: {
15
+ field: 'secret'
16
+ },
17
+ array: [{field: 'secret'}]
18
+ }}
19
+
20
+ let(:value) { 'secret' }
21
+
22
+ context 'when action is unsupported' do
23
+ let(:action) { 'reverse' }
24
+
25
+ it 'throws exception' do
26
+ expect { processed_data }.to raise_exception(Logasm::Preprocessors::Blacklist::UnsupportedActionException)
27
+ end
28
+ end
29
+
30
+ context 'when action is "exclude"' do
31
+ let(:action) { 'exclude' }
32
+
33
+ it 'removes the field' do
34
+ expect(processed_data).not_to include(:field)
35
+ end
36
+
37
+ it 'removes nested field' do
38
+ expect(processed_data).not_to include_at_depth({field: 'secret'}, 1)
39
+ end
40
+
41
+ it 'removes nested in array field' do
42
+ expect(processed_data[:array]).not_to include({field: 'secret'})
43
+ end
44
+
45
+ context 'when field is deeply nested' do
46
+ let(:depth) { 10 }
47
+ let(:data) { data_with_nested_field({field: 'secret'}, depth) }
48
+
49
+ it 'removes deeply nested field' do
50
+ expect(processed_data).not_to include_at_depth({field: 'secret'}, depth)
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'when action is "mask"' do
56
+ let(:action) { 'mask' }
57
+
58
+ it 'masks nested field' do
59
+ expect(processed_data).to include_at_depth({field: '*****'}, 1)
60
+ end
61
+
62
+ it 'masks nested in array field' do
63
+ expect(processed_data[:array]).to include({field: '*****'})
64
+ end
65
+
66
+ context 'when field is string' do
67
+ let(:value) { 'secret' }
68
+
69
+ it 'masks value with asterisks' do
70
+ expect(processed_data).to include(field: '*****')
71
+ end
72
+ end
73
+
74
+ context 'when field is number' do
75
+ let(:value) { 42 }
76
+
77
+ it 'masks number value' do
78
+ expect(processed_data).to include(field: '*****')
79
+ end
80
+ end
81
+
82
+ context 'when field is boolean' do
83
+ let(:value) { true }
84
+
85
+ it 'masks value with asterisks' do
86
+ expect(processed_data).to include(field: '*****')
87
+ end
88
+ end
89
+
90
+ context 'when field is array' do
91
+ let(:value) { [1,2,3,4] }
92
+
93
+ it 'masks value with asterisks' do
94
+ expect(processed_data).to include(field: '*****')
95
+ end
96
+ end
97
+
98
+ context 'when field is hash' do
99
+ let(:value) { {data: {}} }
100
+
101
+ it 'masks value with asterisks' do
102
+ expect(processed_data).to include(field: '*****')
103
+ end
104
+ end
105
+
106
+ context 'when field is deeply nested' do
107
+ let(:depth) { 10 }
108
+ let(:data) { data_with_nested_field({field: 'secret'}, depth) }
109
+
110
+ it 'masks deeply nested field' do
111
+ expect(processed_data).to include_at_depth({field: '*****'}, depth)
112
+ end
113
+ end
114
+ end
115
+
116
+ def data_with_nested_field(field, depth)
117
+ depth.times.inject(field) do |mem|
118
+ {}.merge(data: mem)
119
+ end
120
+ end
121
+
122
+ RSpec::Matchers.define :include_at_depth do |expected_hash, depth|
123
+ match do |actual|
124
+ nested_data = depth.times.inject(actual) do |mem|
125
+ mem[:data]
126
+ end
127
+
128
+ expect(nested_data).to include(expected_hash)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'logasm/preprocessors/json_pointer_trie'
3
+
4
+ RSpec.describe Logasm::Preprocessors::JSONPointerTrie do
5
+ let(:trie) { described_class.new }
6
+
7
+ describe '#includes?' do
8
+ it 'returns true for empty prefix' do
9
+ expect(trie).to include('')
10
+ end
11
+
12
+ it 'returns true if trie contains requested prefix or value itself' do
13
+ trie.insert('/data/nested/key')
14
+
15
+ expect(trie).to include('/data')
16
+ expect(trie).to include('/data/nested')
17
+ expect(trie).to include('/data/nested/key')
18
+ end
19
+
20
+ it 'returns false if trie does not contain requested prefix or value' do
21
+ trie.insert('/data/nested/key')
22
+
23
+ expect(trie).to_not include('/bad_data')
24
+ expect(trie).to_not include('/data/bad_nested')
25
+ expect(trie).to_not include('/data/nested/bad_key')
26
+ end
27
+
28
+ it 'returns true if trie contains requested prefix under wildcard' do
29
+ trie.insert('/data/~/key')
30
+
31
+ expect(trie).to include('/data/arbitrary_key/key')
32
+ expect(trie).to include('/data/another_key/key')
33
+ expect(trie).to_not include('/data/arbitrary_key/bad_nested_key')
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,335 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/logasm/preprocessors/whitelist'
3
+
4
+ RSpec.describe Logasm::Preprocessors::Whitelist, 'when :action is :mask or omitted' do
5
+ subject(:processed_data) { described_class.new(config).process(data) }
6
+
7
+ let(:config) { { pointers: pointers } }
8
+ let(:pointers) { [] }
9
+ let(:data) do
10
+ {
11
+ field: 'secret',
12
+ data: {
13
+ field: 'secret'
14
+ },
15
+ array: [{ field: 'secret' }]
16
+ }
17
+ end
18
+
19
+ it 'masks all non-whitelisted fields' do
20
+ expect(processed_data).to eq(
21
+ field: '*****',
22
+ data: '*****',
23
+ array: '*****'
24
+ )
25
+ end
26
+
27
+ context 'when pointer has trailing slash' do
28
+ let(:pointers) { ['/field/'] }
29
+
30
+ it 'throws exception' do
31
+ expect { processed_data }.to raise_exception(Logasm::Preprocessors::Whitelist::InvalidPointerFormatException)
32
+ end
33
+ end
34
+
35
+ context 'with whitelisted field' do
36
+ let(:pointers) { ['/field'] }
37
+
38
+ it 'includes the field' do
39
+ expect(processed_data).to eq(
40
+ field: 'secret',
41
+ data: '*****',
42
+ array: '*****'
43
+ )
44
+ end
45
+ end
46
+
47
+ context 'with whitelisted nested field' do
48
+ let(:pointers) { ['/data/field'] }
49
+
50
+ it 'includes nested field' do
51
+ expect(processed_data).to eq(
52
+ field: '*****',
53
+ data: {
54
+ field: 'secret'
55
+ },
56
+ array: '*****'
57
+ )
58
+ end
59
+ end
60
+
61
+ context 'with whitelisted array element field' do
62
+ let(:pointers) { ['/array/0/field'] }
63
+
64
+ it 'includes array element' do
65
+ expect(processed_data).to eq(
66
+ field: '*****',
67
+ data: '*****',
68
+ array: [{ field: 'secret' }]
69
+ )
70
+ end
71
+ end
72
+
73
+ context 'with whitelisted hash' do
74
+ it 'includes all whitelisted hash elements' do
75
+ source = { foo: { bar: 'baz' } }
76
+ target = { foo: { bar: 'baz' } }
77
+ expect(process(['/foo/~'], source)).to eq(target)
78
+ end
79
+
80
+ it 'does not include nested elements' do
81
+ source = { foo: { bar: { baz: 'asd' } } }
82
+ target = { foo: { bar: { baz: '*****' } } }
83
+ expect(process(['/foo/~'], source)).to eq(target)
84
+ end
85
+ end
86
+
87
+ context 'with whitelisted array elements field with wildcard' do
88
+ let(:data) do
89
+ {
90
+ array: [
91
+ { field: 'data1', secret: 'secret1' },
92
+ { field: 'data2', secret: 'secret2' }
93
+ ]
94
+ }
95
+ end
96
+ let(:pointers) { ['/array/~/field'] }
97
+
98
+ it 'includes array elements field' do
99
+ expect(processed_data).to include(
100
+ array: [
101
+ { field: 'data1', secret: '*****' },
102
+ { field: 'data2', secret: '*****' }
103
+ ]
104
+ )
105
+ end
106
+ end
107
+
108
+ context 'with whitelisted string array elements with wildcard' do
109
+ let(:data) do
110
+ { array: %w[secret secret] }
111
+ end
112
+ let(:pointers) { ['/array/~'] }
113
+
114
+ it 'includes array elements' do
115
+ expect(processed_data).to include(array: %w[secret secret])
116
+ end
117
+ end
118
+
119
+ context 'with whitelisted string array elements in an array with wildcard' do
120
+ let(:data) do
121
+ {
122
+ nested: [{ array: %w[secret secret] }]
123
+ }
124
+ end
125
+ let(:pointers) { ['/nested/~/array/~'] }
126
+
127
+ it 'includes array elements' do
128
+ expect(processed_data).to include(nested: [{ array: %w[secret secret] }])
129
+ end
130
+ end
131
+
132
+
133
+ context 'with whitelisted array element' do
134
+ let(:pointers) { ['/array/0'] }
135
+
136
+ it 'masks array element' do
137
+ expect(processed_data).to include(array: [{ field: '*****' }])
138
+ end
139
+ end
140
+
141
+ context 'with whitelisted array' do
142
+ let(:pointers) { ['/array'] }
143
+
144
+ it 'masks array' do
145
+ expect(processed_data).to include(array: ['*****'])
146
+ end
147
+ end
148
+
149
+ context 'with whitelisted hash' do
150
+ let(:pointers) { ['/data'] }
151
+
152
+ it 'masks hash' do
153
+ expect(processed_data).to include(data: { field: '*****' })
154
+ end
155
+ end
156
+
157
+ context 'when boolean present' do
158
+ let(:data) { { bool: true } }
159
+
160
+ it 'masks it with asteriks' do
161
+ expect(processed_data).to eq(bool: '*****')
162
+ end
163
+ end
164
+
165
+ context 'when field has slash in the name' do
166
+ let(:data) do
167
+ { 'field_with_/' => 'secret' }
168
+ end
169
+ let(:pointers) { ['/field_with_~1'] }
170
+
171
+ it 'includes field' do
172
+ expect(processed_data).to include('field_with_/'=> 'secret')
173
+ end
174
+ end
175
+
176
+ context 'when field has tilde in the name' do
177
+ let(:data) do
178
+ { 'field_with_~' => 'secret' }
179
+ end
180
+ let(:pointers) { ['/field_with_~0'] }
181
+
182
+ it 'includes field' do
183
+ expect(processed_data).to include('field_with_~'=> 'secret')
184
+ end
185
+ end
186
+
187
+ context 'when field has tilde and 1' do
188
+ let(:data) do
189
+ { 'field_with_~1' => 'secret' }
190
+ end
191
+ let(:pointers) { ['/field_with_~01'] }
192
+
193
+ it 'includes field' do
194
+ expect(processed_data).to include('field_with_~1'=> 'secret')
195
+ end
196
+ end
197
+
198
+ def process(pointers, data)
199
+ described_class.new(pointers: pointers).process(data)
200
+ end
201
+ end
202
+
203
+ RSpec.describe Logasm::Preprocessors::Whitelist, 'when :action is :exclude or :prune' do
204
+ subject(:processed_data) { described_class.new(config).process(data) }
205
+
206
+ let(:config) { { pointers: pointers, action: :prune } }
207
+ let(:pointers) { [] }
208
+ let(:data) do
209
+ {
210
+ field: 'secret',
211
+ data: {
212
+ field: 'secret'
213
+ },
214
+ array: [{ field: 'secret' }, { field2: 'secret' }]
215
+ }
216
+ end
217
+
218
+ context 'when pointers is empty' do
219
+ it 'prunes all fields from the input' do
220
+ expect(processed_data).to eq({})
221
+ end
222
+ end
223
+
224
+ context 'with whitelisted field' do
225
+ let(:pointers) { ['/field'] }
226
+
227
+ it 'includes the field' do
228
+ expect(processed_data).to eq(field: 'secret')
229
+ end
230
+ end
231
+
232
+ context 'with whitelisted nested field' do
233
+ let(:pointers) { ['/data/field'] }
234
+
235
+ it 'includes nested field' do
236
+ expect(processed_data).to eq(data: { field: 'secret' })
237
+ end
238
+ end
239
+
240
+ context 'with whitelisted array element field' do
241
+ let(:pointers) { ['/array/0/field'] }
242
+
243
+ it 'includes array element' do
244
+ expect(processed_data).to eq(array: [{ field: 'secret' }])
245
+ end
246
+ end
247
+
248
+ context 'with whitelisted hash' do
249
+ it 'includes all whitelisted hash elements' do
250
+ source = { foo: { bar: 'baz' } }
251
+ target = { foo: { bar: 'baz' } }
252
+ expect(process(['/foo/~'], source)).to eq(target)
253
+ end
254
+
255
+ it 'does not include nested elements' do
256
+ source = { foo: { bar: { baz: 'asd' } } }
257
+ target = { foo: { bar: {} } }
258
+ expect(process(['/foo/~'], source)).to eq(target)
259
+ end
260
+ end
261
+
262
+ context 'with whitelisted array elements field with wildcard' do
263
+ let(:data) do
264
+ {
265
+ array: [
266
+ { field: 'data1', secret: 'secret1' },
267
+ { field: 'data2', secret: 'secret2' }
268
+ ]
269
+ }
270
+ end
271
+ let(:pointers) { ['/array/~/field'] }
272
+
273
+ it 'includes array elements field' do
274
+ expect(processed_data).to include(
275
+ array: [
276
+ { field: 'data1' },
277
+ { field: 'data2' }
278
+ ]
279
+ )
280
+ end
281
+ end
282
+
283
+ context 'with whitelisted string array elements with wildcard' do
284
+ let(:data) do
285
+ { array: %w[secret1 secret2] }
286
+ end
287
+ let(:pointers) { ['/array/~'] }
288
+
289
+ it 'includes array elements' do
290
+ expect(processed_data).to include(array: %w[secret1 secret2])
291
+ end
292
+ end
293
+
294
+ context 'with whitelisted string array elements in an array with wildcard' do
295
+ let(:data) do
296
+ {
297
+ nested: [{ array: %w[secret1 secret2] }]
298
+ }
299
+ end
300
+ let(:pointers) { ['/nested/~/array/~'] }
301
+
302
+ it 'includes array elements' do
303
+ expect(processed_data).to include(nested: [{ array: %w[secret1 secret2] }])
304
+ end
305
+ end
306
+
307
+
308
+ context 'with whitelisted array element' do
309
+ let(:pointers) { ['/array/0'] }
310
+
311
+ it 'masks array element' do
312
+ expect(processed_data).to eq(array: [{}])
313
+ end
314
+ end
315
+
316
+ context 'with whitelisted array' do
317
+ let(:pointers) { ['/array'] }
318
+
319
+ it 'masks array' do
320
+ expect(processed_data).to include(array: [])
321
+ end
322
+ end
323
+
324
+ context 'with whitelisted hash' do
325
+ let(:pointers) { ['/data'] }
326
+
327
+ it 'masks hash' do
328
+ expect(processed_data).to include(data: {})
329
+ end
330
+ end
331
+
332
+ def process(pointers, data)
333
+ described_class.new(pointers: pointers, action: :prune).process(data)
334
+ end
335
+ end