contrast-agent 4.12.0 → 4.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_module/cs__assess_module.c +48 -0
  3. data/ext/cs__assess_module/cs__assess_module.h +7 -0
  4. data/ext/cs__common/cs__common.c +5 -0
  5. data/ext/cs__common/cs__common.h +8 -0
  6. data/ext/cs__contrast_patch/cs__contrast_patch.c +16 -1
  7. data/ext/cs__os_information/cs__os_information.c +31 -0
  8. data/ext/cs__os_information/cs__os_information.h +7 -0
  9. data/ext/cs__os_information/extconf.rb +5 -0
  10. data/lib/contrast/agent/assess/policy/propagation_method.rb +2 -116
  11. data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
  12. data/lib/contrast/agent/assess/policy/source_method.rb +2 -71
  13. data/lib/contrast/agent/assess/policy/trigger_method.rb +4 -106
  14. data/lib/contrast/agent/assess/property/tagged.rb +2 -128
  15. data/lib/contrast/agent/deadzone/policy/policy.rb +1 -1
  16. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +1 -0
  17. data/lib/contrast/agent/metric_telemetry_event.rb +26 -0
  18. data/lib/contrast/agent/middleware.rb +22 -0
  19. data/lib/contrast/agent/patching/policy/patch.rb +28 -235
  20. data/lib/contrast/agent/patching/policy/patcher.rb +2 -41
  21. data/lib/contrast/agent/request_handler.rb +7 -3
  22. data/lib/contrast/agent/startup_metrics_telemetry_event.rb +71 -0
  23. data/lib/contrast/agent/static_analysis.rb +4 -2
  24. data/lib/contrast/agent/telemetry.rb +129 -0
  25. data/lib/contrast/agent/telemetry_event.rb +34 -0
  26. data/lib/contrast/agent/thread_watcher.rb +43 -14
  27. data/lib/contrast/agent/version.rb +1 -1
  28. data/lib/contrast/agent.rb +6 -0
  29. data/lib/contrast/components/api.rb +34 -0
  30. data/lib/contrast/components/app_context.rb +24 -0
  31. data/lib/contrast/components/config.rb +90 -11
  32. data/lib/contrast/components/contrast_service.rb +6 -0
  33. data/lib/contrast/config/api_configuration.rb +22 -0
  34. data/lib/contrast/config/env_variables.rb +25 -0
  35. data/lib/contrast/config/root_configuration.rb +1 -0
  36. data/lib/contrast/config/service_configuration.rb +2 -1
  37. data/lib/contrast/config.rb +1 -0
  38. data/lib/contrast/configuration.rb +3 -0
  39. data/lib/contrast/framework/manager.rb +14 -12
  40. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +9 -6
  41. data/lib/contrast/framework/rails/patch/support.rb +31 -29
  42. data/lib/contrast/logger/application.rb +4 -0
  43. data/lib/contrast/utils/assess/propagation_method_utils.rb +129 -0
  44. data/lib/contrast/utils/assess/property/tagged_utils.rb +142 -0
  45. data/lib/contrast/utils/assess/source_method_utils.rb +83 -0
  46. data/lib/contrast/utils/assess/trigger_method_utils.rb +138 -0
  47. data/lib/contrast/utils/exclude_key.rb +20 -0
  48. data/lib/contrast/utils/metrics_hash.rb +59 -0
  49. data/lib/contrast/utils/os.rb +23 -0
  50. data/lib/contrast/utils/patching/policy/patch_utils.rb +232 -0
  51. data/lib/contrast/utils/patching/policy/patcher_utils.rb +54 -0
  52. data/lib/contrast/utils/requests_client.rb +150 -0
  53. data/lib/contrast/utils/telemetry.rb +78 -0
  54. data/lib/contrast/utils/telemetry_identifier.rb +137 -0
  55. data/lib/contrast.rb +18 -0
  56. data/ruby-agent.gemspec +2 -1
  57. data/service_executables/VERSION +1 -1
  58. data/service_executables/linux/contrast-service +0 -0
  59. data/service_executables/mac/contrast-service +0 -0
  60. metadata +32 -10
