contrast-agent 4.12.0 → 4.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +1 -0
  3. data/ext/cs__assess_module/cs__assess_module.c +48 -0
  4. data/ext/cs__assess_module/cs__assess_module.h +7 -0
  5. data/ext/cs__common/cs__common.c +5 -0
  6. data/ext/cs__common/cs__common.h +8 -0
  7. data/ext/cs__contrast_patch/cs__contrast_patch.c +16 -1
  8. data/ext/cs__os_information/cs__os_information.c +31 -0
  9. data/ext/cs__os_information/cs__os_information.h +7 -0
  10. data/ext/cs__os_information/extconf.rb +5 -0
  11. data/lib/contrast/agent/assess/policy/policy_node.rb +6 -6
  12. data/lib/contrast/agent/assess/policy/policy_scanner.rb +5 -0
  13. data/lib/contrast/agent/assess/policy/propagation_method.rb +2 -116
  14. data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
  15. data/lib/contrast/agent/assess/policy/propagator/center.rb +1 -1
  16. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +2 -154
  17. data/lib/contrast/agent/assess/policy/source_method.rb +2 -71
  18. data/lib/contrast/agent/assess/policy/trigger_method.rb +45 -110
  19. data/lib/contrast/agent/assess/policy/trigger_node.rb +14 -6
  20. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -1
  21. data/lib/contrast/agent/assess/property/tagged.rb +53 -185
  22. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +40 -6
  23. data/lib/contrast/agent/deadzone/policy/policy.rb +1 -1
  24. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +1 -0
  25. data/lib/contrast/agent/metric_telemetry_event.rb +26 -0
  26. data/lib/contrast/agent/middleware.rb +14 -62
  27. data/lib/contrast/agent/patching/policy/method_policy.rb +3 -89
  28. data/lib/contrast/agent/patching/policy/method_policy_extend.rb +111 -0
  29. data/lib/contrast/agent/patching/policy/patch.rb +28 -235
  30. data/lib/contrast/agent/patching/policy/patcher.rb +14 -49
  31. data/lib/contrast/agent/reporting/report.rb +21 -0
  32. data/lib/contrast/agent/reporting/reporter.rb +142 -0
  33. data/lib/contrast/agent/reporting/reporting_events/finding.rb +90 -0
  34. data/lib/contrast/agent/reporting/reporting_events/preflight.rb +25 -0
  35. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +56 -0
  36. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +37 -0
  37. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +127 -0
  38. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +168 -0
  39. data/lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb +66 -0
  40. data/lib/contrast/agent/request.rb +2 -81
  41. data/lib/contrast/agent/request_context.rb +4 -128
  42. data/lib/contrast/agent/request_context_extend.rb +138 -0
  43. data/lib/contrast/agent/request_handler.rb +7 -3
  44. data/lib/contrast/agent/response.rb +2 -73
  45. data/lib/contrast/agent/startup_metrics_telemetry_event.rb +94 -0
  46. data/lib/contrast/agent/static_analysis.rb +5 -3
  47. data/lib/contrast/agent/telemetry.rb +137 -0
  48. data/lib/contrast/agent/telemetry_event.rb +33 -0
  49. data/lib/contrast/agent/thread_watcher.rb +66 -11
  50. data/lib/contrast/agent/version.rb +1 -1
  51. data/lib/contrast/agent.rb +21 -0
  52. data/lib/contrast/api/communication/connection_status.rb +10 -7
  53. data/lib/contrast/api/communication/messaging_queue.rb +37 -3
  54. data/lib/contrast/api/communication/response_processor.rb +15 -8
  55. data/lib/contrast/api/communication/service_lifecycle.rb +13 -3
  56. data/lib/contrast/api/communication/socket.rb +6 -8
  57. data/lib/contrast/api/communication/socket_client.rb +29 -12
  58. data/lib/contrast/api/communication/speedracer.rb +37 -1
  59. data/lib/contrast/api/communication/tcp_socket.rb +4 -3
  60. data/lib/contrast/api/communication/unix_socket.rb +1 -0
  61. data/lib/contrast/api/decorators/finding.rb +45 -0
  62. data/lib/contrast/components/api.rb +90 -0
  63. data/lib/contrast/components/app_context.rb +10 -41
  64. data/lib/contrast/components/app_context_extend.rb +78 -0
  65. data/lib/contrast/components/base.rb +23 -0
  66. data/lib/contrast/components/config.rb +92 -13
  67. data/lib/contrast/components/contrast_service.rb +11 -0
  68. data/lib/contrast/components/sampling.rb +2 -2
  69. data/lib/contrast/config/agent_configuration.rb +1 -1
  70. data/lib/contrast/config/api_configuration.rb +27 -0
  71. data/lib/contrast/config/api_proxy_configuration.rb +14 -0
  72. data/lib/contrast/config/application_configuration.rb +2 -3
  73. data/lib/contrast/config/assess_configuration.rb +3 -3
  74. data/lib/contrast/config/base_configuration.rb +17 -28
  75. data/lib/contrast/config/certification_configuration.rb +15 -0
  76. data/lib/contrast/config/env_variables.rb +18 -0
  77. data/lib/contrast/config/heap_dump_configuration.rb +6 -6
  78. data/lib/contrast/config/inventory_configuration.rb +1 -5
  79. data/lib/contrast/config/protect_rule_configuration.rb +1 -1
  80. data/lib/contrast/config/request_audit_configuration.rb +18 -0
  81. data/lib/contrast/config/root_configuration.rb +1 -0
  82. data/lib/contrast/config/ruby_configuration.rb +6 -6
  83. data/lib/contrast/config/service_configuration.rb +2 -2
  84. data/lib/contrast/config.rb +1 -1
  85. data/lib/contrast/configuration.rb +4 -2
  86. data/lib/contrast/extension/assess/array.rb +5 -7
  87. data/lib/contrast/extension/thread.rb +31 -12
  88. data/lib/contrast/framework/manager.rb +22 -44
  89. data/lib/contrast/framework/manager_extend.rb +50 -0
  90. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +9 -6
  91. data/lib/contrast/framework/rails/patch/support.rb +31 -29
  92. data/lib/contrast/framework/rails/railtie.rb +1 -1
  93. data/lib/contrast/framework/sinatra/support.rb +2 -1
  94. data/lib/contrast/logger/application.rb +4 -0
  95. data/lib/contrast/logger/log.rb +8 -103
  96. data/lib/contrast/utils/assess/propagation_method_utils.rb +129 -0
  97. data/lib/contrast/utils/assess/property/tagged_utils.rb +165 -0
  98. data/lib/contrast/utils/assess/source_method_utils.rb +83 -0
  99. data/lib/contrast/utils/assess/tracking_util.rb +20 -15
  100. data/lib/contrast/utils/assess/trigger_method_utils.rb +138 -0
  101. data/lib/contrast/utils/class_util.rb +18 -14
  102. data/lib/contrast/utils/exclude_key.rb +20 -0
  103. data/lib/contrast/utils/findings.rb +62 -0
  104. data/lib/contrast/utils/hash_digest.rb +10 -73
  105. data/lib/contrast/utils/hash_digest_extend.rb +86 -0
  106. data/lib/contrast/utils/head_dump_utils_extend.rb +74 -0
  107. data/lib/contrast/utils/heap_dump_util.rb +2 -65
  108. data/lib/contrast/utils/invalid_configuration_util.rb +29 -0
  109. data/lib/contrast/utils/io_util.rb +1 -1
  110. data/lib/contrast/utils/log_utils.rb +108 -0
  111. data/lib/contrast/utils/metrics_hash.rb +59 -0
  112. data/lib/contrast/utils/middleware_utils.rb +87 -0
  113. data/lib/contrast/utils/net_http_base.rb +158 -0
  114. data/lib/contrast/utils/object_share.rb +1 -0
  115. data/lib/contrast/utils/os.rb +23 -0
  116. data/lib/contrast/utils/patching/policy/patch_utils.rb +232 -0
  117. data/lib/contrast/utils/patching/policy/patcher_utils.rb +54 -0
  118. data/lib/contrast/utils/request_utils.rb +88 -0
  119. data/lib/contrast/utils/response_utils.rb +97 -0
  120. data/lib/contrast/utils/substitution_utils.rb +167 -0
  121. data/lib/contrast/utils/tag_util.rb +9 -9
  122. data/lib/contrast/utils/telemetry.rb +79 -0
  123. data/lib/contrast/utils/telemetry_client.rb +90 -0
  124. data/lib/contrast/utils/telemetry_identifier.rb +130 -0
  125. data/lib/contrast.rb +18 -0
  126. data/ruby-agent.gemspec +7 -6
  127. data/service_executables/VERSION +1 -1
  128. data/service_executables/linux/contrast-service +0 -0
  129. data/service_executables/mac/contrast-service +0 -0
  130. metadata +69 -22
  131. data/lib/contrast/config/default_value.rb +0 -17
