tcell_agent 2.3.0 → 2.4.0

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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/bin/tcell_agent +6 -11
  4. data/lib/tcell_agent/agent.rb +18 -13
  5. data/lib/tcell_agent/config_initializer.rb +0 -4
  6. data/lib/tcell_agent/configuration.rb +4 -4
  7. data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
  8. data/lib/tcell_agent/instrumentation.rb +14 -6
  9. data/lib/tcell_agent/instrumentation/cmdi.rb +32 -0
  10. data/lib/tcell_agent/instrumentation/lfi.rb +55 -9
  11. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
  12. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
  13. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
  14. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
  15. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
  16. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
  17. data/lib/tcell_agent/logger.rb +2 -2
  18. data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
  19. data/lib/tcell_agent/policies/headers_policy.rb +2 -2
  20. data/lib/tcell_agent/policies/patches_policy.rb +8 -4
  21. data/lib/tcell_agent/policies/policies_manager.rb +1 -0
  22. data/lib/tcell_agent/policies/policy_polling.rb +4 -3
  23. data/lib/tcell_agent/rails/auth/doorkeeper.rb +1 -0
  24. data/lib/tcell_agent/rails/better_ip.rb +7 -19
  25. data/lib/tcell_agent/rails/dlp.rb +48 -48
  26. data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
  27. data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
  28. data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
  29. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
  30. data/lib/tcell_agent/rails/middleware/global_middleware.rb +1 -5
  31. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
  32. data/lib/tcell_agent/rails/routes/grape.rb +2 -1
  33. data/lib/tcell_agent/rails/settings_reporter.rb +0 -8
  34. data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -6
  35. data/lib/tcell_agent/routes/table.rb +3 -0
  36. data/lib/tcell_agent/rust/agent_config.rb +9 -0
  37. data/lib/tcell_agent/rust/{libtcellagent-alpine-6.2.1.so → libtcellagent-alpine.so} +0 -0
  38. data/lib/tcell_agent/rust/{tcellagent-6.2.1.dll → libtcellagent-x64.dll} +0 -0
  39. data/lib/tcell_agent/rust/{libtcellagent-6.2.1.dylib → libtcellagent.dylib} +0 -0
  40. data/lib/tcell_agent/rust/{libtcellagent-6.2.1.so → libtcellagent.so} +0 -0
  41. data/lib/tcell_agent/rust/native_agent.rb +48 -58
  42. data/lib/tcell_agent/rust/native_library.rb +7 -10
  43. data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
  44. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
  45. data/lib/tcell_agent/servers/puma.rb +25 -8
  46. data/lib/tcell_agent/servers/rack_puma_handler.rb +13 -3
  47. data/lib/tcell_agent/servers/webrick.rb +13 -3
  48. data/lib/tcell_agent/settings_reporter.rb +0 -14
  49. data/lib/tcell_agent/sinatra.rb +1 -0
  50. data/lib/tcell_agent/tcell_context.rb +15 -6
  51. data/lib/tcell_agent/utils/headers.rb +0 -1
  52. data/lib/tcell_agent/utils/strings.rb +2 -2
  53. data/lib/tcell_agent/version.rb +1 -1
  54. data/spec/cruby_spec_helper.rb +26 -0
  55. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
  56. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
  57. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +207 -223
  58. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +89 -70
  59. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +73 -0
  60. data/spec/lib/tcell_agent/patches_spec.rb +2 -1
  61. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
  62. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
  63. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
  64. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
  65. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +14 -8
  66. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
  67. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
  68. data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
  69. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
  70. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
  71. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
  72. data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -16
  73. data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
  74. data/spec/spec_helper.rb +3 -1
  75. data/spec/support/builders.rb +2 -1
  76. data/spec/support/server_mocks/puma_mock.rb +4 -0
  77. data/spec/support/shared_spec.rb +29 -0
  78. data/tcell_agent.gemspec +14 -14
  79. metadata +23 -19
  80. data/Rakefile +0 -18
  81. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
  82. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -131
  83. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -102
@@ -1,6 +1,9 @@
1
+ # rubocop:disable Style/HashSyntax
2
+
1
3
  require 'spec_helper'
2
4
  require 'securerandom'
3
5
 
6
+ FILE_CONTENTS = "This is line one.\nThis is line two.\n".freeze
4
7
  describe 'IO' do
5
8
  before do
6
9
  native_agent = double('native_agent')
