# typed: ignore # Copyright (c) 2015 Sqreen. All Rights Reserved. # Please refer to our terms for more information: https://www.sqreen.com/terms.html require 'yaml' require 'erb' require 'sqreen/performance_notifications/newrelic' module Sqreen # TODO: remove all referecnes to global such as config_get # TODO: move within Sqreen::Configuration @config = nil def self.config_init(framework = nil) @config = Configuration.new(framework) @config.load! if @config && config_get(:report_perf_newrelic) > 0 Sqreen::PerformanceNotifications::NewRelic.enable(config_get(:report_perf_newrelic)) end @config end def self.config_get(name) raise 'No configuration defined' if @config.nil? @config.get(name) end def self.configured? !@config.nil? end CONFIG_FILE_BY_ENV = 'SQREEN_CONFIG_FILE'.freeze CONFIG_DESCRIPTION = [ { :env => :SQREEN_DISABLE, :name => :disable, :default => false, :convert => :to_bool }, { :env => :SQREEN_LIBSQREEN, :name => :libsqreen, :default => true, :convert => :to_bool }, { :env => :SQREEN_WEAVE, :name => :weave, :default => true, :convert => :to_bool }, { :env => :SQREEN_WEAVE_STRATEGY, :name => :weave_strategy, :default => :prepend, :convert => :to_sym }, { :env => :SQREEN_URL, :name => :url, :default => nil }, { :env => :SQREEN_INGESTION_URL, :name => :ingestion_url, :default => nil }, { :env => :SQREEN_PROXY_URL, :name => :proxy_url, :default => nil }, { :env => :SQREEN_TOKEN, :name => :token, :default => nil }, { :env => :SQREEN_APP_NAME, :name => :app_name, :default => nil }, { :env => :SQREEN_RULES, :name => :local_rules, :default => nil }, { :env => :SQREEN_RULES_SIGNATURE, :name => :rules_verify_signature, :default => true }, { :env => :SQREEN_LOG_LEVEL, :name => :log_level, :default => 'INFO', :choice => %w[UNKNOWN FATAL ERROR WARN INFO DEBUG] }, { :env => :SQREEN_LOG_LOCATION, :name => :log_location, :default => 'log/sqreen.log' }, { :env => :SQREEN_RUN_IN_TEST, :name => :run_in_test, :default => false, :convert => :to_bool }, { :env => :SQREEN_BLOCK_ALL_RULES, :name => :block_all_rules, :default => nil }, { :env => :SQREEN_REPORT_PERF_NR, :name => :report_perf_newrelic, :default => 0, :convert => :to_int }, { :env => :SQREEN_REPORT_PERF, :name => :report_perf, :default => false, :convert => :to_bool }, { :env => :SQREEN_INITIAL_FEATURES, :name => :initial_features, :default => nil }, { :env => :SQREEN_IP_HEADER, :name => :ip_header, :default => nil }, { :env => :SQREEN_STRIP_SENSITIVE_DATA, :name => :strip_sensitive_data, :default => true, :convert => :to_bool }, { :env => :SQREEN_STRIP_SENSITIVE_KEYS, :name => :strip_sensitive_keys, :default => nil }, { :env => :SQREEN_STRIP_SENSITIVE_REGEX, :name => :strip_sensitive_regex, :default => nil }, { :env => :SQREEN_NO_SNIFF_DOMAINS, :name => :no_sniff_domains, :default => false }, ].freeze CONFIG_FILE_NAME = 'sqreen.yml'.freeze def self.to_bool(value) %w[1 true].include?(value.to_s.downcase.strip) end def self.to_int(value) str = value.to_s.downcase.strip str = 1 if str == 'true' str.to_i end def self.to_sym(value) value.to_sym end # Class to access configurations variables # This try to load environment by different ways. # 1. By file: # a. From path in environment variable SQREEN_CONFIG_FILE # b. From path in #{Rails.root}/config/sqreen.yml # c. From home in ~/.sqreen.yml # 2. From the environment, which overrides whatever result we found in 1. class Configuration def initialize(framework = nil) @framework = framework @config = default_values end def load! path = find_configuration_file if path file_config = parse_configuration_file(path) @config.merge!(file_config) else Sqreen.log.warn("could not find sqreen configuration file") end env_config = from_environment @config.merge!(env_config) end def get(name) @config[name.to_sym] end def default_values res = {} Sqreen::CONFIG_DESCRIPTION.each do |param| name = param[:name] value = param[:default] choices = param[:choices] if choices && !choices.include?(value) msg = format("Invalid value '%s' for env '%s' (allowed: %s)", value, name, choices) raise Sqreen::Exception, msg end res[name] = param[:convert] ? send(param[:convert], value) : value end res end def from_environment res = {} Sqreen::CONFIG_DESCRIPTION.each do |param| name = param[:name] value = ENV[param[:env].to_s] next unless value res[name] = param[:convert] ? send(param[:convert], value) : value end res end def parse_configuration_file(path) yaml = YAML.load(ERB.new(File.read(path)).result) return {} unless yaml.is_a?(Hash) if @framework env = @framework.framework_infos[:environment] yaml = yaml[env] if env && yaml[env].is_a?(Hash) end res = {} # hash keys loaded by YAML are strings instead of symbols Sqreen::CONFIG_DESCRIPTION.each do |param| name = param[:name] value = yaml[name.to_s] next unless value res[name] = param[:convert] ? send(param[:convert], value) : value end res end def find_user_home homes = %w[HOME HOMEPATH] homes.detect { |h| !ENV[h].nil? } end def find_configuration_file config_file_from_env || local_config_file || config_file_from_home end protected def config_file_from_env return unless (path = ENV[Sqreen::CONFIG_FILE_BY_ENV]) path = File.expand_path(path) unless File.exist?(path) Sqreen.log.warn("could not find sqreen configuration file provided by #{Sqreen::CONFIG_FILE_BY_ENV}: '#{path}'") end Sqreen.log.info("using config file provided by #{Sqreen::CONFIG_FILE_BY_ENV}: '#{path}'") path end def local_config_file if @framework && @framework.root path = File.join(@framework.root.to_s, 'config', CONFIG_FILE_NAME) return path if File.exist?(path) else path = File.expand_path(File.join('config', 'sqreen.yml')) return path if File.exist?(path) end end def config_file_from_home home = find_user_home return unless home path = File.join(ENV[home], '.' + CONFIG_FILE_NAME) return path if File.exist?(path) end def to_bool(value) Sqreen::to_bool(value) end def to_int(value) Sqreen::to_int(value) end def to_sym(value) Sqreen::to_sym(value) end end end