Skip to content

Commit a72b341

Browse files
authored
Merge pull request #4311 from DataDog/appsec-add-rasp-enabled-config
Add Datadog.configuration.appsec.rasp_enabled
2 parents a49a11c + 65e8bfb commit a72b341

File tree

7 files changed

+223
-114
lines changed

7 files changed

+223
-114
lines changed

lib/datadog/appsec.rb

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ def enabled?
1414
Datadog.configuration.appsec.enabled
1515
end
1616

17+
def rasp_enabled?
18+
Datadog.configuration.appsec.rasp_enabled
19+
end
20+
1721
def active_context
1822
Datadog::AppSec::Context.active
1923
end

lib/datadog/appsec/configuration/settings.rb

+9
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ def self.add_settings!(base)
4949
end
5050
end
5151

52+
# RASP or Runtime Application Self-Protection
53+
# is a collection of techniques and heuristics aimed at detecting malicious inputs and preventing
54+
# any potential side-effects on the application resulting from the use of said malicious inputs.
55+
option :rasp_enabled do |o|
56+
o.type :bool, nilable: true
57+
o.env 'DD_APPSEC_RASP_ENABLED'
58+
o.default true
59+
end
60+
5261
option :ruleset do |o|
5362
o.env 'DD_APPSEC_RULES'
5463
o.default :recommended

lib/datadog/appsec/contrib/active_record/instrumentation.rb

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ module Instrumentation
99
module_function
1010

1111
def detect_sql_injection(sql, adapter_name)
12+
return unless AppSec.rasp_enabled?
13+
1214
context = AppSec.active_context
1315
return unless context
1416

spec/datadog/appsec/configuration/settings_spec.rb

+22
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,28 @@ def patcher
7777
end
7878
end
7979

80+
describe '#rasp_enabled' do
81+
context 'when DD_APPSEC_RASP_ENABLED' do
82+
around do |example|
83+
ClimateControl.modify('DD_APPSEC_RASP_ENABLED' => rasp_enabled_env_var) do
84+
example.run
85+
end
86+
end
87+
88+
context 'is not defined' do
89+
let(:rasp_enabled_env_var) { nil }
90+
91+
it { expect(settings.appsec.rasp_enabled).to eq(true) }
92+
end
93+
94+
context 'is defined' do
95+
let(:rasp_enabled_env_var) { 'false' }
96+
97+
it { expect(settings.appsec.rasp_enabled).to eq(false) }
98+
end
99+
end
100+
end
101+
80102
describe '#instrument' do
81103
let(:registry) { {} }
82104
let(:integration_name) { :fake }

spec/datadog/appsec/contrib/active_record/mysql2_adapter_spec.rb

+60-36
Original file line numberDiff line numberDiff line change
@@ -64,46 +64,70 @@
6464
processor.finalize
6565
end
6666

67-
it 'calls waf with correct arguments when querying using .where' do
68-
expect(Datadog::AppSec.active_context).to(
69-
receive(:run_rasp).with(
70-
Datadog::AppSec::Ext::RASP_SQLI,
71-
{},
72-
{
73-
'server.db.statement' => "SELECT `users`.* FROM `users` WHERE `users`.`name` = 'Bob'",
74-
'server.db.system' => 'mysql2'
75-
},
76-
Datadog.configuration.appsec.waf_timeout
77-
).and_call_original
78-
)
79-
80-
User.where(name: 'Bob').to_a
81-
end
67+
context 'when RASP is disabled' do
68+
before do
69+
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(false)
70+
end
8271

83-
it 'calls waf with correct arguments when querying using .find_by_sql' do
84-
expect(Datadog::AppSec.active_context).to(
85-
receive(:run_rasp).with(
86-
Datadog::AppSec::Ext::RASP_SQLI,
87-
{},
88-
{
89-
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
90-
'server.db.system' => 'mysql2'
91-
},
92-
Datadog.configuration.appsec.waf_timeout
93-
).and_call_original
94-
)
95-
96-
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
72+
it 'does not call waf when querying using .where' do
73+
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)
74+
75+
User.where(name: 'Bob').to_a
76+
end
77+
78+
it 'does not call waf when querying using .find_by_sql' do
79+
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)
80+
81+
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
82+
end
9783
end
9884

