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