lenjador 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,335 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/lenjador/preprocessors/whitelist'
3
+
4
+ RSpec.describe Lenjador::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(Lenjador::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 Lenjador::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
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'pry'
4
+ Bundler.setup
5
+
6
+ require 'lenjador'
7
+
8
+ Dir[File.dirname(__FILE__) + '/support/*.rb'].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+ config.order = 'random'
14
+ end
@@ -0,0 +1,11 @@
1
+ RSpec::Matchers.define :implement_interface do |expected|
2
+ required_methods = expected.instance_methods(false)
3
+ match do |actual|
4
+ required_methods - actual.methods == []
5
+ end
6
+
7
+ failure_message do |actual|
8
+ missing_methods = required_methods - actual.methods
9
+ "Expected instance methods #{missing_methods.inspect} to be implemented"
10
+ end
11
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lenjador::Utils do
4
+ let(:now) { Time.utc(2015, 10, 11, 23, 10, 21, 123456) }
5
+
6
+ before do
7
+ allow(Time).to receive(:now) { now }
8
+ end
9
+
10
+ describe '.build_event' do
11
+ subject(:event) { described_class.build_event(metadata, level, application_name) }
12
+
13
+ let(:application_name) { 'test_service' }
14
+ let(:level) { :info }
15
+ let(:metadata) { {x: 'y'} }
16
+
17
+ it 'includes it in the event as application' do
18
+ expect(event[:application]).to eq(application_name)
19
+ end
20
+
21
+ it 'includes log level' do
22
+ expect(event[:level]).to eq(:info)
23
+ end
24
+
25
+ it 'includes timestamp' do
26
+ expect(event[:@timestamp]).to eq('2015-10-11T23:10:21.123Z')
27
+ end
28
+
29
+ context 'when @timestamp provided' do
30
+ let(:metadata) { {message: 'test', :@timestamp => 'a timestamp'} }
31
+
32
+ it 'overwrites @timestamp' do
33
+ expect(subject[:message]).to eq('test')
34
+ expect(subject[:@timestamp]).to eq('a timestamp')
35
+ end
36
+ end
37
+
38
+ context 'when host provided' do
39
+ let(:metadata) { {message: 'test', host: 'xyz'} }
40
+
41
+ it 'overwrites host' do
42
+ expect(subject[:message]).to eq('test')
43
+ expect(subject[:host]).to eq('xyz')
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '.serialize_time_objects!' do
49
+ let(:object) do
50
+ {
51
+ time: Time.now,
52
+ hash: {
53
+ time: Time.now
54
+ },
55
+ array: [
56
+ Time.now,
57
+ {
58
+ time: Time.now
59
+ }
60
+ ]
61
+ }
62
+ end
63
+
64
+ let(:serialized_time) { now.iso8601 }
65
+
66
+ it 'recursively serializes time objects to iso8601' do
67
+ o = object.dup
68
+ described_class.serialize_time_objects!(o)
69
+
70
+ expect(o).to eq(
71
+ time: serialized_time,
72
+ hash: {
73
+ time: serialized_time
74
+ },
75
+ array: [
76
+ serialized_time,
77
+ {
78
+ time: serialized_time
79
+ }
80
+ ]
81
+ )
82
+ end
83
+ end
84
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lenjador
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Salemove
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lru_redux
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bunny
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: benchmark-ips
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: It's lenjadoric
98
+ email:
99
+ - support@salemove.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".ruby-gemset"
107
+ - ".ruby-version"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - README.md
111
+ - Rakefile
112
+ - benchmark/whitelisting.rb
113
+ - lenjador.gemspec
114
+ - lib/lenjador.rb
115
+ - lib/lenjador/adapters.rb
116
+ - lib/lenjador/adapters/stdout_adapter.rb
117
+ - lib/lenjador/adapters/stdout_json_adapter.rb
118
+ - lib/lenjador/null_logger.rb
119
+ - lib/lenjador/preprocessors.rb
120
+ - lib/lenjador/preprocessors/blacklist.rb
121
+ - lib/lenjador/preprocessors/json_pointer_trie.rb
122
+ - lib/lenjador/preprocessors/strategies/mask.rb
123
+ - lib/lenjador/preprocessors/strategies/prune.rb
124
+ - lib/lenjador/preprocessors/whitelist.rb
125
+ - lib/lenjador/utils.rb
126
+ - spec/adapters/stdout_adapter_spec.rb
127
+ - spec/adapters/stdout_json_adapter_spec.rb
128
+ - spec/lenjador_spec.rb
129
+ - spec/preprocessors/blacklist_spec.rb
130
+ - spec/preprocessors/json_pointer_trie.rb
131
+ - spec/preprocessors/whitelist_spec.rb
132
+ - spec/spec_helper.rb
133
+ - spec/support/implement_interface.rb
134
+ - spec/utils_spec.rb
135
+ homepage:
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.6.11
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: What description said
159
+ test_files:
160
+ - spec/adapters/stdout_adapter_spec.rb
161
+ - spec/adapters/stdout_json_adapter_spec.rb
162
+ - spec/lenjador_spec.rb
163
+ - spec/preprocessors/blacklist_spec.rb
164
+ - spec/preprocessors/json_pointer_trie.rb
165
+ - spec/preprocessors/whitelist_spec.rb
166
+ - spec/spec_helper.rb
167
+ - spec/support/implement_interface.rb
168
+ - spec/utils_spec.rb