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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e93674e3ce539710e90605fc2655eff1d988017
4
- data.tar.gz: 482dd34778a453b1a63c6e0bc7976b1c893bb9af
3
+ metadata.gz: 181cef7acfc3208cd9d1af45984aa9d23e0b1e0e
4
+ data.tar.gz: 78925684e4816c2ff9c1851581ed3e7eeedab2d7
5
5
  SHA512:
6
- metadata.gz: 6432e1455a95c5c28c62c7ff85f367316f4ad78d58fc5ffdb03b83b9fb9ffbb21137fd9c9d34423a01ffd00ad10f18d9a19cd9dc93f5ab20b7cfdc4806eb65fd
7
- data.tar.gz: ecac85ac908c46e83a5f850005bef88565955af581512c31ee63e45c1ef3147771780e90fb6db166dbd30fab8c928de0c3086cb8829fd701312c4dbf25f9b064
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._handle_appsensor(request, tcell_response)
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 _handle_appsensor(request, response)
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
- if response_headers['Content-Length']
146
- content_length = response_headers['Content-Length'].to_i
150
+ set_basic_appsensor_meta = false
147
151
 
148
- elsif TCellAgent::Utils::Rails.empty_content?(status_code, response_headers) ||
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 response_body.respond_to?(:to_ary) || response_body.is_a?(Rack::BodyProxy)
153
- old_body = response_body
154
- response_body, content_length = [], 0
155
- old_body.each { |str|
156
- response_body << str
157
- content_length += str.bytesize
158
- }
159
-
160
- if old_body.is_a?(Rack::BodyProxy)
161
- response_body = Rack::BodyProxy.new(response_body) do
162
- old_body.close if old_body.respond_to?(:close)
163
- end
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.streaming_response?(headers)
13
- return TCellAgent::Utils::Strings.present?(headers['Transfer-Encoding']) ||
14
- TCellAgent::Utils::Strings.present?(headers['Content-Transfer-Encoding'])
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
 
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = "0.2.27"
4
+ VERSION = "0.2.28"
5
5
  end
@@ -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
@@ -73,7 +73,7 @@ module TCellAgent
73
73
  # }
74
74
  #end
75
75
  end
76
- tcell_context.filter_body(@body)
76
+ tcell_context.filter_body!(@body)
77
77
  [200, response_headers, [@body]]
78
78
  end
79
79
 
@@ -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.27
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-13 00:00:00.000000000 Z
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