Class: Sqreen::Rules::WAFCB
- Inherits:
-
RuleCB
- Object
- CB
- FrameworkCB
- RuleCB
- Sqreen::Rules::WAFCB
- Defined in:
- lib/sqreen/rules/waf_cb.rb
Constant Summary collapse
- MAX_FIXNUM =
2^30 -1 or 2^62 -1
1.size == 4 ? 1_073_741_823 : 4_611_686_018_427_387_903
- INFINITE_BUDGET_US =
will be converted to a long, so better not to overflow
MAX_FIXNUM
Constants inherited from RuleCB
Constants included from CallCountable
CallCountable::COUNT_CALLS, CallCountable::FAILING, CallCountable::POST, CallCountable::PRE
Constants inherited from CB
Instance Attribute Summary collapse
-
#binding_accessors ⇒ Object
readonly
Returns the value of attribute binding_accessors.
-
#max_run_budget_us ⇒ Object
readonly
Returns the value of attribute max_run_budget_us.
-
#waf_rule_name ⇒ Object
readonly
Returns the value of attribute waf_rule_name.
Attributes inherited from RuleCB
Attributes included from CallCountable
#call_count_interval, #call_counts
Attributes inherited from FrameworkCB
Attributes inherited from CB
#klass, #method, #overtimeable
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(*args) ⇒ WAFCB
constructor
A new instance of WAFCB.
- #pre(instance, args, budget) ⇒ Object
- #record_exception(exception, infos = {}, at = Time.now.utc) ⇒ Object
Methods inherited from RuleCB
#advise_action, #overtime!, #priority, #record_event, #rule_name, #rulespack_id
Methods included from CallCountable
#count_callback_calls, #failing_with_count, #post_with_count, #pre_with_count
Methods included from Conditionable
#condition_callbacks, #failing_with_conditions, #post_with_conditions, #pre_with_conditions
Methods inherited from FrameworkCB
#record_observation, #whitelisted?
Methods inherited from CB
#failing?, #framework, #overtime!, #post?, #pre?, #priority, #to_s, #whitelisted?
Constructor Details
#initialize(*args) ⇒ WAFCB
Returns a new instance of WAFCB.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# 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 |
Instance Attribute Details
#binding_accessors ⇒ Object (readonly)
Returns the value of attribute binding_accessors.
32 33 34 |
# File 'lib/sqreen/rules/waf_cb.rb', line 32 def binding_accessors @binding_accessors end |
#max_run_budget_us ⇒ Object (readonly)
Returns the value of attribute max_run_budget_us.
32 33 34 |
# File 'lib/sqreen/rules/waf_cb.rb', line 32 def max_run_budget_us @max_run_budget_us end |
#waf_rule_name ⇒ Object (readonly)
Returns the value of attribute waf_rule_name.
32 33 34 |
# File 'lib/sqreen/rules/waf_cb.rb', line 32 def waf_rule_name @waf_rule_name end |
Class Method Details
.finalizer(rule_name) ⇒ Object
125 126 127 128 129 130 131 132 |
# 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(rule_name) Sqreen.log.debug("WAF rule #{rule_name} deleted, from #<#{name}:0x#{object_id.to_s(16).rjust(16, '0')}>") end end |
.libsqreen? ⇒ Boolean
24 25 26 |
# File 'lib/sqreen/rules/waf_cb.rb', line 24 def self.libsqreen? Sqreen::Dependency::LibSqreen.required? end |
.waf? ⇒ Boolean
28 29 30 |
# File 'lib/sqreen/rules/waf_cb.rb', line 28 def self.waf? Sqreen::Dependency.const_exist?('LibSqreen::WAF') end |
Instance Method Details
#pre(instance, args, budget) ⇒ Object
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 114 115 116 117 118 119 120 121 122 123 |
# 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 |