9
9
require 'active_record'
10
10
require 'datadog/tracing'
11
11
require 'datadog/appsec'
12
+ require 'devise'
12
13
13
14
RSpec . describe 'Schema extraction for API security' do
14
15
include Rack ::Test ::Methods
15
16
16
17
before do
17
- stub_const ( 'User' , Class . new ( ActiveRecord ::Base ) ) . tap do |klass |
18
+ # NOTE: Due to the legacy code in AppSec component we always patch Devise
19
+ # and this is a minimalistic workaround to trigger the patching and
20
+ # have it configured properly.
21
+ Devise . send ( :remove_const , :Engine )
22
+ load File . join ( Gem . loaded_specs [ 'devise' ] . full_gem_path , 'lib/devise/rails.rb' )
23
+ Devise . setup { |config | config . parent_controller = 'ActionController::Base' }
24
+
25
+ stub_const ( 'Product' , Class . new ( ActiveRecord ::Base ) ) . tap do |klass |
18
26
klass . establish_connection ( { adapter : 'sqlite3' , database : ':memory:' } )
19
27
20
- klass . connection . create_table 'users ' , force : :cascade do |t |
28
+ klass . connection . create_table 'products ' , force : :cascade do |t |
21
29
t . string :name , null : false
22
30
end
23
31
@@ -48,9 +56,10 @@ def initialize(files, dirs = {}, &block)
48
56
Datadog . configure do |config |
49
57
config . tracing . enabled = true
50
58
config . tracing . sampler = sampler
51
- config . apm . tracing . enabled = true
52
59
config . tracing . instrument :rails
53
60
61
+ config . apm . tracing . enabled = true
62
+
54
63
config . appsec . enabled = true
55
64
config . appsec . instrument :rails
56
65
config . appsec . instrument :active_record
@@ -85,20 +94,20 @@ def initialize(files, dirs = {}, &block)
85
94
86
95
app . initialize!
87
96
app . routes . draw do
88
- get '/api/users ' , to : 'api#users '
97
+ get '/api/products ' , to : 'api#products '
89
98
get '/api/search' , to : 'api#search'
90
99
end
91
100
92
101
stub_const ( 'ApiController' , Class . new ( ActionController ::Base ) ) . class_eval do
93
- def users
94
- render json :
{ id :
1 , name :
'John ' , email : '[email protected] ' }
102
+ def products
103
+ render json : { id : 1 , name : 'Widget ' , price : 29.99 }
95
104
end
96
105
97
106
def search
98
- users = User . find_by_sql (
99
- "SELECT * FROM users WHERE name = '#{ params [ :name ] } '"
107
+ products = Product . find_by_sql (
108
+ "SELECT * FROM products WHERE name = '#{ params [ :name ] } '"
100
109
)
101
- render json : users
110
+ render json : products
102
111
end
103
112
end
104
113
@@ -114,6 +123,7 @@ def search
114
123
115
124
Datadog . configuration . reset!
116
125
Datadog . registry [ :rack ] . reset_configuration!
126
+
117
127
Datadog ::AppSec ::RateLimiter . reset!
118
128
Datadog ::AppSec ::APISecurity ::Sampler . reset!
119
129
@@ -146,7 +156,7 @@ def search
146
156
config . appsec . api_security . sample_delay = 30
147
157
end
148
158
149
- get ( '/api/users ' )
159
+ get ( '/api/products ' )
150
160
end
151
161
152
162
it 'extracts schema and adds to span tags' do
@@ -167,7 +177,7 @@ def search
167
177
end
168
178
169
179
context 'when APM sampler rejects the trace' do
170
- before { get ( '/api/users ' ) }
180
+ before { get ( '/api/products ' ) }
171
181
172
182
let ( :sampler ) { instance_double ( Datadog ::Tracing ::Sampling ::Sampler , sample! : false ) }
173
183
@@ -184,7 +194,7 @@ def search
184
194
before do
185
195
allow_any_instance_of ( Datadog ::AppSec ::APISecurity ::Sampler ) . to receive ( :sample? ) . and_return ( false )
186
196
187
- get ( '/api/users ' )
197
+ get ( '/api/products ' )
188
198
end
189
199
190
200
let ( :sampler ) { instance_double ( Datadog ::Tracing ::Sampling ::Sampler , sample! : true ) }
@@ -206,7 +216,7 @@ def search
206
216
config . appsec . api_security . sample_delay = 30
207
217
end
208
218
209
- get ( '/api/users ' )
219
+ get ( '/api/products ' )
210
220
end
211
221
212
222
it 'does not extract schema' do
@@ -226,7 +236,7 @@ def search
226
236
config . appsec . api_security . sample_delay = 30
227
237
end
228
238
229
- get ( '/api/users ' )
239
+ get ( '/api/products ' )
230
240
end
231
241
232
242
let ( :sampler ) { instance_double ( Datadog ::Tracing ::Sampling ::Sampler , sample! : false ) }
@@ -247,7 +257,7 @@ def search
247
257
config . appsec . api_security . sample_delay = 30
248
258
end
249
259
250
- get ( '/api/search' , { 'name' => "Bob '; OR 1=1" } )
260
+ get ( '/api/search' , { 'name' => "Widget '; OR 1=1" } )
251
261
end
252
262
253
263
it 'blocks the request and extracts only request schema' do
0 commit comments