contrast-agent 3.14.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +18 -15
  3. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +1 -0
  4. data/ext/cs__assess_string/cs__assess_string.c +24 -25
  5. data/ext/cs__assess_string/cs__assess_string.h +3 -1
  6. data/ext/cs__common/cs__common.c +4 -2
  7. data/ext/cs__common/cs__common.h +1 -1
  8. data/lib/contrast.rb +1 -1
  9. data/lib/contrast/agent/assess.rb +1 -0
  10. data/lib/contrast/agent/assess/contrast_event.rb +4 -12
  11. data/lib/contrast/agent/assess/finalizers/freeze.rb +3 -1
  12. data/lib/contrast/agent/assess/finalizers/hash.rb +45 -1
  13. data/lib/contrast/agent/assess/policy/patcher.rb +1 -1
  14. data/lib/contrast/agent/assess/policy/policy.rb +0 -2
  15. data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -1
  16. data/lib/contrast/agent/assess/policy/preshift.rb +7 -11
  17. data/lib/contrast/agent/assess/policy/propagation_method.rb +50 -33
  18. data/lib/contrast/agent/assess/policy/propagator/append.rb +8 -5
  19. data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
  20. data/lib/contrast/agent/assess/policy/propagator/center.rb +9 -5
  21. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +5 -3
  22. data/lib/contrast/agent/assess/policy/propagator/insert.rb +6 -3
  23. data/lib/contrast/agent/assess/policy/propagator/keep.rb +4 -1
  24. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +6 -6
  25. data/lib/contrast/agent/assess/policy/propagator/next.rb +7 -5
  26. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +8 -5
  27. data/lib/contrast/agent/assess/policy/propagator/remove.rb +8 -4
  28. data/lib/contrast/agent/assess/policy/propagator/replace.rb +5 -2
  29. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +7 -5
  30. data/lib/contrast/agent/assess/policy/propagator/select.rb +15 -7
  31. data/lib/contrast/agent/assess/policy/propagator/splat.rb +14 -8
  32. data/lib/contrast/agent/assess/policy/propagator/split.rb +14 -8
  33. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +30 -21
  34. data/lib/contrast/agent/assess/policy/propagator/trim.rb +11 -5
  35. data/lib/contrast/agent/assess/policy/source_method.rb +85 -58
  36. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +16 -11
  37. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
  38. data/lib/contrast/agent/assess/policy/trigger_method.rb +38 -15
  39. data/lib/contrast/agent/assess/policy/trigger_node.rb +14 -13
  40. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +2 -1
  41. data/lib/contrast/agent/assess/properties.rb +2 -0
  42. data/lib/contrast/agent/assess/property/updated.rb +136 -0
  43. data/lib/contrast/agent/assess/tracker.rb +66 -0
  44. data/lib/contrast/agent/class_reopener.rb +7 -5
  45. data/lib/contrast/agent/middleware.rb +0 -1
  46. data/lib/contrast/agent/patching/policy/patcher.rb +13 -22
  47. data/lib/contrast/agent/patching/policy/policy.rb +1 -4
  48. data/lib/contrast/agent/response.rb +17 -6
  49. data/lib/contrast/agent/rewriter.rb +1 -3
  50. data/lib/contrast/agent/version.rb +1 -1
  51. data/lib/contrast/api/communication/messaging_queue.rb +1 -4
  52. data/lib/contrast/api/decorators/application_update.rb +2 -4
  53. data/lib/contrast/api/decorators/trace_event.rb +5 -5
  54. data/lib/contrast/components/app_context.rb +11 -9
  55. data/lib/contrast/components/config.rb +3 -13
  56. data/lib/contrast/components/contrast_service.rb +2 -2
  57. data/lib/contrast/config/application_configuration.rb +5 -2
  58. data/lib/contrast/config/service_configuration.rb +8 -2
  59. data/lib/contrast/configuration.rb +88 -47
  60. data/lib/contrast/extension/assess.rb +0 -2
  61. data/lib/contrast/extension/assess/array.rb +8 -5
  62. data/lib/contrast/extension/assess/erb.rb +6 -3
  63. data/lib/contrast/extension/assess/fiber.rb +9 -9
  64. data/lib/contrast/extension/assess/hash.rb +2 -3
  65. data/lib/contrast/extension/assess/kernel.rb +12 -5
  66. data/lib/contrast/extension/assess/marshal.rb +3 -2
  67. data/lib/contrast/extension/assess/regexp.rb +5 -4
  68. data/lib/contrast/extension/assess/string.rb +8 -10
  69. data/lib/contrast/framework/rack/patch/session_cookie.rb +12 -18
  70. data/lib/contrast/framework/rails/patch/assess_configuration.rb +4 -10
  71. data/lib/contrast/framework/rails/support.rb +2 -0
  72. data/lib/contrast/logger/application.rb +11 -3
  73. data/lib/contrast/utils/assess/tracking_util.rb +48 -3
  74. data/lib/contrast/utils/duck_utils.rb +0 -10
  75. data/lib/contrast/utils/env_configuration_item.rb +2 -1
  76. data/lib/contrast/utils/invalid_configuration_util.rb +21 -19
  77. data/lib/contrast/utils/string_utils.rb +10 -5
  78. data/resources/assess/policy.json +0 -10
  79. data/ruby-agent.gemspec +16 -15
  80. data/service_executables/VERSION +1 -1
  81. data/service_executables/linux/contrast-service +0 -0
  82. data/service_executables/mac/contrast-service +0 -0
  83. metadata +42 -21
  84. data/lib/contrast/agent/assess/finalizers/finalize.rb +0 -21
  85. data/lib/contrast/extension/assess/assess_extension.rb +0 -145
  86. data/lib/contrast/utils/freeze_util.rb +0 -32