@@ -0,0 +1,150 @@
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'net/http'
5
+ require 'contrast/components/logger'
6
+ require 'contrast/utils/object_share'
7
+ require 'contrast/agent/version'
8
+ require 'socket'
9
+
10
+ module Contrast
11
+ module Utils
12
+ # This module creates a Net::HTTP client and initiates a connection to the provided result
13
+ module RequestsClient
14
+ ENDPOINT = 'api/v1/telemetry/metrics' # /TelemetryEvent.path
15
+
16
+ class << self
17
+ include Contrast::Components::Logger::InstanceMethods
18
+ # This method initializes the Net::HTTP client we'll need
19
+ # @param url [String]
20
+ # @return [Net::HTTP, nil]
21
+ def initialize_connection url
22
+ addr = URI(url)
23
+ return if addr.host.nil? || addr.port.nil?
24
+ return if addr.scheme != 'https'
25
+
26
+ @_net_http_client = Net::HTTP.new(addr.host, addr.port)
27
+ @_net_http_client.open_timeout = 5
28
+ @_net_http_client.read_timeout = 5
29
+ @_net_http_client.use_ssl = true
30
+ @_net_http_client.verify_mode = OpenSSL::SSL::VERIFY_PEER
31
+ @_net_http_client.verify_depth = 5
32
+ @_net_http_client.start
33
+ return unless @_net_http_client.started?
34
+
35
+ logger.warn('Starting Telemetry connection test')
36
+ return unless connection_verified? @_net_http_client
37
+
38
+ @_net_http_client
39
+ rescue Net::OpenTimeout, Net::ReadTimeout => e
40
+ logger.warn('Telemetry connection failed', e.message)
41
+ nil
42
+ end
43
+
44
+ # This method will be responsible for building the request
45
+ # @param event[Contrast::Agent::TelemetryEvent,Contrast::Agent::StartupMetricsTelemetryEvent]
46
+ # @return [Net::HTTP::Post]
47
+ def build_request event
48
+ return unless valid_event? event
49
+
50
+ string_body = event.to_json.to_s
51
+ header = { 'User-Agent' => "<#{ Contrast::Utils::ObjectShare::RUBY }>-<#{ Contrast::Agent::VERSION }>" }
52
+ path = ENDPOINT + event.path
53
+ @_request = Net::HTTP::Post.new(path, header)
54
+ @_request.body = string_body
55
+ @_request
56
+ end
57
+
58
+ # This method will create the actual request and send it
59
+ # @param event[Contrast::Agent::TelemetryEvent]
60
+ # @param connection[Net::HTTP]
61
+ def send_request event, connection
62
+ return if connection.nil? || event.nil?
63
+ return unless valid_event? event
64
+
65
+ req = build_request event
66
+ connection.request req
67
+ end
68
+
69
+ # This method will handle the response from the tenant
70
+ # @param res [Net::HTTPResponse]
71
+ # @return sleep_time [Integer, nil]
72
+ def handle_response res
73
+ status_code = res.code.to_i
74
+ ready_after = if res.to_hash.keys.map(&:downcase).include?('ready-after')
75
+ res['Ready-After']
76
+ else
77
+ 60
78
+ end
79
+ ready_after if status_code == 429
80
+ end
81
+
82
+ # This method will be responsible for validating the event
83
+ # @param event[Contrast::Agent::TelemetryEvent,Contrast::Agent::StartupMetricsTelemetryEvent]
84
+ def valid_event? event
85
+ return false unless event.cs__is_a?(Contrast::Agent::TelemetryEvent)
86
+ return false unless event.cs__is_a?(Contrast::Agent::StartupMetricsTelemetryEvent)
87
+
88
+ true
89
+ end
90
+
91
+ # Validates connection with Telemetry assigned domain.
92
+ # If connection is running, SSL certificate of the endpoint is valid, Ip address is resolvable
93
+ # and response is received without peer's reset or refuse of connection,
94
+ # then validation returns true. Error handling is in place so that the work of the agent will continue as
95
+ # normal without Telemetry.
96
+ #
97
+ # @param client [Net::HTTP]
98
+ # @return [Boolean] true | false
99
+ def connection_verified? client
100
+ return @_connection_verified unless @_connection_verified.nil?
101
+
102
+ # Before RUBY 2.7 there is no #ipaddr
103
+ ipaddr = if RUBY_VERSION < '2.7.0'
104
+ socket = TCPSocket.open(client.address, client.port)
105
+ ipaddr = socket.peeraddr[3]
106
+ socket.close
107
+ ipaddr
108
+ else
109
+ client.ipaddr
110
+ end
111
+ response = client.request(Net::HTTP::Get.new(client.address))
112
+ verify_cert = OpenSSL::SSL.verify_certificate_identity(client.peer_cert, client.address)
113
+ resolved = resolved? client.address, ipaddr
114
+ @_connection_verified = if resolved && response && verify_cert
115
+ true
116
+ else
117
+ false
118
+ end
119
+ rescue OpenSSL::SSL::SSLError, Resolv::ResolvError, Errno::ECONNRESET, Errno::ECONNREFUSED,
120
+ Errno::ETIMEDOUT, Errno::ESHUTDOWN, Errno::EHOSTDOWN, Errno::EHOSTUNREACH, Errno::EISCONN,
121
+ Errno::ECONNABORTED, Errno::ENETRESET, Errno::ENETUNREACH => e
122
+
123
+ logger.warn('Telemetry connection failed', e.message)
124
+ false
125
+ end
126
+
127
+ private
128
+
129
+ # Resolves the address of the assigned telemetry domain to array of corresponding IPs (if more than one)
130
+ # and runs a matcher to see if current connection IP is in the list.
131
+ # This is called within #verify_connection, if called on it's own there will be no
132
+ # error handling.
133
+ #
134
+ # @param address [String] Human friendly address of assigned telemetry domain
135
+ # @param ipaddr [String] Machine friendly IP address of the assigned telemetry domain
136
+ # @return[Boolean] true if both addresses are resolved | false if one of the addresses
137
+ # is non-resolvable
138
+ def resolved? address, ipaddr
139
+ return @_resolved unless @_resolved.nil?
140
+
141
+ @_resolved = if (addresses = Resolv.getaddresses address)
142
+ addresses.any? { |addr| addr.include?(ipaddr) }
143
+ else
144
+ false
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,78 @@
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent/telemetry'
5
+ require 'contrast/utils/telemetry_identifier'
6
+
7
+ module Contrast
8
+ module Utils
9
+ # Tools for supporting the Telemetry feature
10
+ module Telemetry
11
+ DIR = '/ect/contrast/ruby-agent/'.cs__freeze
12
+ FILE = '.telemetry'.cs__freeze
13
+ CURRENT_DIR = Dir.pwd.cs__freeze
14
+ CONFIG_DIR = CURRENT_DIR + '/config/contrast/'.cs__freeze
15
+ MESSAGE = {
16
+ disclaimer:
17
+ "\n===================================================================================================" \
18
+ "\n\nThe [Contrast Security] [Ruby Agent] " \
19
+ "collects usage data in order to help us improve compatibility\n" \
20
+ "and security coverage. The data is anonymous and does not contain application data. It is collected\n" \
21
+ "by Contrast and is never shared. You can opt-out of telemetry by setting the\n" \
22
+ "'CONTRAST_AGENT_TELEMETRY_OPTOUT' environment variable to '1' or 'true'.\n\n" \
23
+ "===================================================================================================\n\n"
24
+ }.cs__freeze
25
+
26
+ # Here we create the .telemetry file. If the file exist we do nothing.
27
+ #
28
+ # @return[Boolean, nil] true if file is created, false if file already exist
29
+ # and nil if Telemetry is disabled or on unsupported OS.
30
+ def self.create_telemetry_file
31
+ write_mark_file DIR, FILE, CONFIG_DIR
32
+ end
33
+
34
+ def self.disclaimer
35
+ @_disclaimer = MESSAGE[:disclaimer]
36
+ end
37
+
38
+ class << self
39
+ private
40
+
41
+ # Create the mark file
42
+ #
43
+ # @param dir [String] Directory in which the file is to be created
44
+ # @param file [String] filename of the mark file
45
+ # @param config_dir [String] path for the config folder in working directory
46
+ # @return[Boolean, nil] true if file is created, false if file already exist
47
+ # and nil if Telemetry is disabled or on unsupported OS.
48
+ def write_mark_file dir, file, config_dir
49
+ return unless Contrast::Agent::Telemetry.enabled?
50
+ return if Contrast::Utils::OS.windows?
51
+
52
+ @dir = dir
53
+ # After macOS Catalina, you can no longer store files or data in the read-only system volume,
54
+ # nor can we write to the "root" directory ( / ). This results in Errno::EROFS exception.
55
+ # So for the MacOS we would use the config directory of the instrumented application.
56
+ @dir = config_dir if Contrast::Utils::OS.mac?
57
+ return false if File.file? @dir + file
58
+
59
+ begin
60
+ return true if touch @dir, file # rubocop:disable Rails/SkipsModelValidations
61
+ rescue Errno::EROFS
62
+ # If we don't have permission to write to root directory use config instead
63
+ return true if touch config_dir, file # rubocop:disable Rails/SkipsModelValidations
64
+ end
65
+ end
66
+
67
+ # Touches .telemetry file
68
+ #
69
+ # @return[Boolean] true if success, false if fails
70
+ def touch dir, file
71
+ FileUtils.mkdir_p dir unless Dir.exist? dir
72
+ FileUtils.touch dir + file
73
+ File.file? dir + file
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,137 @@
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent/telemetry'
5
+ require 'contrast/utils/os'
6
+ require 'socket'
7
+
8
+ module Contrast
9
+ module Utils
10
+ # Tools for supporting the Telemetry feature
11
+ module Telemetry
12
+ # Gets info about the instrumented application required to build unique identifiers,
13
+ # used in the agent's Telemetry.
14
+ module Identifier
15
+ MAC_REGEX = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.cs__freeze
16
+ LINUX_OS_REG = /hwaddr=.*?(([A-F0-9]{2}:){5}[A-F0-9]{2})/im.cs__freeze
17
+ MAC_OS_PRIMARY = 'en0'.cs__freeze
18
+ LINUX_PRIMARY = 'enp'.cs__freeze
19
+
20
+ # Sinatra and Grape both use similar approach to identify the app_name.
21
+ # Rails has a different way of doing it, but to unify this we'll use this one.
22
+ # If app_name is changed/renamed during production it would still get the
23
+ # new folder's name.
24
+ #
25
+ # @ return [String] name of the application from the current working directory
26
+ def self.app_name
27
+ @_app_name ||= File.basename(Dir.pwd)
28
+ end
29
+
30
+ # Returns the MAC address of the primary network interface, depending on the used OS.
31
+ # If the primary is unknown it finds the first available network interface and gets it's
32
+ # MAC address instead.
33
+ #
34
+ # @return [String, nil] MAC address of the primary network interface or
35
+ # the first available one, or nil if nothing found
36
+ def self.mac
37
+ @_mac = find_mac MAC_OS_PRIMARY if Contrast::Utils::OS.mac? && @_mac.nil?
38
+ @_mac = find_mac LINUX_PRIMARY if Contrast::Utils::OS.linux? && @_mac.nil?
39
+ # or find any available
40
+ @_mac = find_mac if @_mac.nil?
41
+ @_mac
42
+ end
43
+
44
+ class << self
45
+ private
46
+
47
+ # Finds the primary MAC address of all listed network adapters.
48
+ # If primary is not set or unknown, use the first MAC address found
49
+ # from the listed adapters.
50
+ #
51
+ # @param primary [nil, String] optional param if set look only for primary
52
+ # network adapter's name
53
+ # @return [String, nil] MAC address of the first listed network adapter or
54
+ # nil if not found
55
+ def find_mac primary = nil
56
+ result = nil
57
+ idx = 0
58
+ return if interfaces.empty?
59
+
60
+ while idx < interfaces.length
61
+ addr = interfaces[idx].addr
62
+ name = interfaces[idx].name # rubocop:disable Security/Module/Name
63
+ # retrieving MAC address from primary network interface or first available
64
+ mac = retrieve_mac name, addr, primary
65
+ idx += 1
66
+ next unless mac
67
+
68
+ result = mac if mac && (mac.match? MAC_REGEX)
69
+ break if result && !primary
70
+ end
71
+ result
72
+ end
73
+
74
+ # Retrieves MAC address for primary or any network interface.
75
+ # This is OS dependent search.
76
+ #
77
+ # @param name [Sting] interface name of ifaddr
78
+ # @param addr [String] address info
79
+ # example: #<Addrinfo: LINK[en0 aa:bb:cc:00:11:22]>
80
+ # @param primary [nil, String] optional param if set look only for primary
81
+ # network adapter's name
82
+ # @return mac [nil, String] MAC address of primary network interface,
83
+ # any network interface, or nil if no interface is found.
84
+ def retrieve_mac name, addr, primary
85
+ mac = nil
86
+ # Mac OS allow us to use getnameinfo(sockaddr [, flags]) => [hostname, servicename]
87
+ #
88
+ # returned address:
89
+ # <Socket::Ifaddr en0 UP,BROADCAST,RUNNING,NOTRAILERS,SIMPLEX,MULTICAST LINK[en0 aa:bb:cc:00:11:22]>
90
+ if Contrast::Utils::OS.mac?
91
+ mac = addr.getnameinfo[0] unless primary
92
+ mac = addr.getnameinfo[0] if primary && name.include?(primary)
93
+ end
94
+ # In Linux using Socket::addr#getnameinfo results in ai_family not supported exception.
95
+ # In this case we are relying on match filtering of addresses.
96
+ #
97
+ # returned address:
98
+ # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000
99
+ # PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=aa:bb:cc:00:11:22]>
100
+ if primary && Contrast::Utils::OS.linux?
101
+ mac = Regexp.last_match(1) if addr.inspect =~ LINUX_OS_REG && name.include?(primary)
102
+ elsif primary.nil? && Contrast::Utils::OS.linux?
103
+ mac = Regexp.last_match(1) if addr.inspect =~ LINUX_OS_REG
104
+ end
105
+ mac
106
+ end
107
+
108
+ # Returns array of network interfaces.
109
+ # This is OS dependent search.
110
+ #
111
+ # @return interfaces [Array] Returns an array of interface addresses.
112
+ # Socket::Ifaddr - represents a result of getifaddrs().
113
+ def interfaces
114
+ @_interfaces = []
115
+ arr = Socket.getifaddrs
116
+ idx = 0
117
+ check_family = 0
118
+ while idx < arr.length
119
+ # We need only network adapters MACs. Checking for pfamily of every socket address:
120
+ # 18 for Mac OS and 17 for Linux.
121
+ # family should be an address family such as: :INET, :INET6, :UNIX, etc.
122
+ check_family = 18 if Contrast::Utils::OS.mac?
123
+ check_family = 17 if Contrast::Utils::OS.linux?
124
+ if arr[idx].addr.pfamily != check_family
125
+ idx += 1
126
+ next
127
+ end
128
+ @_interfaces << arr[idx]
129
+ idx += 1
130
+ end
131
+ @_interfaces
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
data/lib/contrast.rb CHANGED
@@ -35,6 +35,7 @@ if RUBY_VERSION >= '3.0.0'
35
35
  end
