tcell_agent 2.1.1 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/bin/tcell_agent +41 -150
  4. data/lib/tcell_agent.rb +8 -16
  5. data/lib/tcell_agent/agent.rb +87 -52
  6. data/lib/tcell_agent/config_initializer.rb +62 -0
  7. data/lib/tcell_agent/configuration.rb +72 -267
  8. data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
  9. data/lib/tcell_agent/instrument_servers.rb +14 -18
  10. data/lib/tcell_agent/instrumentation.rb +14 -6
  11. data/lib/tcell_agent/instrumentation/cmdi.rb +47 -15
  12. data/lib/tcell_agent/instrumentation/lfi.rb +68 -11
  13. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
  14. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
  15. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
  16. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
  17. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
  18. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
  19. data/lib/tcell_agent/logger.rb +3 -4
  20. data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
  21. data/lib/tcell_agent/policies/headers_policy.rb +2 -2
  22. data/lib/tcell_agent/policies/patches_policy.rb +8 -4
  23. data/lib/tcell_agent/policies/policies_manager.rb +1 -0
  24. data/lib/tcell_agent/policies/policy_polling.rb +4 -3
  25. data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
  26. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  27. data/lib/tcell_agent/rails/auth/devise.rb +103 -102
  28. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  29. data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -57
  30. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  31. data/lib/tcell_agent/rails/better_ip.rb +7 -19
  32. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  33. data/lib/tcell_agent/rails/dlp.rb +48 -52
  34. data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
  35. data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
  36. data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
  37. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
  38. data/lib/tcell_agent/rails/middleware/global_middleware.rb +3 -4
  39. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
  40. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  41. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  42. data/lib/tcell_agent/rails/routes.rb +3 -6
  43. data/lib/tcell_agent/rails/routes/grape.rb +5 -12
  44. data/lib/tcell_agent/rails/settings_reporter.rb +0 -8
  45. data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -7
  46. data/lib/tcell_agent/routes/table.rb +3 -0
  47. data/lib/tcell_agent/rust/agent_config.rb +52 -32
  48. data/lib/tcell_agent/rust/{libtcellagent-4.18.0.so → libtcellagent-alpine.so} +0 -0
  49. data/lib/tcell_agent/rust/libtcellagent-x64.dll +0 -0
  50. data/lib/tcell_agent/rust/{libtcellagent-4.18.0.dylib → libtcellagent.dylib} +0 -0
  51. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.18.0.so → libtcellagent.so} +0 -0
  52. data/lib/tcell_agent/rust/models.rb +9 -0
  53. data/lib/tcell_agent/rust/native_agent.rb +58 -50
  54. data/lib/tcell_agent/rust/native_library.rb +8 -10
  55. data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
  56. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
  57. data/lib/tcell_agent/servers/puma.rb +30 -13
  58. data/lib/tcell_agent/servers/rack_puma_handler.rb +33 -0
  59. data/lib/tcell_agent/servers/rails_server.rb +4 -4
  60. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  61. data/lib/tcell_agent/servers/webrick.rb +12 -3
  62. data/lib/tcell_agent/settings_reporter.rb +0 -93
  63. data/lib/tcell_agent/sinatra.rb +1 -0
  64. data/lib/tcell_agent/tcell_context.rb +16 -7
  65. data/lib/tcell_agent/utils/headers.rb +0 -1
  66. data/lib/tcell_agent/utils/strings.rb +2 -2
  67. data/lib/tcell_agent/version.rb +1 -1
  68. data/spec/cruby_spec_helper.rb +26 -0
  69. data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
  70. data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
  71. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
  72. data/spec/lib/tcell_agent/instrumentation/cmdi_spec.rb +46 -4
  73. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
  74. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +207 -223
  75. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +89 -70
  76. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +120 -2
  77. data/spec/lib/tcell_agent/patches_spec.rb +2 -1
  78. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
  79. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
  80. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
  81. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
  82. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +14 -8
  83. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
  84. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
  85. data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
  86. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
  87. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
  88. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
  89. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  90. data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -89
  91. data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
  92. data/spec/spec_helper.rb +9 -1
  93. data/spec/support/builders.rb +8 -7
  94. data/spec/support/server_mocks/passenger_mock.rb +7 -0
  95. data/spec/support/server_mocks/puma_mock.rb +21 -0
  96. data/spec/support/server_mocks/rails_mock.rb +7 -0
  97. data/spec/support/server_mocks/thin_mock.rb +7 -0
  98. data/spec/support/server_mocks/unicorn_mock.rb +11 -0
  99. data/spec/support/shared_spec.rb +29 -0
  100. data/tcell_agent.gemspec +14 -14
  101. metadata +44 -27
  102. data/Rakefile +0 -18
  103. data/lib/tcell_agent/authlogic.rb +0 -23
  104. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  105. data/lib/tcell_agent/devise.rb +0 -33
  106. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
  107. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -131
  108. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -163
  109. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  110. data/lib/tcell_agent/rust/tcellagent-4.18.0.dll +0 -0
  111. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -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