99-
it 'adds an event to processor context if waf result is a match' do
100-
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
101-
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
102-
)
85+
context 'when RASP is enabled' do
86+
before do
87+
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(true)
88+
end
89+
90+
it 'calls waf with correct arguments when querying using .where' do
91+
expect(Datadog::AppSec.active_context).to(
92+
receive(:run_rasp).with(
93+
Datadog::AppSec::Ext::RASP_SQLI,
94+
{},
95+
{
96+
'server.db.statement' => "SELECT `users`.* FROM `users` WHERE `users`.`name` = 'Bob'",
97+
'server.db.system' => 'mysql2'
98+
},
99+
Datadog.configuration.appsec.waf_timeout
100+
).and_call_original
101+
)
102+
103+
User.where(name: 'Bob').to_a
104+
end
103105

104-
expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
105-
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
106+
it 'calls waf with correct arguments when querying using .find_by_sql' do
107+
expect(Datadog::AppSec.active_context).to(
108+
receive(:run_rasp).with(
109+
Datadog::AppSec::Ext::RASP_SQLI,
110+
{},
111+
{
112+
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
113+
'server.db.system' => 'mysql2'
114+
},
115+
Datadog.configuration.appsec.waf_timeout
116+
).and_call_original
117+
)
118+
119+
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
120+
end
106121

107-
User.where(name: 'Bob').to_a
122+
it 'adds an event to processor context if waf result is a match' do
123+
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
124+
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
125+
)
126+
127+
expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
128+
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
129+
130+
User.where(name: 'Bob').to_a
131+
end
108132
end
109133
end

spec/datadog/appsec/contrib/active_record/postgresql_adapter_spec.rb

+66-42
Original file line numberDiff line numberDiff line change
@@ -65,52 +65,76 @@
6565
processor.finalize
6666
end
6767

68-
it 'calls waf with correct arguments when querying using .where' do
69-
expected_db_statement = if PlatformHelpers.jruby?
70-
'SELECT "users".* FROM "users" WHERE "users"."name" = ?'
71-
else
72-
'SELECT "users".* FROM "users" WHERE "users"."name" = $1'
73-
end
74-
75-
expect(Datadog::AppSec.active_context).to(
76-
receive(:run_rasp).with(
77-
Datadog::AppSec::Ext::RASP_SQLI,
78-
{},
79-
{
80-
'server.db.statement' => expected_db_statement,
81-
'server.db.system' => 'postgresql'
82-
},
83-
Datadog.configuration.appsec.waf_timeout
84-
).and_call_original
85-
)
86-
87-
User.where(name: 'Bob').to_a
88-
end
68+
context 'when RASP is disabled' do
69+
before do
70+
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(false)
71+
end
8972

90-
it 'calls waf with correct arguments when querying using .find_by_sql' do
91-
expect(Datadog::AppSec.active_context).to(
92-
receive(:run_rasp).with(
93-
Datadog::AppSec::Ext::RASP_SQLI,
94-
{},
95-
{
96-
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
97-
'server.db.system' => 'postgresql'
98-
},
99-
Datadog.configuration.appsec.waf_timeout
100-
).and_call_original
101-
)
102-
103-
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
73+
it 'does not call waf when querying using .where' do
74+
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)
75+
76+
User.where(name: 'Bob').to_a
77+
end
78+
79+
it 'does not call waf when querying using .find_by_sql' do
80+
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)
81+
82+
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
83+
end
10484
end
10585

106-
it 'adds an event to processor context if waf result is a match' do
107-
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
108-
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
109-
)
86+
context 'when RASP is enabled' do
87+
before do
88+
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(true)
89+
end
90+
91+
it 'calls waf with correct arguments when querying using .where' do
92+
expected_db_statement = if PlatformHelpers.jruby?
93+
'SELECT "users".* FROM "users" WHERE "users"."name" = ?'
94+
else
95+
'SELECT "users".* FROM "users" WHERE "users"."name" = $1'
96+
end
97+
98+
expect(Datadog::AppSec.active_context).to(
99+
receive(:run_rasp).with(
100+
Datadog::AppSec::Ext::RASP_SQLI,
101+
{},
102+
{
103+
'server.db.statement' => expected_db_statement,
104+
'server.db.system' => 'postgresql'
105+
},
106+
Datadog.configuration.appsec.waf_timeout
107+
).and_call_original
108+
)
109+
110+
User.where(name: 'Bob').to_a
111+
end
110112