36
36
 
37
37
  require 'contrast/components/agent'
38
+ require 'contrast/components/api'
38
39
  require 'contrast/components/app_context'
39
40
  require 'contrast/components/assess'
40
41
  require 'contrast/components/config'
@@ -47,6 +48,7 @@ require 'contrast/components/scope'
47
48
  require 'contrast/components/settings'
48
49
 
49
50
  module Contrast
51
+ API = Contrast::Components::Api::Interface.new
50
52
  SCOPE = Contrast::Components::Scope::Interface.new
51
53
  CONFIG = Contrast::Components::Config::Interface.new
52
54
  SETTINGS = Contrast::Components::Settings::Interface.new
@@ -76,3 +78,19 @@ if RUBY_VERSION >= '3.0.0'
76
78
  Class.alias_method(:prepend, :cs__orig_prepend)
77
79
  Class.remove_method(:cs__orig_prepend)
78
80
  end
81
+
82
+ if RUBY_VERSION < '3.0.0'
83
+ # Better handles ancestors for older ruby versions.
84
+ # This is called from C, tread lightly.
85
+ class Module
86
+ @_included_in = []
87
+ # Returns array with modules including this instance
88
+ def included_in
89
+ @_included_in ||= [] unless cs__frozen?
90
+ end
91
+
92
+ def self.included_in
93
+ @_included_in ||= [] unless cs__frozen?
94
+ end
95
+ end
96
+ end
data/ruby-agent.gemspec CHANGED
@@ -150,7 +150,8 @@ def self.add_files spec
150
150
  'shared_libraries/libfunchook.so',
