class Sqreen::Rules::WAFCB
Constants
- ERROR_CODES
- INFINITE_BUDGET_US
will be converted to a long, so better not to overflow
- MAX_FIXNUM
2^30 -1 or 2^62 -1
Attributes
binding_accessors[R]
max_run_budget_us[R]
waf_rule_name[R]
Public Class Methods
finalizer(rule_name)
click to toggle source
# File lib/sqreen/rules/waf_cb.rb, line 125 def self.finalizer(rule_name) lambda do |object_id| return unless WAFCB.libsqreen? ::LibSqreen::WAF.delete(waf_rule_name) Sqreen.log.debug("WAF rule #{rule_name} deleted, from #<#{name}:0x#{object_id.to_s(16).rjust(16, '0')}>") end end
libsqreen?()
click to toggle source
# File lib/sqreen/rules/waf_cb.rb, line 24 def self.libsqreen? Sqreen::Dependency::LibSqreen.required? end
new(*args)
click to toggle source
Calls superclass method
Sqreen::Rules::RuleCB::new
# File lib/sqreen/rules/waf_cb.rb, line 34 def initialize(*args) super(*args) @overtimeable = false unless WAFCB.libsqreen? && WAFCB.waf? Sqreen.log.warn('libsqreen gem with waf not found') return end unless @data['values'] Sqreen.log.warn('no values in data') return end ::LibSqreen::WAF.logger = Sqreen.log name = format("%s_%s", SecureRandom.uuid, rule_name) unless @data['values']['waf_rules'] && (::LibSqreen::WAF[name] = @data['values']['waf_rules']) Sqreen.log.error("WAF rule #{name} failed to be set, from #<#{self.class.name}:0x#{object_id.to_s(16).rjust(16, '0')}>") return end @waf_rule_name = name Sqreen.log.debug("WAF rule #{name} set, from #<#{self.class.name}:0x#{object_id.to_s(16).rjust(16, '0')}>") @binding_accessors = @data['values'].fetch('binding_accessors', []).each_with_object({}) do |e, h| h[e] = BindingAccessor.new(e) end # 0 for using defaults (PW_RUN_TIMEOUT) @max_run_budget_us = (@data['values'].fetch('max_budget_ms', 0) * 1000).to_i @max_run_budget_us = INFINITE_BUDGET_US if @max_run_budget_us >= INFINITE_BUDGET_US Sqreen.log.debug { "Max WAF run budget for #{@waf_rule_name} set to #{@max_run_budget_us} us" } ObjectSpace.define_finalizer(self, WAFCB.finalizer(@waf_rule_name.dup)) end
waf?()
click to toggle source
# File lib/sqreen/rules/waf_cb.rb, line 28 def self.waf? Sqreen::Dependency.const_exist?('LibSqreen::WAF') end
Public Instance Methods
pre(instance, args, budget)
click to toggle source
# File lib/sqreen/rules/waf_cb.rb, line 71 def pre(instance, args, budget) return unless WAFCB.libsqreen? && WAFCB.waf? request = framework.request return if !waf_rule_name || !request env = [binding, framework, instance, args] start = Sqreen.time if budget capper = Sqreen::Util::Capper.new(string_size_cap: 4096, size_cap: 150, depth_cap: 10) waf_args = binding_accessors.each_with_object({}) do |(e, b), h| h[e] = capper.call(b.resolve(*env)) end waf_args = Sqreen::Kit::StringSanitizer.sanitize(waf_args) if budget rem_budget_s = budget - (Sqreen.time - start) return advise_action(nil) if rem_budget_s <= 0.0 waf_gen_budget_us = [(rem_budget_s * 1_000_000).to_i, MAX_FIXNUM].min else # no budget waf_gen_budget_us = INFINITE_BUDGET_US end action, data = ::LibSqreen::WAF.run(waf_rule_name, waf_args, waf_gen_budget_us, @max_run_budget_us) case action when :monitor record_event({ waf_data: data }) advise_action(nil) when :block record_event({ waf_data: data }) advise_action(:raise) when :good advise_action(nil) when :timeout Sqreen.log.debug("WAF over time budget: #{action}") advise_action(nil) when :invalid_call Sqreen.log.debug("Error from waf: #{action}") advise_action(nil) raise Sqreen::WAFError.new(waf_rule_name, action, data, waf_args) when :invalid_rule, :invalid_flow, :no_rule Sqreen.log.debug("error from waf: #{action}") advise_action(nil) raise Sqreen::WAFError.new(waf_rule_name, action, data) else Sqreen.log.warn("unexpected action returned from waf") advise_action(nil) end end
record_exception(exception, infos = {}, at = Time.now.utc)
click to toggle source
Calls superclass method
Sqreen::Rules::RuleCB#record_exception
# File lib/sqreen/rules/waf_cb.rb, line 134 def record_exception(exception, infos = {}, at = Time.now.utc) infos.merge!(waf_infos(exception)) if exception.is_a?(Sqreen::WAFError) super(exception, infos, at) end
Private Instance Methods
waf_infos(e)
click to toggle source
see github.com/sqreen/TechDoc/blob/master/content/specs/spec000016-waf-integration.md#error-management
# File lib/sqreen/rules/waf_cb.rb, line 142 def waf_infos(e) { waf: { waf_rule: e.rule_name, error_code: ERROR_CODES[e.error], }.tap do |r| r[:error_data] = e.data if e.data r[:args] = e.args if e.arg end, } end