111-
expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
112-
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
113+
it 'calls waf with correct arguments when querying using .find_by_sql' do
114+
expect(Datadog::AppSec.active_context).to(
115+
receive(:run_rasp).with(
116+
Datadog::AppSec::Ext::RASP_SQLI,
117+
{},
118+
{
119+
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
120+
'server.db.system' => 'postgresql'
121+
},
122+
Datadog.configuration.appsec.waf_timeout
123+
).and_call_original
124+
)
125+
126+
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
127+
end
113128

114-
User.where(name: 'Bob').to_a
129+
it 'adds an event to processor context if waf result is a match' do
130+
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
131+
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
132+
)
133+
134+
expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
135+
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
136+
137+
User.where(name: 'Bob').to_a
138+
end
115139
end
116140
end

spec/datadog/appsec/contrib/active_record/sqlite3_adapter_spec.rb

+60-36
Original file line numberDiff line numberDiff line change
@@ -58,46 +58,70 @@
5858
processor.finalize
5959
end
6060

61-
it 'calls waf with correct arguments when querying using .where' do
62-
expect(Datadog::AppSec.active_context).to(
63-
receive(:run_rasp).with(
64-
Datadog::AppSec::Ext::RASP_SQLI,
65-
{},
66-
{
67-
'server.db.statement' => 'SELECT "users".* FROM "users" WHERE "users"."name" = ?',
68-
'server.db.system' => 'sqlite'
69-
},
70-
Datadog.configuration.appsec.waf_timeout
71-
).and_call_original
72-
)
73-
74-
User.where(name: 'Bob').to_a
75-
end
61+
context 'when RASP is disabled' do
62+
before do
63+
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(false)
64+
end
7665

77-
it 'calls waf with correct arguments when querying using .find_by_sql' do
78-
expect(Datadog::AppSec.active_context).to(
79-
receive(:run_rasp).with(
80-
Datadog::AppSec::Ext::RASP_SQLI,
81-
{},
82-
{
83-
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
84-
'server.db.system' => 'sqlite'
85-
},
86-
Datadog.configuration.appsec.waf_timeout
87-
).and_call_original
88-
)
89-
90-
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
66+
it 'does not call waf when querying using .where' do
67+
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)
68+
69+
User.where(name: 'Bob').to_a
70+
end
71+
72+
it 'does not call waf when querying using .find_by_sql' do
73+
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)
74+
75+
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
76+
end
9177
end
9278

93-
it 'adds an event to processor context if waf result is a match' do
94-
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
95-
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
96-
)
79+
context 'when RASP is enabled' do
80+
before do
81+
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(true)
82+
end
83+
84+
it 'calls waf with correct arguments when querying using .where' do
85+
expect(Datadog::AppSec.active_context).to(
86+
receive(:run_rasp).with(
87+
Datadog::AppSec::Ext::RASP_SQLI,
88+
{},
89+
{
90+
'server.db.statement' => 'SELECT "users".* FROM "users" WHERE "users"."name" = ?',
91+
'server.db.system' => 'sqlite'
92+
},
93+
Datadog.configuration.appsec.waf_timeout
94+
).and_call_original
95+
)
96+
97+
User.where(name: 'Bob').to_a
98+
end
9799

98-
expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
99-
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
100+
it 'calls waf with correct arguments when querying using .find_by_sql' do
101+
expect(Datadog::AppSec.active_context).to(
102+
receive(:run_rasp).with(
103+
Datadog::AppSec::Ext::RASP_SQLI,
104+
{},
105+
{
106+
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
107+
'server.db.system' => 'sqlite'
108+
},
109+
Datadog.configuration.appsec.waf_timeout
110+
).and_call_original
111+
)
112+
113+
User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
114+
end
100115

101-
User.where(name: 'Bob').to_a
116+
it 'adds an event to processor context if waf result is a match' do
117+
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
118+
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
119+
)
120+
121+
expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
122+
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
123+
124+
User.where(name: 'Bob').to_a
125+
end
102126
end
103127
end

0 commit comments

Comments
 (0)