151
151
  'shared_libraries/funchook.h',
152
152
  'funchook/src/libfunchook.dylib',
153
- 'funchook/src/libfunchook.so')
153
+ 'funchook/src/libfunchook.so',
154
+ '.secrets.baseline')
154
155
  end
155
156
  end
156
157
 
@@ -1 +1 @@
1
- 2.26.0
1
+ 2.27.3
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrast-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.0
4
+ version: 4.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - galen.palmer@contrastsecurity.com
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: exe
15
15
  cert_chain: []
16
- date: 2021-10-14 00:00:00.000000000 Z
16
+ date: 2021-11-09 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -617,18 +617,19 @@ executables:
617
617
  - contrast_service
618
618
  extensions:
619
619
  - ext/cs__common/extconf.rb
620
+ - ext/cs__os_information/extconf.rb
621
+ - ext/cs__assess_regexp/extconf.rb
622
+ - ext/cs__assess_string_interpolation26/extconf.rb
623
+ - ext/cs__contrast_patch/extconf.rb
624
+ - ext/cs__assess_active_record_named/extconf.rb
625
+ - ext/cs__assess_module/extconf.rb
620
626
  - ext/cs__assess_array/extconf.rb
627
+ - ext/cs__assess_kernel/extconf.rb
628
+ - ext/cs__assess_basic_object/extconf.rb
629
+ - ext/cs__assess_hash/extconf.rb
621
630
  - ext/cs__assess_fiber_track/extconf.rb
