Class: Contrast::Agent::Assess::Policy::PolicyNode
- Inherits:
-
Patching::Policy::PolicyNode
- Object
- Patching::Policy::PolicyNode
- Contrast::Agent::Assess::Policy::PolicyNode
- Defined in:
- lib/contrast/agent/assess/policy/policy_node.rb
Overview
This class functions to translate our policy.json into an actionable Ruby object, allowing for dynamic patching over hardcoded patching.
Direct Known Subclasses
Constant Summary collapse
- JSON_TAGS =
'tags'
- JSON_DATAFLOW =
'dataflow'
- JSON_SOURCE =
The keys used to read from policy.json to create the individual policy nodes. These are common across node types
'source'
- ALL_TYPE =
'A'
- JSON_TARGET =
'target'
- TO_MARKER =
'2'
- ORIGINAL_OBJECT_METHODS =
Here are all methods that can use original objects without mutation the source. For methods with REMOVE action, their (!) bang alternative is not listed, since this methods tends to mutate the original (shortens it’s length, remove special symbols..) and causes mismatch in tags range representation of the target. In short preshift is needed.
%i[ capitalize capitalize! chomp to_s to_str downcase downcase! lstrip strip upcase! upcase ].cs__freeze
- TO_S =
%w[to_s to_str].cs__freeze
- RESPONSE_SOURCES =
Here are all Responses that will be tracked as sources, or methods they use, like body.
%w[Net::HTTPResponse Rack::Response Sinatra::Response].cs__freeze
Constants inherited from Patching::Policy::PolicyNode
Patching::Policy::PolicyNode::JSON_CLASS_NAME, Patching::Policy::PolicyNode::JSON_INSTANCE_METHOD, Patching::Policy::PolicyNode::JSON_METHOD_NAME, Patching::Policy::PolicyNode::JSON_METHOD_SCOPE, Patching::Policy::PolicyNode::JSON_METHOD_VISIBILITY, Patching::Policy::PolicyNode::JSON_PROPERTIES
Instance Attribute Summary collapse
- #source_string ⇒ String readonly
-
#sources ⇒ Object
readonly
Returns the value of attribute sources.
- #tags ⇒ Set<String>
- #target_string ⇒ String
- #targets ⇒ Array<String> readonly
- #type ⇒ Symbol
Attributes inherited from Patching::Policy::PolicyNode
#class_name, #instance_method, #method_name, #method_scope, #method_visibility, #properties
Instance Method Summary collapse
-
#add_property(name, value) ⇒ Object
Sometimes we need to tie information to an event.
-
#assign_on_bang_check(policy_hash) ⇒ Object
If we have KEEP action on String, and the method is to_s, that method would return self: String#to_s => self or string.
-
#build_action ⇒ Object
Convert our action, built from our source and target, into the TS appropriate action.
- #feature ⇒ String
- #get_property(name) ⇒ String
-
#initialize(policy_hash = {}) ⇒ PolicyNode
constructor
A new instance of PolicyNode.
- #node_class ⇒ String
- #node_type ⇒ Symbol
-
#response_source_node? ⇒ Boolean
This method will check if the policy node is for response method.
-
#use_original_object? ⇒ Boolean
This method will check if a method is fit to use it’s original object and that the method is without bang - it does not change the source, but rather creates a copy of it.
-
#use_original_on_bang_method? ⇒ Boolean
This method will check if a method is fit to use it’s original object and that the target return is the same as object - a bang method modifying the source.
-
#use_response_as_source? ⇒ Boolean
This method will check if policy is fit to use response as source.
-
#validate ⇒ Object
Don’t let nodes be created that will be missing things we need later on.
-
#validate_tags ⇒ Object
TeamServer is picky.
Methods included from Components::Logger::InstanceMethods
Methods inherited from Patching::Policy::PolicyNode
Methods included from Components::Scope::InstanceMethods
#contrast_enter_method_scopes!, #contrast_exit_method_scopes!, #with_app_scope, #with_contrast_scope, #with_deserialization_scope, #with_split_scope
Constructor Details
#initialize(policy_hash = {}) ⇒ PolicyNode
Returns a new instance of PolicyNode.
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 64 def initialize policy_hash = {} super(policy_hash) @source_string = policy_hash[JSON_SOURCE] @target_string = policy_hash[JSON_TARGET] @tags = Set.new(policy_hash[JSON_TAGS]) @sources = convert_policy_markers(source_string) @targets = convert_policy_markers(target_string) @_use_original_object = ORIGINAL_OBJECT_METHODS.include?(@method_name) @_use_original_on_bang_method = assign_on_bang_check(policy_hash) @_use_response_as_source = RESPONSE_SOURCES.include?(@class_name) end |
Instance Attribute Details
#source_string ⇒ String (readonly)
37 38 39 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 37 def source_string @source_string end |
#sources ⇒ Object (readonly)
Returns the value of attribute sources.
33 34 35 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 33 def sources @sources end |
#tags ⇒ Set<String>
30 31 32 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 30 def @tags end |
#target_string ⇒ String
39 40 41 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 39 def target_string @target_string end |
#targets ⇒ Array<String> (readonly)
35 36 37 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 35 def targets @targets end |
#type ⇒ Symbol
32 33 34 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 32 def type @type end |
Instance Method Details
#add_property(name, value) ⇒ Object
Sometimes we need to tie information to an event. We’ll add a properties section to the patch node, which can pass them along to the pre-dtm event
119 120 121 122 123 124 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 119 def add_property name, value return unless name && value @properties ||= {} @properties[name] = value end |
#assign_on_bang_check(policy_hash) ⇒ Object
If we have KEEP action on String, and the method is to_s, that method would return self: String#to_s => self or string. This method is included here to cover the situations such as String.to_s.html_safe, where normally the dynamic sources properties get lost. To solve this we will simply return the original object here.
82 83 84 85 86 87 88 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 82 def assign_on_bang_check policy_hash return true if @_use_original_object && TO_S.include?(policy_hash[JSON_METHOD_NAME]) @_use_original_object && # Check if method name ends with a (!) bang unless is the to_s method: policy_hash[JSON_METHOD_NAME].end_with?(Contrast::Utils::ObjectShare::BANG) end |
#build_action ⇒ Object
Convert our action, built from our source and target, into the TS appropriate action. That’s a single source to single target marker (A,O,P,R)
Creation (source nodes) don’t have sources (they are the source) Trigger (trigger nodes) don’t have targets (they are the target) Everything else (propagation nodes) are Source2Target
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 169 def build_action @event_action ||= case node_class when Contrast::Agent::Assess::Policy::SourceNode::SOURCE :CREATION when Contrast::Agent::Assess::Policy::TriggerNode::TRIGGER :TRIGGER else if source_string.nil? :CREATION elsif target_string.nil? :TRIGGER else # TeamServer can't handle the multi-source or multi-target values. Give it some help # by changing them to 'A' source = all_type?(source_string) ? ALL_TYPE : source_string target = all_type?(target_string) ? ALL_TYPE : target_string (source[0] + TO_MARKER + target[0]).to_sym end end @event_action end |
#feature ⇒ String
91 92 93 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 91 def feature 'Assess' end |
#get_property(name) ⇒ String
128 129 130 131 132 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 128 def get_property name return unless @properties @properties[name] end |
#node_class ⇒ String
96 97 98 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 96 def node_class 'Node' end |
#node_type ⇒ Symbol
101 102 103 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 101 def node_type :TYPE_METHOD end |
#response_source_node? ⇒ Boolean
This method will check if the policy node is for response method.
220 221 222 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 220 def response_source_node? @_use_response_as_source end |
#use_original_object? ⇒ Boolean
This method will check if a method is fit to use it’s original object and that the method is without bang - it does not change the source, but rather creates a copy of it.
197 198 199 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 197 def use_original_object? @_use_original_object && Contrast::ASSESS.track_original_object? end |
#use_original_on_bang_method? ⇒ Boolean
This method will check if a method is fit to use it’s original object and that the target return is the same as object - a bang method modifying the source.
206 207 208 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 206 def use_original_on_bang_method? @_use_original_on_bang_method && Contrast::ASSESS.track_original_object? end |
#use_response_as_source? ⇒ Boolean
This method will check if policy is fit to use response as source.
213 214 215 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 213 def use_response_as_source? Contrast::ASSESS.track_response_as_source? end |
#validate ⇒ Object
Don’t let nodes be created that will be missing things we need later on. Really, if they don’t have these things, they couldn’t have done their jobs anyway.
139 140 141 142 143 144 145 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 139 def validate super rescue ArgumentError => e logger.debug('Validation of policy node failed with: ', e) nil end |
#validate_tags ⇒ Object
TeamServer is picky. The tags here match to ENUMs there. If there isn’t a matching ENUM in TS land, the database gets got. We really don’t want to get them, so we’re going to prevent the node from being made.
@raise raises if any of the tags is invalid
153 154 155 156 157 158 159 160 |
# File 'lib/contrast/agent/assess/policy/policy_node.rb', line 153 def &.each do |tag| next if Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_TAGS.include?(tag) || Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_SOURCE_TAGS.include?(tag) raise(ArgumentError, "#{ node_class } #{ id } had an invalid tag. #{ tag } is not a known value.") end end |