class HackerOne::Client::Api
Public Class Methods
# File lib/hackerone/client.rb, line 59 def initialize(program = nil) @program = program end
Private Class Methods
# File lib/hackerone/client.rb, line 198 def self.hackerone_api_connection unless ENV["HACKERONE_TOKEN_NAME"] && ENV["HACKERONE_TOKEN"] raise NotConfiguredError, "HACKERONE_TOKEN_NAME HACKERONE_TOKEN environment variables must be set" end @connection ||= Faraday.new(url: "https://api.hackerone.com/v1") do |faraday| faraday.basic_auth(ENV["HACKERONE_TOKEN_NAME"], ENV["HACKERONE_TOKEN"]) faraday.adapter Faraday.default_adapter end end
# File lib/hackerone/client.rb, line 181 def self.parse_response(response, extract_data: true) if response.status.to_s.start_with?("4") raise ArgumentError, "API called failed, probably your fault: #{response.body}" elsif response.status.to_s.start_with?("5") raise RuntimeError, "API called failed, probably their fault: #{response.body}" elsif response.success? response_body_json = JSON.parse(response.body, symbolize_names: true) if extract_data && response_body_json.key?(:data) response_body_json[:data] else response_body_json end else raise RuntimeError, "Not sure what to do here: #{response.body}" end end
Public Instance Methods
Public: create a new report
title: The title of the report summary: Summary of the report impact: Impact of the report severity_rating: severity of report, must be one of api.hackerone.com/reference/#severity-ratings source: where the report came from, i.e. API, Bugcrowd, etc.
returns an HackerOne::Client::Report
object or raises an error if error during creation
# File lib/hackerone/client.rb, line 127 def create_report(title:, summary:, impact:, severity_rating:, source:) raise ArgumentError, "Program cannot be nil" unless program data = { "data": { "type": "report", "attributes": { "team_handle": program, "title": title, "vulnerability_information": summary, "impact": impact, "severity_rating": severity_rating, "source": source } } } Report.new(post("reports", data)) end
# File lib/hackerone/client.rb, line 63 def program @program || HackerOne::Client.program end
Public: retrieve a report
id: the ID of a specific report
returns an HackerOne::Client::Report
object or raises an error if no report is found.
# File lib/hackerone/client.rb, line 152 def report(id) Report.new(get("reports/#{id}")) end
# File lib/hackerone/client.rb, line 67 def reporters raise ArgumentError, "Program cannot be nil" unless program response = self.class.hackerone_api_connection.get do |req| req.url "programs/#{Program.find(program).id}/reporters" end data = self.class.parse_response(response) if data.nil? raise RuntimeError, "Expected data attribute in response: #{response.body}" end data.map do |reporter| Reporter.new(reporter) end end
Returns all reports in a given state, optionally with a time bound
program: the HackerOne
program to search on (configure globally with Hackerone::Client.program=) since (optional): a time bound, don't include reports earlier than since
. Must be a DateTime object. before (optional): a time bound, don't include reports later than before
. Must be a DateTime object. state (optional): state that a report is in, by default new
returns all open reports or an empty array
# File lib/hackerone/client.rb, line 91 def reports(since: 3.days.ago, before: nil, state: :new) raise ArgumentError, "Program cannot be nil" unless program raise ArgumentError, "State is invalid" unless REPORT_STATES.include?(state.to_s) response = self.class.hackerone_api_connection.get do |req| options = { "filter[state][]" => state, "filter[program][]" => program } unless since.nil? options["filter[created_at__gt]"] = since.iso8601 end unless before.nil? options["filter[created_at__lt]"] = before.iso8601 end req.url "reports", options end data = self.class.parse_response(response) data.map do |report| Report.new(report) end end
Private Instance Methods
# File lib/hackerone/client.rb, line 169 def get(endpoint, params = nil) response = with_retry do self.class.hackerone_api_connection.get do |req| req.headers["Content-Type"] = "application/json" req.params = params || {} req.url endpoint end end self.class.parse_response(response) end
# File lib/hackerone/client.rb, line 157 def post(endpoint, body) response = with_retry do self.class.hackerone_api_connection.post do |req| req.headers["Content-Type"] = "application/json" req.body = body.to_json req.url endpoint end end self.class.parse_response(response) end
# File lib/hackerone/client.rb, line 209 def with_retry(attempts = 3, &block) attempts_remaining = attempts begin yield rescue StandardError if attempts_remaining > 0 attempts_remaining -= 1 sleep (attempts - attempts_remaining) retry else raise end end end