tcell_agent 2.3.0 → 2.5.1
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 +6 -11
- data/lib/tcell_agent/agent.rb +18 -13
- data/lib/tcell_agent/config_initializer.rb +2 -5
- data/lib/tcell_agent/configuration.rb +4 -4
- data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
- data/lib/tcell_agent/instrumentation/cmdi.rb +32 -0
- data/lib/tcell_agent/instrumentation/lfi.rb +55 -9
- 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 +2 -2
- 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/doorkeeper.rb +1 -0
- data/lib/tcell_agent/rails/better_ip.rb +7 -19
- data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
- data/lib/tcell_agent/rails/dlp.rb +48 -48
- 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 +1 -5
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
- data/lib/tcell_agent/rails/routes/grape.rb +2 -1
- data/lib/tcell_agent/rails/settings_reporter.rb +3 -6
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -6
- data/lib/tcell_agent/routes/table.rb +3 -0
- data/lib/tcell_agent/rust/agent_config.rb +18 -0
- data/lib/tcell_agent/rust/{libtcellagent-alpine-6.2.1.so → libtcellagent-alpine.so} +0 -0
- data/lib/tcell_agent/rust/{tcellagent-6.2.1.dll → libtcellagent-x64.dll} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-6.2.1.dylib → libtcellagent.dylib} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-6.2.1.so → libtcellagent.so} +0 -0
- data/lib/tcell_agent/rust/native_agent.rb +51 -59
- data/lib/tcell_agent/rust/native_library.rb +7 -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 +25 -8
- data/lib/tcell_agent/servers/rack_puma_handler.rb +13 -3
- data/lib/tcell_agent/servers/webrick.rb +14 -4
- data/lib/tcell_agent/settings_reporter.rb +0 -14
- data/lib/tcell_agent/sinatra.rb +1 -0
- data/lib/tcell_agent/tcell_context.rb +15 -6
- 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/spec/cruby_spec_helper.rb +26 -0
- data/spec/lib/tcell_agent/instrument_servers_spec.rb +42 -7
- data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
- data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
- data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +207 -223
- data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +89 -70
- data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +73 -0
- 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/settings_reporter_spec.rb +2 -16
- data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
- data/spec/spec_helper.rb +3 -1
- data/spec/support/builders.rb +2 -1
- data/spec/support/server_mocks/{puma_mock.rb → puma_mock_1.rb} +5 -1
- data/spec/support/server_mocks/puma_mock_2.rb +26 -0
- data/spec/support/server_mocks/puma_mock_3.rb +22 -0
- data/spec/support/shared_spec.rb +29 -0
- data/tcell_agent.gemspec +14 -14
- metadata +29 -21
- data/Rakefile +0 -18
- data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
- data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -131
- data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -102
|
Binary file
|
|
Binary file
|
|
@@ -9,55 +9,6 @@ require 'tcell_agent/utils/headers'
|
|
|
9
9
|
module TCellAgent
|
|
10
10
|
module Rust
|
|
11
11
|
class NativeAgent # rubocop:disable Metrics/ClassLength
|
|
12
|
-
def self.test_event_sender(events)
|
|
13
|
-
config = TCellAgent.configuration
|
|
14
|
-
event_sender = {
|
|
15
|
-
:uuid => config.uuid,
|
|
16
|
-
:hostname => config.host_identifier,
|
|
17
|
-
:agent_type => 'Ruby',
|
|
18
|
-
:agent_version => TCellAgent::VERSION,
|
|
19
|
-
:app_id => config.app_id,
|
|
20
|
-
:api_key => config.api_key,
|
|
21
|
-
:tcell_input_url => config.tcell_input_url,
|
|
22
|
-
:events => events
|
|
23
|
-
}
|
|
24
|
-
event_sender_pointer = FFI::MemoryPointer.from_string(
|
|
25
|
-
JSON.dump(event_sender)
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
|
|
29
|
-
# config_pointer.size - 1: strips null terminator
|
|
30
|
-
result_size = TCellAgent::Rust::NativeLibrary.test_event_sender(
|
|
31
|
-
event_sender_pointer, event_sender_pointer.size - 1, buf, buf.size
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
response = NativeAgentResponse.new('test_event_sender', buf, result_size)
|
|
35
|
-
|
|
36
|
-
response.errors
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def self.test_policies
|
|
40
|
-
config = TCellAgent.configuration
|
|
41
|
-
policies_info = {
|
|
42
|
-
:app_id => config.app_id,
|
|
43
|
-
:api_key => config.api_key,
|
|
44
|
-
:tcell_api_url => config.tcell_api_url
|
|
45
|
-
}
|
|
46
|
-
policies_info_pointer = FFI::MemoryPointer.from_string(
|
|
47
|
-
JSON.dump(policies_info)
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
|
|
51
|
-
# config_pointer.size - 1: strips null terminator
|
|
52
|
-
result_size = TCellAgent::Rust::NativeLibrary.test_policies(
|
|
53
|
-
policies_info_pointer, policies_info_pointer.size - 1, buf, buf.size
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
response = NativeAgentResponse.new('test_event_sender', buf, result_size)
|
|
57
|
-
|
|
58
|
-
response.errors
|
|
59
|
-
end
|
|
60
|
-
|
|
61
12
|
def self.test_agent(config)
|
|
62
13
|
agent_config = TCellAgent::Rust::AgentConfig.new(config)
|
|
63
14
|
|
|
@@ -133,6 +84,7 @@ module TCellAgent
|
|
|
133
84
|
:headers => header_params,
|
|
134
85
|
:cookies => cookie_params,
|
|
135
86
|
:path_params => path_params,
|
|
87
|
+
:reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
|
|
136
88
|
:remote_address => appsensor_meta.remote_address,
|
|
137
89
|
:full_uri => appsensor_meta.location,
|
|
138
90
|
:session_id => appsensor_meta.session_id,
|
|
@@ -143,7 +95,6 @@ module TCellAgent
|
|
|
143
95
|
:content_type => appsensor_meta.content_type,
|
|
144
96
|
:request_body => appsensor_meta.raw_request_body
|
|
145
97
|
}
|
|
146
|
-
|
|
147
98
|
request_response_json[:sql_exceptions] = appsensor_meta.sql_exceptions if appsensor_meta.sql_exceptions
|
|
148
99
|
request_response_json[:database_result_sizes] = appsensor_meta.database_result_sizes if appsensor_meta.database_result_sizes
|
|
149
100
|
|
|
@@ -184,13 +135,15 @@ module TCellAgent
|
|
|
184
135
|
:method => appsensor_meta.method,
|
|
185
136
|
:path => appsensor_meta.path,
|
|
186
137
|
:remote_address => appsensor_meta.remote_address,
|
|
138
|
+
:reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
|
|
187
139
|
:request_bytes_length => appsensor_meta.request_content_bytes_len,
|
|
188
140
|
:query_params => query_params,
|
|
189
|
-
:post_params =>
|
|
141
|
+
:post_params => post_params,
|
|
190
142
|
:headers => header_params,
|
|
191
143
|
:cookies => cookie_params,
|
|
192
144
|
:content_type => appsensor_meta.content_type,
|
|
193
|
-
:full_uri => appsensor_meta.location
|
|
145
|
+
:full_uri => appsensor_meta.location,
|
|
146
|
+
:request_body => appsensor_meta.raw_request_body
|
|
194
147
|
}
|
|
195
148
|
|
|
196
149
|
patches_request_pointer = FFI::MemoryPointer.from_string(
|
|
@@ -213,6 +166,37 @@ module TCellAgent
|
|
|
213
166
|
response.response
|
|
214
167
|
end
|
|
215
168
|
|
|
169
|
+
def apply_suspicious_quick_check(appsensor_meta)
|
|
170
|
+
return {} unless appsensor_meta
|
|
171
|
+
|
|
172
|
+
sus_quick_check_request_json = {
|
|
173
|
+
:reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
|
|
174
|
+
:method => appsensor_meta.method,
|
|
175
|
+
:path => appsensor_meta.path,
|
|
176
|
+
:full_uri => appsensor_meta.location,
|
|
177
|
+
:request_bytes_length => appsensor_meta.request_content_bytes_len
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if appsensor_meta.reverse_proxy_header_value.nil?
|
|
181
|
+
sus_quick_check_request_json.merge(
|
|
182
|
+
{
|
|
183
|
+
:client_ip_override => appsensor_meta.remote_address
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
sus_quick_check_request_ptr = FFI::MemoryPointer.from_string(
|
|
189
|
+
JSON.dump(sus_quick_check_request_json)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# sus_quick_check_request_ptr.size - 1: strips null terminator
|
|
193
|
+
TCellAgent::Rust::NativeLibrary.suspicious_quick_check_apply(
|
|
194
|
+
FFI::Pointer.new(@agent_ptr),
|
|
195
|
+
sus_quick_check_request_ptr,
|
|
196
|
+
sus_quick_check_request_ptr.size - 1
|
|
197
|
+
)
|
|
198
|
+
end
|
|
199
|
+
|
|
216
200
|
def apply_cmdi(command, tcell_context)
|
|
217
201
|
return unless TCellAgent::Utils::Strings.present?(command)
|
|
218
202
|
|
|
@@ -220,6 +204,7 @@ module TCellAgent
|
|
|
220
204
|
:command => command,
|
|
221
205
|
:method => tcell_context.request_method,
|
|
222
206
|
:path => tcell_context.path,
|
|
207
|
+
:reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
|
|
223
208
|
:remote_address => tcell_context.remote_address,
|
|
224
209
|
:route_id => tcell_context.route_id,
|
|
225
210
|
:session_id => tcell_context.session_id,
|
|
@@ -247,10 +232,11 @@ module TCellAgent
|
|
|
247
232
|
response.response
|
|
248
233
|
end
|
|
249
234
|
|
|
250
|
-
def get_headers(tcell_context)
|
|
235
|
+
def get_headers(content_type, tcell_context)
|
|
251
236
|
return unless tcell_context
|
|
252
237
|
|
|
253
238
|
headers_request = {
|
|
239
|
+
:content_type => content_type,
|
|
254
240
|
:method => tcell_context.request_method,
|
|
255
241
|
:path => tcell_context.path,
|
|
256
242
|
:route_id => tcell_context.route_id.to_s,
|
|
@@ -288,8 +274,9 @@ module TCellAgent
|
|
|
288
274
|
:status_code => status_code,
|
|
289
275
|
:method => tcell_context.request_method,
|
|
290
276
|
:path => tcell_context.path,
|
|
277
|
+
:reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
|
|
291
278
|
:remote_addr => tcell_context.remote_address,
|
|
292
|
-
:full_uri => tcell_context.
|
|
279
|
+
:full_uri => tcell_context.uri,
|
|
293
280
|
:route_id => tcell_context.route_id,
|
|
294
281
|
:session_id => tcell_context.session_id,
|
|
295
282
|
:user_id => tcell_context.user_id
|
|
@@ -353,11 +340,12 @@ module TCellAgent
|
|
|
353
340
|
:event_name => event_name,
|
|
354
341
|
:user_id => user_id,
|
|
355
342
|
:user_agent => tcell_context.user_agent,
|
|
343
|
+
:reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
|
|
356
344
|
:remote_address => tcell_context.remote_address,
|
|
357
345
|
:header_keys => header_keys,
|
|
358
|
-
:
|
|
346
|
+
:password => password,
|
|
359
347
|
:session_id => tcell_context.session_id,
|
|
360
|
-
:full_uri => tcell_context.
|
|
348
|
+
:full_uri => tcell_context.uri,
|
|
361
349
|
:referrer => tcell_context.referrer,
|
|
362
350
|
:user_valid => user_valid
|
|
363
351
|
}
|
|
@@ -395,11 +383,14 @@ module TCellAgent
|
|
|
395
383
|
if tcell_context
|
|
396
384
|
file_access_info = file_access_info.merge(
|
|
397
385
|
{
|
|
398
|
-
:full_uri => tcell_context.
|
|
386
|
+
:full_uri => tcell_context.uri,
|
|
387
|
+
:reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
|
|
399
388
|
:remote_address => tcell_context.remote_address,
|
|
400
389
|
:route_id => tcell_context.route_id,
|
|
401
390
|
:session_id => tcell_context.session_id,
|
|
402
|
-
:user_id => tcell_context.user_id
|
|
391
|
+
:user_id => tcell_context.user_id,
|
|
392
|
+
:method => tcell_context.request_method,
|
|
393
|
+
:request_path => tcell_context.path
|
|
403
394
|
}
|
|
404
395
|
)
|
|
405
396
|
end
|
|
@@ -471,6 +462,7 @@ module TCellAgent
|
|
|
471
462
|
:session_id => tcell_context && tcell_context.session_id,
|
|
472
463
|
:user_id => tcell_context && tcell_context.user_id,
|
|
473
464
|
:user_agent => tcell_context && tcell_context.user_agent,
|
|
465
|
+
:reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
|
|
474
466
|
:remote_address => tcell_context && tcell_context.remote_address
|
|
475
467
|
}
|
|
476
468
|
message_pointer = FFI::MemoryPointer.from_string(
|
|
@@ -522,7 +514,7 @@ module TCellAgent
|
|
|
522
514
|
end
|
|
523
515
|
end
|
|
524
516
|
|
|
525
|
-
#
|
|
517
|
+
# NOTE: for tests
|
|
526
518
|
def update_policies(policies)
|
|
527
519
|
return {} unless TCellAgent::Utils::Strings.present?(policies)
|
|
528
520
|
|
|
@@ -6,22 +6,20 @@ module TCellAgent
|
|
|
6
6
|
require 'ffi'
|
|
7
7
|
extend FFI::Library
|
|
8
8
|
|
|
9
|
-
VERSION = '6.2.1'.freeze
|
|
10
|
-
prefix = 'lib'
|
|
11
9
|
extension = '.so'
|
|
12
10
|
variant = ''
|
|
13
11
|
if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
|
12
|
+
variant = '-x64'
|
|
14
13
|
extension = '.dll'
|
|
15
|
-
prefix = ''
|
|
16
14
|
elsif /darwin/ =~ RUBY_PLATFORM
|
|
17
15
|
extension = '.dylib'
|
|
18
16
|
elsif /musl/ =~ RUBY_PLATFORM
|
|
19
|
-
variant = 'alpine
|
|
17
|
+
variant = '-alpine'
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
begin
|
|
23
21
|
ffi_lib File.join(File.dirname(__FILE__),
|
|
24
|
-
"#{
|
|
22
|
+
"libtcellagent#{variant}#{extension}")
|
|
25
23
|
|
|
26
24
|
# All the rust library calls have the following response api:
|
|
27
25
|
#
|
|
@@ -36,6 +34,7 @@ module TCellAgent
|
|
|
36
34
|
attach_function :poll_new_policies, %i[pointer pointer size_t], :int
|
|
37
35
|
attach_function :appfirewall_apply, %i[pointer pointer size_t pointer size_t], :int
|
|
38
36
|
attach_function :patches_apply, %i[pointer pointer size_t pointer size_t], :int
|
|
37
|
+
attach_function :suspicious_quick_check_apply, %i[pointer pointer size_t], :int
|
|
39
38
|
attach_function :cmdi_apply, %i[pointer pointer size_t pointer size_t], :int
|
|
40
39
|
attach_function :get_headers, %i[pointer pointer size_t pointer size_t], :int
|
|
41
40
|
attach_function :get_js_agent_script_tag, %i[pointer pointer size_t pointer size_t], :int
|
|
@@ -48,17 +47,15 @@ module TCellAgent
|
|
|
48
47
|
attach_function :log_message, %i[pointer pointer size_t pointer size_t], :int
|
|
49
48
|
|
|
50
49
|
attach_function :update_policies, %i[pointer pointer size_t pointer size_t], :int
|
|
51
|
-
attach_function :test_event_sender, %i[pointer size_t pointer size_t], :int
|
|
52
|
-
attach_function :test_policies, %i[pointer size_t pointer size_t], :int
|
|
53
50
|
attach_function :test_agent, %i[pointer size_t pointer size_t], :int
|
|
54
51
|
|
|
55
52
|
def self.common_lib_available?
|
|
56
53
|
true
|
|
57
54
|
end
|
|
58
|
-
rescue LoadError =>
|
|
55
|
+
rescue LoadError => e
|
|
59
56
|
logger = TCellAgent::ModuleLogger.new(TCellAgent::RubyLogger.new, name)
|
|
60
|
-
logger.error("Failed loading agent library. #{
|
|
61
|
-
logger.exception(
|
|
57
|
+
logger.error("Failed loading agent library. #{e.message}")
|
|
58
|
+
logger.exception(e)
|
|
62
59
|
|
|
63
60
|
def self.common_lib_available? # rubocop:disable Lint/DuplicateMethods
|
|
64
61
|
false
|
|
@@ -7,59 +7,6 @@ require 'etc'
|
|
|
7
7
|
|
|
8
8
|
module TCellAgent
|
|
9
9
|
module SensorEvents
|
|
10
|
-
class ServerAgentDetailsSensorEvent < TCellSensorEvent
|
|
11
|
-
include TCellAgent::ModuleLoggerAccess
|
|
12
|
-
|
|
13
|
-
def initialize
|
|
14
|
-
super('server_agent_details')
|
|
15
|
-
@flush = true
|
|
16
|
-
@ensure = true
|
|
17
|
-
|
|
18
|
-
self['user'] = 'unknown'
|
|
19
|
-
self['group'] = 'unknown'
|
|
20
|
-
|
|
21
|
-
begin
|
|
22
|
-
login = Etc.getlogin
|
|
23
|
-
if login
|
|
24
|
-
self['user'] = login
|
|
25
|
-
begin
|
|
26
|
-
info = Etc.getpwnam(login)
|
|
27
|
-
self['group'] = info.gid.to_s
|
|
28
|
-
rescue StandardError => te
|
|
29
|
-
module_logger.debug("Could not get group id: #{te.message}")
|
|
30
|
-
module_logger.exception(te)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
rescue StandardError => to
|
|
34
|
-
module_logger.debug("Could not get user & group: #{to.message}")
|
|
35
|
-
module_logger.exception(te)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
module_logger.debug("User #{self['user']}")
|
|
39
|
-
module_logger.debug("Group #{self['group']}")
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
class ServerAgentDetailsLanguageEvent < TCellSensorEvent
|
|
44
|
-
def initialize(language, language_version)
|
|
45
|
-
super('server_agent_details')
|
|
46
|
-
@flush = true
|
|
47
|
-
@ensure = true
|
|
48
|
-
self['language'] = language
|
|
49
|
-
self['language_version'] = language_version
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
class ServerAgentAppFrameworkEvent < TCellSensorEvent
|
|
54
|
-
def initialize(framework_name, framework_version)
|
|
55
|
-
super('server_agent_details')
|
|
56
|
-
@flush = true
|
|
57
|
-
@ensure = true
|
|
58
|
-
self['app_framework'] = framework_name
|
|
59
|
-
self['app_framework_version'] = framework_version
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
10
|
class ServerAgentPackagesSensorEvent < TCellSensorEvent
|
|
64
11
|
include TCellAgent::ModuleLoggerAccess
|
|
65
12
|
|
|
@@ -75,59 +22,15 @@ module TCellAgent
|
|
|
75
22
|
packages.push(package)
|
|
76
23
|
module_logger.debug("Adding packages #{x.name}")
|
|
77
24
|
end
|
|
78
|
-
rescue StandardError =>
|
|
79
|
-
module_logger.error("Exception adding package: #{
|
|
80
|
-
module_logger.exception(
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
module_logger.error("Exception adding package: #{e.message}")
|
|
27
|
+
module_logger.exception(e)
|
|
81
28
|
end
|
|
82
29
|
end
|
|
83
30
|
self['packages'] = packages
|
|
84
31
|
end
|
|
85
32
|
end
|
|
86
33
|
|
|
87
|
-
class AppFramework < TCellSensorEvent
|
|
88
|
-
def initialize(name, version)
|
|
89
|
-
super('appserver_framework')
|
|
90
|
-
@flush = false
|
|
91
|
-
@ensure = true
|
|
92
|
-
self['n'] = name
|
|
93
|
-
self['v'] = version
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
class AppAuthFramework < TCellSensorEvent
|
|
98
|
-
def initialize(name, version)
|
|
99
|
-
super('appserver_auth_framework')
|
|
100
|
-
@flush = false
|
|
101
|
-
@ensure = true
|
|
102
|
-
self['n'] = name
|
|
103
|
-
self['v'] = version
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
class AppFrameworkSetting < TCellSensorEvent
|
|
108
|
-
def initialize(framework_name, setting, value)
|
|
109
|
-
super('appserver_framework_setting')
|
|
110
|
-
@flush = false
|
|
111
|
-
@ensure = true
|
|
112
|
-
self['framework'] = framework_name
|
|
113
|
-
self['s'] = setting
|
|
114
|
-
self['v'] = value
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
class AppCookie < TCellSensorEvent
|
|
119
|
-
def initialize(name, value, secure, http_only, session)
|
|
120
|
-
super('appserver_framework_setting')
|
|
121
|
-
@flush = false
|
|
122
|
-
@ensure = true
|
|
123
|
-
self['n'] = name
|
|
124
|
-
self['v'] = value
|
|
125
|
-
self['http_only'] = http_only
|
|
126
|
-
self['secure'] = secure
|
|
127
|
-
self['session'] = session
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
34
|
class AppRoutesSensorEvent < TCellSensorEvent
|
|
132
35
|
def initialize(uri, method, route_id, params = nil, destination = nil)
|
|
133
36
|
super('appserver_routes')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
if defined?(Puma.cli_config)
|
|
2
2
|
if Puma.cli_config.options[:preload_app]
|
|
3
|
-
if Puma.cli_config.options[:workers] == 0
|
|
3
|
+
if Puma.cli_config.options[:workers] == 0
|
|
4
4
|
# Puma is running in single mode, so run both the initial instrumentation and
|
|
5
5
|
# start the agent
|
|
6
6
|
Puma::Runner.class_eval do
|
|
@@ -15,24 +15,41 @@ if defined?(Puma.cli_config)
|
|
|
15
15
|
else
|
|
16
16
|
Puma::Server.class_eval do
|
|
17
17
|
alias_method :tcell_original_run, :run
|
|
18
|
-
def run(background = true)
|
|
19
|
-
TCellAgent.thread_agent.start('Puma Cluster Mode (Worker)')
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
if defined?(Gem::Version) &&
|
|
20
|
+
defined?(Puma::Const::PUMA_VERSION) &&
|
|
21
|
+
(Gem::Version.new(Puma::Const::PUMA_VERSION) < Gem::Version.new('5.1.0'))
|
|
22
|
+
def run(background = true)
|
|
23
|
+
TCellAgent.thread_agent.start('Puma')
|
|
24
|
+
tcell_original_run(background)
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
def run(background = true, thread_name: 'server')
|
|
28
|
+
TCellAgent.thread_agent.start('Puma')
|
|
29
|
+
tcell_original_run(background, :thread_name => thread_name)
|
|
30
|
+
end
|
|
22
31
|
end
|
|
23
32
|
end
|
|
24
33
|
end
|
|
25
|
-
|
|
26
34
|
else
|
|
27
35
|
# this ensures instrumentation runs for preload_app = false.
|
|
28
36
|
# Instrumentation will run for each worker but there's
|
|
29
37
|
# nothing we can do about that (Unicorn's preload_app behaves the same way)
|
|
30
38
|
Puma::Server.class_eval do
|
|
31
39
|
alias_method :tcell_original_run, :run
|
|
32
|
-
def run(background = true)
|
|
33
|
-
TCellAgent.thread_agent.start('Puma Cluster Mode (Worker)')
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
if defined?(Gem::Version) &&
|
|
42
|
+
defined?(Puma::Const::PUMA_VERSION) &&
|
|
43
|
+
(Gem::Version.new(Puma::Const::PUMA_VERSION) < Gem::Version.new('5.1.0'))
|
|
44
|
+
def run(background = true)
|
|
45
|
+
TCellAgent.thread_agent.start('Puma')
|
|
46
|
+
tcell_original_run(background)
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
def run(background = true, thread_name: 'server')
|
|
50
|
+
TCellAgent.thread_agent.start('Puma')
|
|
51
|
+
tcell_original_run(background, :thread_name => thread_name)
|
|
52
|
+
end
|
|
36
53
|
end
|
|
37
54
|
end
|
|
38
55
|
end
|
|
@@ -9,10 +9,20 @@ Rack::Handler::Puma.class_eval do
|
|
|
9
9
|
if defined?(Puma::Server) && !Puma::Server.instance_methods.include?(:tcell_original_run)
|
|
10
10
|
Puma::Server.class_eval do
|
|
11
11
|
alias_method :tcell_original_run, :run
|
|
12
|
-
def run(background = true)
|
|
13
|
-
TCellAgent.thread_agent.start('Puma')
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
if defined?(Gem::Version) &&
|
|
14
|
+
defined?(Puma::Const::PUMA_VERSION) &&
|
|
15
|
+
(Gem::Version.new(Puma::Const::PUMA_VERSION) >= Gem::Version.new('5.1.0'))
|
|
16
|
+
def run(background = true, thread_name: 'server')
|
|
17
|
+
TCellAgent.thread_agent.start('Puma')
|
|
18
|
+
tcell_original_run(background, :thread_name => thread_name)
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
def run(background = true)
|
|
22
|
+
TCellAgent.thread_agent.start('Puma')
|
|
23
|
+
|
|
24
|
+
tcell_original_run(background)
|
|
25
|
+
end
|
|
16
26
|
end
|
|
17
27
|
end
|
|
18
28
|
end
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
Rack::Handler::WEBrick.class_eval do
|
|
2
2
|
class << self
|
|
3
|
-
alias_method :
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
alias_method :tcell_original_run, :run
|
|
4
|
+
|
|
5
|
+
if defined?(Gem::Version) &&
|
|
6
|
+
defined?(Rack.release) &&
|
|
7
|
+
Gem::Version.new(Rack.release) < Gem::Version.new('2.2.0')
|
|
8
|
+
def run(app, options = {})
|
|
9
|
+
TCellAgent.thread_agent.start('WEBrick')
|
|
10
|
+
tcell_original_run(app, options)
|
|
11
|
+
end
|
|
12
|
+
else
|
|
13
|
+
def run(app, **options)
|
|
14
|
+
TCellAgent.thread_agent.start('WEBrick')
|
|
15
|
+
tcell_original_run(app, **options)
|
|
16
|
+
end
|
|
7
17
|
end
|
|
8
18
|
end
|
|
9
19
|
end
|
|
@@ -7,25 +7,11 @@ require 'thread'
|
|
|
7
7
|
module TCellAgent
|
|
8
8
|
def self.report_settings
|
|
9
9
|
Thread.new do
|
|
10
|
-
TCellAgent::Instrumentation.safe_block('Instrumenting Agent Details') do
|
|
11
|
-
event = TCellAgent::SensorEvents::ServerAgentDetailsSensorEvent.new
|
|
12
|
-
TCellAgent.send_event(event)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
10
|
TCellAgent::Instrumentation.safe_block('Instrumenting Server Packages') do
|
|
16
11
|
event = TCellAgent::SensorEvents::ServerAgentPackagesSensorEvent.new
|
|
17
12
|
TCellAgent.send_event(event)
|
|
18
13
|
end
|
|
19
14
|
|
|
20
|
-
TCellAgent::Instrumentation.safe_block('Instrumenting Language Info') do
|
|
21
|
-
TCellAgent.send_event(
|
|
22
|
-
TCellAgent::SensorEvents::ServerAgentDetailsLanguageEvent.new(
|
|
23
|
-
'Ruby',
|
|
24
|
-
RUBY_VERSION
|
|
25
|
-
)
|
|
26
|
-
)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
15
|
TCellAgent::Instrumentation.safe_block('Instrumenting Native Lib Status') do
|
|
30
16
|
require 'tcell_agent/rust/native_agent'
|
|
31
17
|
|
data/lib/tcell_agent/sinatra.rb
CHANGED
|
@@ -16,6 +16,7 @@ module TCellAgent
|
|
|
16
16
|
TCellAgent::Instrumentation.safe_block('Setting Headers') do
|
|
17
17
|
headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HEADERS)
|
|
18
18
|
policy_headers = headers_policy.get_headers(
|
|
19
|
+
headers['Content-Type'],
|
|
19
20
|
request.env[TCellAgent::Instrumentation::TCELL_ID]
|
|
20
21
|
)
|
|
21
22
|
policy_headers.each do |header_info|
|
|
@@ -43,7 +43,8 @@ module TCellAgent
|
|
|
43
43
|
tcell_context.session_id,
|
|
44
44
|
tcell_context.user_id,
|
|
45
45
|
tcell_context.transaction_id,
|
|
46
|
-
tcell_context.uri
|
|
46
|
+
tcell_context.uri,
|
|
47
|
+
tcell_context.reverse_proxy_header_value
|
|
47
48
|
)
|
|
48
49
|
meta_data.path = tcell_context.path
|
|
49
50
|
|
|
@@ -70,7 +71,8 @@ module TCellAgent
|
|
|
70
71
|
:response_headers,
|
|
71
72
|
:csrf_exception_name,
|
|
72
73
|
:sql_exceptions,
|
|
73
|
-
:database_result_sizes
|
|
74
|
+
:database_result_sizes,
|
|
75
|
+
:reverse_proxy_header_value
|
|
74
76
|
|
|
75
77
|
attr_reader :flattened_get_dict,
|
|
76
78
|
:flattened_cookie_dict,
|
|
@@ -85,7 +87,8 @@ module TCellAgent
|
|
|
85
87
|
session_id,
|
|
86
88
|
user_id,
|
|
87
89
|
transaction_id,
|
|
88
|
-
location
|
|
90
|
+
location,
|
|
91
|
+
reverse_proxy_header_value)
|
|
89
92
|
@method = method
|
|
90
93
|
@remote_address = remote_address
|
|
91
94
|
@route_id = route_id
|
|
@@ -93,7 +96,7 @@ module TCellAgent
|
|
|
93
96
|
@user_id = user_id
|
|
94
97
|
@transaction_id = transaction_id
|
|
95
98
|
@location = location
|
|
96
|
-
@
|
|
99
|
+
@reverse_proxy_header_value = reverse_proxy_header_value
|
|
97
100
|
|
|
98
101
|
@flattened_get_dict = {}
|
|
99
102
|
@flattened_cookie_dict = {}
|
|
@@ -148,6 +151,7 @@ module TCellAgent
|
|
|
148
151
|
if !content_length.nil? && content_length > TCELL_MAX_BODY_LENGTH || request.content_type.nil?
|
|
149
152
|
return nil
|
|
150
153
|
end
|
|
154
|
+
|
|
151
155
|
raw_post_data = nil
|
|
152
156
|
# Positions strio to the beginning of input, resetting lineno to zero.
|
|
153
157
|
# rails 4.1 seems to read the stringIO directly and so body.gets is empty
|
|
@@ -171,10 +175,15 @@ module TCellAgent
|
|
|
171
175
|
self.get_dict = request.GET
|
|
172
176
|
self.cookie_dict = request.cookies
|
|
173
177
|
|
|
174
|
-
self.post_dict = if @content_type.start_with?('application/json', 'application/xml')
|
|
178
|
+
self.post_dict = if @content_type.start_with?('application/json', 'application/xml') ||
|
|
179
|
+
(@content_type.start_with?('multipart/form-data') && @request_content_bytes_len == 0)
|
|
175
180
|
{}
|
|
176
181
|
else
|
|
177
|
-
|
|
182
|
+
begin
|
|
183
|
+
request.POST
|
|
184
|
+
rescue EOFError
|
|
185
|
+
{}
|
|
186
|
+
end
|
|
178
187
|
end
|
|
179
188
|
|
|
180
189
|
self.headers_dict = request.env
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module TCellAgent
|
|
2
2
|
module Utils
|
|
3
3
|
module Strings
|
|
4
|
-
BLANK_RE = /\A[[:space:]]*\z
|
|
4
|
+
BLANK_RE = /\A[[:space:]]*\z/.freeze
|
|
5
5
|
|
|
6
6
|
def self.blank?(str)
|
|
7
|
-
str.nil? || str.empty? || BLANK_RE === str
|
|
7
|
+
str.nil? || str.empty? || BLANK_RE === str
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def self.present?(str)
|
data/lib/tcell_agent/version.rb
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'tcell_agent'
|
|
2
|
+
|
|
3
|
+
TCellAgent.configuration.enabled = true
|
|
4
|
+
TCellAgent.configuration.instrument = true
|
|
5
|
+
TCellAgent.configuration.enable_intercept_requests = true
|
|
6
|
+
TCellAgent.configuration.disabled_instrumentation = []
|
|
7
|
+
TCellAgent.thread_agent.instrument_built_ins
|
|
8
|
+
|
|
9
|
+
# This monkey patch turns off blocking for LFI/CMDI when run in CRuby specs/
|
|
10
|
+
# test suite. The original method also depends on a Rails installation,
|
|
11
|
+
# which CRuby does not have installed.
|
|
12
|
+
module TCellAgent
|
|
13
|
+
module Instrumentation
|
|
14
|
+
module Lfi
|
|
15
|
+
def self.block_file_access?(_path, _mode)
|
|
16
|
+
false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module Cmdi
|
|
22
|
+
def self.block_command?(_cmd)
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|