622
631
  - ext/cs__assess_marshal_module/extconf.rb
623
- - ext/cs__assess_active_record_named/extconf.rb
624
- - ext/cs__assess_basic_object/extconf.rb
625
632
  - ext/cs__assess_string/extconf.rb
626
- - ext/cs__assess_string_interpolation26/extconf.rb
627
- - ext/cs__assess_hash/extconf.rb
628
- - ext/cs__assess_module/extconf.rb
629
- - ext/cs__assess_regexp/extconf.rb
630
- - ext/cs__assess_kernel/extconf.rb
631
- - ext/cs__contrast_patch/extconf.rb
632
633
  - ext/cs__assess_yield_track/extconf.rb
633
634
  extra_rdoc_files: []
634
635
  files:
@@ -687,6 +688,9 @@ files:
687
688
  - ext/cs__contrast_patch/cs__contrast_patch.c
688
689
  - ext/cs__contrast_patch/cs__contrast_patch.h
689
690
  - ext/cs__contrast_patch/extconf.rb
691
+ - ext/cs__os_information/cs__os_information.c
692
+ - ext/cs__os_information/cs__os_information.h
693
+ - ext/cs__os_information/extconf.rb
690
694
  - ext/extconf_common.rb
691
695
  - funchook/LICENSE
692
696
  - funchook/Makefile.in
