module Sqreen::Signals::HttpTraceRedaction

Public Class Methods

redact_trace!(trace, redactor) click to toggle source

@param [Sqreen::Kit::Signals::Specialized::HttpTrace] trace @param [Sqreen::SensitiveDataRedactor] redactor

# File lib/sqreen/signals/http_trace_redaction.rb, line 18
def redact_trace!(trace, redactor)
  return unless redactor
  # redact headers (keys unsafe)
  # @type [Sqreen::Kit::Signals::Context::HttpContext]
  http_context = trace.context

  all_redacted = []

  # Redact headers; save redacted values
  # headers are encoded as [key, value], not a hash, so
  # they require some transformation
  orig_headers = http_context.headers
  if orig_headers
    headers = orig_headers.map { |(k, v)| { k => v } }
    headers, redacted = redactor.redact(headers)
    http_context.headers = headers.map(&:first)
    all_redacted += redacted
  end

  # Redact params; save redacted values
  Kit::Signals::Context::HttpContext::PARAMS_ATTRS.each do |attr|
    value = http_context.public_send(attr)
    next unless value
    value, redacted = redactor.redact(value)
    all_redacted += redacted
    http_context.public_send(:"#{attr}=", value)
  end

  all_redacted = all_redacted.uniq.map(&:downcase)

  # Redact attacks and exceptions
  # XXX: no redaction for infos in attacks/exceptions except for WAF data
  # Is this the correct behavior?
  redact_attacks!(trace, redactor, all_redacted)
  redact_exceptions!(trace, redactor, all_redacted)
end

Private Class Methods

redact_attacks!(trace, redactor, redacted_data) click to toggle source

@param [Sqreen::Kit::Signals::Specialized::HttpTrace] trace @param [Sqreen::SensitiveDataRedactor] redactor Redacts WAF data according to specific rules therefor Redacts infos according to general rules

# File lib/sqreen/signals/http_trace_redaction.rb, line 61
def redact_attacks!(trace, redactor, redacted_data)
  trace.data.each do |signal|
    next unless signal.is_a?(Kit::Signals::Specialized::Attack)
    # @type [Sqreen::Kit::Signals::Specialized::Attack::Payload] payload
    payload = signal.payload
    next unless payload.infos

    if payload.infos[:waf_data]
      redact_waf_attack_data!(payload.infos, redacted_data)
    end
    payload.infos, = redactor.redact(payload.infos)
  end
end
redact_exceptions!(trace, redactor, redacted_data) click to toggle source
# File lib/sqreen/signals/http_trace_redaction.rb, line 75
def redact_exceptions!(trace, redactor, redacted_data)
  trace.data.each do |signal|
    next unless signal.is_a?(Kit::Signals::Specialized::SqreenException)
    infos = signal.infos
    next unless infos

    redact_waf_exception_data!(signal.infos, redacted_data) if signal.infos[:waf]
    signal.infos, = redactor.redact(infos)
  end
end
redact_waf_attack_data!(infos, redacted_data) click to toggle source

@param [Hash] infos from WAF attack

# File lib/sqreen/signals/http_trace_redaction.rb, line 87
def redact_waf_attack_data!(infos, redacted_data)
  begin
    parsed = JSON.parse(infos[:waf_data])
  rescue JSON::JSONError => e
    logger.warn("waf_data is not valid json: #{e.message}")
    return
  end
  redacted = parsed.each do |w|
    next unless (filters = w['filter'])

    filters.each do |f|
      next unless (v = f['resolved_value'])
      next unless redacted_data.include?(v.downcase)

      f['match_status'] = SensitiveDataRedactor::MASK
      f['resolved_value'] = SensitiveDataRedactor::MASK
    end
  end
  infos[:waf_data] = JSON.dump(redacted)
end
redact_waf_exception_data!(infos, redacted_data) click to toggle source

see github.com/sqreen/TechDoc/blob/master/content/specs/spec000022-waf-data-sanitization.md#changes-to-the-agents

# File lib/sqreen/signals/http_trace_redaction.rb, line 109
def redact_waf_exception_data!(infos, redacted_data)
  return if redacted_data.empty?
  infos[:waf].delete(:args)
end