Class: ShieldPressTracker::Reporter

Inherits:
Object
  • Object
show all
Defined in:
lib/shieldpress_tracker/reporter.rb

Constant Summary collapse

SENSITIVE_KEY =
/authorization|cookie|password|passwd|secret|token|api[_-]?key|credential/i
SENSITIVE_TEXT =
/(bearer\s+)[A-Za-z0-9._~+\-\/=]+|([?&](?:password|passwd|secret|token|api[_-]?key)=)[^&\s]+/i

Instance Method Summary collapse

Constructor Details

#initialize(api_url, api_key, debug = false) ⇒ Reporter

Returns a new instance of Reporter.



24
# File 'lib/shieldpress_tracker/reporter.rb', line 24

def initialize(api_url, api_key, debug = false); @uri, @api_key, @debug = URI(api_url + "/api/tracker/report"), api_key, debug end

Instance Method Details

#redact(value, depth = 0) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/shieldpress_tracker/reporter.rb', line 10

def redact(value, depth = 0)
  return "[MAX_DEPTH]" if depth > 12
  case value
  when Hash
    value.each_with_object({}) { |(key, item), out| out[key] = key.to_s.match?(SENSITIVE_KEY) ? "[REDACTED]" : redact(item, depth + 1) }
  when Array
    value.first(500).map { |item| redact(item, depth + 1) }
  when String
    value.gsub(SENSITIVE_TEXT) { "#{Regexp.last_match(1) || Regexp.last_match(2)}[REDACTED]" }[0, 16_384]
  else
    value
  end
end

#send(payload) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/shieldpress_tracker/reporter.rb', line 25

def send(payload)
  payload = redact(payload)
  body = JSON.generate(payload)
  if body.bytesize > 512 * 1024
    payload[:_truncated] = true; payload[:errors] = Array(payload[:errors]).first(20)
    payload[:security][:events] = Array(payload[:security][:events]).first(10) if payload[:security]
    body = JSON.generate(payload)
  end
  request = Net::HTTP::Post.new(@uri); request["Content-Type"] = "application/json"
  request["Authorization"] = "Bearer #{@api_key}"; request["User-Agent"] = "shieldpress-tracker-ruby/1.0.0"; request.body = body
  response = Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.scheme == "https", open_timeout: 5, read_timeout: 10) { |http| http.request(request) }
  response.code.to_i.between?(200, 299)
rescue StandardError => e
  warn("[ShieldPress] report failed: #{e.message}") if @debug
  false
end