Skip to content

Commit

Permalink
Merge branch 'master' into change-system-tests-workflow-run-conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
Strech authored Jan 24, 2025
2 parents 83716d9 + a72b341 commit f2c2b98
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 114 deletions.
4 changes: 4 additions & 0 deletions lib/datadog/appsec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ def enabled?
Datadog.configuration.appsec.enabled
end

def rasp_enabled?
Datadog.configuration.appsec.rasp_enabled
end

def active_context
Datadog::AppSec::Context.active
end
Expand Down
9 changes: 9 additions & 0 deletions lib/datadog/appsec/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ def self.add_settings!(base)
end
end

# RASP or Runtime Application Self-Protection
# is a collection of techniques and heuristics aimed at detecting malicious inputs and preventing
# any potential side-effects on the application resulting from the use of said malicious inputs.
option :rasp_enabled do |o|
o.type :bool, nilable: true
o.env 'DD_APPSEC_RASP_ENABLED'
o.default true
end

option :ruleset do |o|
o.env 'DD_APPSEC_RULES'
o.default :recommended
Expand Down
2 changes: 2 additions & 0 deletions lib/datadog/appsec/contrib/active_record/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ module Instrumentation
module_function

def detect_sql_injection(sql, adapter_name)
return unless AppSec.rasp_enabled?

context = AppSec.active_context
return unless context

Expand Down
22 changes: 22 additions & 0 deletions spec/datadog/appsec/configuration/settings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ def patcher
end
end

describe '#rasp_enabled' do
context 'when DD_APPSEC_RASP_ENABLED' do
around do |example|
ClimateControl.modify('DD_APPSEC_RASP_ENABLED' => rasp_enabled_env_var) do
example.run
end
end

context 'is not defined' do
let(:rasp_enabled_env_var) { nil }

it { expect(settings.appsec.rasp_enabled).to eq(true) }
end

context 'is defined' do
let(:rasp_enabled_env_var) { 'false' }

it { expect(settings.appsec.rasp_enabled).to eq(false) }
end
end
end

describe '#instrument' do
let(:registry) { {} }
let(:integration_name) { :fake }
Expand Down
96 changes: 60 additions & 36 deletions spec/datadog/appsec/contrib/active_record/mysql2_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,46 +64,70 @@
processor.finalize
end

it 'calls waf with correct arguments when querying using .where' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT `users`.* FROM `users` WHERE `users`.`name` = 'Bob'",
'server.db.system' => 'mysql2'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.where(name: 'Bob').to_a
end
context 'when RASP is disabled' do
before do
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(false)
end

it 'calls waf with correct arguments when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
'server.db.system' => 'mysql2'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
it 'does not call waf when querying using .where' do
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)

User.where(name: 'Bob').to_a
end

it 'does not call waf when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
end
end

it 'adds an event to processor context if waf result is a match' do
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
)
context 'when RASP is enabled' do
before do
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(true)
end

it 'calls waf with correct arguments when querying using .where' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT `users`.* FROM `users` WHERE `users`.`name` = 'Bob'",
'server.db.system' => 'mysql2'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.where(name: 'Bob').to_a
end

expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
it 'calls waf with correct arguments when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
'server.db.system' => 'mysql2'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
end

User.where(name: 'Bob').to_a
it 'adds an event to processor context if waf result is a match' do
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
)

expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original

User.where(name: 'Bob').to_a
end
end
end
108 changes: 66 additions & 42 deletions spec/datadog/appsec/contrib/active_record/postgresql_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,52 +65,76 @@
processor.finalize
end

it 'calls waf with correct arguments when querying using .where' do
expected_db_statement = if PlatformHelpers.jruby?
'SELECT "users".* FROM "users" WHERE "users"."name" = ?'
else
'SELECT "users".* FROM "users" WHERE "users"."name" = $1'
end

expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => expected_db_statement,
'server.db.system' => 'postgresql'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.where(name: 'Bob').to_a
end
context 'when RASP is disabled' do
before do
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(false)
end

it 'calls waf with correct arguments when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
'server.db.system' => 'postgresql'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
it 'does not call waf when querying using .where' do
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)

User.where(name: 'Bob').to_a
end

it 'does not call waf when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
end
end

it 'adds an event to processor context if waf result is a match' do
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
)
context 'when RASP is enabled' do
before do
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(true)
end

it 'calls waf with correct arguments when querying using .where' do
expected_db_statement = if PlatformHelpers.jruby?
'SELECT "users".* FROM "users" WHERE "users"."name" = ?'
else
'SELECT "users".* FROM "users" WHERE "users"."name" = $1'
end

expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => expected_db_statement,
'server.db.system' => 'postgresql'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.where(name: 'Bob').to_a
end

expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
it 'calls waf with correct arguments when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
'server.db.system' => 'postgresql'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
end

User.where(name: 'Bob').to_a
it 'adds an event to processor context if waf result is a match' do
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
)

expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original

User.where(name: 'Bob').to_a
end
end
end
96 changes: 60 additions & 36 deletions spec/datadog/appsec/contrib/active_record/sqlite3_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,46 +58,70 @@
processor.finalize
end

it 'calls waf with correct arguments when querying using .where' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => 'SELECT "users".* FROM "users" WHERE "users"."name" = ?',
'server.db.system' => 'sqlite'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.where(name: 'Bob').to_a
end
context 'when RASP is disabled' do
before do
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(false)
end

it 'calls waf with correct arguments when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
'server.db.system' => 'sqlite'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
it 'does not call waf when querying using .where' do
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)

User.where(name: 'Bob').to_a
end

it 'does not call waf when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).not_to receive(:run_rasp)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
end
end

it 'adds an event to processor context if waf result is a match' do
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
)
context 'when RASP is enabled' do
before do
allow(Datadog::AppSec).to receive(:rasp_enabled?).and_return(true)
end

it 'calls waf with correct arguments when querying using .where' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => 'SELECT "users".* FROM "users" WHERE "users"."name" = ?',
'server.db.system' => 'sqlite'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.where(name: 'Bob').to_a
end

expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original
it 'calls waf with correct arguments when querying using .find_by_sql' do
expect(Datadog::AppSec.active_context).to(
receive(:run_rasp).with(
Datadog::AppSec::Ext::RASP_SQLI,
{},
{
'server.db.statement' => "SELECT * FROM users WHERE name = 'Bob'",
'server.db.system' => 'sqlite'
},
Datadog.configuration.appsec.waf_timeout
).and_call_original
)

User.find_by_sql("SELECT * FROM users WHERE name = 'Bob'").to_a
end

User.where(name: 'Bob').to_a
it 'adds an event to processor context if waf result is a match' do
result = Datadog::AppSec::SecurityEngine::Result::Match.new(
events: [], actions: {}, derivatives: {}, timeout: false, duration_ns: 0, duration_ext_ns: 0
)

expect(Datadog::AppSec.active_context).to receive(:run_rasp).and_return(result)
expect(Datadog::AppSec.active_context.events).to receive(:<<).and_call_original

User.where(name: 'Bob').to_a
end
end
end

0 comments on commit f2c2b98

Please sign in to comment.