Class: Contrast::Agent::Reporting::ReporterClient

Inherits:
Utils::NetHttpBase show all
Includes:
Endpoints, ReporterClientUtils, ResponseHandlerUtils, Components::Logger::InstanceMethods
Defined in:
lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb

Overview

This class creates a Net::HTTP client and initiates a connection to the provided result

Constant Summary collapse

RECORDABLE_EVENTS =

Returns events that may result in configuration changes.

Returns:

  • (Array<Class>)

    events that may result in configuration changes

[
  Contrast::Agent::Reporting::ServerSettings,
  Contrast::Agent::Reporting::ApplicationSettings,
  Contrast::Agent::Reporting::AgentStartup,
  Contrast::Agent::Reporting::ApplicationStartup
].cs__freeze
SERVICE_NAME =
'Reporter'
REPORT_CONFIG_WHEN =
%w[200 304].cs__freeze

Constants included from ResponseHandlerUtils

Contrast::Agent::Reporting::ResponseHandlerUtils::APP_NON_EXISTENT_MSG, Contrast::Agent::Reporting::ResponseHandlerUtils::ERROR_CODES, Contrast::Agent::Reporting::ResponseHandlerUtils::FORBIDDEN_MSG, Contrast::Agent::Reporting::ResponseHandlerUtils::FORBIDDEN_NO_ACTION_MSG, Contrast::Agent::Reporting::ResponseHandlerUtils::RETRY_AFTER_MSG, Contrast::Agent::Reporting::ResponseHandlerUtils::SUSPEND_MSG, Contrast::Agent::Reporting::ResponseHandlerUtils::UNPROCESSABLE_ENTITY_MSG, Contrast::Agent::Reporting::ResponseHandlerUtils::UNSUCCESSFULLY_RECEIVED_MSG

Constants included from ReporterClientUtils

Contrast::Agent::Reporting::ReporterClientUtils::STARTUP_EVENTS, Contrast::Agent::Reporting::ReporterClientUtils::STRING_ENCODING

Constants included from Endpoints

Endpoints::APP_LANGUAGE, Endpoints::ENDPOINT_VERSION, Endpoints::NG_ENDPOINTS

Constants included from Resend

Contrast::Agent::Reporting::Resend::END_RESENDING_MESSAGE, Contrast::Agent::Reporting::Resend::RESCUE_ATTEMPTS, Contrast::Agent::Reporting::Resend::RESENDING_MESSAGE, Contrast::Agent::Reporting::Resend::RETRY_ERRORS, Contrast::Agent::Reporting::Resend::TIMEOUT

Instance Attribute Summary collapse

Attributes inherited from Utils::NetHttpBase

#client_name

Instance Method Summary collapse

Methods included from Components::Logger::InstanceMethods

#cef_logger, #logger

Methods included from ResponseHandlerUtils

#last_application_modified, #last_response_code, #last_server_modified, #stop_reporting

Methods included from ReporterClientUtils

#audit

Methods included from Endpoints

application_activity, application_inventory, application_settings, application_startup, effective_config, heartbeat, library_usage, observed_route, server_settings, trace_observed

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

Methods included from Resend

#disable_reporting, #end_of_rescue, #handle_resend, #handle_response_error, #try_resend

Methods inherited from Utils::NetHttpBase

#connection_verified?, last_error, last_error=

Constructor Details

#initializeReporterClient

Returns a new instance of ReporterClient.



42
43
44
45
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 42

def initialize
  @headers = Contrast::Agent::Reporting::Headers.new
  super()
end

Instance Attribute Details

#headersContrast::Agent::Reporting::Headers (readonly)

Returns the current value of headers.

Returns:



24
25
26
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 24

def headers
  @headers
end

Instance Method Details

#compress_event(event, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY) ⇒ String

Compress data with Zlib

Parameters:

  • event (Contrast::Agent::Reporting::ReportingEvent)
  • level (Integer) (defaults to: Zlib::DEFAULT_COMPRESSION)

    compression level

  • strategy (Integer) (defaults to: Zlib::DEFAULT_STRATEGY)

    compression strategy

Returns:

  • (String)

    compressed data



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 158

def compress_event event, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY
  compressed_data = StringIO.new.set_encoding(STRING_ENCODING)
  gzip = Zlib::GzipWriter.new(compressed_data, level, strategy)
  gzip.write(event.event_json)
  gzip.close
  gzip = nil
  compressed_event = compressed_data.string.dup
  compressed_data.close
  compressed_data = nil
  compressed_event
ensure
  gzip&.close
  compressed_data&.close
  compressed_event
end

#decompress(compresed_data) ⇒ Object

