tcell_agent 0.2.27 → 0.2.28

Sign up to get free protection for your applications and to get access to all the features.
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