# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/utils/object_share' module Contrast module Agent module DiagnosticsConfig # Diagnostics tools to be included in config components. module DiagnosticsTools CHECK = 'd' # Converts current configuration for array of values to effective config values class and appends them to # EffectiveConfig class. Must be used inside Config Components only. # # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig] # @param config_values [Array<String>] array of the names of values. # @param canonical_prefix [String] starting of the path to config => api.proxy... # @param name_prefix [String] the name of the config prefix => contrast.api_key, contrast.url def add_effective_config_values effective_config, config_values, canonical_prefix, name_prefix return if config_values.to_s.empty? config_values.each do |config| Contrast::Agent::DiagnosticsConfig::EffectiveConfigValue.new.tap do |value| next if (config_val = send(config.to_sym)).to_s.empty? config_name = assign_name(config) value.canonical_name = "#{ canonical_prefix }.#{ config_name }" value.name = "#{ name_prefix }.#{ config_name }" value.value = config_val value.source = Contrast::CONFIG.sources.get(value.canonical_name) if value.source == Contrast::Components::Config::Sources::YAML value.filename = Contrast::CONFIG.config_file_path end effective_config.values << value rescue StandardError => e log_error(e) next end end end # Converts current configuration for single value to effective config values class and appends them to # EffectiveConfig class. Must be used inside Config Components only. # # @param effective_config [Contrast::Agent::DiagnosticsConfig::EffectiveConfig] # @param config_name [String] name of the config. # @param config_value [String, Boolean] value of the config. # @param canonical_prefix [String] starting of the path to config => api.proxy... # @param name_prefix [String] the name of the config prefix => contrast.api_key, contrast.url def add_single_effective_value effective_config, config_name, config_value, canonical_prefix, name_prefix Contrast::Agent::DiagnosticsConfig::EffectiveConfigValue.new.tap do |value| break if config_value.to_s.empty? value.value = config_value value.canonical_name = "#{ canonical_prefix }.#{ config_name }" value.name = "#{ name_prefix }.#{ config_name }" value.source = Contrast::CONFIG.sources.get(value.canonical_name) if value.source == Contrast::Components::Config::Sources::YAML value.filename = Contrast::CONFIG.config_file_path end effective_config.values << value rescue StandardError => e log_error(e) next end end private # Assigns a proper name for the config removing '?' out of method names. # # @param config [String] name of the configuration # @return [String] def assign_name config return Contrast::Utils::ObjectShare::EMPTY_STRING unless config name = config.dup if name.end_with?(Contrast::Utils::ObjectShare::QUESTION_MARK) # check and remove '?' : start_bundled_service? => start_bundled_service name.delete!(Contrast::Utils::ObjectShare::QUESTION_MARK) name.chop! if name.end_with?(CHECK) name end name end # Logs any caught error. # # @param error [StandardError] def log_error error Contrast::CONFIG.proto_logger.warn('Could not write effective config to file: ', error: error, backtrace: error.backtrace) end end end end end