Reads compressed data

Parameters:



177
178
179
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 177

def decompress compresed_data
  Zlib::GzipReader.wrap(StringIO.new(compresed_data), &:read)
end

#diagnosticsContrast::Config::Diagnostics::Monitor



148
149
150
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 148

def diagnostics
  @_diagnostics ||= Contrast::Config::Diagnostics::Monitor.new(Contrast::LOGGER.path)
end

#enter_run_modeObject



201
202
203
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 201

def enter_run_mode
  response_handler.enter_run_mode
end

#initialize_connectionNet::HTTP?

This method initializes the Net::HTTP client we’ll need. it will validate the connection and make the first request. If connection is valid and response is available then the open connection is returned.

Returns:

  • (Net::HTTP, nil)

    Return open connection or nil



52
53
54
55
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 52

def initialize_connection
  # for this client we would use proxy and custom certificate file if available
  super(SERVICE_NAME, Contrast::API.api_url, use_proxy: true, use_custom_cert: true)
end

#modeObject



197
198
199
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 197

def mode
  response_handler.mode
end

#process_event_response(event, response, connection) ⇒ Object

Only two types of events require processing when returned from TeamServer; preflight and settings. For Settings, we want to update internally and then report the resulting configuration. For preflight, we want to process the response and send findings if requested.

Parameters:



100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 100

def process_event_response event, response, connection
  case event
  when Contrast::Agent::Reporting::Preflight
    process_preflight_response(event, response, connection)
  when Contrast::Agent::Reporting::AgentStartup,
    Contrast::Agent::Reporting::ApplicationStartup,
    Contrast::Agent::Reporting::ApplicationSettings,
    Contrast::Agent::Reporting::ServerSettings

    process_settings_response(response, event)
    report_configuration(response, event)
  end
end

#put_to_sleepObject



189
190
191
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 189

def put_to_sleep
  response_handler.put_to_sleep
end

#report_configuration(response, event) ⇒ Object

Write effective config to file: If we are here the create and server messages are sent and the code received is 200 or 304. In case of 304 there will be no new settings and we can write current ones. This is done on every settings request.

Parameters:



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 121

def report_configuration response, event
  return unless response

  diagnostics.config.determine_config_status(response_handler.last_response_code || response.code)
  return unless REPORT_CONFIG_WHEN.include?(response_handler.last_response_code || response.code)
  return unless RECORDABLE_EVENTS.include?(event&.cs__class)

  logger.info('[Reporter Diagnostics] last response code:', response_code: response_handler.last_response_code)
  diagnostics.write_to_file
  config_event = Contrast::Agent::Reporting::AgentEffectiveConfig.new(diagnostics)
  Contrast::Agent.reporter.send_event(config_event)
rescue StandardError => e
  #  Don't let this error bubble up and stop the agent reporting, with resending triggered.
  logger.error('[Reporter] Error while reporting configuration', error: e, event_type: event&.cs__class)
end

#response_handlerContrast::Agent::Reporting::ResponseHandler



143
144
145
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 143

def response_handler
  @_response_handler ||= Contrast::Agent::Reporting::ResponseHandler.new
end

#send_event(event, connection) ⇒ Object

Check event type and send it to appropriate TS endpoint

Parameters:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 72

def send_event event, connection
  return unless connection
  return unless event.valid?

  logger.debug('[Reporter] Preparing to send reporting event', event_class: event.cs__class)
  request = build_request(event)
  begin
    response = connection.request(request)
  rescue StandardError => e
    handle_response_error(event, connection, e)
    return
  end
  audit.audit_event(event, response) if ::Contrast::API.request_audit_enable
  process_event_response(event, response, connection)
  response
rescue StandardError => e
  logger.error('[Reporter] Error while processing event sent to TeamServer',
               error: e,
               event_type: event&.cs__class)
end

#sleep?Boolean

Forwarders #

Returns:

  • (Boolean)


185
186
187
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 185

def sleep?
  response_handler.sleep?
end

#startup!(connection) ⇒ Object

Start the client for first time and sent startup event

Parameters:

  • connection (Net::HTTP)

    open connection



60
61
62
63
64
65
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 60

def startup! connection
  return if status.startup_messages_sent?
  return unless connection

  send_agent_startup(connection)
end

#statusContrast::Agent::Reporting::ConnectionStatus



138
139
140
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 138

def status
  @_status ||= Contrast::Agent::Reporting::ConnectionStatus.new
end

#timeoutObject



193
194
195
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 193

def timeout
  response_handler.timeout
end

#wake_upObject



205
206
207
# File 'lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb', line 205

def wake_up
  response_handler.wake_up
end