@@ -894,6 +898,7 @@ files:
894
898
  - lib/contrast/agent/inventory/policy/datastores.rb
895
899
  - lib/contrast/agent/inventory/policy/policy.rb
896
900
  - lib/contrast/agent/inventory/policy/trigger_node.rb
901
+ - lib/contrast/agent/metric_telemetry_event.rb
897
902
  - lib/contrast/agent/middleware.rb
898
903
  - lib/contrast/agent/module_data.rb
899
904
  - lib/contrast/agent/patching/policy/after_load_patch.rb
@@ -944,7 +949,10 @@ files:
944
949
  - lib/contrast/agent/rule_set.rb
945
950
  - lib/contrast/agent/scope.rb
946
951
  - lib/contrast/agent/service_heartbeat.rb
952
+ - lib/contrast/agent/startup_metrics_telemetry_event.rb
947
953
  - lib/contrast/agent/static_analysis.rb
954
+ - lib/contrast/agent/telemetry.rb
955
+ - lib/contrast/agent/telemetry_event.rb
948
956
  - lib/contrast/agent/thread.rb
949
957
  - lib/contrast/agent/thread_watcher.rb
950
958
  - lib/contrast/agent/tracepoint_hook.rb
@@ -986,6 +994,7 @@ files:
986
994
  - lib/contrast/api/dtm.pb.rb