@@ -61,9 +61,7 @@ module Contrast
61
61
  status ||= Contrast::Agent::Patching::Policy::PatchStatus.get_status(mod)
62
62
  status.failed_rewrite!
63
63
  ensure
64
- with_contrast_scope do
65
- opener&.commit_patches
66
- end
64
+ opener&.commit_patches
67
65
  logger.trace('Rewriting complete',
68
66
  module: module_data.name,
69
67
  result: Contrast::Agent::Patching::Policy::PatchStatus.get_status(
@@ -3,6 +3,6 @@
3
3
 
4
4
  module Contrast
5
5
  module Agent
6
- VERSION = '3.14.0'
6
+ VERSION = '3.15.0'
7
7
  end
8
8
  end
@@ -67,10 +67,7 @@ module Contrast
67
67
  def preprocess_event event
68
68
  return unless event.is_a?(Contrast::Api::Dtm::Activity)
69
69
 
70
- # So set their tags
71
- event.finding_tags = Contrast::Utils::StringUtils.force_utf8(ASSESS.tags)
72
-
73
- # and see if they're even enabled
70
+ # See if they're even enabled
74
71
  event.findings.delete_if { |finding| ASSESS.rule_disabled?(finding.rule_id) }
75
72
  end
76
73
  end
@@ -18,10 +18,8 @@ module Contrast
18
18
  klass.extend(ClassMethods)
19
19
  end
20
20
 
21
- def append_library_update library_dtm_list, library_tags
22
- lib_tags = Contrast::Utils::StringUtils.protobuf_format(library_tags)
21
+ def append_library_update library_dtm_list
23
22
  library_dtm_list.each do |library_dtm|
24
- library_dtm.tags = lib_tags
25
23
  libraries[library_dtm.hash_code] = library_dtm
26
24
  end
27
25
  end
@@ -46,7 +44,7 @@ module Contrast
46
44
  msg = new
47
45
  msg.append_route_coverage_data(Contrast::Agent.framework_manager.find_route_discovery_data)
48
46
  msg.append_platform_version(Contrast::Agent.framework_manager.platform_version)
49
- msg.append_library_update(Contrast::Utils::GemfileReader.instance.library_pb_list, CONFIG.root.inventory.tags)
47
+ msg.append_library_update(Contrast::Utils::GemfileReader.instance.library_pb_list)
50
48
  msg
51
49
  end
52
50
  end
@@ -32,19 +32,19 @@ module Contrast
32
32
 
33
33
  properties = case taint_target
34
34
  when Contrast::Utils::ObjectShare::OBJECT_KEY
35
- contrast_event.object.cs__properties
35
+ Contrast::Agent::Assess::Tracker.properties(contrast_event.object)
36
36
  when Contrast::Utils::ObjectShare::RETURN_KEY
37
- contrast_event.ret.cs__properties
37
+ Contrast::Agent::Assess::Tracker.properties(contrast_event.ret)
38
38
  else
39
39
  target = contrast_event.args[taint_target]
40
40
  if target.is_a?(Hash)
41
41
  if contrast_event.policy_node&.targets&.any?
42
- target[contrast_event.policy_node.targets[0]].cs__properties
42
+ Contrast::Agent::Assess::Tracker.properties(target[contrast_event.policy_node.targets[0]])
43
43
  else
44
- target[contrast_event.policy_node.sources[0]].cs__properties
44
+ Contrast::Agent::Assess::Tracker.properties(target[contrast_event.policy_node.sources[0]])
45
45
  end
46
46
  else
47
- target.cs__properties
47
+ Contrast::Agent::Assess::Tracker.properties(target)
48
48
  end
49
49
  end
50
50
 
@@ -15,7 +15,7 @@ module Contrast
15
15
  include Contrast::Components::ComponentBase
16
16
  include Contrast::Components::Interface
17
17
 
18
- access_component :agent, :config
18
+ access_component :agent, :analysis, :config
19
19
 
20
20
  DEFAULT_APP_NAME = 'rails'
21
21
  DEFAULT_APP_PATH = '/'
@@ -79,7 +79,6 @@ module Contrast
79
79
  msg = Contrast::Api::Dtm::ApplicationCreate.new
80
80
 
81
81
  msg.group = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.group
82
- msg.tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.tags
83
82
  msg.app_version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.version.to_s
84
83
  msg.code = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.code
85
84
  msg.metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.metadata
@@ -92,13 +91,16 @@ module Contrast
92
91
 
93
92
  def build_agent_startup_message
94
93
  msg = Contrast::Api::Dtm::AgentStartup.new
95
- msg.server_name = Contrast::Utils::StringUtils.protobuf_format server_name
96
- msg.server_path = Contrast::Utils::StringUtils.protobuf_format server_path
97
- msg.server_type = Contrast::Utils::StringUtils.protobuf_format server_type
98
- msg.server_version = Contrast::Agent::VERSION
99
- msg.version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.version
100
- msg.environment = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.environment
101
- msg.tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.tags
94
+ msg.server_name = Contrast::Utils::StringUtils.protobuf_format server_name
95
+ msg.server_path = Contrast::Utils::StringUtils.protobuf_format server_path
96
+ msg.server_type = Contrast::Utils::StringUtils.protobuf_format server_type
97
+ msg.server_version = Contrast::Agent::VERSION
98
+ msg.version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.version
99
+ msg.environment = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.environment
100
+ msg.server_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.tags
101
+ msg.application_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.tags
102
+ msg.library_tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.inventory.tags
103
+ msg.finding_tags = Contrast::Utils::StringUtils.protobuf_format ASSESS.tags
102
104
  msg
103
105
  end
104
106
 
@@ -34,8 +34,7 @@ module Contrast
34
34
  def build log: true
35
35
  @_valid = nil
36
36
  @config = Contrast::Configuration.new
37
- defaults
38
- overrides
37
+ env_overrides
39
38
  validate(log: log)
40
39
  end
41
40
  alias_method :rebuild, :build
@@ -70,11 +69,11 @@ module Contrast
70
69
  end
71
70
 
72
71
  def session_id
73
- @_session_id ||= raw.application.session_id || Contrast::Utils::ObjectShare::EMPTY_STRING
72
+ @_session_id ||= raw.application.session_id
74
73
  end
75
74
 
76
75
  def session_metadata
77
- @_session_metadata ||= raw.application.session_metadata || Contrast::Utils::ObjectShare::EMPTY_STRING
76
+ @_session_metadata ||= raw.application.session_metadata
78
77
  end
79
78
 
80
79
  def valid?
@@ -105,15 +104,6 @@ module Contrast
105
104
  true
106
105
  end
107
106
 
108
- def defaults
109
- raw.agent.service.host ||= Contrast::Configuration::DEFAULT_HOST
110
- raw.agent.service.port ||= Contrast::Configuration::DEFAULT_PORT
111
- end
112
-
113
- def overrides
114
- env_overrides
115
- end
116
-
117
107
  def env_overrides
118
108
  # For env variables resembling CONTRAST__WHATEVER__NESTED_VALUE
119
109
  # override raw.whatever.nested_value
@@ -36,11 +36,11 @@ module Contrast
36
36
  end
37
37
 
38
38
  def host
39
- @_host ||= (CONFIG.root.agent.service.host || Contrast::Configuration::DEFAULT_HOST).to_s
39
+ @_host ||= CONFIG.root.agent.service.host.to_s
40
40
  end
41
41
 
42
42
  def port
43
- @_port ||= (CONFIG.root.agent.service.port || DEFAULT_PORT).to_i
43
+ @_port ||= CONFIG.root.agent.service.port.to_i
44
44
  end
45
45
 
46
46
  def socket_path
@@ -1,6 +1,9 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'contrast/config/default_value'
5
+ require 'contrast/utils/object_share'
6
+
4
7
  module Contrast
5
8
  module Config
6
9
  # Common Configuration settings. Those in this section pertain to the
@@ -15,8 +18,8 @@ module Contrast
15
18
  tags: EMPTY_VALUE,
16
19
  code: EMPTY_VALUE,
17
20
  metadata: EMPTY_VALUE,
18
- session_id: EMPTY_VALUE,
19
- session_metadata: EMPTY_VALUE
21
+ session_id: Contrast::Config::DefaultValue.new(Contrast::Utils::ObjectShare::EMPTY_STRING),
22
+ session_metadata: Contrast::Config::DefaultValue.new(Contrast::Utils::ObjectShare::EMPTY_STRING)
20
23
  }.cs__freeze
21
24
 
22
25
  def initialize hsh
@@ -1,15 +1,21 @@
1
1
  # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'contrast/config/default_value'
5
+ require 'contrast/config/logger_configuration'
6
+
4
7
  module Contrast
5
8
  module Config
6
9
  # Common Configuration settings. Those in this section pertain to the
7
10
  # communication between the Agent & the Service.
8
11
  class ServiceConfiguration < BaseConfiguration
12
+ DEFAULT_HOST = '127.0.0.1'
13
+ DEFAULT_PORT = '30555'
14
+
9
15
  KEYS = {
10
16
  enable: EMPTY_VALUE,
11
- host: EMPTY_VALUE,
12
- port: EMPTY_VALUE,
17
+ host: Contrast::Config::DefaultValue.new(DEFAULT_HOST),
18
+ port: Contrast::Config::DefaultValue.new(DEFAULT_PORT),
13
19
  socket: EMPTY_VALUE,
14
20
  logger: Contrast::Config::LoggerConfiguration
15
21
  }.cs__freeze
@@ -24,8 +24,6 @@ module Contrast
24
24
  attr_reader :default_name, :root
25
25
 
26
26
  DEFAULT_YAML_PATH = 'contrast_security.yaml'
27
- DEFAULT_HOST = '127.0.0.1'
28
- DEFAULT_PORT = '30555'
29
27
  MILLISECOND_MARKER = '_ms'
30
28
  CONVERSION = {
31
29
  'agent.service.enable' => 'agent.start_bundled_service'
@@ -37,9 +35,6 @@ module Contrast
37
35
  '/etc/contrast/',
38
36
  '/etc/'
39
37
  ].cs__freeze
40
- REMOVE_FIELDS = [
41
- 'contrast'
42
- ].cs__freeze
43
38
 
44
39
  def initialize cli_options = nil, default_name = DEFAULT_YAML_PATH
45
40
  @default_name = default_name
@@ -53,7 +48,6 @@ module Contrast
53
48
 
54
49
  # Some in-flight rewrites to maintain backwards compatibility
55
50
  config_kv = update_prop_keys(config_kv)
56
- config_kv = deprecate_fields(config_kv)
57
51
 
58
52
  @root = Contrast::Config::RootConfiguration.new(config_kv)
59
53
  end
@@ -73,6 +67,13 @@ module Contrast
73
67
  root&.cs__respond_to?(method_name) || super
74
68
  end
75
69
 
70
+ # Get a loggable YAML format of this configuration
71
+ # @return [String] the current active configuration of the Agent,
72
+ # represented as a YAML string
73
+ def loggable
74
+ convert_to_hash.to_yaml
75
+ end
76
+
76
77
  protected
77
78
 
78
79
  # TODO: RUBY-546 move utility methods to auxiliary classes
@@ -80,26 +81,16 @@ module Contrast
80
81
  def load_config
81
82
  config = {}
82
83
  configuration_paths.find do |path|
83
- found = File.exist?(path)
84
- next unless found
84
+ next unless File.exist?(path)
85
85
 
86
- readable = File.readable?(path)
87
- unless readable
88
- puts "!!! Contrast - Configuration file at #{ path } is not readable by current user"
86
+ unless File.readable?(path)
87
+ log_file_read_error(path)
89
88
  next
90
89
  end
91
90
  config = yaml_to_hash(path) || {}
92
91
  break
93
92
  end
94
93
 
95
- if config.empty?
96
- puts "!!! Contrast - working directory: #{ Dir.pwd }"
97
- puts '!!! Contrast - valid configuration file could not be found at any of the search paths'
98
- puts 'Valid configuration paths are: '
99
- configuration_paths.each do |path|
100
- puts(path)
101
- end
102
- end
103
94
  config
104
95
  end
105
96
 
@@ -109,9 +100,10 @@ module Contrast
109
100
  yaml = IO.read(path)
110
101
  yaml = ERB.new(yaml).result if defined?(ERB)
111
102
  return YAML.safe_load(yaml)
103
+ rescue Psych::Exception => e
104
+ log_yaml_parse_error(path, e)
112
105
  rescue RuntimeError => e
113
- puts "ERROR: unable to load configuration from path due to #{ e }"
114
- puts "ERROR: path=#{ path } pwd=#{ Dir.pwd }"
106
+ puts "WARN: Unable to load configuration. #{ e }; path: #{ path }, pwd: #{ Dir.pwd }"
115
107
  end
116
108
  end
117
109
 
@@ -122,29 +114,20 @@ module Contrast
122
114
  # files to match the new agreed upon standard configuration
123
115
  # names, so that one file works for all agents
124
116
  def update_prop_keys config
125
- converted = false
126
117
  CONVERSION.each_pair do |old_method, new_method|
127
118
  # See if the old value was set and needs to be translated
128
119
  deprecated_keys = old_method.split('.')
129
-
130
120
  old_value = config
131
121
  deprecated_keys.each do |key|
132
122
  old_value = old_value[key]
133
123
  break if old_value.nil?
134
124
  end
125
+ next if old_value.nil? # have to account for literal false
135
126
 
136
- next if old_value.nil?
137
-
138
- converted = true
139
-
140
- puts "The deprecated property #{ old_method } is being set."
141
- puts "Please update your config to use the property #{ new_method } instead."
142
-
127
+ log_deprecated_property(old_method, new_method)
143
128
  new_keys = new_method.split('.')
144
-
145
129
  # We changed the seconds values into ms values. Multiply them accordingly
146
130
  old_value = old_value.to_i * 1000 if new_method.end_with?(MILLISECOND_MARKER)
147
-
148
131
  new_value = config
149
132
  end_idx = new_keys.length - 1
150
133
  new_keys.each_with_index do |new_key, index|
@@ -161,21 +144,6 @@ module Contrast
161
144
  config
162
145
  end
163
146
 
164
- def deprecate_fields hash
165
- REMOVE_FIELDS.each do |field|
166
- path = field.split('.')
167
- active_path = hash
168
- path.each_with_index do |delete_path, index|
169
- if index == path.length - 1 && active_path
170
- active_path.delete(delete_path)
171
- elsif active_path
172
- active_path = active_path[delete_path]
173
- end
174
- end
175
- end
176
- hash
177
- end
178
-
179
147
  # Base paths to check for the contrast configuration file, sorted by
180
148
  # reverse order of precedence (first is most important).
181
149
  def configuration_paths
@@ -208,5 +176,78 @@ module Contrast
208
176
  end
209
177
  new_hash
210
178
  end
179
+
180
+ private
181
+
182
+ # We cannot use all access components at this point, unfortunately, as they
183
+ # may not have been initialized. Instead, we need to access the logger
184
+ # directly.
185
+ def logger
186
+ @_logger ||= (Contrast::Logger::Log.instance.logger if defined?(Contrast::Logger::Log))
187
+ end
188
+
189
+ # When we fail to parse a configuration because it is misformatted, log an
190
+ # appropriate message based on the Agent Onboarding specification
191
+ def log_yaml_parse_error path, exception
192
+ hash = {
193
+ path: path,
194
+ pwd: Dir.pwd
195
+ }
196
+ if exception.is_a?(Psych::SyntaxError)
197
+ hash[:context] = exception.context
198
+ hash[:column] = exception.column
199
+ hash[:line] = exception.line
200
+ hash[:offset] = exception.offset
201
+ hash[:problem] = exception.problem
202
+ end
203
+
204
+ if logger
205
+ logger.warn('YAML validator found an error', hash)
206
+ else
207
+ puts "CONTRAST - WARN: YAML validator found an error. #{ hash.inspect }"
208
+ end
209
+ end
210
+
211
+ def log_file_read_error path
212
+ if logger
213
+ logger.warn('Configuration file is not readable by current user', path: path)
214
+ else
215
+ puts "CONTRAST - WARN: Configuration file is not readable by current user; path: #{ path }"
216
+ end
217
+ end
218
+
219
+ def log_deprecated_property old_method, new_method
220
+ if logger
221
+ logger.warn('Deprecated property in use', old_method: old_method, new_method: new_method)
222
+ else
223
+ puts "CONTRAST - WARN: Deprecated property in use; old_method: #{ old_method }, new_method: #{ new_method }"
224
+ end
225
+ end
226
+
227
+ # Convert this entire configuration into a hash, walking down the entries
228
+ # in the thing to convert and setting them in the given hash. For now, this
229
+ # logs every possible key, whether set or not. If we want to change that
230
+ # behavior, we can skip adding keys to the hash if the value is nil, blank,
231
+ # or Contrast::Config::DefaultValue depending on desired behavior
232
+ #
233
+ # @param hash [Hash] the hash to populate
234
+ # @param convert [Contrast::Config::BaseConfiguration, Object] the level of
235
+ # configuration from which to convert. Note that at least one top level
236
+ # Contrast::Config::BaseConfiguration is required for anything to be set
237
+ # in the hash
238
+ # @return [Hash, Object] the leaf of each
239
+ # Contrast::Config::BaseConfiguration will be returned in the N > 0 steps
240
+ # the Hash will be returned at the end of the 0 level
241
+ def convert_to_hash convert=root, hash={}
242
+ case convert
243
+ when Contrast::Config::BaseConfiguration
244
+ convert.cs__class::KEYS.each_key do |key|
245
+ hash[key] = convert_to_hash(convert.send(key), {})
246
+ end
247
+ hash
248
+ else
249
+ convert
250
+ end
251
+ end
211
252
  end
212
253
  end
@@ -30,8 +30,6 @@ module Contrast
30
30
  require 'contrast/agent/assess/policy/policy'
31
31
  require 'contrast/agent/assess/policy/patcher'
32
32
 
33
- # classes that don't play nice w/ our standard propagation
34
- require 'contrast/extension/assess/assess_extension'
35
33
  # this needs to come first b/c array and others work on strings and
36
34
  # expect them to be trackable
37
35
  require 'contrast/extension/assess/string'
@@ -35,23 +35,26 @@ module Contrast
35
35
  # operation happens in C, we have to do it here rather than rely on the
36
36
  # patch of our String append or concat methods.
37
37
  def cs__track_join ary, separator, ret
38
- return unless ary
38
+ return ret unless ary
39
39
  return ret if Contrast::Agent::Patching::Policy::Patch.skip_assess_analysis?
40
40
 
41
41
  with_contrast_scope do
42
+ properties = Contrast::Agent::Assess::Tracker.properties(ret)
43
+ return ret unless properties
44
+
42
45
  shift = 0
43
46
  separator_length = separator.nil? ? 0 : separator.to_s.length
44
47
  ary.each do |obj|
45
48
  if obj # skip nil here
46
- ret.cs__copy_from(obj, shift)
49
+ properties.copy_from(obj, ret, shift)
47
50
  shift += obj.to_s.length
48
51
  end
49
52
  shift += separator_length
50
53
  end
51
- return ret unless ret.cs__tracked?
54
+ return ret unless Contrast::Agent::Assess::Tracker.tracked?(ret)
52
55
 
53
- ret.cs__properties.cleanup_tags
54
- ret.cs__properties.build_event(
56
+ properties.cleanup_tags
57
+ properties.build_event(
55
58
  ARRAY_JOIN_NODE,
56
59
  ret,
57
60
  ary,