tcell_agent 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/bin/tcell_agent +10 -2
  3. data/lib/tcell_agent.rb +3 -3
  4. data/lib/tcell_agent/agent.rb +42 -52
  5. data/lib/tcell_agent/agent/event_processor.rb +129 -162
  6. data/lib/tcell_agent/agent/fork_pipe_manager.rb +57 -62
  7. data/lib/tcell_agent/agent/policy_manager.rb +83 -104
  8. data/lib/tcell_agent/agent/policy_types.rb +24 -29
  9. data/lib/tcell_agent/agent/route_manager.rb +36 -46
  10. data/lib/tcell_agent/agent/static_agent.rb +19 -21
  11. data/lib/tcell_agent/api.rb +23 -28
  12. data/lib/tcell_agent/appsensor/injections_reporter.rb +7 -11
  13. data/lib/tcell_agent/authlogic.rb +7 -7
  14. data/lib/tcell_agent/cmdi.rb +22 -23
  15. data/lib/tcell_agent/config/unknown_options.rb +71 -69
  16. data/lib/tcell_agent/configuration.rb +187 -191
  17. data/lib/tcell_agent/devise.rb +13 -15
  18. data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
  19. data/lib/tcell_agent/instrumentation.rb +120 -124
  20. data/lib/tcell_agent/logger.rb +29 -45
  21. data/lib/tcell_agent/patches.rb +5 -5
  22. data/lib/tcell_agent/policies/dataloss_policy.rb +263 -288
  23. data/lib/tcell_agent/policies/http_redirect_policy.rb +25 -37
  24. data/lib/tcell_agent/policies/http_tx_policy.rb +48 -52
  25. data/lib/tcell_agent/policies/login_fraud_policy.rb +15 -20
  26. data/lib/tcell_agent/policies/policy.rb +0 -2
  27. data/lib/tcell_agent/policies/rust_policies.rb +24 -29
  28. data/lib/tcell_agent/rails.rb +2 -3
  29. data/lib/tcell_agent/rails/auth/authlogic.rb +2 -2
  30. data/lib/tcell_agent/rails/auth/devise.rb +2 -2
  31. data/lib/tcell_agent/rails/auth/doorkeeper.rb +2 -2
  32. data/lib/tcell_agent/rails/better_ip.rb +12 -16
  33. data/lib/tcell_agent/rails/csrf_exception.rb +4 -7
  34. data/lib/tcell_agent/rails/dlp.rb +208 -107
  35. data/lib/tcell_agent/rails/dlp/process_request.rb +37 -47
  36. data/lib/tcell_agent/rails/dlp_handler.rb +9 -11
  37. data/lib/tcell_agent/rails/js_agent_insert.rb +11 -14
  38. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +8 -7
  39. data/lib/tcell_agent/rails/middleware/context_middleware.rb +4 -5
  40. data/lib/tcell_agent/rails/middleware/global_middleware.rb +5 -8
  41. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +24 -27
  42. data/lib/tcell_agent/rails/on_start.rb +5 -5
  43. data/lib/tcell_agent/rails/responses.rb +7 -9
  44. data/lib/tcell_agent/rails/routes.rb +62 -81
  45. data/lib/tcell_agent/rails/routes/grape.rb +25 -30
  46. data/lib/tcell_agent/rails/routes/route_id.rb +9 -14
  47. data/lib/tcell_agent/rails/settings_reporter.rb +44 -33
  48. data/lib/tcell_agent/rails/tcell_body_proxy.rb +15 -18
  49. data/lib/tcell_agent/routes/table.rb +31 -33
  50. data/lib/tcell_agent/rust/{libtcellagent-1.3.0.dylib → libtcellagent-1.3.1.dylib} +0 -0
  51. data/lib/tcell_agent/rust/{libtcellagent-1.3.0.so → libtcellagent-1.3.1.so} +0 -0
  52. data/lib/tcell_agent/rust/{libtcellagent-alpine-1.3.0.so → libtcellagent-alpine-1.3.1.so} +0 -0
  53. data/lib/tcell_agent/rust/models.rb +32 -37
  54. data/lib/tcell_agent/rust/tcellagent-1.3.1.dll +0 -0
  55. data/lib/tcell_agent/rust/whisperer.rb +101 -104
  56. data/lib/tcell_agent/sensor_events/app_config.rb +7 -7
  57. data/lib/tcell_agent/sensor_events/appsensor_event.rb +26 -27
  58. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +20 -88
  59. data/lib/tcell_agent/sensor_events/command_injection.rb +52 -80
  60. data/lib/tcell_agent/sensor_events/discovery.rb +27 -27
  61. data/lib/tcell_agent/sensor_events/dlp.rb +50 -56
  62. data/lib/tcell_agent/sensor_events/honeytokens.rb +9 -9
  63. data/lib/tcell_agent/sensor_events/metrics.rb +20 -21
  64. data/lib/tcell_agent/sensor_events/patches.rb +10 -12
  65. data/lib/tcell_agent/sensor_events/sensor.rb +32 -36
  66. data/lib/tcell_agent/sensor_events/server_agent.rb +130 -127
  67. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +60 -80
  68. data/lib/tcell_agent/sensor_events/util/utils.rb +3 -5
  69. data/lib/tcell_agent/servers/passenger.rb +5 -9
  70. data/lib/tcell_agent/servers/puma.rb +18 -27
  71. data/lib/tcell_agent/servers/rails_server.rb +5 -9
  72. data/lib/tcell_agent/servers/thin.rb +2 -4
  73. data/lib/tcell_agent/servers/unicorn.rb +18 -27
  74. data/lib/tcell_agent/servers/webrick.rb +2 -4
  75. data/lib/tcell_agent/settings_reporter.rb +126 -0
  76. data/lib/tcell_agent/sinatra.rb +24 -26
  77. data/lib/tcell_agent/start_background_thread.rb +21 -142
  78. data/lib/tcell_agent/system_info.rb +4 -3
  79. data/lib/tcell_agent/tcell_context.rb +150 -0
  80. data/lib/tcell_agent/userinfo.rb +3 -3
  81. data/lib/tcell_agent/utils/io.rb +19 -24
  82. data/lib/tcell_agent/utils/params.rb +9 -15
  83. data/lib/tcell_agent/utils/queue_with_timeout.rb +26 -32
  84. data/lib/tcell_agent/utils/strings.rb +4 -6
  85. data/lib/tcell_agent/version.rb +1 -1
  86. data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +5 -5
  87. data/spec/lib/tcell_agent/agent/static_agent_spec.rb +7 -7
  88. data/spec/lib/tcell_agent/cmdi_spec.rb +21 -21
  89. data/spec/lib/tcell_agent/hooks/login_fraud_spec.rb +29 -24
  90. data/spec/lib/tcell_agent/instrumentation_spec.rb +4 -4
  91. data/spec/lib/tcell_agent/patches_spec.rb +8 -8
  92. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +23 -23
  93. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +2 -2
  94. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +69 -0
  95. data/spec/lib/tcell_agent/rails/dlp_spec.rb +1039 -0
  96. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +271 -0
  97. data/spec/lib/tcell_agent/rails/logger_spec.rb +5 -5
  98. data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +3 -3
  99. data/spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb +4 -4
  100. data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +5 -5
  101. data/spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb +1 -1
  102. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +11 -8
  103. data/spec/lib/tcell_agent/rails/responses_spec.rb +2 -2
  104. data/spec/lib/tcell_agent/rails/routes/grape_spec.rb +2 -2
  105. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +1 -1
  106. data/spec/lib/tcell_agent/rails/routes/routes_spec.rb +4 -4
  107. data/spec/lib/tcell_agent/rust/models_spec.rb +83 -75
  108. data/spec/lib/tcell_agent/rust/whisperer_spec.rb +14 -14
  109. data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +19 -70
  110. data/spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb +1 -1
  111. data/spec/lib/tcell_agent/settings_reporter_spec.rb +162 -0
  112. data/spec/lib/tcell_agent/tcell_context_spec.rb +154 -0
  113. data/spec/spec_helper.rb +5 -0
  114. metadata +18 -10
  115. data/lib/tcell_agent/appsensor/meta_data.rb +0 -132
  116. data/lib/tcell_agent/patches/meta_data.rb +0 -59
  117. data/lib/tcell_agent/rust/tcellagent-1.3.0.dll +0 -0
  118. data/spec/lib/tcell_agent/appsensor/meta_data_spec.rb +0 -71
