Class: NVDFeedScraper::Feed
- Inherits:
-
Object
- Object
- NVDFeedScraper::Feed
- Defined in:
- lib/nvd_feed_api.rb
Overview
Feed object.
Class Attribute Summary collapse
-
.default_storage_location ⇒ String
Get / set default feed storage location, where will be stored JSON feeds and archives by default.
Instance Attribute Summary collapse
-
#gz_url ⇒ String
The URL of the gz archive of the feed.
-
#json_file ⇒ String
readonly
The path of the saved JSON file.
-
#meta ⇒ Meta
readonly
The Meta object of the feed.
-
#meta_url ⇒ String
The URL of the metadata file of the feed.
-
#name ⇒ String
The name of the feed.
-
#updated ⇒ String
The last update date of the feed information on the NVD website.
-
#zip_url ⇒ String
The URL of the zip archive of the feed.
Instance Method Summary collapse
-
#available_cves ⇒ Array<String>
Return a list with the name of all available CVEs in the feed.
-
#cve(*arg_cve) ⇒ Object
Search for CVE in the feed.
-
#download_file(file_url, opts = {}) ⇒ String
protected
Download a file.
-
#download_gz(opts = {}) ⇒ String
Download the gz archive of the feed.
-
#download_zip(opts = {}) ⇒ String
Download the zip archive of the feed.
-
#initialize(name, updated, meta_url, gz_url, zip_url) ⇒ Feed
constructor
A new instance of Feed.
-
#json_pull(opts = {}) ⇒ String
Download the JSON feed and fill the attribute.
-
#meta_pull ⇒ Meta
Create or update the Meta object (fill the attribute).
Constructor Details
#initialize(name, updated, meta_url, gz_url, zip_url) ⇒ Feed
A new instance of Feed.
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/nvd_feed_api.rb', line 94 def initialize(name, updated, , gz_url, zip_url) @name = name @updated = updated @meta_url = @gz_url = gz_url @zip_url = zip_url # do not pull meta and json automatically for speed and memory footprint @meta = nil @json_file = nil end |
Class Attribute Details
.default_storage_location ⇒ String
Get / set default feed storage location, where will be stored JSON feeds and archives by default.
35 36 37 |
# File 'lib/nvd_feed_api.rb', line 35 def default_storage_location @default_storage_location end |
Instance Attribute Details
#gz_url ⇒ String
Returns the URL of the gz archive of the feed.
57 58 59 |
# File 'lib/nvd_feed_api.rb', line 57 def gz_url @gz_url end |
#json_file ⇒ String (readonly)
Return nil if not previously loaded by #json_pull.
Returns the path of the saved JSON file.
86 87 88 |
# File 'lib/nvd_feed_api.rb', line 86 def json_file @json_file end |
#meta ⇒ Meta (readonly)
Return nil if not previously loaded by #meta_pull. Note that #json_pull also calls #meta_pull.
Returns the Meta object of the feed.
75 76 77 |
# File 'lib/nvd_feed_api.rb', line 75 def @meta end |
#meta_url ⇒ String
Returns the URL of the metadata file of the feed.
52 53 54 |
# File 'lib/nvd_feed_api.rb', line 52 def @meta_url end |
#name ⇒ String
Returns the name of the feed.
42 43 44 |
# File 'lib/nvd_feed_api.rb', line 42 def name @name end |
#updated ⇒ String
Returns the last update date of the feed information on the NVD website.
47 48 49 |
# File 'lib/nvd_feed_api.rb', line 47 def updated @updated end |
#zip_url ⇒ String
Returns the URL of the zip archive of the feed.
62 63 64 |
# File 'lib/nvd_feed_api.rb', line 62 def zip_url @zip_url end |
Instance Method Details
#available_cves ⇒ Array<String>
Return a list with the name of all available CVEs in the feed. Can only be called after #json_pull.
246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/nvd_feed_api.rb', line 246 def available_cves raise 'json_file is nil, it needs to be populated with json_pull' if @json_file.nil? raise "json_file (#{@json_file}) doesn't exist" unless File.file?(@json_file) doc = Oj::Doc.open(File.read(@json_file)) # Quicker than doc.fetch('/CVE_Items').size doc_size = doc.fetch('/CVE_data_numberOfCVEs').to_i cve_names = [] (1..doc_size).each do |i| doc.move("/CVE_Items/#{i}") cve_names.push(doc.fetch('cve/CVE_data_meta/ID')) end doc.close return cve_names end |
#cve(cve) ⇒ Hash #cve(cve_arr) ⇒ Array #cve(cve, *) ⇒ Array
implement a CVE Class instead of returning a Hash.
#json_pull is needed before using this method. Remember you’re searching only in the current feed.
Search for CVE in the feed.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/nvd_feed_api.rb', line 194 def cve(*arg_cve) raise 'json_file is nil, it needs to be populated with json_pull' if @json_file.nil? raise "json_file (#{@json_file}) doesn't exist" unless File.file?(@json_file) return_value = nil raise 'no argument provided, 1 or more expected' if arg_cve.empty? if arg_cve.length == 1 if arg_cve[0].is_a?(String) raise "bad CVE name (#{arg_cve[0]})" unless /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(arg_cve[0]) doc = Oj::Doc.open(File.read(@json_file)) # Quicker than doc.fetch('/CVE_Items').size doc_size = doc.fetch('/CVE_data_numberOfCVEs').to_i (1..doc_size).each do |i| if arg_cve[0].upcase == doc.fetch("/CVE_Items/#{i}/cve/CVE_data_meta/ID") return_value = doc.fetch("/CVE_Items/#{i}") break end end doc.close elsif arg_cve[0].is_a?(Array) return_value = [] # Sorting CVE can allow us to parse quicker # Upcase to be sure include? works cves_to_find = arg_cve[0].map(&:upcase).sort raise 'one of the provided arguments is not a String' unless cves_to_find.all? { |x| x.is_a?(String) } raise 'bad CVE name' unless cves_to_find.all? { |x| /^CVE-[0-9]{4}-[0-9]{4,}$/i.match?(x) } doc = Oj::Doc.open(File.read(@json_file)) # Quicker than doc.fetch('/CVE_Items').size doc_size = doc.fetch('/CVE_data_numberOfCVEs').to_i (1..doc_size).each do |i| doc.move("/CVE_Items/#{i}") cve_id = doc.fetch('cve/CVE_data_meta/ID') if cves_to_find.include?(cve_id) return_value.push(doc.fetch) cves_to_find.delete(cve_id) elsif cves_to_find.empty? break end end raise "#{cves_to_find.join(', ')} are unexisting CVEs in this feed" unless cves_to_find.empty? else raise "the provided argument (#{arg_cve[0]}) is nor a String or an Array" end else # Overloading a list of arguments as one array argument return_value = cve(arg_cve) end return return_value end |
#download_file(file_url, opts = {}) ⇒ String (protected)
Download a file.
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/nvd_feed_api.rb', line 321 def download_file(file_url, opts = {}) opts[:destination_path] ||= Feed.default_storage_location opts[:sha256] ||= nil destination_path = opts[:destination_path] destination_path += '/' unless destination_path[-1] == '/' skip_download = false uri = URI(file_url) filename = uri.path.split('/').last destination_file = destination_path + filename unless opts[:sha256].nil? if File.file?(destination_file) # Verify hash to see if it is the latest computed_h = Digest::SHA256.file(destination_file) skip_download = true if opts[:sha256].casecmp(computed_h.hexdigest).zero? end end unless skip_download res = Net::HTTP.get_response(uri) raise "#{file_url} ended with #{res.code} #{res.}" unless res.is_a?(Net::HTTPSuccess) open(destination_file, 'wb') do |file| file.write(res.body) end end return destination_file end |
#download_gz(opts = {}) ⇒ String
Download the gz archive of the feed.
121 122 123 |
# File 'lib/nvd_feed_api.rb', line 121 def download_gz(opts = {}) download_file(@gz_url, opts) end |
#download_zip(opts = {}) ⇒ String
Download the zip archive of the feed.
131 132 133 |
# File 'lib/nvd_feed_api.rb', line 131 def download_zip(opts = {}) download_file(@zip_url, opts) end |
#json_pull(opts = {}) ⇒ String
Will downlaod and save the zip of the JSON file, unzip and save it. This massively consume time.
Download the JSON feed and fill the attribute.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/nvd_feed_api.rb', line 140 def json_pull(opts = {}) opts[:destination_path] ||= Feed.default_storage_location skip_download = false destination_path = opts[:destination_path] destination_path += '/' unless destination_path[-1] == '/' filename = URI(@zip_url).path.split('/').last.chomp('.zip') # do not use @json_file for destination_file because of offline loading destination_file = destination_path + filename if File.file?(destination_file) # Verify hash to see if it is the latest computed_h = Digest::SHA256.file(destination_file) skip_download = true if .sha256.casecmp(computed_h.hexdigest).zero? end if skip_download @json_file = destination_file else zip_path = download_zip(opts) Archive::Zip.open(zip_path) do |z| z.extract(destination_path, flatten: true) end @json_file = zip_path.chomp('.zip') # Verify hash integrity computed_h = Digest::SHA256.file(@json_file) raise "File corruption: #{@json_file}" unless .sha256.casecmp(computed_h.hexdigest).zero? end return @json_file end |
#meta_pull ⇒ Meta
Create or update the Meta object (fill the attribute).
108 109 110 111 112 113 |
# File 'lib/nvd_feed_api.rb', line 108 def = NVDFeedScraper::Meta.new(@meta_url) .parse # update @meta @meta = end |