Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[APPSEC-55378] Extract processor context into separate file #4023

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 0 additions & 67 deletions lib/datadog/appsec/processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,6 @@ module Datadog
module AppSec
# Processor integrates libddwaf into datadog/appsec
class Processor
# Context manages a sequence of runs
class Context
attr_reader :time_ns, :time_ext_ns, :timeouts, :events

def initialize(processor)
@context = Datadog::AppSec::WAF::Context.new(processor.send(:handle))
@time_ns = 0.0
@time_ext_ns = 0.0
@timeouts = 0
@events = []
@run_mutex = Mutex.new
end

def run(input, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
@run_mutex.lock

start_ns = Core::Utils::Time.get_time(:nanosecond)

input.reject! do |_, v|
case v
when TrueClass, FalseClass
false
else
v.nil? ? true : v.empty?
end
end

_code, res = @context.run(input, timeout)

stop_ns = Core::Utils::Time.get_time(:nanosecond)

# these updates are not thread safe and should be protected
@time_ns += res.total_runtime
@time_ext_ns += (stop_ns - start_ns)
@timeouts += 1 if res.timeout

res
ensure
@run_mutex.unlock
end

def extract_schema
return unless extract_schema?

input = {
'waf.context.processor' => {
'extract-schema' => true
}
}

_code, res = @context.run(input, WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)

res
end

def finalize
@context.finalize
end

private

def extract_schema?
Datadog.configuration.appsec.api_security.enabled &&
Datadog.configuration.appsec.api_security.sample_rate.sample?
end
end

attr_reader :diagnostics, :addresses

def initialize(ruleset:, telemetry:)
Expand Down
74 changes: 74 additions & 0 deletions lib/datadog/appsec/processor/context.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

module Datadog
module AppSec
class Processor
# Context manages a sequence of runs
class Context
attr_reader :time_ns, :time_ext_ns, :timeouts, :events

def initialize(processor)
@context = Datadog::AppSec::WAF::Context.new(processor.send(:handle))
@time_ns = 0.0
@time_ext_ns = 0.0
@timeouts = 0
@events = []
@run_mutex = Mutex.new
end

def run(input, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
@run_mutex.lock

start_ns = Core::Utils::Time.get_time(:nanosecond)

input.reject! do |_, v|
case v
when TrueClass, FalseClass
false
else
v.nil? ? true : v.empty?
end
end

_code, res = @context.run(input, timeout)

stop_ns = Core::Utils::Time.get_time(:nanosecond)

# these updates are not thread safe and should be protected
@time_ns += res.total_runtime
@time_ext_ns += (stop_ns - start_ns)
@timeouts += 1 if res.timeout

res
ensure
@run_mutex.unlock
end

def extract_schema
return unless extract_schema?

input = {
'waf.context.processor' => {
'extract-schema' => true
}
}

_code, res = @context.run(input, WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)

res
end

def finalize
@context.finalize
end

private

def extract_schema?
Datadog.configuration.appsec.api_security.enabled &&
Datadog.configuration.appsec.api_security.sample_rate.sample?
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/datadog/appsec/scope.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require_relative 'processor'
require_relative 'processor/context'

module Datadog
module AppSec
Expand Down
30 changes: 4 additions & 26 deletions sig/datadog/appsec/processor.rbs
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
module Datadog
module AppSec
class Processor
class Context
type event = untyped
type data = WAF::data

attr_reader time_ns: ::Float
attr_reader time_ext_ns: ::Float
attr_reader timeouts: ::Integer
attr_reader events: ::Array[event]

@context: WAF::Context

@run_mutex: ::Thread::Mutex

def initialize: (Processor processor) -> void
def run: (Hash[untyped, untyped] input, ?::Integer timeout) -> WAF::Result
def extract_schema: () -> WAF::Result?
def finalize: () -> void

private
def extract_schema?: () -> bool
end

def self.active_context: () -> Context

private

attr_reader diagnostics: untyped
attr_reader addresses: untyped
attr_reader diagnostics: WAF::LibDDWAF::Object?
attr_reader addresses: ::Array[::String]

@handle: WAF::Handle
@ruleset: ::Hash[::String, untyped]
@addresses: ::Array[::String]

def initialize: (ruleset: ::Hash[untyped, untyped], telemetry: Datadog::Core::Telemetry::Component) -> void
def initialize: (ruleset: ::Hash[untyped, untyped], telemetry: Core::Telemetry::Component) -> void
def ready?: () -> bool
def finalize: () -> void

Expand All @@ -44,7 +22,7 @@ module Datadog

def require_libddwaf: () -> bool
def libddwaf_provides_waf?: () -> bool
def create_waf_handle: (Datadog::Core::Configuration::Settings::_AppSec settings, ::Hash[String, untyped] ruleset) -> bool
def create_waf_handle: (Core::Configuration::Settings::_AppSec settings, ::Hash[String, untyped] ruleset) -> bool
def libddwaf_platform: () -> ::String
def ruby_platforms: () -> ::Array[::String]
end
Expand Down
27 changes: 27 additions & 0 deletions sig/datadog/appsec/processor/context.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Datadog
module AppSec
class Processor
class Context
type event = untyped
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think event is a ::Hash[Symbol, untyped] according to where it's used (e.g.: https://github.com/DataDog/dd-trace-rb/blob/master/lib/datadog/appsec/contrib/rack/gateway/watcher.rb#L47), I'm not sure it is more useful than declaring it as untyped though

Suggested change
type event = untyped
type event = ::Hash[Symbol, untyped]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, I'm not sure that I fully understand the code to change it now, we have events from the WAF module too and so far they are always empty.

I think we can definitely change it as soon as we 100% sure.

type data = WAF::data

attr_reader time_ns: ::Float
attr_reader time_ext_ns: ::Float
attr_reader timeouts: ::Integer
attr_reader events: ::Array[event]

@context: WAF::Context

@run_mutex: ::Thread::Mutex

def initialize: (Processor processor) -> void
def run: (Hash[untyped, untyped] input, ?::Integer timeout) -> WAF::Result
def extract_schema: () -> WAF::Result?
def finalize: () -> void

private
def extract_schema?: () -> bool
end
end
end
end
Loading
Loading