# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true cs__scoped_require 'contrast/utils/sinatra_helper' cs__scoped_require 'rubygems/version' 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, :config DEFAULT_APP_NAME = 'rails' DEFAULT_APP_PATH = '/' DEFAULT_SERVER_NAME = 'localhost' DEFAULT_SERVER_PATH = '/' def ready? @_ready ||= AGENT.enabled? && Contrast::Utils::ServiceSenderUtil.connection_established? && Contrast::Utils::ServiceResponseUtil.update_received? end 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 name @_name ||= begin tmp = CONFIG.root.application.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 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 msg = Contrast::Api::Dtm::ApplicationCreate.new msg.group = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.group msg.tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.tags msg.app_version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.version.to_s msg.code = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.code msg.metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.metadata # Other fields have limits in TeamServer, the rest don't. msg.session_id = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.session_id, truncate: false msg.session_metadata = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.application.session_metadata, truncate: false msg end def build_agent_startup_message msg = Contrast::Api::Dtm::AgentStartup.new msg.server_name = Contrast::Utils::StringUtils.protobuf_format server_name msg.server_path = Contrast::Utils::StringUtils.protobuf_format server_path msg.server_type = Contrast::Utils::StringUtils.protobuf_format server_type msg.server_version = Contrast::Agent::VERSION msg.version = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.version msg.environment = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.environment msg.tags = Contrast::Utils::StringUtils.protobuf_format CONFIG.root.server.tags msg end def pid Process.pid end def ppid Process.ppid end def pgid Process.getpgid(pid) end def client_id @_client_id ||= [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