Skip to content

Commit

Permalink
Add appsec.auto_user_instrumentation.mode config
Browse files Browse the repository at this point in the history
  • Loading branch information
Strech committed Feb 6, 2025
1 parent a70cf66 commit 8f00db5
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 14 deletions.
75 changes: 64 additions & 11 deletions lib/datadog/appsec/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,29 @@ module Settings
DEFAULT_OBFUSCATOR_KEY_REGEX = '(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt'
DEFAULT_OBFUSCATOR_VALUE_REGEX = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=[^;]|"\s*:\s*"[^"]+")|bearer\s+[a-z0-9\._\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\w=-]+\.ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}[^\-]+[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*[a-z0-9\/\.+]{100,}'
# rubocop:enable Layout/LineLength

DISABLED_AUTO_USER_INSTRUMENTATION_MODE = 'disabled'
ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE = 'anonymization'
IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE = 'identification'
AUTO_USER_INSTRUMENTATION_MODES = [
DISABLED_AUTO_USER_INSTRUMENTATION_MODE,
ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE,
IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
].freeze
AUTO_USER_INSTRUMENTATION_MODES_ALIASES = {
'ident' => IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE,
'anon' => ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE,
}.freeze

# NOTE: These two constants are deprecated
SAFE_TRACK_USER_EVENTS_MODE = 'safe'
EXTENDED_TRACK_USER_EVENTS_MODE = 'extended'
APPSEC_VALID_TRACK_USER_EVENTS_MODE = [
'safe',
'extended'
SAFE_TRACK_USER_EVENTS_MODE, EXTENDED_TRACK_USER_EVENTS_MODE
].freeze
APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES = [
'1',
'true'
].concat(APPSEC_VALID_TRACK_USER_EVENTS_MODE).freeze
APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES = ['1', 'true'].concat(
APPSEC_VALID_TRACK_USER_EVENTS_MODE
).freeze

def self.extended(base)
base = base.singleton_class unless base.is_a?(Class)
Expand Down Expand Up @@ -149,6 +164,29 @@ def self.add_settings!(base)
end
end

settings :auto_user_instrumentation do
define_method(:enabled?) { get_option(:mode) != DISABLED_AUTO_USER_INSTRUMENTATION_MODE }

option :mode do |o|
o.type :string
o.env 'DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE'
o.default IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
o.setter do |value|
mode = AUTO_USER_INSTRUMENTATION_MODES_ALIASES.fetch(value, value)
next mode if AUTO_USER_INSTRUMENTATION_MODES.include?(mode)

Datadog.logger.warn(
'The appsec.auto_user_instrumentation.mode value provided is not supported. ' \
"Supported values are: #{AUTO_USER_INSTRUMENTATION_MODES.join(' | ')}. " \
"Using default value: #{IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE}."
)

IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE
end
end
end

# DEV-3.0: Remove `track_user_events.enabled` and `track_user_events.mode` options
settings :track_user_events do
option :enabled do |o|
o.default true
Expand All @@ -161,24 +199,39 @@ def self.add_settings!(base)
APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES.include?(env_value.strip.downcase)
end
end
o.after_set do
Core.log_deprecation(key: :appsec_track_user_events_enabled) do
'The appsec.track_user_events.enabled setting has been deprecated for removal. ' \
'Please remove it from your Datadog.configure block and use ' \
'appsec.auto_user_instrumentation.mode instead.'
end
end
end

option :mode do |o|
o.type :string
o.env 'DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING'
o.default 'safe'
o.default SAFE_TRACK_USER_EVENTS_MODE
o.setter do |v|
if APPSEC_VALID_TRACK_USER_EVENTS_MODE.include?(v)
v
elsif v == 'disabled'
'safe'
SAFE_TRACK_USER_EVENTS_MODE
else
Datadog.logger.warn(
'The appsec.track_user_events.mode value provided is not supported.' \
'Supported values are: safe | extended.' \
'Using default value `safe`'
"Supported values are: #{APPSEC_VALID_TRACK_USER_EVENTS_MODE.join(' | ')}." \
"Using default value: #{SAFE_TRACK_USER_EVENTS_MODE}."
)
'safe'

SAFE_TRACK_USER_EVENTS_MODE
end
end
o.after_set do
Core.log_deprecation(key: :appsec_track_user_events_mode) do
'The appsec.track_user_events.mode setting has been deprecated for removal. ' \
'Please remove it from your Datadog.configure block and use ' \
'appsec.auto_user_instrumentation.mode instead.'
end
end
end
Expand Down
22 changes: 19 additions & 3 deletions sig/datadog/appsec/configuration/settings.rbs
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
module Datadog
module AppSec
module Configuration
# Settings
module Settings
extend Datadog::Core::Configuration::Base::ClassMethods
include Datadog::Core::Configuration::Base::InstanceMethods
extend Datadog::Core::Configuration::Options::ClassMethods
include Datadog::Core::Configuration::Options::InstanceMethods

DEFAULT_OBFUSCATOR_KEY_REGEX: ::String

DEFAULT_OBFUSCATOR_VALUE_REGEX: ::String
APPSEC_VALID_TRACK_USER_EVENTS_MODE: ::Array[String]
APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES: ::Array[String]

DISABLED_AUTO_USER_INSTRUMENTATION_MODE: ::String

ANONYMIZATION_AUTO_USER_INSTRUMENTATION_MODE: ::String

IDENTIFICATION_AUTO_USER_INSTRUMENTATION_MODE: ::String

AUTO_USER_INSTRUMENTATION_MODES: ::Array[::String]

AUTO_USER_INSTRUMENTATION_MODES_ALIASES: ::Hash[::String, ::String]

SAFE_TRACK_USER_EVENTS_MODE: ::String

EXTENDED_TRACK_USER_EVENTS_MODE: ::String

APPSEC_VALID_TRACK_USER_EVENTS_MODE: ::Array[::String]

APPSEC_VALID_TRACK_USER_EVENTS_ENABLED_VALUES: ::Array[::String]

def self.extended: (untyped base) -> untyped

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

describe 'track_user_events' do
before { allow(Datadog).to receive(:logger).and_return(spy(Datadog::Core::Logger)) }

describe '#enabled' do
subject(:enabled) { settings.appsec.track_user_events.enabled }

Expand All @@ -479,6 +481,17 @@ def patcher
end
end

context 'when deprication message should be emitted' do
let(:track_user_events_enabled) { 'true' }

it 'writes the deprication message' do
expect(Datadog::Core).to receive(:log_deprecation) do |_, &block|
expect(block.call).to match(/setting has been deprecated for removal/)
end
expect(enabled).to eq(true)
end
end

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

Expand Down Expand Up @@ -562,6 +575,18 @@ def patcher
settings.appsec.track_user_events.mode = track_user_events_mode
end

context 'when deprication message should be emitted' do
let(:track_user_events_mode) { 'extended' }

it 'writes the deprication message' do
expect(Datadog::Core).to receive(:log_deprecation) do |_, &block|
expect(block.call).to match(/setting has been deprecated for removal/)
end

set_appsec_track_user_events_mode
end
end

context 'when given a supported value' do
let(:track_user_events_mode) { 'extended' }

Expand All @@ -582,6 +607,92 @@ def patcher
end
end

describe 'auto_user_instrumentation.mode' do
before { allow(Datadog).to receive(:logger).and_return(logger) }

let(:logger) { instance_double(Datadog::Core::Logger) }

context 'when valid value is set' do
before { settings.appsec.auto_user_instrumentation.mode = 'disabled' }

it { expect(settings.appsec.auto_user_instrumentation.mode).to eq('disabled') }
end

context 'when valid short value is set' do
before { settings.appsec.auto_user_instrumentation.mode = 'anon' }

it 'expands the alias value to the long version' do
expect(settings.appsec.auto_user_instrumentation.mode).to eq('anonymization')
end
end

context 'when invalid value is set' do
it 'sets the value to the default and writes a warning message' do
expect(logger).to receive(:warn).with(/value provided is not supported/)
settings.appsec.auto_user_instrumentation.mode = 'unknown'

expect(settings.appsec.auto_user_instrumentation.mode).to eq('identification')
end
end

context 'when valid DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE is set' do
around do |example|
ClimateControl.modify('DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE' => 'disabled') do
example.run
end
end

it { expect(settings.appsec.auto_user_instrumentation.mode).to eq('disabled') }
end

context 'when valid DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE short value is set' do
around do |example|
ClimateControl.modify('DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE' => 'anon') do
example.run
end
end

it 'expands the alias value to the long version' do
expect(settings.appsec.auto_user_instrumentation.mode).to eq('anonymization')
end
end

context 'when invalid DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE is set' do
around do |example|
ClimateControl.modify('DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE' => 'unknown') do
example.run
end
end

it 'sets the value to the default and writes a warning message' do
expect(logger).to receive(:warn).with(/value provided is not supported/)
expect(settings.appsec.auto_user_instrumentation.mode).to eq('identification')
end
end

context 'when no value or env variable is set' do
it { expect(settings.appsec.auto_user_instrumentation.mode).to eq('identification') }
end
end

describe 'auto_user_instrumentation.enabled?' do
context 'when explicitly disabled' do
before { settings.appsec.auto_user_instrumentation.mode = 'disabled' }

it { expect(settings.appsec.auto_user_instrumentation).not_to be_enabled }
end

context 'when explicitly enabled' do
before { settings.appsec.auto_user_instrumentation.mode = 'identification' }

it { expect(settings.appsec.auto_user_instrumentation).to be_enabled }
end

context 'when default value is used' do
it { expect(settings.appsec.auto_user_instrumentation).to be_enabled }
end
end

describe 'block' do
describe 'templates' do
[
Expand Down

0 comments on commit 8f00db5

Please sign in to comment.