@@ -6,15 +6,15 @@ require 'contrast/api/communication/socket'
6
6
  module Contrast
7
7
  module Api
8
8
  module Communication
9
- # This class allows us to create a TCP Socket to communicate to the Service
10
- # (Speed Racer). Either it or the Unix Socket will be used, as determined
11
- # by the configuration options set for Service communication.
9
+ # This class allows us to create a TCP Socket to communicate to the Service (Speed Racer). Either it or the Unix
10
+ # Socket will be used, as determined by the configuration options set for Service communication.
12
11
  class TcpSocket
13
12
  include Contrast::Api::Communication::Socket
14
13
 
15
14
  attr_reader :host, :port
16
15
 
17
16
  # Create the socket
17
+ #
18
18
  # @param host [String] socket target hostname or IP address
19
19
  # @param port [String,Integer] socket target port
20
20
  def initialize host, port
@@ -22,6 +22,7 @@ module Contrast
22
22
  @port = port.to_i
23
23
  end
24
24
 
25
+ # @return [::TCPSocket]
25
26
  def new_socket
26
27
  ::TCPSocket.new(host, port)
27
28
  end
@@ -18,6 +18,7 @@ module Contrast
18
18
  @path = path
19
19
  end
20
20
 
21
+ # @return [::UNIXSocket]
21
22
  def new_socket