@@ -17,8 +20,9 @@ describe 'IO' do
17
20
  @file_contents = "This is line one.\nThis is line two.\n"
18
21
  @file_length = @file_contents.length
19
22
 
20
- @new_file_name = '/tmp/' + SecureRandom.uuid
23
+ @new_file_name = NEW_FILE_NAME
21
24
  @new_file_contents_offset = "This OFFSETe one.\nThis is line two.\n"
25
+ @new_file_contents_offset_bytes = "\x00\x00\x00\x00\x00OFFSET"
22
26
  end
23
27
 
24
28
  describe '.binread' do
@@ -50,23 +54,20 @@ describe 'IO' do
50
54
  result = IO.binread('|echo test')
51
55
  expect(result).to eq "test\n"
52
56
  end
53
- context 'with a filename' do
54
- it 'should still be able to read file' do
55
- result = IO.binread(@filename)
56
- expect(result).to eq @file_contents
57
- end
57
+
58
+ it 'should read the file normally' do
59
+ result = IO.binread(@filename)
60
+ expect(result).to eq @file_contents
58
61
  end
59
- context 'with a filename and a length of 20' do
60
- it 'should read 20 bytes of the file' do
61
- result = IO.binread(@filename, 20)
62
- expect(result).to eq @file_contents[0..19]
63
- end
62
+
63
+ it 'should read 20 bytes of the file' do
64
+ result = IO.binread(@filename, 20)
65
+ expect(result).to eq @file_contents[0..19]
64
66
  end
65
- context 'with a filename and a length of 20 and an offset of 5' do
66
- it 'should read 20 bytes starting from the 5th byte' do
67
- result = IO.binread(@filename, 20, 5)
68
- expect(result).to eq @file_contents[5..24]
69
- end
67
+
68
+ it 'should read 20 bytes starting from the 5th byte' do
69
+ result = IO.binread(@filename, 20, 5)
70
+ expect(result).to eq @file_contents[5..24]
70
71
  end
71
72
  end
72
73
  context 'with a file blocked for read/write' do
@@ -80,30 +81,27 @@ describe 'IO' do
80
81
  end
81
82
  end
82
83
 
83
- it 'should still be able to execute OS commands', :skip_before do
84
+ it 'should execute shell commands', :skip_before do
84
85
  result = IO.binread('|echo test')
85
86
  expect(result).to eq "test\n"
86
87
  end
87
- context 'with a filename' do
88
- it 'should not be able to read the file' do
89
- expect do
90
- IO.binread(@filename)
91
- end.to raise_error(IOError)
92
- end
88
+
89
+ it 'should receive an IOError' do
90
+ expect do
91
+ IO.binread(@filename)
92
+ end.to raise_error(IOError)
93
93
  end
94
- context 'with a filename and a length of 20' do
95
- it 'should not be able to read the file' do
96
- expect do
97
- IO.binread(@filename, 20)
98
- end.to raise_error(IOError)
99
- end
94
+
95
+ it 'should receive an IOError' do
96
+ expect do
97
+ IO.binread(@filename, 20)
98
+ end.to raise_error(IOError)
100
99
  end
101
- context 'with a filename and a length of 20 and an offset of 5' do
102
- it 'should not be able to read the file' do
103
- expect do
104
- IO.binread(@filename, 20, 5)
105
- end.to raise_error(IOError)
106
- end
100
+
101
+ it 'should receive an IOError' do
102
+ expect do
103
+ IO.binread(@filename, 20, 5)
104
+ end.to raise_error(IOError)
107
105
  end
108
106
  end
109
107
  end
@@ -122,6 +120,7 @@ describe 'IO' do
122
120
  end.to raise_error(ArgumentError)
123
121
  end
124
122
  end
123
+
125
124
  context 'with a file not blocked for read/write' do
126
125
  before do
