tcell_agent 0.2.27 → 0.2.28
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/lib/tcell_agent/instrumentation.rb +1 -1
- data/lib/tcell_agent/policies/appsensor_policy.rb +2 -0
- data/lib/tcell_agent/rails/dlp.rb +0 -36
- data/lib/tcell_agent/rails/dlp_handler.rb +68 -0
- data/lib/tcell_agent/rails/js_agent_insert.rb +71 -0
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +0 -35
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +55 -26
- data/lib/tcell_agent/rails/responses.rb +10 -3
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +94 -0
- data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +13 -0
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/instrumentation_spec.rb +4 -4
- data/spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb +1 -1
- data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +216 -0
- data/spec/lib/tcell_agent/rails/responses_spec.rb +0 -39
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 181cef7acfc3208cd9d1af45984aa9d23e0b1e0e
|
4
|
+
data.tar.gz: 78925684e4816c2ff9c1851581ed3e7eeedab2d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59c4b7ab789fd0444906ff922561d7faa60ab7d6c224c292ed84123db5e065ea31786f662a25021b1ba9bd980bb38156072bcc5f15b3eec0f0a1222f8a2d339a
|
7
|
+
data.tar.gz: c4e7c7d069401d297bb0e17d03c3ae998f69149302e65d699cc47c512be8275d421e25c4cc059b815c76c9cb74710f7c075d59ac1f00fb873f2245fc968bf3fc
|
@@ -109,7 +109,7 @@ module TCellAgent
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
def filter_body(body)
|
112
|
+
def filter_body!(body)
|
113
113
|
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
114
114
|
if dlp_policy and self.session_id
|
115
115
|
session_id_actions = dlp_policy.get_actions_for_session_id
|
@@ -99,6 +99,8 @@ module TCellAgent
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def check_response_size(appsensor_meta)
|
102
|
+
return unless @enabled
|
103
|
+
|
102
104
|
TCellAgent::Instrumentation.safe_block("AppSensor Testing Response Size") do
|
103
105
|
if self.options.has_key?("resp_size")
|
104
106
|
self.options["resp_size"].check(appsensor_meta)
|
@@ -265,42 +265,6 @@ module TCellAgent
|
|
265
265
|
end
|
266
266
|
end
|
267
267
|
|
268
|
-
module TCellAgent
|
269
|
-
ActiveSupport.on_load(:action_controller) do
|
270
|
-
ActionController::Base.class_eval do
|
271
|
-
if (::Rails::VERSION::MAJOR == 5)
|
272
|
-
around_action :global_request_logging
|
273
|
-
elsif (::Rails::VERSION::MAJOR < 5)
|
274
|
-
around_filter :global_request_logging
|
275
|
-
end
|
276
|
-
def global_request_logging
|
277
|
-
begin
|
278
|
-
yield
|
279
|
-
|
280
|
-
if TCellAgent.configuration.enabled &&
|
281
|
-
TCellAgent.configuration.should_instrument? &&
|
282
|
-
TCellAgent.configuration.should_intercept_requests?
|
283
|
-
|
284
|
-
TCellAgent::Instrumentation.safe_block("Running DLP Logging Filters") {
|
285
|
-
if TCellAgent::Utils::Rails.empty_content?(response.status, response.headers) ||
|
286
|
-
TCellAgent::Utils::Rails.streaming_response?(response.headers)
|
287
|
-
return
|
288
|
-
end
|
289
|
-
|
290
|
-
tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
291
|
-
if tcell_context
|
292
|
-
response.body = tcell_context.filter_body(response.body)
|
293
|
-
end
|
294
|
-
}
|
295
|
-
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
|
304
268
|
class Logger
|
305
269
|
alias_method :tcell_old_add, :add
|
306
270
|
def add(severity, message = nil, progname = nil, &block)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'tcell_agent/instrumentation'
|
2
|
+
require 'tcell_agent/rails/responses'
|
3
|
+
|
4
|
+
module TCellAgent
|
5
|
+
module Instrumentation
|
6
|
+
module Rails
|
7
|
+
module DLPHandler
|
8
|
+
|
9
|
+
def self.report_and_redact_now(dlp_handler, tcell_context, rack_body, content_length)
|
10
|
+
TCellAgent::Instrumentation.safe_block("Handling DLP Report and Redact Now") do
|
11
|
+
if dlp_handler
|
12
|
+
new_content_length = 0
|
13
|
+
new_body = []
|
14
|
+
rack_body.each { |str|
|
15
|
+
dlp_handler.call(tcell_context, str)
|
16
|
+
new_body << str
|
17
|
+
new_content_length += str.bytesize
|
18
|
+
}
|
19
|
+
rack_body.close if rack_body.respond_to?(:close)
|
20
|
+
|
21
|
+
rack_body = new_body
|
22
|
+
content_length = new_content_length
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
[rack_body, content_length]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.handle_dlp!(tcell_context, response)
|
30
|
+
TCellAgent::Instrumentation.safe_block("Running DLP Logging Filters") do
|
31
|
+
tcell_context.filter_body!(response)
|
32
|
+
end
|
33
|
+
|
34
|
+
response
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.get_handler_and_context(request, response_headers)
|
38
|
+
dlp_handler = nil
|
39
|
+
tcell_context = nil
|
40
|
+
|
41
|
+
TCellAgent::Instrumentation.safe_block("DLP Handler get handler and context") do
|
42
|
+
if TCellAgent.configuration.enabled &&
|
43
|
+
TCellAgent.configuration.should_instrument? &&
|
44
|
+
TCellAgent.configuration.should_intercept_requests?
|
45
|
+
|
46
|
+
# do all this work so that dlp doesn't run at all unless it's on and there
|
47
|
+
# are rules to run
|
48
|
+
if TCellAgent::Utils::Rails.processable_response?(response_headers)
|
49
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
50
|
+
if dlp_policy && dlp_policy.get_actions_for_session_id
|
51
|
+
tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
52
|
+
if tcell_context && tcell_context.session_id
|
53
|
+
dlp_handler = Proc.new { |tc, resp|
|
54
|
+
self.handle_dlp!(tc, resp)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
[dlp_handler, tcell_context]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'tcell_agent/instrumentation'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Instrumentation
|
5
|
+
module Rails
|
6
|
+
module JSAgent
|
7
|
+
|
8
|
+
HEAD_SEARCH_REGEX=/<head>/
|
9
|
+
|
10
|
+
def self.insert_now(js_agent_handler, script_insert, rack_body, content_length)
|
11
|
+
TCellAgent::Instrumentation.safe_block("Handling JSAgent Insert Now") do
|
12
|
+
if js_agent_handler
|
13
|
+
new_content_length = 0
|
14
|
+
newbody = []
|
15
|
+
rack_body.each { |str|
|
16
|
+
# this modifies str itself
|
17
|
+
js_agent_handler.call(script_insert, str)
|
18
|
+
|
19
|
+
newbody << str
|
20
|
+
new_content_length += str.bytesize
|
21
|
+
}
|
22
|
+
rack_body.close if rack_body.respond_to?(:close)
|
23
|
+
|
24
|
+
rack_body = newbody
|
25
|
+
content_length = new_content_length
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
[rack_body, content_length]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.handle_js_agent_insert(script_insert, response)
|
33
|
+
TCellAgent::Instrumentation.safe_block("Handling JSAgent insert") do
|
34
|
+
return !!response.sub!(
|
35
|
+
TCellAgent::Instrumentation::Rails::JSAgent::HEAD_SEARCH_REGEX,
|
36
|
+
"<head>#{script_insert}"
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.get_handler_and_script_insert(response_headers)
|
44
|
+
js_agent_handler = nil
|
45
|
+
script_insert = nil
|
46
|
+
|
47
|
+
TCellAgent::Instrumentation.safe_block("JSAgent get handler and script insert") do
|
48
|
+
if (response_headers.fetch("Content-Type","").start_with?'text/html')
|
49
|
+
script_tag_policy = TCellAgent.policy(TCellAgent::PolicyTypes::CSP)
|
50
|
+
if (script_tag_policy && script_tag_policy.js_agent_api_key)
|
51
|
+
base_url_vars = ""
|
52
|
+
if (script_tag_policy.js_agent_api_base_url)
|
53
|
+
base_url_vars = " tcellbaseurl=\"#{script_tag_policy.js_agent_api_base_url}\""
|
54
|
+
end
|
55
|
+
script_insert = "<script src=\"#{script_tag_policy.js_agent_url}\" "
|
56
|
+
script_insert += "tcellapikey=\"#{script_tag_policy.js_agent_api_key}\" "
|
57
|
+
script_insert += "tcellappid=\"#{script_tag_policy.js_agent_app_id}\"#{base_url_vars}></script>\n"
|
58
|
+
js_agent_handler = Proc.new { |si, resp|
|
59
|
+
self.handle_js_agent_insert(si, resp)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
[js_agent_handler, script_insert]
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -18,12 +18,10 @@ module TCellAgent
|
|
18
18
|
module Rails
|
19
19
|
module Middleware
|
20
20
|
class BodyFilterMiddleware
|
21
|
-
HEAD_SEARCH_REGEX=/<head>/
|
22
21
|
def initialize(app)
|
23
22
|
@app = app
|
24
23
|
end
|
25
24
|
def call(env)
|
26
|
-
request = Rack::Request.new(env)
|
27
25
|
orig = (Time.now.to_f * 1000).to_i
|
28
26
|
|
29
27
|
response = @app.call(env)
|
@@ -53,39 +51,6 @@ module TCellAgent
|
|
53
51
|
end
|
54
52
|
end
|
55
53
|
}
|
56
|
-
response = self._handle_js_agent_add(request, response)
|
57
|
-
end
|
58
|
-
|
59
|
-
response
|
60
|
-
end
|
61
|
-
def replace_in_body(script_tag_policy, body)
|
62
|
-
base_url_vars = ""
|
63
|
-
if (script_tag_policy.js_agent_api_base_url)
|
64
|
-
base_url_vars = " tcellbaseurl=\"#{script_tag_policy.js_agent_api_base_url}\""
|
65
|
-
end
|
66
|
-
script_insert = "\n<script src=\"#{script_tag_policy.js_agent_url}\" tcellapikey=\"#{script_tag_policy.js_agent_api_key}\" tcellappid=\"#{script_tag_policy.js_agent_app_id}\"#{base_url_vars}></script>\n"
|
67
|
-
body.sub!(BodyFilterMiddleware::HEAD_SEARCH_REGEX,"<head>#{script_insert}")
|
68
|
-
end
|
69
|
-
def _handle_js_agent_add(request, response)
|
70
|
-
TCellAgent::Instrumentation.safe_block("Handling JSAgent add") do
|
71
|
-
status, headers, rack_body = response
|
72
|
-
if TCellAgent::Utils::Rails.empty_content?(status, headers) ||
|
73
|
-
TCellAgent::Utils::Rails.streaming_response?(headers)
|
74
|
-
return response
|
75
|
-
end
|
76
|
-
|
77
|
-
if (headers.fetch("Content-Type","").start_with?'text/html')
|
78
|
-
script_tag_policy = TCellAgent.policy(TCellAgent::PolicyTypes::CSP)
|
79
|
-
if (script_tag_policy &&
|
80
|
-
script_tag_policy.js_agent_api_key)
|
81
|
-
newbody = []
|
82
|
-
rack_body.each { |str|
|
83
|
-
newbody_part = self.replace_in_body(script_tag_policy, str) || str
|
84
|
-
newbody << newbody_part
|
85
|
-
}
|
86
|
-
response = [status, headers, newbody]
|
87
|
-
end
|
88
|
-
end
|
89
54
|
end
|
90
55
|
|
91
56
|
response
|
@@ -14,6 +14,9 @@ require 'cgi'
|
|
14
14
|
|
15
15
|
require 'tcell_agent/instrumentation'
|
16
16
|
require 'tcell_agent/rails/responses'
|
17
|
+
require 'tcell_agent/rails/js_agent_insert'
|
18
|
+
require 'tcell_agent/rails/dlp_handler'
|
19
|
+
require 'tcell_agent/rails/tcell_body_proxy'
|
17
20
|
|
18
21
|
module TCellAgent
|
19
22
|
module Instrumentation
|
@@ -21,9 +24,6 @@ module TCellAgent
|
|
21
24
|
module Middleware
|
22
25
|
|
23
26
|
class HeadersMiddleware
|
24
|
-
|
25
|
-
STATUSES_MISSING_CONTENT_LENGTH = Set.new((100..199).to_a + [204, 205, 304])
|
26
|
-
|
27
27
|
def initialize(app)
|
28
28
|
@app = app
|
29
29
|
end
|
@@ -37,7 +37,7 @@ module TCellAgent
|
|
37
37
|
TCellAgent::Instrumentation.safe_block("Handling Request") {
|
38
38
|
tcell_response = response
|
39
39
|
unless request.env[TCellAgent::Instrumentation::TCELL_ID].ip_blocking_triggered
|
40
|
-
tcell_response = self.
|
40
|
+
tcell_response = self._handle_appsensor_js_agent_and_dlp(request, tcell_response)
|
41
41
|
end
|
42
42
|
tcell_response = self._handle_redirect(request, tcell_response)
|
43
43
|
tcell_response = self._set_csp_header(request, tcell_response)
|
@@ -137,37 +137,66 @@ module TCellAgent
|
|
137
137
|
response
|
138
138
|
end
|
139
139
|
|
140
|
-
def
|
141
|
-
TCellAgent::Instrumentation.safe_block("Handling AppSensor") do
|
140
|
+
def _handle_appsensor_js_agent_and_dlp(request, response)
|
141
|
+
TCellAgent::Instrumentation.safe_block("Handling AppSensor, JS Agent, and DLP") do
|
142
142
|
status_code, response_headers, response_body = response
|
143
143
|
|
144
|
+
js_agent_handler, script_insert =
|
145
|
+
TCellAgent::Instrumentation::Rails::JSAgent.get_handler_and_script_insert(response_headers)
|
146
|
+
dlp_handler, tcell_context =
|
147
|
+
TCellAgent::Instrumentation::Rails::DLPHandler.get_handler_and_context(request, response_headers)
|
148
|
+
|
144
149
|
content_length = 0
|
145
|
-
|
146
|
-
content_length = response_headers['Content-Length'].to_i
|
150
|
+
set_basic_appsensor_meta = false
|
147
151
|
|
148
|
-
|
149
|
-
TCellAgent::Utils::Rails.streaming_response?(response_headers)
|
152
|
+
if TCellAgent::Utils::Rails.empty_content?(status_code, response_headers)
|
150
153
|
content_length = 0
|
151
154
|
|
152
|
-
elsif
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
155
|
+
elsif response_headers['Content-Length']
|
156
|
+
content_length = response_headers['Content-Length'].to_i
|
157
|
+
|
158
|
+
# when content length is present it can be inferred that the
|
159
|
+
# response is not a streaming response, so js agent insertion
|
160
|
+
# and dlp reports and redactions can be done up front
|
161
|
+
response_body, content_length =
|
162
|
+
TCellAgent::Instrumentation::Rails::JSAgent.insert_now(js_agent_handler,
|
163
|
+
script_insert,
|
164
|
+
response_body,
|
165
|
+
content_length)
|
166
|
+
|
167
|
+
response_body, content_length =
|
168
|
+
TCellAgent::Instrumentation::Rails::DLPHandler.report_and_redact_now(dlp_handler,
|
169
|
+
tcell_context,
|
170
|
+
response_body,
|
171
|
+
content_length)
|
172
|
+
|
173
|
+
|
174
|
+
response_headers['Content-Length'] = content_length.to_s
|
175
|
+
|
176
|
+
elsif response_body.is_a?(Rack::BodyProxy)
|
177
|
+
response_body = TCellAgent::Instrumentation::Rails::TCellBodyProxy.new(
|
178
|
+
response_body,
|
179
|
+
TCellAgent::Utils::Rails.processable_response?(response_headers),
|
180
|
+
js_agent_handler,
|
181
|
+
script_insert,
|
182
|
+
dlp_handler,
|
183
|
+
tcell_context)
|
184
|
+
set_basic_appsensor_meta = true
|
185
|
+
end
|
186
|
+
|
187
|
+
appsensor_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AppSensor)
|
188
|
+
if appsensor_policy
|
189
|
+
event = TCellAgent::SensorEvents::AppSensorMetaEvent.build(
|
190
|
+
request, content_length, status_code, response_headers
|
191
|
+
)
|
192
|
+
TCellAgent.send_event(event)
|
193
|
+
|
194
|
+
if set_basic_appsensor_meta
|
195
|
+
response_body.appsensor_policy = appsensor_policy
|
196
|
+
response_body.appsensor_meta = TCellAgent::SensorEvents::AppSensorMetaEvent.build_basic(event)
|
164
197
|
end
|
165
198
|
end
|
166
199
|
|
167
|
-
event = TCellAgent::SensorEvents::AppSensorMetaEvent.build(
|
168
|
-
request, content_length, status_code, response_headers
|
169
|
-
)
|
170
|
-
TCellAgent.send_event(event)
|
171
200
|
return [status_code, response_headers, response_body]
|
172
201
|
end
|
173
202
|
|
@@ -9,9 +9,16 @@ module TCellAgent
|
|
9
9
|
(!!headers['Content-Length'] && headers['Content-Length'].to_i == 0)
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.
|
13
|
-
|
14
|
-
|
12
|
+
def self.processable_response?(response_headers)
|
13
|
+
content_disposition = response_headers['Content-Disposition']
|
14
|
+
is_attachment = content_disposition && !!(content_disposition =~ /^attachment/i)
|
15
|
+
|
16
|
+
content_type = response_headers['Content-Type']
|
17
|
+
applicable_content_type = content_type &&
|
18
|
+
(content_type == /application\/json/ ||
|
19
|
+
content_type == /application\/xml/ ||
|
20
|
+
!!(content_type =~ /^text/))
|
21
|
+
return !is_attachment && applicable_content_type
|
15
22
|
end
|
16
23
|
|
17
24
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'tcell_agent/instrumentation'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Instrumentation
|
5
|
+
module Rails
|
6
|
+
|
7
|
+
class TCellBodyProxy
|
8
|
+
|
9
|
+
attr_accessor :appsensor_policy, :appsensor_meta
|
10
|
+
|
11
|
+
# for specs
|
12
|
+
attr_accessor :content_length
|
13
|
+
|
14
|
+
def initialize(body,
|
15
|
+
process_js_and_dlp,
|
16
|
+
js_agent_insertion_proc,
|
17
|
+
script_insert,
|
18
|
+
dlp_cleaner_proc,
|
19
|
+
tcell_context)
|
20
|
+
@content_length = 0
|
21
|
+
@body = body
|
22
|
+
|
23
|
+
@process_js_and_dlp = process_js_and_dlp
|
24
|
+
|
25
|
+
@js_agent_insertion_proc = js_agent_insertion_proc
|
26
|
+
@script_insert = script_insert
|
27
|
+
|
28
|
+
@dlp_cleaner_proc = dlp_cleaner_proc
|
29
|
+
@tcell_context = tcell_context
|
30
|
+
end
|
31
|
+
|
32
|
+
def close
|
33
|
+
TCellAgent::Instrumentation.safe_block("Handling Response Size Length") do
|
34
|
+
if @content_length > 0 && @appsensor_meta && @appsensor_policy
|
35
|
+
@appsensor_meta.response_content_bytes_len = @content_length
|
36
|
+
@appsensor_policy.check_response_size(@appsensor_meta)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
@body.close if @body.respond_to?(:close)
|
41
|
+
end
|
42
|
+
|
43
|
+
def each(&block)
|
44
|
+
return to_enum(:each) unless block_given?
|
45
|
+
|
46
|
+
@body.each { |body_chunk|
|
47
|
+
process_body!(body_chunk)
|
48
|
+
|
49
|
+
yield body_chunk
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def respond_to?(method_name, include_all=false)
|
54
|
+
@body.respond_to?(method_name, include_all)
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(method_name, *args, &block)
|
58
|
+
@body.__send__(method_name, *args, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def process_body!(body)
|
62
|
+
TCellAgent::Instrumentation.safe_block("Processing tcell body proxy body") do
|
63
|
+
chunked_response_match = nil
|
64
|
+
if body.class.name == "String"
|
65
|
+
if body =~ /^([[:xdigit:]]+)(;.+)?\r\n/
|
66
|
+
chunked_response_match = $1
|
67
|
+
@content_length += chunked_response_match.to_i(16)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if body.class.name == "ActionView::OutputBuffer" ||
|
72
|
+
(body.class.name == "String" && !chunked_response_match)
|
73
|
+
@content_length += body.bytesize
|
74
|
+
|
75
|
+
if @process_js_and_dlp
|
76
|
+
if @js_agent_insertion_proc
|
77
|
+
if @js_agent_insertion_proc.call(@script_insert, body)
|
78
|
+
# js agent was successfully inserted so no need to keep
|
79
|
+
# calling this proc
|
80
|
+
@js_agent_insertion_proc = nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
if @dlp_cleaner_proc
|
84
|
+
@dlp_cleaner_proc.call(@tcell_context, body)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -59,6 +59,19 @@ module TCellAgent
|
|
59
59
|
|
60
60
|
meta_event
|
61
61
|
end
|
62
|
+
|
63
|
+
def build_basic(appsensor_meta)
|
64
|
+
meta_event = AppSensorMetaEvent.new
|
65
|
+
meta_event.location = appsensor_meta.location
|
66
|
+
meta_event.method =appsensor_meta.method
|
67
|
+
meta_event.remote_address = appsensor_meta.remote_address
|
68
|
+
meta_event.route_id = appsensor_meta.route_id
|
69
|
+
meta_event.session_id = appsensor_meta.session_id
|
70
|
+
meta_event.user_id = appsensor_meta.user_id
|
71
|
+
meta_event.route_id = appsensor_meta.route_id
|
72
|
+
|
73
|
+
meta_event
|
74
|
+
end
|
62
75
|
end
|
63
76
|
|
64
77
|
|
data/lib/tcell_agent/version.rb
CHANGED
@@ -30,7 +30,7 @@ module TCellAgent
|
|
30
30
|
|
31
31
|
body = "this is about tim123123my 3123123."
|
32
32
|
TCellAgent.empty_event_queue
|
33
|
-
context.filter_body(body)
|
33
|
+
context.filter_body!(body)
|
34
34
|
expect(body).to eq("this is about [redacted] 3123123.")
|
35
35
|
expect(TCellAgent.event_queue.length).to eq(1)
|
36
36
|
TCellAgent.set_thread_agent(nil)
|
@@ -55,7 +55,7 @@ module TCellAgent
|
|
55
55
|
|
56
56
|
body = "this is about tim123123my 3123123."
|
57
57
|
TCellAgent.empty_event_queue
|
58
|
-
context.filter_body(body)
|
58
|
+
context.filter_body!(body)
|
59
59
|
expect(body).to eq("this is about tim123123my 3123123.")
|
60
60
|
expect(TCellAgent.event_queue.length).to eq(1)
|
61
61
|
TCellAgent.set_thread_agent(nil)
|
@@ -131,7 +131,7 @@ module TCellAgent
|
|
131
131
|
context.add_response_db_filter(true, action, "don", "sam", "tim", "fred")
|
132
132
|
body = "this is about timmy1 3123123."
|
133
133
|
TCellAgent.empty_event_queue
|
134
|
-
context.filter_body(body)
|
134
|
+
context.filter_body!(body)
|
135
135
|
expect(body).to eq("this is about [redacted] [redacted].")
|
136
136
|
expect(TCellAgent.event_queue.length).to eq(2)
|
137
137
|
end
|
@@ -152,7 +152,7 @@ module TCellAgent
|
|
152
152
|
context.add_response_db_filter(true, action, "don", "sam", "tim", "fred")
|
153
153
|
body = "this is about timmy1 3123123."
|
154
154
|
TCellAgent.empty_event_queue
|
155
|
-
context.filter_body(body)
|
155
|
+
context.filter_body!(body)
|
156
156
|
expect(body).to eq("this is about timmy1 3123123.")
|
157
157
|
expect(TCellAgent.event_queue.length).to eq(3) # timmy, timmy1, 3123123
|
158
158
|
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module TCellAgent
|
4
|
+
module Instrumentation
|
5
|
+
module Rails
|
6
|
+
|
7
|
+
describe TCellBodyProxy do
|
8
|
+
|
9
|
+
context "#close" do
|
10
|
+
context "missing appsensor policy" do
|
11
|
+
context "zero content length" do
|
12
|
+
it "should not call appsensor policy" do
|
13
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
14
|
+
Rack::BodyProxy.new(["body"]) { },
|
15
|
+
true,
|
16
|
+
nil, nil, nil, nil)
|
17
|
+
|
18
|
+
tcell_body_proxy.content_length = 0
|
19
|
+
|
20
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
21
|
+
"Handling Response Size Length"
|
22
|
+
).and_call_original
|
23
|
+
|
24
|
+
tcell_body_proxy.close
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "non zerno content length" do
|
29
|
+
it "should not call appsensor policy" do
|
30
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
31
|
+
Rack::BodyProxy.new(["body"]) { },
|
32
|
+
true,
|
33
|
+
nil, nil, nil, nil)
|
34
|
+
|
35
|
+
tcell_body_proxy.content_length = 512
|
36
|
+
|
37
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
38
|
+
"Handling Response Size Length"
|
39
|
+
).and_call_original
|
40
|
+
|
41
|
+
tcell_body_proxy.close
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with appsensor policy" do
|
47
|
+
context "zero content length" do
|
48
|
+
it "should not call appsensor policy" do
|
49
|
+
appsensor_policy = double("appsensor_policy")
|
50
|
+
appsensor_meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
|
51
|
+
|
52
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
53
|
+
Rack::BodyProxy.new(["body"]) { },
|
54
|
+
true,
|
55
|
+
nil, nil, nil, nil)
|
56
|
+
tcell_body_proxy.appsensor_policy = appsensor_policy
|
57
|
+
tcell_body_proxy.appsensor_meta = appsensor_meta
|
58
|
+
|
59
|
+
tcell_body_proxy.content_length = 0
|
60
|
+
|
61
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
62
|
+
"Handling Response Size Length"
|
63
|
+
).and_call_original
|
64
|
+
expect(appsensor_policy).to_not receive(:check_response_size)
|
65
|
+
|
66
|
+
tcell_body_proxy.close
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "non zerno content length" do
|
71
|
+
it "should not call appsensor policy" do
|
72
|
+
appsensor_policy = double("appsensor_policy")
|
73
|
+
appsensor_meta = TCellAgent::SensorEvents::AppSensorMetaEvent.new
|
74
|
+
|
75
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
76
|
+
Rack::BodyProxy.new(["body"]) { },
|
77
|
+
true,
|
78
|
+
nil, nil, nil, nil)
|
79
|
+
tcell_body_proxy.appsensor_policy = appsensor_policy
|
80
|
+
tcell_body_proxy.appsensor_meta = appsensor_meta
|
81
|
+
|
82
|
+
tcell_body_proxy.content_length = 512
|
83
|
+
|
84
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
85
|
+
"Handling Response Size Length"
|
86
|
+
).and_call_original
|
87
|
+
expect(appsensor_policy).to receive(:check_response_size).with(appsensor_meta)
|
88
|
+
|
89
|
+
tcell_body_proxy.close
|
90
|
+
|
91
|
+
expect(appsensor_meta.response_content_bytes_len).to eq(512)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "#each" do
|
98
|
+
context "with no block given" do
|
99
|
+
it "should return an enumerator" do
|
100
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
101
|
+
Rack::BodyProxy.new(["body"]) { },
|
102
|
+
true,
|
103
|
+
nil, nil, nil, nil)
|
104
|
+
expect(tcell_body_proxy.each.class.name).to eq("Enumerator")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with a string response" do
|
109
|
+
context "with a chunked response" do
|
110
|
+
it "should only calculate content length" do
|
111
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
112
|
+
Rack::BodyProxy.new(["2d\r\nsome content\r\n"]) { },
|
113
|
+
false,
|
114
|
+
nil, nil, nil, nil)
|
115
|
+
|
116
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
117
|
+
"Processing tcell body proxy body").and_call_original
|
118
|
+
|
119
|
+
tcell_body_proxy.each { |b| }
|
120
|
+
|
121
|
+
expect(tcell_body_proxy.content_length).to eq(45)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "with a non chunked response" do
|
126
|
+
context "that should not be processed" do
|
127
|
+
it "should only calculate content length" do
|
128
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
129
|
+
Rack::BodyProxy.new(["some content"]) { },
|
130
|
+
false,
|
131
|
+
nil, nil, nil, nil)
|
132
|
+
|
133
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
134
|
+
"Processing tcell body proxy body").and_call_original
|
135
|
+
|
136
|
+
tcell_body_proxy.each { |b| }
|
137
|
+
|
138
|
+
expect(tcell_body_proxy.content_length).to eq(12)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "that should be processed" do
|
143
|
+
it "should call js and dlp procs as well as calculate content length" do
|
144
|
+
js_agent_insertion_proc = double("js_agent_insertion_proc")
|
145
|
+
dlp_cleaner_proc = double("dlp_cleaner_proc")
|
146
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
147
|
+
Rack::BodyProxy.new(["some content"]) { },
|
148
|
+
true,
|
149
|
+
js_agent_insertion_proc, "script_insert", dlp_cleaner_proc, nil)
|
150
|
+
|
151
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
152
|
+
"Processing tcell body proxy body").and_call_original
|
153
|
+
expect(js_agent_insertion_proc).to receive(:call).with("script_insert", "some content")
|
154
|
+
expect(dlp_cleaner_proc).to receive(:call).with(nil, "some content")
|
155
|
+
|
156
|
+
tcell_body_proxy.each { |b| }
|
157
|
+
|
158
|
+
expect(tcell_body_proxy.content_length).to eq(12)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "with an ActionView::OutputBuffer" do
|
165
|
+
context "that should not be processed" do
|
166
|
+
it "should only calculate content length" do
|
167
|
+
body_chunk = "some content"
|
168
|
+
js_agent_insertion_proc = double("js_agent_insertion_proc")
|
169
|
+
dlp_cleaner_proc = double("dlp_cleaner_proc")
|
170
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
171
|
+
Rack::BodyProxy.new([body_chunk]) { },
|
172
|
+
false,
|
173
|
+
nil, nil, nil, nil)
|
174
|
+
|
175
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
176
|
+
"Processing tcell body proxy body").and_call_original
|
177
|
+
expect(body_chunk).to receive(:class).and_return(
|
178
|
+
double("body_class", name: "ActionView::OutputBuffer"))
|
179
|
+
expect(body_chunk).to receive(:class).and_return(
|
180
|
+
double("body_class", name: "ActionView::OutputBuffer"))
|
181
|
+
expect(js_agent_insertion_proc).to_not receive(:call)
|
182
|
+
expect(dlp_cleaner_proc).to_not receive(:call)
|
183
|
+
|
184
|
+
tcell_body_proxy.each { |b| }
|
185
|
+
|
186
|
+
expect(tcell_body_proxy.content_length).to eq(12)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context "that should be processed" do
|
191
|
+
it "should call js and dlp procs as well as calculate content length" do
|
192
|
+
body_chunk = "some content"
|
193
|
+
js_agent_insertion_proc = double("js_agent_insertion_proc")
|
194
|
+
dlp_cleaner_proc = double("dlp_cleaner_proc")
|
195
|
+
tcell_body_proxy = TCellBodyProxy.new(
|
196
|
+
Rack::BodyProxy.new([body_chunk]) { },
|
197
|
+
true,
|
198
|
+
js_agent_insertion_proc, "script_insert", dlp_cleaner_proc, nil)
|
199
|
+
|
200
|
+
expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
|
201
|
+
"Processing tcell body proxy body").and_call_original
|
202
|
+
expect(js_agent_insertion_proc).to receive(:call).with("script_insert", body_chunk)
|
203
|
+
expect(dlp_cleaner_proc).to receive(:call).with(nil, body_chunk)
|
204
|
+
|
205
|
+
tcell_body_proxy.each { |b| }
|
206
|
+
|
207
|
+
expect(tcell_body_proxy.content_length).to eq(12)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -75,45 +75,6 @@ module TCellAgent
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
context ".streaming_response?" do
|
79
|
-
context "with empty headers" do
|
80
|
-
it "should return false" do
|
81
|
-
expect(Rails.streaming_response?({})).to eq(false)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context "with headers" do
|
86
|
-
context "that are missing Transfer-Encoding" do
|
87
|
-
context "that are missing Content-Transfer-Encoding" do
|
88
|
-
it "should return false" do
|
89
|
-
expect(Rails.streaming_response?({})).to eq(false)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context "that have Content-Transfer-Encoding" do
|
94
|
-
it "should return true" do
|
95
|
-
expect(Rails.streaming_response?({"Content-Transfer-Encoding" => "chunked"})).to eq(true)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context "that have Transfer-Encoding" do
|
102
|
-
context "that are missing Content-Transfer-Encoding" do
|
103
|
-
it "should return true" do
|
104
|
-
expect(Rails.streaming_response?({"Transfer-Encoding" => "chunked"})).to eq(true)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context "that have Content-Transfer-Encoding" do
|
109
|
-
it "should return true" do
|
110
|
-
expect(Rails.streaming_response?({
|
111
|
-
"Transfer-Encoding" => "chunked",
|
112
|
-
"Content-Transfer-Encoding" => "chunked"})).to eq(true)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
78
|
end
|
118
79
|
|
119
80
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tcell_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garrett
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -191,6 +191,8 @@ files:
|
|
191
191
|
- lib/tcell_agent/rails/csrf_exception.rb
|
192
192
|
- lib/tcell_agent/rails/dlp/process_request.rb
|
193
193
|
- lib/tcell_agent/rails/dlp.rb
|
194
|
+
- lib/tcell_agent/rails/dlp_handler.rb
|
195
|
+
- lib/tcell_agent/rails/js_agent_insert.rb
|
194
196
|
- lib/tcell_agent/rails/middleware/body_filter_middleware.rb
|
195
197
|
- lib/tcell_agent/rails/middleware/context_middleware.rb
|
196
198
|
- lib/tcell_agent/rails/middleware/global_middleware.rb
|
@@ -201,6 +203,7 @@ files:
|
|
201
203
|
- lib/tcell_agent/rails/routes/route_id.rb
|
202
204
|
- lib/tcell_agent/rails/routes.rb
|
203
205
|
- lib/tcell_agent/rails/settings_reporter.rb
|
206
|
+
- lib/tcell_agent/rails/tcell_body_proxy.rb
|
204
207
|
- lib/tcell_agent/rails.rb
|
205
208
|
- lib/tcell_agent/routes/table.rb
|
206
209
|
- lib/tcell_agent/sensor_events/app_config.rb
|
@@ -321,6 +324,7 @@ files:
|
|
321
324
|
- spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb
|
322
325
|
- spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb
|
323
326
|
- spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb
|
327
|
+
- spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb
|
324
328
|
- spec/lib/tcell_agent/rails/responses_spec.rb
|
325
329
|
- spec/lib/tcell_agent/rails/routes/grape_spec.rb
|
326
330
|
- spec/lib/tcell_agent/rails/routes/route_id_spec.rb
|
@@ -472,6 +476,7 @@ test_files:
|
|
472
476
|
- spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb
|
473
477
|
- spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb
|
474
478
|
- spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb
|
479
|
+
- spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb
|
475
480
|
- spec/lib/tcell_agent/rails/responses_spec.rb
|
476
481
|
- spec/lib/tcell_agent/rails/routes/grape_spec.rb
|
477
482
|
- spec/lib/tcell_agent/rails/routes/route_id_spec.rb
|