22
23
  ::UNIXSocket.new(path)
23
24
  end
@@ -0,0 +1,45 @@
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/api/dtm.pb'
5
+ require 'contrast/utils/string_utils'
6
+ require 'contrast/components/base'
7
+
8
+ module Contrast
9
+ module Api
10
+ module Decorators
11
+ # Used to decorate the {Contrast::Api::Dtm::Finding} protobuf
12
+ # model so it can own the request which its data is for.
13
+ module Finding
14
+ def self.included klass
15
+ klass.extend(ClassMethods)
16
+ end
17
+
18
+ # Used to add class methods to the AgentStartup class on inclusion of the decorator
19
+ module ClassMethods
20
+ def build
21
+ new
22
+ end
23
+
24
+ def to_controlled_hash finding, *_args
25
+ {
26
+ hash_code: finding.hash_code,
27
+ platform: finding.platform,
28
+ rule_id: finding.rule_id,
29
+ evidence: finding.evidence,
30
+ properties: finding.properties,
31
+ events: finding.events,
32
+ tags: finding.tags,
33
+ version: finding.version,
34
+ routes: finding.routes,
35
+ session_id: finding.session_id,
36
+ teamserver_url: ::Contrast::API.api_url
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ Contrast::Api::Dtm::Finding.include(Contrast::Api::Decorators::Finding)
@@ -0,0 +1,90 @@
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/components/base'
5
+ require 'contrast/components/config'
6
+
7
+ module Contrast
8
+ module Components
9
+ module Api
10
+ # A wrapper build around the Common Agent Configuration project to allow
11
+ # for Api keys to be mapped with their values contained in their
12
+ # parent_configuration_spec.yaml.
13
+ class Interface
14
+ include Contrast::Components::ComponentBase
15
+
16
+ def api_url
17
+ @_api_url ||= ::Contrast::CONFIG.root.api.url
18
+ end
19
+
20
+ def api_key
21
+ @_api_key ||= ::Contrast::CONFIG.root.api.api_key
22
+ end
23
+
24
+ def service_key
25
+ @_service_key ||= ::Contrast::CONFIG.root.api.service_key
26
+ end
27
+
28
+ def username
29
+ @_username ||= ::Contrast::CONFIG.root.api.user_name
30
+ end
31
+
32
+ def proxy_enabled?
33
+ @_proxy_enabled = true?(::Contrast::CONFIG.root.api.proxy.enable) if @_proxy_enabled.nil?
34
+ @_proxy_enabled
35
+ end
36
+
37
+ def proxy_url
38
+ @_proxy_url ||= ::Contrast::CONFIG.root.api.proxy.url
39
+ end
40
+
41
+ def request_audit_enable
42
+ @_request_audit_enable ||= true?(::Contrast::CONFIG.root.api.request_audit.enable)
43
+ end
44
+
45
+ def request_audit_requests
46
+ return @_request_audit_requests unless @_request_audit_requests.nil?
47
+
48
+ @_request_audit_requests = true?(::Contrast::CONFIG.root.api.request_audit.requests)
49
+ end
50
+
51
+ def request_audit_responses
52
+ return @_request_audit_responses unless @_request_audit_responses.nil?
53
+
54
+ @_request_audit_responses = true?(::Contrast::CONFIG.root.api.request_audit.responses)
55
+ end
56
+
57
+ def request_audit_path
58
+ @_request_audit_path ||= ::Contrast::CONFIG.root.api.request_audit.path.to_s
59
+ end
60
+
61
+ def certification_enabled?
62
+ @_certification_enabled ||= certification_truly_enabled?(::Contrast::CONFIG.root.api.certificate)
63
+ end
64
+
65
+ def certification_ca_file
66
+ @_certification_ca_file ||= ::Contrast::CONFIG.root.api.certificate.ca_file
67
+ end
68
+
69
+ def certification_cert_file
70
+ @_certification_cert_file ||= ::Contrast::CONFIG.root.api.certificate.cert_file
71
+ end
72
+
73
+ def certification_key_file
74
+ @_certification_key_file ||= ::Contrast::CONFIG.root.api.certificate.key_file
75
+ end
76
+
77
+ private
78
+
79
+ def certification_truly_enabled? config_path
80
+ return false unless true?(config_path.enable)
81
+ return true if file_exists?(certification_ca_file) && valid_cert?(certification_ca_file)
82
+ return true if file_exists?(certification_cert_file) && valid_cert?(certification_cert_file)
83
+ return true if file_exists?(certification_key_file) && valid_cert?(certification_key_file)
84
+
85
+ false
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -5,6 +5,7 @@ require 'rubygems/version'
5
5
  require 'contrast/api/decorators/agent_startup'
6
6
  require 'contrast/api/decorators/application_startup'
7
7
  require 'contrast/utils/object_share'
8
+ require 'contrast/components/app_context_extend'
8
9
 
9
10
  module Contrast
10
11
  module Components
@@ -15,6 +16,7 @@ module Contrast
15
16
  # Specifically, this allows for querying the state of the Application,
16
17
  # including the Client, Process, and Server information.
17
18
  class Interface
19
+ include Contrast::Components::AppContextExtend
18
20
  include Contrast::Components::ComponentBase
19
21
  include Contrast::Components::Logger::InstanceMethods
20
22
 
@@ -46,6 +48,14 @@ module Contrast
46
48
  end
47
49
  end
48
50
 
51
+ def session_id
52
+ @_session_id ||= build_app_startup_message.session_id
53
+ end
54
+
55
+ def app_version
56
+ @_app_version ||= Contrast::CONFIG.root.application.version
57
+ end
58
+
49
59
  def path
50
60
  @_path ||= begin
51
61
  tmp = ::Contrast::CONFIG.root.application.path
@@ -76,47 +86,6 @@ module Contrast
76
86
  end
77
87
  end
78
88
 
79
- def build_app_startup_message
80
- Contrast::Api::Dtm::ApplicationCreate.build
81
- end
82
-
83
- def build_agent_startup_message
84
- msg = Contrast::Api::Dtm::AgentStartup.build(server_name, server_path, server_type)
85
- logger.info('Application context',
86
- server_name: msg.server_name,
87
- server_path: msg.server_path,
88
- server_type: msg.server_type,
89
- application_name: app_name,
90
- application_path: path,
91
- application_language: Contrast::Utils::ObjectShare::RUBY)
92
-
93
- msg
94
- end
95
-
96
- def pid
97
- Process.pid
98
- end
99
-
100
- def ppid
101
- Process.ppid
102
- end
103
-
104
- def pgid
105
- Process.getpgid(pid)
106
- end
107
-
108
- def client_id
109
- @_client_id ||= [app_name, pgid].join('-')
110
- end
111
-
112
- def instrument_middleware_stack?
113
- !Contrast::Utils::JobServersRunning.job_servers_running?
114
- end
115
-
116
- def disabled_agent_rake_tasks
117
- ::Contrast::CONFIG.root.agent.ruby.disabled_agent_rake_tasks
118
- end
119
-
120
89
  # Determines if the Process we're currently in matches that of the
121
90
  # Process in which the App Context instance was created.
122
91
  # If it doesn't, that indicates the running context is in a new
@@ -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
+ module Contrast
5
+ module Components
6
+ # A wrapper build around the Common Agent Configuration project to allow
7
+ # for access of the values contained in its
8
+ # parent_configuration_spec.yaml.
9
+ # Specifically, this allows for querying the state of the Application,
10
+ # including the Client, Process, and Server information.
11
+ module AppContextExtend
12
+ SUPPORTED_FRAMEWORKS = %w[rails sinatra grape rack].cs__freeze
13
+ SUPPORTED_SERVERS = %w[passenger puma thin unicorn].cs__freeze
14
+
15
+ def build_app_startup_message
16
+ @_build_app_startup_message ||= Contrast::Api::Dtm::ApplicationCreate.build
17
+ end
18
+
19
+ def build_agent_startup_message
20
+ msg = Contrast::Api::Dtm::AgentStartup.build(server_name, server_path, server_type)
21
+ logger.info('Application context',
22
+ server_name: msg.server_name,
23
+ server_path: msg.server_path,
24
+ server_type: msg.server_type,
25
+ application_name: app_name,
26
+ application_path: path,
27
+ application_language: Contrast::Utils::ObjectShare::RUBY)
28
+
29
+ msg
30
+ end
31
+
32
+ def pid
33
+ Process.pid
34
+ end
35
+
36
+ def ppid
37
+ Process.ppid
38
+ end
39
+
40
+ def pgid
41
+ Process.getpgid(pid)
42
+ end
43
+
44
+ def client_id
45
+ @_client_id ||= [app_name, pgid].join('-')
46
+ end
47
+
48
+ def app_and_server_information
49
+ {
50
+ application_info: find_gem_information(SUPPORTED_FRAMEWORKS),
51
+ server_info: find_gem_information(SUPPORTED_SERVERS)
52
+ }
53
+ end
54
+
55
+ def find_gem_information arr
56
+ arr.each do |framework|
57
+ next unless Gem.loaded_specs.key?(framework)
58
+
59
+ loaded = Gem.loaded_specs[framework]
60
+ next unless loaded
61
+
62
+ name = loaded.instance_variable_get(:@name)
63
+ version = loaded.instance_variable_get(:@version).to_s
64
+ return [name, version].join(' ')
65
+ end
66
+ nil
67
+ end
68
+
69
+ def instrument_middleware_stack?
70
+ !Contrast::Utils::JobServersRunning.job_servers_running?
71
+ end
72
+
73
+ def disabled_agent_rake_tasks
74
+ ::Contrast::CONFIG.root.agent.ruby.disabled_agent_rake_tasks
75
+ end
76
+ end
77
+ end
78
+ end
@@ -35,6 +35,29 @@ module Contrast
35
35
 
36
36
  config_param.downcase == Contrast::Utils::ObjectShare::TRUE
37
37
  end
38
+
39
+ # this method will check if a path could be possibly used
40
+ # So for example if we pass a path to a file - we'll check
41
+ # if there is actually that file and if it's with certain extension
42
+ #
43
+ # @param config_path [String,nil]
44
+ # @return [Boolean]
45
+ def valid_cert? config_path
46
+ return false if config_path.nil?
47
+
48
+ exts = %w[.pem .crt .cer].cs__freeze
49
+ return false unless exts.include?(File.extname(config_path))
50
+
51
+ true
52
+ end
53
+
54
+ # check if file exists at all
55
+ # @param path [String,nil]
56
+ def file_exists? path
57
+ return false unless path
58
+
59
+ File.exist? path
60
+ end
38
61
  end
39
62
  end
40
63
  end
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/utils/env_configuration_item'
5
+ require 'ougai'
5
6
  require 'contrast/configuration'
6
7
 
7
8
  module Contrast
@@ -23,17 +24,33 @@ module Contrast
23
24
  # time than to silently fail to deliver functionality.
24
25
  module Config
25
26
  CONTRAST_ENV_MARKER = 'CONTRAST__'
27
+ CONTRAST_LOG = 'contrast_agent.log'
28
+ CONTRAST_NAME = 'Contrast Agent'
26
29
 
27
30
  class Interface # :nodoc:
28
31
  def initialize
29
32
  build
30
33
  end
31
34
 
32
- def build log: true
35
+ # Basic logger for handling configuration validation logging
36
+ # the file to log is determined by the default one or set
37
+ # by the config file, if that configuration is found
38
+ def proto_logger
39
+ @_proto_logger ||= begin
40
+ @_proto_logger = ::Ougai::Logger.new(logger_path || CONTRAST_LOG)
41
+ @_proto_logger.progname = CONTRAST_NAME
42
+ @_proto_logger.level = ::Ougai::Logging::Severity::WARN
43
+ @_proto_logger.formatter = Contrast::Logger::Format.new
44
+ @_proto_logger.formatter.datetime_format = '%Y-%m-%dT%H:%M:%S.%L%z'
45
+ @_proto_logger
46
+ end
47
+ end
48
+
49
+ def build
33
50
  @_valid = nil
34
51
  @config = Contrast::Configuration.new
35
52
  env_overrides
36
- validate(log: log)
53
+ validate
37
54
  end
38
55
  alias_method :rebuild, :build
39
56
 
@@ -43,7 +60,7 @@ module Contrast
43
60
  end
44
61
 
45
62
  def valid?
46
- @_valid = validate(log: false) if @_valid.nil?
63
+ @_valid = validate if @_valid.nil?
47
64
  @_valid
48
65
  end
49
66
 
@@ -59,20 +76,28 @@ module Contrast
59
76
 
60
77
  SESSION_VARIABLES = 'Invalid configuration. '\
61
78
  "Setting both application.session_id and application.session_metadata is not allowed.\n"
62
- def validate log: false
79
+ API_URL = "Invalid configuration. Missing a required connection value 'url' is not set."
80
+ API_KEY = "Invalid configuration. Missing a required connection value 'api_key' is not set."
81
+ API_SERVICE_KEY = "Invalid configuration. Missing a required connection value 'service_tag' is not set."
82
+ API_USERNAME = "Invalid configuration. Missing a required connection value 'user_name' is not set."
83
+ def validate
63
84
  # The config has information about how to construct the logger.
64
85
  # If the config is invalid, and you want to know about it, then
65
86
  # you have a circular dependency if you try to log it,
66
- # hence `log: false`.
87
+ # so we use basic proto_logger to do this job.
67
88
  if !session_id.empty? && !session_metadata.empty?
68
- if log
69
- cs__class.log_error(SESSION_VARIABLES)
70
- else
71
- puts SESSION_VARIABLES
72
- end
89
+ proto_logger.error(SESSION_VARIABLES)
73
90
  return false
74
91
  end
75
-
92
+ if bypass
93
+ msg = []
94
+ msg << API_URL unless api_url
95
+ msg << API_KEY unless api_key
96
+ msg << API_SERVICE_KEY unless api_service_key
97
+ msg << API_USERNAME unless api_username
98
+ msg.any? { |m| proto_logger.error(m) }
99
+ return false unless msg.empty?
100
+ end
76
101
  true
77
102
  end
78
103
 
@@ -95,7 +120,7 @@ module Contrast
95
120
  # @return [String,nil] the value of the session id set in the
96
121
  # configuration, or nil if unset
97
122
  def session_id
98
- @config.application.session_id
123
+ root.application.session_id
99
124
  end
100
125
 
101
126
  # Typically, this would be accessed through
@@ -106,7 +131,61 @@ module Contrast
106
131
  # @return [String,nil] the value of the session metadata set in the
107
132
  # configuration, or nil if unset
108
133
  def session_metadata
109
- @config.application.session_metadata
134
+ root.application.session_metadata
135
+ end
136
+
137
+ # Typically, the following values would be accessed through Contrast::Components::AppContext
138
+ # and Contrast::Components::API, but we're too early in the initialization of the Agent to use
139
+ # that mechanism, so we look it up directly for ourselves.
140
+ #
141
+ # @return [String, nil]
142
+ def api_url
143
+ root.api.url
144
+ end
145
+
146
+ # Typically, the following values would be accessed through Contrast::Components::AppContext
147
+ # and Contrast::Components::API, but we're too early in the initialization of the Agent to use
148
+ # that mechanism, so we look it up directly for ourselves.
149
+ #
150
+ # @return [String, nil]
151
+ def api_key
152
+ root.api.api_key
153
+ end
154
+
155
+ # Typically, the following values would be accessed through Contrast::Components::AppContext
156
+ # and Contrast::Components::API, but we're too early in the initialization of the Agent to use
157
+ # that mechanism, so we look it up directly for ourselves.
158
+ #
159
+ # @return [String, nil]
160
+ def api_service_key
161
+ root.api.service_key
162
+ end
163
+
164
+ # Typically, the following values would be accessed through Contrast::Components::AppContext
165
+ # and Contrast::Components::API, but we're too early in the initialization of the Agent to use
166
+ # that mechanism, so we look it up directly for ourselves.
167
+ #
168
+ # @return [String, nil]
169
+ def api_username
170
+ root.api.user_name
171
+ end
172
+
173
+ # Typically, the following values would be accessed through Contrast::Components::AppContext
174
+ # and Contrast::Components::API, but we're too early in the initialization of the Agent to use
175
+ # that mechanism, so we look it up directly for ourselves.
176
+ #
177
+ # @return [String, nil]
178
+ def bypass
179
+ root.agent.service.bypass
180
+ end
181
+
182
+ # Typically, the following values would be accessed through Contrast::Components::AppContext
183
+ # and Contrast::Components::Logger, but we're too early in the initialization of the Agent to use
184
+ # that mechanism, so we look it up directly for ourselves.
185
+ #
186
+ # @return [String, nil]
187
+ def logger_path
188
+ root.agent.logger.path
110
189
  end
111
190
  end
112
191
  end
@@ -15,6 +15,7 @@ module Contrast
15
15
  include Contrast::Components::ComponentBase
16
16
 
17
17
  DEFAULT_SERVICE_LOG = 'contrast_service.log'
18
+ DEFAULT_SERVICE_LEVEL = :TRACE
18
19
  # The Rails ActionDispatch regexp for localhost IP + literal localhost
19
20
  # https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/request.rb#L32
20
21
  LOCALHOST = Regexp.union [/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/, /^localhost$/]
@@ -31,6 +32,12 @@ module Contrast
31
32
  (LOCALHOST.match?(host) || !!socket_path)
32
33
  end
33
34
 
35
+ def use_agent_communication?
36
+ return @_use_agent_communication unless @_use_agent_communication.nil?
37
+
38
+ @_use_agent_communication = true?(::Contrast::CONFIG.root.agent.service.bypass)
39
+ end
40
+
34
41
  def host
35
42
  @_host ||=
36
43
  (::Contrast::CONFIG.root.agent.service.host || Contrast::Config::ServiceConfiguration::DEFAULT_HOST).to_s
@@ -53,6 +60,10 @@ module Contrast
53
60
  @_logger_path ||= ::Contrast::CONFIG.root.agent.service.logger.path || DEFAULT_SERVICE_LOG
54
61
  end
55
62
 
63
+ def logger_level
64
+ @_logger_level ||= ::Contrast::CONFIG.root.agent.service.logger.level || DEFAULT_SERVICE_LEVEL
65
+ end
66
+
56
67
  private
57
68
 
58
69
  def disabled?
@@ -14,7 +14,7 @@ module Contrast
14
14
  DEFAULT_SAMPLING_WINDOW_MS = 180_000
15
15
  end
16
16
 
17
- module ClassMethods #:nodoc:
17
+ module ClassMethods # :nodoc:
18
18
  include Contrast::Components::ComponentBase
19
19
  include Constants
20
20
 
@@ -90,7 +90,7 @@ module Contrast
90
90
  end
91
91
  end
92
92
 
93
- module InstanceMethods #:nodoc:
93
+ module InstanceMethods # :nodoc:
94
94
  include Contrast::Components::ComponentBase
95
95
  include Constants
96
96
  include ClassMethods
@@ -8,7 +8,7 @@ module Contrast
8
8
  class AgentConfiguration < BaseConfiguration
9
9
  KEYS = {
10
10
  enable: EMPTY_VALUE,
11
- start_bundled_service: Contrast::Config::DefaultValue.new(true),
11
+ start_bundled_service: true,
12
12
  omit_body: EMPTY_VALUE,
13
13
  service: Contrast::Config::ServiceConfiguration,
14
14
  logger: Contrast::Config::LoggerConfiguration,
@@ -0,0 +1,27 @@
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/config/api_proxy_configuration'
5
+ require 'contrast/config/certification_configuration'
6
+ require 'contrast/config/request_audit_configuration'
7
+
8
+ module Contrast
9
+ module Config
10
+ # Api keys configuration
11
+ class ApiConfiguration < BaseConfiguration
12
+ URL = 'https://app.contrastsecurity.com/contrast'
13
+ KEYS = {
14
+ api_key: EMPTY_VALUE,
15
+ url: URL,
16
+ user_name: EMPTY_VALUE,
17
+ service_key: EMPTY_VALUE,
18
+ proxy: Contrast::Config::ApiProxyConfiguration,
19
+ request_audit: Contrast::Config::RequestAuditConfiguration,
20
+ certificate: Contrast::Config::CertificationConfiguration
21
+ }.cs__freeze
22
+ def initialize hsh
23
+ super(hsh, KEYS)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
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
+ module Contrast
5
+ module Config
6
+ # Api Proxy keys configuration
7
+ class ApiProxyConfiguration < BaseConfiguration
8
+ KEYS = { enable: false, url: EMPTY_VALUE }.cs__freeze
9
+ def initialize hsh
10
+ super(hsh, KEYS)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,7 +1,6 @@
1
1
  # Copyright (c) 2021 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
4
  require 'contrast/utils/object_share'
6
5
 
7
6
  module Contrast
@@ -18,8 +17,8 @@ module Contrast
18
17
  tags: EMPTY_VALUE,
19
18
  code: EMPTY_VALUE,
20
19
  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
+ session_id: Contrast::Utils::ObjectShare::EMPTY_STRING,
21
+ session_metadata: Contrast::Utils::ObjectShare::EMPTY_STRING
23
22
  }.cs__freeze
24
23
 
25
24
  def initialize hsh
@@ -9,11 +9,11 @@ module Contrast
9
9
  KEYS = {
10
10
  tags: EMPTY_VALUE,
11
11
  enable: EMPTY_VALUE,
12
- enable_scan_response: Contrast::Config::DefaultValue.new('true'),
13
- enable_dynamic_sources: Contrast::Config::DefaultValue.new('true'),
12
+ enable_scan_response: true,
13
+ enable_dynamic_sources: true,
14
14
  sampling: Contrast::Config::SamplingConfiguration,
15
15
  rules: Contrast::Config::AssessRulesConfiguration,
16
- stacktraces: Contrast::Config::DefaultValue.new('ALL')
16
+ stacktraces: 'ALL'
17
17
  }.cs__freeze
18
18
 
19
19
  def initialize hsh