127
126
  expect(TCellAgent).to receive(:policy).with(
@@ -130,28 +129,36 @@ describe 'IO' do
130
129
  expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
131
130
  end
132
131
 
133
- context 'with a nonexistent filename and string' do
132
+ after(:each) do
133
+ File.delete(@new_file_name)
134
+ end
135
+
136
+ context 'with a non-existent file' do
134
137
  it 'should create the file' do
135
138
  IO.binwrite(@new_file_name, '')
136
139
  expect(File.exist?(@new_file_name)).to be_truthy
137
- File.delete(@new_file_name)
138
140
  end
141
+
139
142
  it 'should write to the file' do
140
143
  expect(IO.binwrite(@new_file_name, @file_contents)).to eq @file_length
141
- File.delete(@new_file_name)
142
144
  end
143
- end
144
- context 'with a nonexistent filename and string and offset' do
145
- it 'should write to the file at the offset value 5' do
146
- expect(TCellAgent).to receive(:policy).with(
147
- TCellAgent::PolicyTypes::LFI
148
- ).and_return(@local_files_policy, @local_files_policy)
149
- expect(@local_files_policy).to receive(:block_file_access?).and_return(false, false)
150
145
 
151
- IO.binwrite(@new_file_name, @file_contents)
152
- IO.binwrite(@new_file_name, 'OFFSET', 5)
153
- expect(IO.binread(@new_file_name)).to eq @new_file_contents_offset
154
- File.delete(@new_file_name)
146
+ context 'using offset, perm' do
147
+ after :each do
148
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('444')
149
+
150
+ expect(TCellAgent).to receive(:policy).with(
151
+ TCellAgent::PolicyTypes::LFI
152
+ ).and_return(@local_files_policy)
153
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
154
+ expect(File.open(@new_file_name).read).to eq @new_file_contents_offset_bytes
155
+ end
156
+
157
+ test_ruby2_ruby3_keywords(IO,
158
+ 'binwrite',
159
+ [NEW_FILE_NAME, 'OFFSET', 5],
160
+ { perm: 0o444 },
161
+ 6)
155
162
  end
156
163
  end
157
164
  end
@@ -163,19 +170,10 @@ describe 'IO' do
163
170
  expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
164
171
  end
165
172
 
166
- context 'with a nonexistent filename and a string' do
167
- it 'should not be able to write to the file' do
168
- expect do
169
- IO.binwrite(@new_file_name, @file_contents)
170
- end.to raise_error(IOError)
171
- end
172
- end
173
- context 'with a nonexistent filename and a string and an offset' do
174
- it 'should not be able to write to the file' do
175
- expect do
176
- IO.binwrite(@new_file_name, @file_contents)
177
- end.to raise_error(IOError)
178
- end
173
+ it 'should not be able to create and write to a file' do
174
+ expect do
175
+ IO.binwrite(@new_file_name, @file_contents)
176
+ end.to raise_error(IOError)
179
177
  end
180
178
  end
181
179
  end
@@ -196,20 +194,18 @@ describe 'IO' do
196
194
  expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
197
195
  end
198
196
 
199
- context 'with a filename' do
200
- it 'should be able to read the file' do
201
- result = ''
202
- IO.foreach(@filename) { |line| result << line }
203
- expect(result).to eq @file_contents
204
- end
197
+ it 'should be able to read the file' do
198
+ result = ''
199
+ IO.foreach(@filename) { |line| result << line }
200
+ expect(result).to eq @file_contents
205
201
  end
206
- context 'with a filename and a limit 16' do
207
- it 'should split each line to a max length of 16' do
208
- result = ''
209
- IO.foreach(@filename, 16) { |line| result << line }
210
- expect(result).to eq @file_contents
211
- end
202
+
203
+ it 'should split each line to a max length of 16' do
204
+ result = ''
205
+ IO.foreach(@filename, 16) { |line| result << line }
206
+ expect(result).to eq @file_contents
212
207
  end
208
+
213
209
  context 'with a filename and sep' do
214
210
  # TODO: no documentation on how to use sep
215
211
  end
@@ -225,14 +221,18 @@ describe 'IO' do
225
221
  expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
226
222
  end
227
223
 
228
- context 'with a filename' do
229
- it 'should not be able to read the file' do
230
- expect do
231
- result = ''
232
- IO.foreach(@filename) { |line| result << line }
233
- expect(result).to eq @file_contents
234
- end.to raise_error(IOError)
235
- end
224
+ it 'returns an IOError' do
225
+ expect do
226
+ result = ''
227
+ IO.foreach(@filename) { |line| result << line }
228
+ end.to raise_error(IOError)
229
+ end
230
+
231
+ it 'returns an IOError if it is non-existent' do
232
+ expect do
233
+ result = ''
234
+ IO.foreach('/tmp/bad-file-name') { |line| result << line }
235
+ end.to raise_error(IOError)
236
236
  end
237
237
  end
238
238
  end
@@ -260,27 +260,22 @@ describe 'IO' do
260
260
  end
261
261
  end
262
262
 
263
- it 'should still be able to execute OS commands', :skip_before do
263
+ it 'executes OS commands', :skip_before do
264
264
  result = IO.read('|echo test')
265
265
  expect(result).to eq "test\n"
266
266
  end
267
- context 'with a filename' do
268
- it 'should read the file' do
269
- result = IO.read(@filename)
270
- expect(result).to eq @file_contents
271
- end
272
- end
273
- context 'with a filename and a length of 20' do
274
- it 'should read 20 bytes of the file' do
275
- result = IO.read(@filename, 20)
276
- expect(result).to eq @file_contents[0..19]
277
- end
267
+
268
+ it 'returns the file contents' do
269
+ result = IO.read(@filename)
270
+ expect(result).to eq @file_contents
278
271
  end
279
- context 'with a filename and a length of 20 and an offset of 5' do
280
- it 'should read 20 bytes starting from the 5th byte' do
281
- result = IO.read(@filename, 20, 5)
282
- expect(result).to eq @file_contents[5..24]
283
- end
272
+
273
+ context 'using length, offset, mode' do
274
+ test_ruby2_ruby3_keywords(IO,
275
+ 'read',
276
+ [get_test_resource_path('lfi_sample_file.txt'), 20, 5],
277
+ { mode: 'rb' },
278
+ FILE_CONTENTS[5..24])
284
279
  end
285
280
  end
286
281
  context 'with a file blocked for read/write' do
@@ -295,30 +290,24 @@ describe 'IO' do
295
290
  end
296
291
  end
297
292
 
298
- it 'should still be able to execute OS commands', :skip_before do
293
+ it 'executes OS commands', :skip_before do
299
294
  result = IO.read('|echo test')
300
295
  expect(result).to eq "test\n"
301
296
  end
302
- context 'with a filename' do
303
- it 'should not be able to read the file' do
304
- expect do
305
- IO.read(@filename)
306
- end.to raise_error(IOError)
307
- end
297
+ it 'receeive an IOError' do
298
+ expect do
299
+ IO.read(@filename)
300
+ end.to raise_error(IOError)
308
301
  end
309
- context 'with a filename and a length 20' do
310
- it 'should not be able to read the file' do
311
- expect do
312
- IO.read(@filename, 20)
313
- end.to raise_error(IOError)
314
- end
302
+ it 'receeive an IOError' do
303
+ expect do
304
+ IO.read(@filename, 20)
305
+ end.to raise_error(IOError)
315
306
  end
316
- context 'with a filename and a length and an offset 5' do
317
- it 'should not be able to read the file' do
318
- expect do
319
- IO.read(@filename, 20, 5)
320
- end.to raise_error(IOError)
321
- end
307
+ it 'receeive an IOError' do
308
+ expect do
309
+ IO.read(@filename, 20, 5)
310
+ end.to raise_error(IOError)
322
311
  end
323
312
  end
324
313
  end
@@ -346,21 +335,30 @@ describe 'IO' do
346
335
  end
347
336
  end
348
337
 
349
- context 'with a filename' do
350
- it 'should read the file' do
351
- result = IO.readlines(@filename)
352
- expect(result[0] + result[1]).to eq @file_contents
353
- end
338
+ it 'reads the file normally' do
339
+ result = IO.readlines(@filename)
340
+ expect(result[0] + result[1]).to eq @file_contents
354
341
  end
355
- context 'with a filename and a limit 20' do
356
- it 'should read 20 bytes of the file' do
342
+
343
+ context 'using limit, separator' do
344
+ it 'splits the file and splits it into 5 char chunks' do
357
345
  exp_result = ['This ', 'is li', 'ne on', "e.\n", 'This ', 'is li', 'ne tw', "o.\n"]
358
346
  result = IO.readlines(@filename, 5)
359
347
  expect(result).to eq exp_result
360
348
  end
361
- end
362
- context 'with a filename and a limit of 20 and sep' do
363
- # TODO
349
+
350
+ it 'splits the file based on the sep and limit' do
351
+ exp_result = ['This ', 'is ', 'line ', "one.\n", 'This ', 'is ', 'line ', "two.\n"]
352
+ result = IO.readlines(@filename, ' ', 5)
353
+ expect(result).to eq exp_result
354
+ end
355
+
356
+ test_ruby2_ruby3_keywords(IO,
357
+ 'readlines',
358
+ [get_test_resource_path('lfi_sample_file.txt'), ' ', 5],
359
+ { chomp: true },
360
+ ['This', 'is', 'line', "one.\n", 'This', 'is', 'line', "two.\n"],
361
+ '2.4.0')
364
362
  end
365
363
  end
366
364
  context 'with a file blocked for read/write' do
@@ -379,12 +377,11 @@ describe 'IO' do
379
377
  result = IO.readlines('|echo test')[0]
380
378
  expect(result).to eq "test\n"
381
379
  end
382
- context 'with a filename' do
383
- it 'should not be able to read the file' do
384
- expect do
385
- IO.readlines(@filename)
386
- end.to raise_error(IOError)
387
- end
380
+
381
+ it 'should not be able to read the file' do
382
+ expect do
383
+ IO.readlines(@filename)
384
+ end.to raise_error(IOError)
388
385
  end
389
386
  end
390
387
  end
@@ -403,16 +400,7 @@ describe 'IO' do
403
400
  end.to raise_error(Errno::ENOENT)
404
401
  end
405
402
  end
406
- context 'with a nonexistent file' do
407
- context 'with mode r' do
408
- it 'should raise an error' do
409
- end
410
- end
411
- context 'with mode w' do
412
- it 'should return an integer' do
413
- end
414
- end
415
- end
403
+
416
404
  context 'with a file not blocked for read/write' do
417
405
  before do
418
406
  expect(TCellAgent).to receive(:policy).with(
@@ -421,27 +409,27 @@ describe 'IO' do
421
409
  expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
422
410
  end
423
411
 
424
- context 'with a filename' do
425
- it 'should return an integer' do
426
- fd = IO.sysopen(@filename)
427
- expect(fd).to be_a(Integer)
428
- end
429
- it 'should open the file for read' do
430
- fd = IO.sysopen(@filename)
431
- expect(IO.new(fd).read).to eq @file_contents
432
- end
412
+ it 'returns an integer' do
413
+ fd = IO.sysopen(@filename)
414
+ expect(fd).to be_a(Integer)
433
415
  end
434
- context 'with a filename and mode w' do
435
- it 'should return an integer' do
436
- fd = IO.sysopen(@new_file_name, 'w')
437
- expect(fd).to be_a(Integer)
438
- end
439
- it 'should open the file for write' do
440
- fd = IO.sysopen(@new_file_name, 'w')
441
- file = IO.new(fd, 'w')
442
- file.puts @file_contents
443
- file.rewind
444
- end
416
+ it 'opens the file for read' do
417
+ fd = IO.sysopen(@filename)
418
+ expect(IO.new(fd).read).to eq @file_contents
419
+ end
420
+ it 'uses the mode when set' do
421
+ fd = IO.sysopen(@new_file_name, 'w')
422
+ expect(fd).to be_a(Integer)
423
+
424
+ file = IO.new(fd, 'w')
425
+ file.puts @file_contents
426
+ file.rewind
427
+ end
428
+ it 'should open the file for write' do
429
+ fd = IO.sysopen(@new_file_name, 'w')
430
+ file = IO.new(fd, 'w')
431
+ file.puts @file_contents
432
+ file.rewind
445
433
  end
446
434
  end
447
435
  context 'with a file blocked for read/write' do
@@ -452,19 +440,16 @@ describe 'IO' do
452
440
  expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
453
441
  end
454
442
 
455
- context 'with a filename' do
456
- it 'should not be able to open the file for read' do
457
- expect do
458
- IO.sysopen(@filename)
459
- end.to raise_error(IOError)
460
- end
443
+ it 'should not be able to open the file for read' do
444
+ expect do
445
+ IO.sysopen(@filename)
446
+ end.to raise_error(IOError)
461
447
  end
462
- context 'with a filename and mode' do
463
- it 'should not be able to open the file for read' do
464
- expect do
465
- IO.sysopen(@filename, 'r')
466
- end.to raise_error(IOError)
467
- end
448
+
449
+ it 'should not be able to open the file for read' do
450
+ expect do
451
+ IO.sysopen(@filename, 'r')
452
+ end.to raise_error(IOError)
468
453
  end
469
454
  end
470
455
  end
@@ -491,48 +476,49 @@ describe 'IO' do
491
476
  expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
492
477
  end
493
478
 
494
- context 'with a filename that doe not exist' do
495
- it 'should create the file' do
496
- IO.write(@new_file_name, @file_contents)
497
- expect(File.exist?(@new_file_name)).to be_truthy
498
- File.delete(@new_file_name)
499
- end
500
- it 'should write to the file' do
501
- expect(TCellAgent).to receive(:policy).with(
502
- TCellAgent::PolicyTypes::LFI
503
- ).and_return(@local_files_policy)
504
- expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
479
+ after :each do
480
+ File.delete(@new_file_name)
481
+ end
482
+ it 'creates the file' do
483
+ IO.write(@new_file_name, @file_contents)
484
+ expect(File.exist?(@new_file_name)).to be_truthy
485
+ end
486
+ it 'writes to the file' do
487
+ expect(TCellAgent).to receive(:policy).with(
488
+ TCellAgent::PolicyTypes::LFI
489
+ ).and_return(@local_files_policy)
490
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
505
491
 
506
- IO.write(@new_file_name, @file_contents)
507
- expect(IO.read(@new_file_name)).to eq @file_contents
508
- File.delete(@new_file_name)
509
- end
492
+ IO.write(@new_file_name, @file_contents)
493
+ expect(File.open(@new_file_name).read).to eq @file_contents
510
494
  end
511
- context 'with a filename that does exist' do
512
- it 'should overwrite the file' do
513
- expect(TCellAgent).to receive(:policy).with(
514
- TCellAgent::PolicyTypes::LFI
515
- ).and_return(@local_files_policy)
516
- expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
517
495
 
518
- IO.write(@new_file_name, @file_contents)
519
- expect(IO.read(@new_file_name)).to eq @file_contents
520
- File.delete(@new_file_name)
521
- end
496
+ it 'writes over the file' do
497
+ expect(TCellAgent).to receive(:policy).with(
498
+ TCellAgent::PolicyTypes::LFI
499
+ ).and_return(@local_files_policy)
500
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
501
+
502
+ IO.write(@new_file_name, @file_contents)
503
+ expect(File.open(@new_file_name).read).to eq @file_contents
522
504
  end
523
- context 'with a filename that does exist and an offset 5' do
524
- it 'should overwrite the file starting at the offset value' do
505
+
506
+ context 'using offset, perm' do
507
+ after :each do
508
+ expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('444')
509
+
525
510
  expect(TCellAgent).to receive(:policy).with(
526
511
  TCellAgent::PolicyTypes::LFI
527
- ).and_return(@local_files_policy, @local_files_policy)
528
- expect(@local_files_policy).to receive(:block_file_access?).and_return(false, false)
529
-
530
- exp_results = @file_contents.dup
531
- exp_results[1..6] = 'OFFSET'
532
- IO.write(@new_file_name, @file_contents)
533
- IO.write(@new_file_name, 'OFFSET', 1)
534
- expect(IO.read(@new_file_name)).to eq exp_results
512
+ ).and_return(@local_files_policy)
513
+ expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
514
+ expect(File.open(@new_file_name).read).to eq @new_file_contents_offset_bytes
535
515
  end
516
+
517
+ test_ruby2_ruby3_keywords(IO,
518
+ 'write',
519
+ [NEW_FILE_NAME, 'OFFSET', 5],
520
+ { perm: 0o444 },
521
+ 6)
536
522
  end
537
523
  end
538
524
  context 'with a file blocked for read/write' do
@@ -543,20 +529,18 @@ describe 'IO' do
543
529
  expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
544
530
  end
545
531
 
546
- context 'with a filename that does not exist' do
547
- it 'should not be able to write to the file' do
548
- expect do
549
- IO.write(@new_file_name, '')
550
- end.to raise_error(IOError)
551
- end
532
+ it 'raises an IOError' do
533
+ expect do
534
+ IO.write(@new_file_name, '')
535
+ end.to raise_error(IOError)
552
536
  end
553
- context 'with a filename that does exist' do
554
- it 'should not be able to write to the file' do
555
- expect do
556
- IO.write(@filename, @file_contents)
557
- end.to raise_error(IOError)
558
- end
537
+ it 'should not be able to create and write to the file' do
538
+ expect do
539
+ IO.write(@filename, @file_contents)
540
+ end.to raise_error(IOError)
559
541
  end
560
542
  end
561
543
  end
562
544
  end
545
+
546
+ # rubocop:enable Style/HashSyntax