Class: Datadog::AppSec::Context Private

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/appsec/context.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Request-bound context providing threat detection interface.

Activated at the start of a request (see Contrib::Rack::RequestMiddleware) and shared across all instrumentations within that request’s lifecycle.

Accumulates security events, metrics, and state needed for coordinated threat detection.

Constant Summary collapse

ActiveContextError =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Steep: github.com/soutaro/steep/issues/1880

Class.new(StandardError)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(trace, span, waf_runner) ⇒ Context

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Context.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/datadog/appsec/context.rb', line 54

def initialize(trace, span, waf_runner)
  @trace = trace
  @span = span
  @waf_runner = waf_runner
  @metrics = Metrics::Collector.new
  @downstream_body_sampler = CounterSampler.new(
    Datadog.configuration.appsec.api_security.downstream_body_analysis.sample_rate
  )
  @state = {
    events: [],
    interrupted: false,
    downstream_body_analyzed_count: 0
  }
end

Instance Attribute Details

#downstream_body_samplerObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Sampler for downstream HTTP request/response body analysis.



33
34
35
# File 'lib/datadog/appsec/context.rb', line 33

def downstream_body_sampler
  @downstream_body_sampler
end

#spanObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

TODO: add delegators for active trace span



23
24
25
# File 'lib/datadog/appsec/context.rb', line 23

def span
  @span
end

#stateObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Shared mutable storage for counters, flags, and data accumulated during the request’s lifecycle.

NOTE: This attribute is a subject to change, but in a current form

it's a `Hash`-like structure.


30
31
32
# File 'lib/datadog/appsec/context.rb', line 30

def state
  @state
end

#traceObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

TODO: add delegators for active trace span



23
24
25
# File 'lib/datadog/appsec/context.rb', line 23

def trace
  @trace
end

Class Method Details

.activate(context) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Raises:

  • (ArgumentError)


36
37
38
39
40
41
# File 'lib/datadog/appsec/context.rb', line 36

def activate(context)
  raise ArgumentError, 'not a Datadog::AppSec::Context' unless context.instance_of?(Context)
  raise ActiveContextError, 'another context is active, nested contexts are not supported' if active

  Thread.current[Ext::ACTIVE_CONTEXT_KEY] = context
end

.activeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



49
50
51
# File 'lib/datadog/appsec/context.rb', line 49

def active
  Thread.current[Ext::ACTIVE_CONTEXT_KEY]
end

.deactivateObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



43
44
45
46
47
# File 'lib/datadog/appsec/context.rb', line 43

def deactivate
  active&.finalize!
ensure
  Thread.current[Ext::ACTIVE_CONTEXT_KEY] = nil
end

Instance Method Details

#eventsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



85
86
87
# File 'lib/datadog/appsec/context.rb', line 85

def events
  @state[:events]
end

#export_metricsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



114
115
116
117
118
119
# File 'lib/datadog/appsec/context.rb', line 114

def export_metrics
  return if @span.nil?

  Metrics::Exporter.export_waf_metrics(@metrics.waf, @span)
  Metrics::Exporter.export_rasp_metrics(@metrics.rasp, @span)
end

#export_request_telemetryObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



121
122
123
124
125
126
# File 'lib/datadog/appsec/context.rb', line 121

def export_request_telemetry
  return if @trace.nil?

  Metrics::TelemetryExporter.export_waf_request_metrics(@metrics.waf, self)
  Metrics::TelemetryExporter.export_api_security_metrics(self)
end

#extract_schema!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



105
106
107
108
109
110
111
112
# File 'lib/datadog/appsec/context.rb', line 105

def extract_schema!
  waf_result = @waf_runner.run({'waf.context.processor' => {'extract-schema' => true}}, {})
  security_event = AppSec::SecurityEvent.new(waf_result, trace: trace, span: span)

  @state[:schema_extracted] = security_event.schema?

  events.push(security_event)
end

#finalize!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



128
129
130
# File 'lib/datadog/appsec/context.rb', line 128

def finalize!
  @waf_runner.finalize!
end

#interrupted?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


93
94
95
# File 'lib/datadog/appsec/context.rb', line 93

def interrupted?
  @state[:interrupted]
end

#mark_as_interrupted!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



89
90
91
# File 'lib/datadog/appsec/context.rb', line 89

def mark_as_interrupted!
  @state[:interrupted] = true
end

#run_rasp(type, persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT, phase: nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



76
77
78
79
80
81
82
83
# File 'lib/datadog/appsec/context.rb', line 76

def run_rasp(type, persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT, phase: nil)
  result = @waf_runner.run(persistent_data, ephemeral_data, timeout)

  Metrics::Telemetry.report_rasp(type, result, phase: phase)
  @metrics.record_rasp(result, type: type, phase: phase)

  result
end

#run_waf(persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



69
70
71
72
73
74
# File 'lib/datadog/appsec/context.rb', line 69

def run_waf(persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
  result = @waf_runner.run(persistent_data, ephemeral_data, timeout)

  @metrics.record_waf(result)
  result
end

#waf_runner_known_addressesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



101
102
103
# File 'lib/datadog/appsec/context.rb', line 101

def waf_runner_known_addresses
  @waf_runner.waf_addresses
end

#waf_runner_ruleset_versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



97
98
99
# File 'lib/datadog/appsec/context.rb', line 97

def waf_runner_ruleset_version
  @waf_runner.ruleset_version
end