# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'rubygems/version' require 'contrast/api/decorators/agent_startup' require 'contrast/api/decorators/application_startup' require 'contrast/utils/object_share' module Contrast module Components module AppContext # A wrapper build around the Common Agent Configuration project to allow # for access of the values contained in its # parent_configuration_spec.yaml. # Specifically, this allows for querying the state of the Application, # including the Client, Process, and Server information. class Interface include Contrast::Components::ComponentBase include Contrast::Components::Interface access_component :agent, :analysis, :config, :logging DEFAULT_APP_NAME = 'rails' DEFAULT_APP_PATH = '/' DEFAULT_SERVER_NAME = 'localhost' DEFAULT_SERVER_PATH = '/' def initialize original_pid end def server_type @_server_type ||= begin tmp = CONFIG.root.server.type tmp = Contrast::Agent.framework_manager.server_type unless Contrast::Utils::StringUtils.present?(tmp) tmp end end def app_name @_app_name ||= begin tmp = CONFIG.root.application.name # rubocop:disable Security/Module/Name tmp = Contrast::Agent.framework_manager.app_name unless Contrast::Utils::StringUtils.present?(tmp) tmp = File.basename(Dir.pwd) unless Contrast::Utils::StringUtils.present?(tmp) Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_APP_NAME) rescue StandardError DEFAULT_APP_NAME end end def path @_path ||= begin tmp = CONFIG.root.application.path Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_APP_PATH) rescue StandardError DEFAULT_APP_PATH end end def server_name @_server_name ||= begin tmp = CONFIG.root.server.name # rubocop:disable Security/Module/Name tmp = Socket.gethostname unless Contrast::Utils::StringUtils.present?(tmp) tmp = Contrast::Utils::StringUtils.force_utf8(tmp) Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_SERVER_NAME) rescue StandardError DEFAULT_SERVER_NAME end end def server_path @_server_path ||= begin tmp = CONFIG.root.server.path tmp = Dir.pwd unless Contrast::Utils::StringUtils.present?(tmp) Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_SERVER_PATH) rescue StandardError DEFAULT_SERVER_PATH end end def build_app_startup_message Contrast::Api::Dtm::ApplicationCreate.build end def build_agent_startup_message msg = Contrast::Api::Dtm::AgentStartup.build(server_name, server_path, server_type) logger.info('Application context', server_name: msg.server_name, server_path: msg.server_path, server_type: msg.server_type, application_name: app_name, application_path: path, application_language: Contrast::Utils::ObjectShare::RUBY) msg end def pid Process.pid end def ppid Process.ppid end def pgid Process.getpgid(pid) end def client_id @_client_id ||= [app_name, pgid].join('-') end def instrument_middleware_stack? !Contrast::Utils::JobServersRunning.job_servers_running? end def disabled_agent_rake_tasks CONFIG.root.agent.ruby.disabled_agent_rake_tasks end # Determines if the Process we're currently in matches that of the # Process in which the App Context instance was created. # If it doesn't, that indicates the running context is in a new # Process. # @return [Boolean] if we're in the original Process in which the # App Context instance was initialized. def in_new_process? current_pid = Process.pid original_pid = pid current_pid != original_pid end private def original_pid @_original_pid ||= Process.pid end end COMPONENT_INTERFACE = Interface.new end end end