Class: Contrast::Agent::ExclusionMatcher

Inherits:
Object
  • Object
show all
Includes:
Components::Interface
Defined in:
lib/contrast/agent/exclusion_matcher.rb

Overview

Exclusions are ways for the User to tell the Agent to ignore sections of the Application. If a request or an event matches one of these, the functions of the Agent are suppressed for that request or event.

Instance Method Summary collapse

Methods included from Components::Interface

included

Constructor Details

#initialize(excl) ⇒ Contrast::Agent::ExclusionMatcher

Create a matcher around an exclusion sent from TeamServer.



19
20
21
22
23
24
25
26
27
# File 'lib/contrast/agent/exclusion_matcher.rb', line 19

def initialize excl
  @exclusion = excl
  @protect = @exclusion.protect
  @assess = @exclusion.assess

  handle_wildcard_input
  handle_wildcard_url
  handle_wildcard_code
end

Instance Method Details

#assess?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/contrast/agent/exclusion_matcher.rb', line 90

def assess?
  @assess
end

#assess_rule?(rule) ⇒ Boolean

Determine if the given rule is excluded by this exclusion. In this case, the ‘assessment_rules` being empty means apply to all rules, not no rules

Parameters:

  • rule
    • the id of the rule which we’re checking for exclusion

Returns:

  • (Boolean)


123
124
125
126
127
128
# File 'lib/contrast/agent/exclusion_matcher.rb', line 123

def assess_rule? rule
  assess? &&
      (@exclusion.assessment_rules.empty? ||
          @exclusion.assessment_rules.include?(rule)
      )
end

#build_regexp(pattern, start_anchor = false, end_anchor = false) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/contrast/agent/exclusion_matcher.rb', line 78

def build_regexp pattern, start_anchor = false, end_anchor = false
  pattern = Contrast::Utils::ObjectShare::CARROT + pattern if start_anchor
  pattern += Contrast::Utils::ObjectShare::DOLLAR_SIGN if end_anchor
  Regexp.compile(pattern)
rescue RegexpError => e
  logger.error('Unable to generate a pattern for exclusion matching.', e, pattern: pattern)
end

#code?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/contrast/agent/exclusion_matcher.rb', line 94

def code?
  @exclusion.type == Contrast::Api::Settings::Exclusion::ExclusionType::CODE
end

#handle_wildcard_codeObject

According to the docs for exclusions, code applies to the entire stacktrace of the caller, and can act as a regexp. Per our user instructions in the Contrast UI, these comparisons must be done at the end of the input. docs.contrastsecurity.com/admin-policymgmt.html#exclude



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/contrast/agent/exclusion_matcher.rb', line 64

def handle_wildcard_code
  return unless @exclusion.denylist&.any?

  @wildcard_exclusions = []
  @exclusion.denylist.each do |code|
    class_name, method_name = code.split(Contrast::Utils::ObjectShare::COLON)
    class_pattern = build_regexp(class_name, false, true)
    method_pattern = build_regexp(method_name)
    next unless class_pattern && method_pattern

    @wildcard_exclusions << [class_pattern, method_pattern]
  end
end

#handle_wildcard_inputObject

According to the docs for exclusions, user input applies to all inputs if the name supplied is an ‘*’ or ‘.*’. The name matcher does NOT support regexp beyond this. docs.contrastsecurity.com/admin-policymgmt.html#exclude



33
34
35
36
37
38
# File 'lib/contrast/agent/exclusion_matcher.rb', line 33

def handle_wildcard_input
  return unless @exclusion.input_name

  @wildcard_input = @exclusion.input_name == '.*' ||
      @exclusion.input_name == Contrast::Utils::ObjectShare::ASTERISK
end

#handle_wildcard_urlObject

According to the docs for exclusions, urls apply to all urls if the url supplied is ‘/.*’ or if the URL mode is all. Otherwise, the URL supplied is to be treated as a regular expression that must match the entire URL against which it is tested. docs.contrastsecurity.com/admin-policymgmt.html#exclude



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/contrast/agent/exclusion_matcher.rb', line 45

def handle_wildcard_url
  @wildcard_url = match_all?
  return if @wildcard_url
  return unless @exclusion.urls&.any?

  @wildcard_url ||= @exclusion.urls.any? { |test| test == '/.*' }
  return if @wildcard_url

  @urls = []
  @exclusion.urls.each do |url|
    url_pattern = build_regexp(url, true, true)
    @urls << url_pattern if url_pattern
  end
end

#match_all?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/contrast/agent/exclusion_matcher.rb', line 102

def match_all?
  @exclusion.urls.nil? || @exclusion.urls.empty?
end

#match_code?(stack_trace) ⇒ Boolean

Returns:

  • (Boolean)


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/contrast/agent/exclusion_matcher.rb', line 130

def match_code? stack_trace
  return false unless code?
  return false if @wildcard_exclusions&.empty?

  @wildcard_exclusions.each do |code|
    class_name = code[0]
    method_name = code[1]
    stack_trace.each do |location|
      next unless location.base_label.match?(method_name)
      next unless location.path.match?(class_name)

      return true
    end
  end

  false
end

#nameObject



98
99
100
# File 'lib/contrast/agent/exclusion_matcher.rb', line 98

def name
  @exclusion.name
end

#protect?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/contrast/agent/exclusion_matcher.rb', line 86

def protect?
  @protect
end

#protection_rule?(rule) ⇒ Boolean

Determine if the given rule is excluded by this exclusion. In this case, the ‘protection_rules` being empty means apply to all rules, not no rules

Parameters:

  • rule
    • the id of the rule which we’re checking for exclusion

Returns:

  • (Boolean)


111
112
113
114
115
116
# File 'lib/contrast/agent/exclusion_matcher.rb', line 111

def protection_rule? rule
  protect? &&
      (@exclusion.protection_rules.empty? ||
          @exclusion.protection_rules.include?(rule)
      )
end