Class: Brew::Vulns::OsvClient
- Inherits:
-
Object
- Object
- Brew::Vulns::OsvClient
- Defined in:
- lib/brew/vulns/osv_client.rb
Defined Under Namespace
Constant Summary collapse
- API_BASE =
"https://api.osv.dev/v1"- BATCH_SIZE =
1000- OPEN_TIMEOUT =
10- READ_TIMEOUT =
30
Instance Method Summary collapse
- #execute_request(uri, request) ⇒ Object
- #fetch_all_pages(response, original_payload) ⇒ Object
- #get(path) ⇒ Object
- #get_vulnerability(vuln_id) ⇒ Object
- #post(path, payload) ⇒ Object
- #query(repo_url:, version:) ⇒ Object
- #query_batch(packages) ⇒ Object
Instance Method Details
#execute_request(uri, request) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/brew/vulns/osv_client.rb', line 80 def execute_request(uri, request) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = uri.scheme == "https" http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.open_timeout = OPEN_TIMEOUT http.read_timeout = READ_TIMEOUT response = http.request(request) case response when Net::HTTPSuccess JSON.parse(response.body) else raise ApiError, "OSV API error: #{response.code} #{response.}" end rescue JSON::ParserError => e raise ApiError, "Invalid JSON response from OSV API: #{e.}" rescue Net::OpenTimeout, Net::ReadTimeout => e raise ApiError, "OSV API timeout: #{e.}" rescue SocketError, Errno::ECONNREFUSED => e raise ApiError, "OSV API connection error: #{e.}" rescue OpenSSL::SSL::SSLError => e raise ApiError, "OSV API SSL error: #{e.}" end |
#fetch_all_pages(response, original_payload) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/brew/vulns/osv_client.rb', line 105 def fetch_all_pages(response, original_payload) vulns = response["vulns"] || [] page_token = response["next_page_token"] while page_token payload = original_payload.merge(page_token: page_token) response = post("/query", payload) vulns.concat(response["vulns"] || []) page_token = response["next_page_token"] end vulns end |
#get(path) ⇒ Object
72 73 74 75 76 77 78 |
# File 'lib/brew/vulns/osv_client.rb', line 72 def get(path) uri = URI("#{API_BASE}#{path}") request = Net::HTTP::Get.new(uri) request["Content-Type"] = "application/json" execute_request(uri, request) end |
#get_vulnerability(vuln_id) ⇒ Object
59 60 61 |
# File 'lib/brew/vulns/osv_client.rb', line 59 def get_vulnerability(vuln_id) get("/vulns/#{URI.encode_uri_component(vuln_id)}") end |
#post(path, payload) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'lib/brew/vulns/osv_client.rb', line 63 def post(path, payload) uri = URI("#{API_BASE}#{path}") request = Net::HTTP::Post.new(uri) request["Content-Type"] = "application/json" request.body = JSON.generate(payload) execute_request(uri, request) end |
#query(repo_url:, version:) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/brew/vulns/osv_client.rb', line 18 def query(repo_url:, version:) payload = { package: { name: repo_url, ecosystem: "GIT" }, version: version } response = post("/query", payload) fetch_all_pages(response, payload) end |
#query_batch(packages) ⇒ Object
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 |
# File 'lib/brew/vulns/osv_client.rb', line 31 def query_batch(packages) return [] if packages.empty? results = Array.new(packages.size) { [] } packages.each_slice(BATCH_SIZE).with_index do |batch, batch_idx| queries = batch.map do |pkg| { package: { name: pkg[:repo_url], ecosystem: "GIT" }, version: pkg[:version] } end response = post("/querybatch", { queries: queries }) batch_results = response["results"] || [] batch_results.each_with_index do |result, idx| global_idx = batch_idx * BATCH_SIZE + idx results[global_idx] = result["vulns"] || [] end end results end |