987
995
  - lib/contrast/api/settings.pb.rb
988
996
  - lib/contrast/components/agent.rb
997
+ - lib/contrast/components/api.rb
989
998
  - lib/contrast/components/app_context.rb
990
999
  - lib/contrast/components/assess.rb
991
1000
  - lib/contrast/components/base.rb
@@ -1000,11 +1009,13 @@ files:
1000
1009
  - lib/contrast/components/settings.rb
1001
1010
  - lib/contrast/config.rb
1002
1011
  - lib/contrast/config/agent_configuration.rb
1012
+ - lib/contrast/config/api_configuration.rb
1003
1013
  - lib/contrast/config/application_configuration.rb
1004
1014
  - lib/contrast/config/assess_configuration.rb
1005
1015
  - lib/contrast/config/assess_rules_configuration.rb
1006
1016
  - lib/contrast/config/base_configuration.rb
1007
1017
  - lib/contrast/config/default_value.rb
1018
+ - lib/contrast/config/env_variables.rb
1008
1019
  - lib/contrast/config/exception_configuration.rb
1009
1020
  - lib/contrast/config/heap_dump_configuration.rb
1010
1021
  - lib/contrast/config/inventory_configuration.rb
@@ -1064,26 +1075,37 @@ files:
1064
1075
  - lib/contrast/security_exception.rb
1065
1076
  - lib/contrast/tasks/config.rb
1066
1077
  - lib/contrast/tasks/service.rb
1078
+ - lib/contrast/utils/assess/propagation_method_utils.rb
1079
+ - lib/contrast/utils/assess/property/tagged_utils.rb
1067
1080
  - lib/contrast/utils/assess/sampling_util.rb
1081
+ - lib/contrast/utils/assess/source_method_utils.rb
1068
1082
  - lib/contrast/utils/assess/tracking_util.rb
1083
+ - lib/contrast/utils/assess/trigger_method_utils.rb
1069
1084
  - lib/contrast/utils/class_util.rb
1070
1085
  - lib/contrast/utils/duck_utils.rb
1071
1086
  - lib/contrast/utils/env_configuration_item.rb
1087
+ - lib/contrast/utils/exclude_key.rb
1072
1088
  - lib/contrast/utils/hash_digest.rb
1073
1089
  - lib/contrast/utils/heap_dump_util.rb
1074
1090
  - lib/contrast/utils/invalid_configuration_util.rb
1075
1091
  - lib/contrast/utils/io_util.rb
1076
1092
  - lib/contrast/utils/job_servers_running.rb
1077
1093
  - lib/contrast/utils/lru_cache.rb
1094
+ - lib/contrast/utils/metrics_hash.rb
1078
1095
  - lib/contrast/utils/object_share.rb
1079
1096
  - lib/contrast/utils/os.rb
1097
+ - lib/contrast/utils/patching/policy/patch_utils.rb
1098
+ - lib/contrast/utils/patching/policy/patcher_utils.rb
1080
1099
  - lib/contrast/utils/preflight_util.rb
1100
+ - lib/contrast/utils/requests_client.rb
1081
1101
  - lib/contrast/utils/resource_loader.rb
1082
1102
  - lib/contrast/utils/ruby_ast_rewriter.rb
1083
1103
  - lib/contrast/utils/sha256_builder.rb
1084
1104
  - lib/contrast/utils/stack_trace_utils.rb
1085
1105
  - lib/contrast/utils/string_utils.rb
1086
1106
  - lib/contrast/utils/tag_util.rb
1107
+ - lib/contrast/utils/telemetry.rb
1108
+ - lib/contrast/utils/telemetry_identifier.rb
1087
1109
  - lib/contrast/utils/thread_tracker.rb
1088
1110
  - lib/contrast/utils/timer.rb
1089
1111
  - resources/assess/policy.json