Class: QueryHandler

Inherits:
Object
  • Object
show all
Includes:
Prevoty::BuildQueryResult
Defined in:
lib/prevoty/query_handler.rb

Instance Method Summary collapse

Methods included from Prevoty::BuildQueryResult

#build_result

Constructor Details

#initialize(opts) ⇒ QueryHandler

Returns a new instance of QueryHandler.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/prevoty/query_handler.rb', line 10

def initialize(opts)
    @base = opts[:api_base] ||= 'https://api.prevoty.com'
    @client = ::Prevoty::Client.new(opts[:api_key], @base)
    @policy_key = opts[:policy_key] ||= ''
    @mode = opts[:mode] ||= 'monitor'
    @log_verbosity = opts[:log_verbosity] ||= 'incident'
    @reporting_milliseconds = opts[:reporting_milliseconds] ||= 10000
    @reporting_count = opts[:reporting_count] ||= 50
    @db_vendor = opts[:db_vendor] ||= ''
    @db_version = opts[:db_version] ||= ''
    @db_name = opts[:db_name] ||= ''
    @violation_mode = opts[:violation_mode] ||= 'block'
    @failure_mode = opts[:failure_mode] ||= 'continue'

    if @mode === 'monitor'
      @monitor = ::Prevoty::QueryMonitor.new(@client, opts)
    end
end

Instance Method Details

#handle(name, start, finish, id, payload) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/prevoty/query_handler.rb', line 29

def handle(name, start, finish, id, payload)
  # ActiveRecord does some wonky stuff on startup that causes a query to be
  # executed that doesn't seem to pass through the rack middleware so the
  # request_storage key doesn't exist. It's unclear if there are other
  # situations that also cause this but because of it we need to use try here
  # to ensure there are no nil pointer exceptions
  if Thread.current[:request_storage].try(:[], :skip_processing)
    return
  end

  unless payload[:name] =~ /SQL|Load/
    return
  end

  case @mode
  when 'monitor'
    package = {vendor: @db_vendor, database: @db_name, version: @db_version, query: payload[:sql]}
    @monitor.process(package)
  when 'protect'
    begin
      resp = nil
      ActiveSupport::Notifications.instrument('prevoty:query:protect') do |resp_payload|
        resp = resp_payload[:response] = @client.analyze_query(payload[:sql], @policy_key)
      end

      # always log because we're either set to all or incident
      if resp.processed and not resp.compliant
        ::Prevoty::LOGGER << build_result(@mode, payload[:sql], resp).to_json + "\n"
        raise ::Prevoty::QueryViolation.new if @violation_mode === 'block'
      elsif resp.processed and resp.compliant
        # all good, only log if log verbosity is all
        if @log_verbosity === 'all'
          ::Prevoty::LOGGER << build_result(@mode, payload[:sql], resp).to_json + "\n"
        end
      elsif not resp.processed and not resp.compliant
        # query failure
        if @log_verbosity === 'all'
          ::Prevoty::LOGGER << build_result(@mode, payload[:sql], resp).to_json + "\n"
        end
        ActiveSupport::Notifications.instrument('prevoty:query:failure', response: resp)
        raise ::Prevoty::QueryFailure.new
      end
    rescue ::Prevoty::QueryViolation => e
      # need to catch and rethrow to catch other exceptions
      raise e
    rescue ::Prevoty::QueryFailure => e
      # need to catch and rethrow to catch other exceptions
      raise e
    rescue Exception => e
      Rails.logger.error e.message
      raise e if @failure_mode === 'block'
    end
  end
end