class SoarAuditingProvider::AuditingProvider

Constants

DEFAULT_FLOW_ID_GENERATOR
DEFAULT_LEVEL
DEFAULT_NFRS
DEFAULT_QUEUE_WORKER_CONFIG

Attributes

configuration[R]
service_identifier[RW]
startup_flow_id[W]

Public Class Methods

new(configuration) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 24
def initialize(configuration)
  @configuration = configuration

  @auditors = create_auditors(configuration)
  raise ArgumentError.new("Invalid auditors provided") if not @auditors.is_a?(Hash)
  raise ArgumentError.new("No auditors provided") if @auditors.nil? or @auditors.empty?

  select_auditor(configuration['default_nfrs'])
  @flow_id_generator = @configuration["flow_id_generator"] || DEFAULT_FLOW_ID_GENERATOR
  create_auditing_worker
  @buffer_overflow_count = 0
  install_at_exit_handler
  initialize_metrics
end

Public Instance Methods

<<(data, flow_identifier = nil)
Alias for: info
audit_exception(exception:, level: :error, flow_id: nil, message: nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 89
def audit_exception(exception:, level: :error, flow_id: nil, message: nil)
  exception_message = "#{exception.class}: #{exception.message}"
  exception_message = "#{message} - #{exception_message}" if message
  exception_message = exception_message + ":\n\t" + exception.backtrace.join("\n\t")
  level = :error if not is_valid_audit_level?(level)
  send(level,exception_message,flow_id)
end
debug(data, flow_identifier = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 55
def debug(data, flow_identifier = nil)
  audit(:debug, data, flow_identifier)
end
detailed_status() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 77
def detailed_status
  detail = basic_status_detail
  detail = detail.merge(verbose_status_detail) if @configuration['verbose_detail']
  detail
end
error(data, flow_identifier = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 69
def error(data, flow_identifier = nil)
  audit(:error, data, flow_identifier)
end
fatal(data, flow_identifier = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 73
def fatal(data, flow_identifier = nil)
  audit(:fatal, data, flow_identifier)
end
flush(timeout: 1) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 83
def flush(timeout: 1)
  if @worker
    @worker.flush(timeout: timeout)
  end
end
info(data, flow_identifier = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 59
def info(data, flow_identifier = nil)
  audit(:info, data, flow_identifier)
end
Also aliased as: <<
select(nfrs = DEFAULT) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 97
def select(nfrs = DEFAULT)
  if nfrs.nil? or nfrs.empty?
    auditor_selected = @auditors.keys.first
  else
    auditor_selected = nil
    @auditors.each do |auditor, configuration|
      auditor_nfrs = configuration['nfrs']
      nfrs_matched = true
      nfrs.each do |nfr, value|
        nfrs_matched = false if not auditor_nfrs[nfr] or (auditor_nfrs[nfr] != value)
      end
      if nfrs_matched
        auditor_selected = auditor
        break
      end
    end
    raise NFRMatchError.new("Could not match NFRs to an auditor") if auditor_selected.nil?
  end
  configuration = @auditors[auditor_selected]
  @auditor = auditor_selected
  return @auditor, configuration
end
select_auditor(nfrs) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 43
def select_auditor(nfrs)
  select(nfrs)
  set_audit_level(configured_audit_level)
end
set_audit_level(level) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 48
def set_audit_level(level)
  @auditor.set_audit_level(level)
rescue ArgumentError
  $stderr.puts 'Invalid auditing level'
  raise
end
startup_flow_id() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 39
def startup_flow_id
  @startup_flow_id ||= @flow_id_generator.call
end
warn(data, flow_identifier = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 65
def warn(data, flow_identifier = nil)
  audit(:warn, data, flow_identifier)
end

Private Instance Methods

audit(level, data, flow_identifier = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 148
def audit(level, data, flow_identifier = nil)
  flow_identifier ||= @flow_id_generator.call
  formatted_data = format(level, prepend_caller_information(data), flow_identifier)
  audit_formatted(level, formatted_data)
end
audit_formatted(level, data) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 154
def audit_formatted(level, data)
  if @worker
    enqueue(level, data)
  else
    auditor_caller(level, data)
  end
end
auditor_caller(level, data) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 193
def auditor_caller(level, data)
  @auditor.send(level,data)
end
basic_status_detail() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 242
def basic_status_detail
  {
    'audit_buffer_overflows' => @buffer_overflow_count,
    'enqueued_audit_events'  => @enqueued_audit_events,
    'startup_flow_id'        => startup_flow_id,
    'startup_timestamp'      => @startup_timestamp
  }
end
configured_audit_level() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 232
def configured_audit_level
  (@configuration["level"] || DEFAULT_LEVEL).to_sym
end
create_auditing_worker() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 182
def create_auditing_worker
  if !direct_auditor_call?
    config =  @configuration['queue_worker'] || DEFAULT_QUEUE_WORKER_CONFIG
    @worker = AuditingWorker.instance
    @worker.configure(queue_worker_configuration: config, auditor_audit_method: method(:auditor_caller))
    @worker.start
  else
    @worker = nil
  end
end
create_auditor(auditor_factory,auditor_name) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 211
def create_auditor(auditor_factory,auditor_name)
  auditor_factory.create(auditor_name)
rescue
  $stderr.puts 'Invalid auditor configuration'
  raise
end
create_auditors(configuration) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 197
def create_auditors(configuration)
  auditor_factory = SoarConfiguredFactory::ConfiguredFactory.new(configuration['auditors'])
  auditors = {}
  configuration['auditors'].each do |auditor_name, auditor_configuration|
    raise 'Missing auditor configuration' if auditor_configuration.nil?
    auditor = create_auditor(auditor_factory,auditor_name)
    auditors[auditor] = { 'name' => auditor_name, 'nfrs' => auditor_configuration['nfrs'] }
  end
  auditors
rescue
  $stderr.puts 'Failure initializing auditor'
  raise
end
direct_auditor_call?(configuration = @configuration) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 218
def direct_auditor_call?(configuration = @configuration)
  configuration['direct_auditor_call'] == 'true' or
    (configuration['direct_auditor_call'].nil? and @auditor.prefer_direct_call?)
end
enqueue(level, data) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 162
def enqueue(level, data)
  @worker.enqueue(level, data)
  @enqueued_audit_events += 1
rescue AuditingOverflowError
  increase_buffer_overflow_count
  $stderr.puts "Audit buffer full, unable to audit event : #{level} : #{data}"
end
exit_cleanup(exception = nil) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 142
def exit_cleanup(exception = nil)
  audit_exception(exception: exception, level: :fatal, flow_id: startup_flow_id) if exception
  info("Application exit",startup_flow_id)
  flush
end
format(level, data, flow_identifier) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 174
def format(level, data, flow_identifier)
  if "json" == output_format
    SoarJsonAuditingFormatter::Formatter.format(level,@service_identifier,flow_identifier,Time.now.utc.iso8601(3),data)
  else
    SoarAuditingFormatter::Formatter.format(level,@service_identifier,flow_identifier,Time.now.utc.iso8601(3),data)
  end
end
increase_buffer_overflow_count() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 170
def increase_buffer_overflow_count
  @buffer_overflow_count += 1
end
initialize_metrics() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 227
def initialize_metrics
  @startup_timestamp     = Time.now.utc.iso8601(3)
  @enqueued_audit_events = 0
end
install_at_exit_handler() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 134
def install_at_exit_handler
  if 'true' == @configuration['install_exit_handler']
    Kernel.at_exit do
      exit_cleanup
    end
  end
end
is_valid_audit_level?(level) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 251
def is_valid_audit_level?(level)
  [:debug, :info, :warn, :error, :fatal].include?(level)
end
output_format() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 223
def output_format
  @configuration['output_format'] || 'string'
end
prepend_caller_information(data) click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 122
def prepend_caller_information(data)
  if 'true' == @configuration['add_caller_source_location']
    if data is_a?(Hash)
      data['caller_source_location'] = "#{caller_locations(2,1)[0]}"
    else
      caller_key_value_pair = SoarAuditingFormatter::Formatter.optional_field_format("caller_source_location","#{caller_locations(2,1)[0]}")
      data = "#{caller_key_value_pair} #{data}"
    end
  end
  data
end
verbose_status_detail() click to toggle source
# File lib/soar_auditing_provider/auditing_provider.rb, line 236
def verbose_status_detail
  {
    'worker' => (@worker.status_detail if @worker)
  }
end