Class: Datadog::AppSec::WAF::Context

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

Overview

Constant Summary collapse

EMPTY_RESULT =
{
  "events" => [],     #: WAF::events
  "actions" => {},    #: WAF::actions
  "attributes" => {}, #: WAF::attributes
  "duration" => 0,
  "timeout" => false,
  "keep" => false
}.freeze
SUCCESS_RESULT_CODES =
%i[ddwaf_ok ddwaf_match].freeze
RESULT_CODE_TO_STATUS =
{
  ddwaf_ok: :ok,
  ddwaf_match: :match,
  ddwaf_err_internal: :err_internal,
  ddwaf_err_invalid_object: :err_invalid_object,
  ddwaf_err_invalid_argument: :err_invalid_argument
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(context_ptr) ⇒ Context

Returns a new instance of Context.



26
27
28
# File 'lib/datadog/appsec/waf/context.rb', line 26

def initialize(context_ptr)
  @context_ptr = context_ptr
end

Instance Method Details

#finalize!Object

Destroys the WAF context and sets the pointer to nil.

The instance becomes unusable after this method is called.



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/datadog/appsec/waf/context.rb', line 33

def finalize!
  context_ptr_to_destroy = @context_ptr
  @context_ptr = nil

  retained.each do |retained_obj|
    next unless retained_obj.is_a?(LibDDWAF::Object)

    LibDDWAF.ddwaf_object_free(retained_obj)
  end

  retained.clear
  LibDDWAF.ddwaf_context_destroy(context_ptr_to_destroy)
end

#run(persistent_data, ephemeral_data, timeout = LibDDWAF::DDWAF_RUN_TIMEOUT) ⇒ Result

Runs the WAF context with the given persistent and ephemeral data.

Returns:

  • (Result)

    the result of the WAF run

Raises:

  • (ConversionError)

    if the conversion of persistent or ephemeral data fails

  • (LibDDWAFError)

    if libddwaf could not create the result object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/datadog/appsec/waf/context.rb', line 53

def run(persistent_data, ephemeral_data, timeout = LibDDWAF::DDWAF_RUN_TIMEOUT)
  ensure_pointer_presence!

  persistent_data_obj = Converter.ruby_to_object(
    persistent_data,
    max_container_size: LibDDWAF::DDWAF_MAX_CONTAINER_SIZE,
    max_container_depth: LibDDWAF::DDWAF_MAX_CONTAINER_DEPTH,
    max_string_length: LibDDWAF::DDWAF_MAX_STRING_LENGTH,
    coerce: false
  )
  if persistent_data_obj.null?
    raise ConversionError, "Could not convert persistent data: #{persistent_data.inspect}"
  end

  # retain C objects in memory for subsequent calls to run
  retain(persistent_data_obj)

  ephemeral_data_obj = Converter.ruby_to_object(
    ephemeral_data,
    max_container_size: LibDDWAF::DDWAF_MAX_CONTAINER_SIZE,
    max_container_depth: LibDDWAF::DDWAF_MAX_CONTAINER_DEPTH,
    max_string_length: LibDDWAF::DDWAF_MAX_STRING_LENGTH,
    coerce: false
  )
  if ephemeral_data_obj.null?
    raise ConversionError, "Could not convert ephemeral data: #{ephemeral_data.inspect}"
  end

  result_obj = LibDDWAF::Object.new
  raise LibDDWAFError, "Could not create result object" if result_obj.null?

  code = LibDDWAF.ddwaf_run(@context_ptr, persistent_data_obj, ephemeral_data_obj, result_obj, timeout)
  result = Converter.object_to_ruby(result_obj)

  # NOTE: In case of the error, `libddwaf` will not "fill" the result
  #       object, so it will be empty and the conversion of it will return
  #       `nil`, but that is not a conversion issue.
  if SUCCESS_RESULT_CODES.include?(code) && result.nil?
    raise ConversionError, "Could not convert result into object: #{code}"
  end

  result ||= EMPTY_RESULT
  result = Result.new(
    status: RESULT_CODE_TO_STATUS[code],
    events: result["events"],
    actions: result["actions"],
    attributes: result["attributes"],
    duration: result["duration"],
    timeout: result["timeout"],
    keep: result["keep"]
  )

  if persistent_data_obj.truncated? || ephemeral_data_obj.truncated?
    result.mark_input_truncated!
  end

  result
ensure
  LibDDWAF.ddwaf_object_free(result_obj) if result_obj
  LibDDWAF.ddwaf_object_free(ephemeral_data_obj) if ephemeral_data_obj
end