@@ -283,7 +283,7 @@ module TCellAgent
283
283
  }
284
284
  )
285
285
 
286
- meta_data = TCellAgent::Patches::MetaData.new(
286
+ meta_data = TCellAgent::MetaData.new(
287
287
  'get',
288
288
  '1.3.3.4',
289
289
  'route_id',
@@ -294,7 +294,7 @@ module TCellAgent
294
294
  )
295
295
  expect(@rust_policies.block_request?(meta_data)).to eq(true)
296
296
 
297
- meta_data = TCellAgent::Patches::MetaData.new(
297
+ meta_data = TCellAgent::MetaData.new(
298
298
  'get',
299
299
  '1.1.1.1',
300
300
  'route_id',
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ module TCellAgent
4
+ describe 'CsrfExceptionReporter' do
5
+ class WrapperClass
6
+ include TCellAgent::CsrfExceptionReporter
7
+
8
+ def request; end
9
+ end
10
+
11
+ before(:all) do
12
+ @csrf_class = WrapperClass.new
13
+ end
14
+
15
+ context 'nil rust policies' do
16
+ it 'should not set csrf_exception_name' do
17
+ expect(TCellAgent).to receive(:policy).and_return(nil)
18
+ expect(@csrf_class).to_not receive(:request)
19
+
20
+ @csrf_class.handle_unverified_request
21
+ end
22
+ end
23
+
24
+ context 'appfirewall_enabled=false' do
25
+ it 'should not set csrf_exception_name' do
26
+ rust_policies = double('rust_policies',
27
+ :appfirewall_enabled => false)
28
+
29
+ expect(TCellAgent).to receive(:policy).and_return(rust_policies)
30
+ expect(@csrf_class).to_not receive(:request)
31
+
32
+ @csrf_class.handle_unverified_request
33
+ end
34
+ end
35
+
36
+ context 'appfirewall_enabled=true and nil tcell_data' do
37
+ it 'should not set csrf_exception_name' do
38
+ rust_policies = double('rust_policies',
39
+ :appfirewall_enabled => true)
40
+ request = double('request',
41
+ :env => {})
42
+
43
+ expect(TCellAgent).to receive(:policy).and_return(rust_policies)
44
+ expect(@csrf_class).to receive(:request).and_return(request)
45
+
46
+ @csrf_class.handle_unverified_request
47
+ end
48
+ end
49
+
50
+ context 'appfirewall_enabled=true and tcell_data present' do
51
+ it 'should set csrf_exception_name' do
52
+ tcell_data = TCellAgent::Instrumentation::TCellData.new
53
+ expect(tcell_data.csrf_exception_name).to be(nil)
54
+
55
+ rust_policies = double('rust_policies',
56
+ :appfirewall_enabled => true)
57
+ request = double('request',
58
+ :env => { TCellAgent::Instrumentation::TCELL_ID => tcell_data })
59
+
60
+ expect(TCellAgent).to receive(:policy).and_return(rust_policies)
61
+ expect(@csrf_class).to receive(:request).and_return(request)
62
+
63
+ @csrf_class.handle_unverified_request
64
+
65
+ expect(tcell_data.csrf_exception_name).to eq('ActionController::InvalidAuthenticityToken')
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,1039 @@
1
+ require 'spec_helper'
2
+
3
+ module TCellAgent
4
+ module DLP
5
+ class SomeColumn
6
+ attr_accessor :name
7
+ def initialize(name = nil)
8
+ @name = name
9
+ end
10
+ end
11
+
12
+ class SomeModel
13
+ class << self
14
+ def table_name
15
+ 'some_models'
16
+ end
17
+
18
+ def columns
19
+ [SomeColumn.new('id'), SomeColumn.new('name'), SomeColumn.new('email')]
20
+ end
21
+
22
+ def connection_config
23
+ {
24
+ :database => 'something/test_database'
25
+ }
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '.instrument_pluck' do
31
+ context 'with empty results' do
32
+ it 'should skip over instrumentation' do
33
+ expect(TCellAgent).to_not receive(:configuration)
34
+
35
+ TCellAgent::DLP.instrument_pluck([], [:id], SomeModel)
36
+ end
37
+ end
38
+
39
+ context 'with no dlp policy' do
40
+ it 'should skip over instrumentation' do
41
+ configuration = double(
42
+ 'configuration',
43
+ {
44
+ :enabled => true,
45
+ :should_instrument? => true,
46
+ :should_intercept_requests? => true
47
+ }
48
+ )
49
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
50
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(nil)
51
+
52
+ TCellAgent::DLP.instrument_pluck([10], [:id], SomeModel)
53
+ end
54
+ end
55
+
56
+ context 'with dlp policy disabled' do
57
+ it 'should skip over instrumentation' do
58
+ configuration = double(
59
+ 'configuration',
60
+ {
61
+ :enabled => true,
62
+ :should_instrument? => true,
63
+ :should_intercept_requests? => true
64
+ }
65
+ )
66
+ dataloss_policy = double(
67
+ 'dataloss_policy',
68
+ {
69
+ :enabled => false
70
+ }
71
+ )
72
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
73
+ expect(TCellAgent).to receive(:policy).with(
74
+ TCellAgent::PolicyTypes::DATALOSS
75
+ ).and_return(dataloss_policy)
76
+
77
+ TCellAgent::DLP.instrument_pluck([10], [:id], SomeModel)
78
+ end
79
+ end
80
+
81
+ context 'with dlp policy enabled' do
82
+ context 'with database_discovery_enabled' do
83
+ it 'should send model columns to tcell service' do
84
+ configuration = double(
85
+ 'configuration',
86
+ {
87
+ :enabled => true,
88
+ :should_instrument? => true,
89
+ :should_intercept_requests? => true,
90
+ :max_data_ex_db_records_per_request => 1
91
+ }
92
+ )
93
+ dataloss_policy = double(
94
+ 'dataloss_policy',
95
+ {
96
+ :enabled => true,
97
+ :database_discovery_enabled => true
98
+ }
99
+ )
100
+ request_env = double('request_env', {})
101
+ tcell_context = double(
102
+ 'tcell_context',
103
+ {
104
+ :route_id => 'ma_route_id',
105
+ :database_result_sizes => []
106
+ }
107
+ )
108
+
109
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
110
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
111
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
112
+ :fetch
113
+ ).and_return(request_env)
114
+ expect(request_env).to receive(:[]).with(
115
+ TCellAgent::Instrumentation::TCELL_ID
116
+ ).and_return(tcell_context)
117
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
118
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
119
+ ).and_return(nil)
120
+
121
+ expect(TCellAgent).to receive(:discover_database_fields).with(
122
+ 'ma_route_id', 'test_database', '*', 'some_models', ['id']
123
+ )
124
+
125
+ TCellAgent::DLP.instrument_pluck([10], [:id], SomeModel)
126
+
127
+ expect(tcell_context.database_result_sizes).to eq([1])
128
+ end
129
+ end
130
+
131
+ context 'with database_discovery_enabled == false' do
132
+ context 'with zero columns passed to pluck' do
133
+ context 'that doesn\'t have any rules set' do
134
+ it 'should not send anything to tcell' do
135
+ configuration = double(
136
+ 'configuration',
137
+ {
138
+ :enabled => true,
139
+ :should_instrument? => true,
140
+ :should_intercept_requests? => true,
141
+ :max_data_ex_db_records_per_request => 1000
142
+ }
143
+ )
144
+ dataloss_policy = double(
145
+ 'dataloss_policy',
146
+ {
147
+ :enabled => true,
148
+ :database_discovery_enabled => false
149
+ }
150
+ )
151
+ request_env = double('request_env', {})
152
+ tcell_context = double(
153
+ 'tcell_context',
154
+ {
155
+ :route_id => 'ma_route_id',
156
+ :database_result_sizes => []
157
+ }
158
+ )
159
+
160
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
161
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
162
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
163
+ :fetch
164
+ ).and_return(request_env)
165
+ expect(request_env).to receive(:[]).with(
166
+ TCellAgent::Instrumentation::TCELL_ID
167
+ ).and_return(tcell_context)
168
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
169
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
170
+ ).and_return(nil)
171
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
172
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
173
+ ).and_return(nil)
174
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
175
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
176
+ ).and_return(nil)
177
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
178
+
179
+ expect(TCellAgent).to_not receive(:discover_database_fields)
180
+
181
+ TCellAgent::DLP.instrument_pluck([10], [], SomeModel)
182
+
183
+ expect(tcell_context.database_result_sizes).to eq([1])
184
+ end
185
+ end
186
+
187
+ context 'that has a rule set' do
188
+ it 'should add a response filter' do
189
+ configuration = double(
190
+ 'configuration',
191
+ {
192
+ :enabled => true,
193
+ :should_instrument? => true,
194
+ :should_intercept_requests? => true,
195
+ :max_data_ex_db_records_per_request => 1000
196
+ }
197
+ )
198
+ dataloss_policy = double(
199
+ 'dataloss_policy',
200
+ {
201
+ :enabled => true,
202
+ :database_discovery_enabled => false
203
+ }
204
+ )
205
+ request_env = double('request_env', {})
206
+ tcell_context = double(
207
+ 'tcell_context',
208
+ {
209
+ :route_id => 'ma_route_id',
210
+ :database_result_sizes => []
211
+ }
212
+ )
213
+ id_rule = double('id_rule')
214
+
215
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
216
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
217
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
218
+ :fetch
219
+ ).and_return(request_env)
220
+ expect(request_env).to receive(:[]).with(
221
+ TCellAgent::Instrumentation::TCELL_ID
222
+ ).and_return(tcell_context)
223
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
224
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
225
+ ).and_return([id_rule])
226
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
227
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
228
+ ).and_return(nil)
229
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
230
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
231
+ ).and_return(nil)
232
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
233
+
234
+ expect(TCellAgent).to_not receive(:discover_database_fields)
235
+ expect(tcell_context).to receive(:add_response_db_filter).with(
236
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
237
+ )
238
+
239
+ TCellAgent::DLP.instrument_pluck([[10, 'name', 'email']], [], SomeModel)
240
+
241
+ expect(tcell_context.database_result_sizes).to eq([1])
242
+ end
243
+ end
244
+
245
+ context 'that has two rules set' do
246
+ it 'should add a response filter' do
247
+ configuration = double(
248
+ 'configuration',
249
+ {
250
+ :enabled => true,
251
+ :should_instrument? => true,
252
+ :should_intercept_requests? => true,
253
+ :max_data_ex_db_records_per_request => 1000
254
+ }
255
+ )
256
+ dataloss_policy = double(
257
+ 'dataloss_policy',
258
+ {
259
+ :enabled => true,
260
+ :database_discovery_enabled => false
261
+ }
262
+ )
263
+ request_env = double('request_env', {})
264
+ tcell_context = double(
265
+ 'tcell_context',
266
+ {
267
+ :route_id => 'ma_route_id',
268
+ :database_result_sizes => []
269
+ }
270
+ )
271
+ id_rule = double('id_rule')
272
+ id_rule_dos = double('id_rule_dos')
273
+
274
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
275
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
276
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
277
+ :fetch
278
+ ).and_return(request_env)
279
+ expect(request_env).to receive(:[]).with(
280
+ TCellAgent::Instrumentation::TCELL_ID
281
+ ).and_return(tcell_context)
282
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
283
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
284
+ ).and_return([id_rule, id_rule_dos])
285
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
286
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
287
+ ).and_return(nil)
288
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
289
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
290
+ ).and_return(nil)
291
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
292
+
293
+ expect(TCellAgent).to_not receive(:discover_database_fields)
294
+ expect(tcell_context).to receive(:add_response_db_filter).with(
295
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
296
+ )
297
+ expect(tcell_context).to receive(:add_response_db_filter).with(
298
+ 10, id_rule_dos, 'test_database', '*', 'some_models', 'id'
299
+ )
300
+
301
+ TCellAgent::DLP.instrument_pluck([[10, 'name', 'email']], [], SomeModel)
302
+
303
+ expect(tcell_context.database_result_sizes).to eq([1])
304
+ end
305
+ end
306
+ end
307
+
308
+ context 'with one column passed to pluck' do
309
+ context 'that doesn\'t have any rules set' do
310
+ it 'should not send anything to tcell' do
311
+ configuration = double(
312
+ 'configuration',
313
+ {
314
+ :enabled => true,
315
+ :should_instrument? => true,
316
+ :should_intercept_requests? => true,
317
+ :max_data_ex_db_records_per_request => 1000
318
+ }
319
+ )
320
+ dataloss_policy = double(
321
+ 'dataloss_policy',
322
+ {
323
+ :enabled => true,
324
+ :database_discovery_enabled => false
325
+ }
326
+ )
327
+ request_env = double('request_env', {})
328
+ tcell_context = double(
329
+ 'tcell_context',
330
+ {
331
+ :route_id => 'ma_route_id',
332
+ :database_result_sizes => []
333
+ }
334
+ )
335
+
336
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
337
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
338
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
339
+ :fetch
340
+ ).and_return(request_env)
341
+ expect(request_env).to receive(:[]).with(
342
+ TCellAgent::Instrumentation::TCELL_ID
343
+ ).and_return(tcell_context)
344
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
345
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
346
+ ).and_return(nil)
347
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
348
+
349
+ expect(TCellAgent).to_not receive(:discover_database_fields)
350
+
351
+ TCellAgent::DLP.instrument_pluck([10], [:id], SomeModel)
352
+
353
+ expect(tcell_context.database_result_sizes).to eq([1])
354
+ end
355
+ end
356
+
357
+ context 'that has a rule set' do
358
+ it 'should add a response filter' do
359
+ configuration = double(
360
+ 'configuration',
361
+ {
362
+ :enabled => true,
363
+ :should_instrument? => true,
364
+ :should_intercept_requests? => true,
365
+ :max_data_ex_db_records_per_request => 1000
366
+ }
367
+ )
368
+ dataloss_policy = double(
369
+ 'dataloss_policy',
370
+ {
371
+ :enabled => true,
372
+ :database_discovery_enabled => false
373
+ }
374
+ )
375
+ request_env = double('request_env', {})
376
+ tcell_context = double(
377
+ 'tcell_context',
378
+ {
379
+ :route_id => 'ma_route_id',
380
+ :database_result_sizes => []
381
+ }
382
+ )
383
+ id_rule = double('id_rule')
384
+
385
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
386
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
387
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
388
+ :fetch
389
+ ).and_return(request_env)
390
+ expect(request_env).to receive(:[]).with(
391
+ TCellAgent::Instrumentation::TCELL_ID
392
+ ).and_return(tcell_context)
393
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
394
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
395
+ ).and_return([id_rule])
396
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
397
+
398
+ expect(TCellAgent).to_not receive(:discover_database_fields)
399
+ expect(tcell_context).to receive(:add_response_db_filter).with(
400
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
401
+ )
402
+
403
+ TCellAgent::DLP.instrument_pluck([10], [:id], SomeModel)
404
+
405
+ expect(tcell_context.database_result_sizes).to eq([1])
406
+ end
407
+ end
408
+
409
+ context 'that has two rules set' do
410
+ it 'should add a response filter' do
411
+ configuration = double(
412
+ 'configuration',
413
+ {
414
+ :enabled => true,
415
+ :should_instrument? => true,
416
+ :should_intercept_requests? => true,
417
+ :max_data_ex_db_records_per_request => 1000
418
+ }
419
+ )
420
+ dataloss_policy = double(
421
+ 'dataloss_policy',
422
+ {
423
+ :enabled => true,
424
+ :database_discovery_enabled => false
425
+ }
426
+ )
427
+ request_env = double('request_env', {})
428
+ tcell_context = double(
429
+ 'tcell_context',
430
+ {
431
+ :route_id => 'ma_route_id',
432
+ :database_result_sizes => []
433
+ }
434
+ )
435
+ id_rule = double('id_rule')
436
+ id_rule_dos = double('id_rule_dos')
437
+
438
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
439
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
440
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
441
+ :fetch
442
+ ).and_return(request_env)
443
+ expect(request_env).to receive(:[]).with(
444
+ TCellAgent::Instrumentation::TCELL_ID
445
+ ).and_return(tcell_context)
446
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
447
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
448
+ ).and_return([id_rule, id_rule_dos])
449
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
450
+
451
+ expect(TCellAgent).to_not receive(:discover_database_fields)
452
+ expect(tcell_context).to receive(:add_response_db_filter).with(
453
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
454
+ )
455
+ expect(tcell_context).to receive(:add_response_db_filter).with(
456
+ 10, id_rule_dos, 'test_database', '*', 'some_models', 'id'
457
+ )
458
+
459
+ TCellAgent::DLP.instrument_pluck([10], [:id], SomeModel)
460
+
461
+ expect(tcell_context.database_result_sizes).to eq([1])
462
+ end
463
+ end
464
+
465
+ context 'that is namespaced' do
466
+ it 'should add a response filter' do
467
+ configuration = double(
468
+ 'configuration',
469
+ {
470
+ :enabled => true,
471
+ :should_instrument? => true,
472
+ :should_intercept_requests? => true,
473
+ :max_data_ex_db_records_per_request => 1000
474
+ }
475
+ )
476
+ dataloss_policy = double(
477
+ 'dataloss_policy',
478
+ {
479
+ :enabled => true,
480
+ :database_discovery_enabled => false
481
+ }
482
+ )
483
+ request_env = double('request_env', {})
484
+ tcell_context = double(
485
+ 'tcell_context',
486
+ {
487
+ :route_id => 'ma_route_id',
488
+ :database_result_sizes => []
489
+ }
490
+ )
491
+ id_rule = double('id_rule')
492
+ id_rule_dos = double('id_rule_dos')
493
+
494
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
495
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
496
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
497
+ :fetch
498
+ ).and_return(request_env)
499
+ expect(request_env).to receive(:[]).with(
500
+ TCellAgent::Instrumentation::TCELL_ID
501
+ ).and_return(tcell_context)
502
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
503
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
504
+ ).and_return([id_rule, id_rule_dos])
505
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
506
+ expect(tcell_context).to receive(:add_response_db_filter).with(
507
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
508
+ )
509
+ expect(tcell_context).to receive(:add_response_db_filter).with(
510
+ 10, id_rule_dos, 'test_database', '*', 'some_models', 'id'
511
+ )
512
+
513
+ expect(TCellAgent).to_not receive(:discover_database_fields)
514
+
515
+ TCellAgent::DLP.instrument_pluck([10], ['some_models.id'], SomeModel)
516
+
517
+ expect(tcell_context.database_result_sizes).to eq([1])
518
+ end
519
+ end
520
+ end
521
+
522
+ context 'with two columns passed to pluck' do
523
+ context 'that doesn\'t have any rules set' do
524
+ it 'should not send anything to tcell' do
525
+ configuration = double(
526
+ 'configuration',
527
+ {
528
+ :enabled => true,
529
+ :should_instrument? => true,
530
+ :should_intercept_requests? => true,
531
+ :max_data_ex_db_records_per_request => 1000
532
+ }
533
+ )
534
+ dataloss_policy = double(
535
+ 'dataloss_policy',
536
+ {
537
+ :enabled => true,
538
+ :database_discovery_enabled => false
539
+ }
540
+ )
541
+ request_env = double('request_env', {})
542
+ tcell_context = double(
543
+ 'tcell_context',
544
+ {
545
+ :route_id => 'ma_route_id',
546
+ :database_result_sizes => []
547
+ }
548
+ )
549
+
550
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
551
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
552
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
553
+ :fetch
554
+ ).and_return(request_env)
555
+ expect(request_env).to receive(:[]).with(
556
+ TCellAgent::Instrumentation::TCELL_ID
557
+ ).and_return(tcell_context)
558
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
559
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
560
+ ).and_return(nil)
561
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
562
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
563
+ ).and_return(nil)
564
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
565
+
566
+ expect(TCellAgent).to_not receive(:discover_database_fields)
567
+
568
+ TCellAgent::DLP.instrument_pluck([[10, 'dies'], [20, 'veinte']], %i[id name], SomeModel)
569
+
570
+ expect(tcell_context.database_result_sizes).to eq([2])
571
+ end
572
+ end
573
+
574
+ context 'that has a rule set' do
575
+ it 'should add a response filter' do
576
+ configuration = double(
577
+ 'configuration',
578
+ {
579
+ :enabled => true,
580
+ :should_instrument? => true,
581
+ :should_intercept_requests? => true,
582
+ :max_data_ex_db_records_per_request => 1000
583
+ }
584
+ )
585
+ dataloss_policy = double(
586
+ 'dataloss_policy',
587
+ {
588
+ :enabled => true,
589
+ :database_discovery_enabled => false
590
+ }
591
+ )
592
+ request_env = double('request_env', {})
593
+ tcell_context = double(
594
+ 'tcell_context',
595
+ {
596
+ :route_id => 'ma_route_id',
597
+ :database_result_sizes => []
598
+ }
599
+ )
600
+ id_rule = double('id_rule')
601
+
602
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
603
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
604
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
605
+ :fetch
606
+ ).and_return(request_env)
607
+ expect(request_env).to receive(:[]).with(
608
+ TCellAgent::Instrumentation::TCELL_ID
609
+ ).and_return(tcell_context)
610
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
611
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
612
+ ).and_return([id_rule])
613
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
614
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
615
+ ).and_return(nil)
616
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
617
+
618
+ expect(TCellAgent).to_not receive(:discover_database_fields)
619
+ expect(tcell_context).to receive(:add_response_db_filter).with(
620
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
621
+ )
622
+ expect(tcell_context).to receive(:add_response_db_filter).with(
623
+ 20, id_rule, 'test_database', '*', 'some_models', 'id'
624
+ )
625
+
626
+ TCellAgent::DLP.instrument_pluck([[10, 'dies'], [20, 'veinte']], %i[id name], SomeModel)
627
+
628
+ expect(tcell_context.database_result_sizes).to eq([2])
629
+ end
630
+
631
+ context 'that is namespaced' do
632
+ it 'should not send anything to tcell' do
633
+ configuration = double(
634
+ 'configuration',
635
+ {
636
+ :enabled => true,
637
+ :should_instrument? => true,
638
+ :should_intercept_requests? => true,
639
+ :max_data_ex_db_records_per_request => 1000
640
+ }
641
+ )
642
+ dataloss_policy = double(
643
+ 'dataloss_policy',
644
+ {
645
+ :enabled => true,
646
+ :database_discovery_enabled => false
647
+ }
648
+ )
649
+ request_env = double('request_env', {})
650
+ tcell_context = double(
651
+ 'tcell_context',
652
+ {
653
+ :route_id => 'ma_route_id',
654
+ :database_result_sizes => []
655
+ }
656
+ )
657
+
658
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
659
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
660
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
661
+ :fetch
662
+ ).and_return(request_env)
663
+ expect(request_env).to receive(:[]).with(
664
+ TCellAgent::Instrumentation::TCELL_ID
665
+ ).and_return(tcell_context)
666
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
667
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
668
+ ).and_return(nil)
669
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
670
+
671
+ expect(TCellAgent).to_not receive(:discover_database_fields)
672
+
673
+ TCellAgent::DLP.instrument_pluck([10], ['some_other_models.name', 'some_models.id'], SomeModel)
674
+
675
+ expect(tcell_context.database_result_sizes).to eq([1])
676
+ end
677
+ end
678
+ end
679
+
680
+ context 'that has two rules set' do
681
+ it 'should add a response filter' do
682
+ configuration = double(
683
+ 'configuration',
684
+ {
685
+ :enabled => true,
686
+ :should_instrument? => true,
687
+ :should_intercept_requests? => true,
688
+ :max_data_ex_db_records_per_request => 1000
689
+ }
690
+ )
691
+ dataloss_policy = double(
692
+ 'dataloss_policy',
693
+ {
694
+ :enabled => true,
695
+ :database_discovery_enabled => false
696
+ }
697
+ )
698
+ request_env = double('request_env', {})
699
+ tcell_context = double(
700
+ 'tcell_context',
701
+ {
702
+ :route_id => 'ma_route_id',
703
+ :database_result_sizes => []
704
+ }
705
+ )
706
+ id_rule = double('id_rule')
707
+ id_rule_dos = double('id_rule_dos')
708
+
709
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
710
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
711
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
712
+ :fetch
713
+ ).and_return(request_env)
714
+ expect(request_env).to receive(:[]).with(
715
+ TCellAgent::Instrumentation::TCELL_ID
716
+ ).and_return(tcell_context)
717
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
718
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
719
+ ).and_return([id_rule, id_rule_dos])
720
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
721
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
722
+ ).and_return(nil)
723
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
724
+
725
+ expect(TCellAgent).to_not receive(:discover_database_fields)
726
+ expect(tcell_context).to receive(:add_response_db_filter).with(
727
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
728
+ )
729
+ expect(tcell_context).to receive(:add_response_db_filter).with(
730
+ 10, id_rule_dos, 'test_database', '*', 'some_models', 'id'
731
+ )
732
+ expect(tcell_context).to receive(:add_response_db_filter).with(
733
+ 20, id_rule, 'test_database', '*', 'some_models', 'id'
734
+ )
735
+ expect(tcell_context).to receive(:add_response_db_filter).with(
736
+ 20, id_rule_dos, 'test_database', '*', 'some_models', 'id'
737
+ )
738
+
739
+ TCellAgent::DLP.instrument_pluck([[10, 'dies'], [20, 'veinte']], %i[id name], SomeModel)
740
+
741
+ expect(tcell_context.database_result_sizes).to eq([2])
742
+ end
743
+ end
744
+ end
745
+ end
746
+ end
747
+ end
748
+
749
+ describe '.instrument_find_by_sql' do
750
+ context 'with empty results' do
751
+ it 'should skip over instrumentation' do
752
+ expect(TCellAgent).to_not receive(:configuration)
753
+
754
+ TCellAgent::DLP.instrument_find_by_sql([])
755
+ end
756
+ end
757
+
758
+ context 'with no dlp policy' do
759
+ it 'should skip over instrumentation' do
760
+ configuration = double(
761
+ 'configuration',
762
+ {
763
+ :enabled => true,
764
+ :should_instrument? => true,
765
+ :should_intercept_requests? => true
766
+ }
767
+ )
768
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
769
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(nil)
770
+
771
+ TCellAgent::DLP.instrument_find_by_sql([SomeModel.new])
772
+ end
773
+ end
774
+
775
+ context 'with dlp policy disabled' do
776
+ it 'should skip over instrumentation' do
777
+ configuration = double(
778
+ 'configuration',
779
+ {
780
+ :enabled => true,
781
+ :should_instrument? => true,
782
+ :should_intercept_requests? => true
783
+ }
784
+ )
785
+ dataloss_policy = double(
786
+ 'dataloss_policy',
787
+ {
788
+ :enabled => false
789
+ }
790
+ )
791
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
792
+ expect(TCellAgent).to receive(:policy).with(
793
+ TCellAgent::PolicyTypes::DATALOSS
794
+ ).and_return(dataloss_policy)
795
+
796
+ TCellAgent::DLP.instrument_find_by_sql([SomeModel.new])
797
+ end
798
+ end
799
+
800
+ context 'with dlp policy enabled' do
801
+ context 'with database_discovery_enabled' do
802
+ it 'should send model columns to tcell service' do
803
+ configuration = double(
804
+ 'configuration',
805
+ {
806
+ :enabled => true,
807
+ :should_instrument? => true,
808
+ :should_intercept_requests? => true,
809
+ :max_data_ex_db_records_per_request => 1
810
+ }
811
+ )
812
+ dataloss_policy = double(
813
+ 'dataloss_policy',
814
+ {
815
+ :enabled => true,
816
+ :database_discovery_enabled => true
817
+ }
818
+ )
819
+ request_env = double('request_env', {})
820
+ tcell_context = double(
821
+ 'tcell_context',
822
+ {
823
+ :route_id => 'ma_route_id',
824
+ :database_result_sizes => []
825
+ }
826
+ )
827
+
828
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
829
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
830
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
831
+ :fetch
832
+ ).and_return(request_env)
833
+ expect(request_env).to receive(:[]).with(
834
+ TCellAgent::Instrumentation::TCELL_ID
835
+ ).and_return(tcell_context)
836
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
837
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
838
+ ).and_return(nil)
839
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
840
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
841
+ ).and_return(nil)
842
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
843
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
844
+ ).and_return(nil)
845
+
846
+ expect(TCellAgent).to receive(:discover_database_fields).with(
847
+ 'ma_route_id', 'test_database', '*', 'some_models', %w[id name email]
848
+ )
849
+
850
+ TCellAgent::DLP.instrument_find_by_sql([SomeModel.new])
851
+
852
+ expect(tcell_context.database_result_sizes).to eq([1])
853
+ end
854
+ end
855
+
856
+ context 'with database_discovery_enabled == false' do
857
+ context 'that doesn\'t have any rules set' do
858
+ it 'should not send anything to tcell' do
859
+ configuration = double(
860
+ 'configuration',
861
+ {
862
+ :enabled => true,
863
+ :should_instrument? => true,
864
+ :should_intercept_requests? => true,
865
+ :max_data_ex_db_records_per_request => 1000
866
+ }
867
+ )
868
+ dataloss_policy = double(
869
+ 'dataloss_policy',
870
+ {
871
+ :enabled => true,
872
+ :database_discovery_enabled => false
873
+ }
874
+ )
875
+ request_env = double('request_env', {})
876
+ tcell_context = double(
877
+ 'tcell_context',
878
+ {
879
+ :route_id => 'ma_route_id',
880
+ :database_result_sizes => []
881
+ }
882
+ )
883
+
884
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
885
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
886
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
887
+ :fetch
888
+ ).and_return(request_env)
889
+ expect(request_env).to receive(:[]).with(
890
+ TCellAgent::Instrumentation::TCELL_ID
891
+ ).and_return(tcell_context)
892
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
893
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
894
+ ).and_return(nil)
895
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
896
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
897
+ ).and_return(nil)
898
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
899
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
900
+ ).and_return(nil)
901
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
902
+
903
+ expect(TCellAgent).to_not receive(:discover_database_fields)
904
+
905
+ TCellAgent::DLP.instrument_find_by_sql([SomeModel.new])
906
+
907
+ expect(tcell_context.database_result_sizes).to eq([1])
908
+ end
909
+ end
910
+
911
+ context 'that has a rule set' do
912
+ it 'should add a response filter' do
913
+ configuration = double(
914
+ 'configuration',
915
+ {
916
+ :enabled => true,
917
+ :should_instrument? => true,
918
+ :should_intercept_requests? => true,
919
+ :max_data_ex_db_records_per_request => 1000
920
+ }
921
+ )
922
+ dataloss_policy = double(
923
+ 'dataloss_policy',
924
+ {
925
+ :enabled => true,
926
+ :database_discovery_enabled => false
927
+ }
928
+ )
929
+ request_env = double('request_env', {})
930
+ tcell_context = double(
931
+ 'tcell_context',
932
+ {
933
+ :route_id => 'ma_route_id',
934
+ :database_result_sizes => []
935
+ }
936
+ )
937
+ id_rule = double('id_rule')
938
+ some_model = SomeModel.new
939
+
940
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
941
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
942
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
943
+ :fetch
944
+ ).and_return(request_env)
945
+ expect(request_env).to receive(:[]).with(
946
+ TCellAgent::Instrumentation::TCELL_ID
947
+ ).and_return(tcell_context)
948
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
949
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
950
+ ).and_return([id_rule])
951
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
952
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
953
+ ).and_return(nil)
954
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
955
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
956
+ ).and_return(nil)
957
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
958
+
959
+ expect(TCellAgent).to_not receive(:discover_database_fields)
960
+ expect(some_model).to receive(:[]).with(:id).and_return(10)
961
+ expect(tcell_context).to receive(:add_response_db_filter).with(
962
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
963
+ )
964
+
965
+ TCellAgent::DLP.instrument_find_by_sql([some_model])
966
+
967
+ expect(tcell_context.database_result_sizes).to eq([1])
968
+ end
969
+ end
970
+
971
+ context 'that has two rules set' do
972
+ it 'should add a response filter' do
973
+ configuration = double(
974
+ 'configuration',
975
+ {
976
+ :enabled => true,
977
+ :should_instrument? => true,
978
+ :should_intercept_requests? => true,
979
+ :max_data_ex_db_records_per_request => 1000
980
+ }
981
+ )
982
+ dataloss_policy = double(
983
+ 'dataloss_policy',
984
+ {
985
+ :enabled => true,
986
+ :database_discovery_enabled => false
987
+ }
988
+ )
989
+ request_env = double('request_env', {})
990
+ tcell_context = double(
991
+ 'tcell_context',
992
+ {
993
+ :route_id => 'ma_route_id',
994
+ :database_result_sizes => []
995
+ }
996
+ )
997
+ id_rule = double('id_rule')
998
+ id_rule_dos = double('id_rule_dos')
999
+ some_model = SomeModel.new
1000
+
1001
+ allow(TCellAgent).to receive(:configuration).and_return(configuration)
1002
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::DATALOSS).and_return(dataloss_policy)
1003
+ expect(TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS).to receive(
1004
+ :fetch
1005
+ ).and_return(request_env)
1006
+ expect(request_env).to receive(:[]).with(
1007
+ TCellAgent::Instrumentation::TCELL_ID
1008
+ ).and_return(tcell_context)
1009
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
1010
+ 'test_database', '*', 'some_models', 'id', 'ma_route_id'
1011
+ ).and_return([id_rule, id_rule_dos])
1012
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
1013
+ 'test_database', '*', 'some_models', 'name', 'ma_route_id'
1014
+ ).and_return(nil)
1015
+ expect(dataloss_policy).to receive(:get_actions_for_table).with(
1016
+ 'test_database', '*', 'some_models', 'email', 'ma_route_id'
1017
+ ).and_return(nil)
1018
+ expect(dataloss_policy).to_not receive(:get_actions_for_table)
1019
+
1020
+ expect(TCellAgent).to_not receive(:discover_database_fields)
1021
+ expect(some_model).to receive(:[]).with(:id).and_return(10)
1022
+ expect(some_model).to receive(:[]).with(:id).and_return(10)
1023
+ expect(tcell_context).to receive(:add_response_db_filter).with(
1024
+ 10, id_rule, 'test_database', '*', 'some_models', 'id'
1025
+ )
1026
+ expect(tcell_context).to receive(:add_response_db_filter).with(
1027
+ 10, id_rule_dos, 'test_database', '*', 'some_models', 'id'
1028
+ )
1029
+
1030
+ TCellAgent::DLP.instrument_find_by_sql([some_model])
1031
+
1032
+ expect(tcell_context.database_result_sizes).to eq([1])
1033
+ end
1034
+ end
1035
+ end
1036
+ end
1037
+ end
1038
+ end
1039
+ end