diff --git a/microsoft_kb/microsoft_kb_checker.rb b/microsoft_kb/microsoft_kb_checker.rb index 69d47a2..b74c4dd 100644 --- a/microsoft_kb/microsoft_kb_checker.rb +++ b/microsoft_kb/microsoft_kb_checker.rb @@ -2,17 +2,18 @@ # This will check microsoft security portal for the kbs assosicated with an operating system for a given CVE. # -# usage: --cve CVE-2020-1234 --os "Windows Server 2012 R2" +# end goal usage: --cve CVE-2020-1234 --os "Windows Server 2012 R2" # require 'json' require 'rest-client' +require 'pry' class MicrosoftKbChecker - attr_accessor :cve_id, :os_name + attr_accessor :options - def initialize(cve_id, os_name) - @cve_id = cve_id, - @os_name = os_name + # options hash {:cve_id => 'cve-2020-1234', :os_name => 'Windows Server 2012'} + def initialize(options) + @options = options end AVAILABLE_OS = [ @@ -63,6 +64,7 @@ class MicrosoftKbChecker ].freeze def cve_url + cve = options[:cve_id] "https://portal.msrc.microsoft.com/api/security-guidance/en-US/CVE/#{cve}" end @@ -78,12 +80,46 @@ class MicrosoftKbChecker JSON.parse(response) end - def find_os - if AVAILABLE_OS.include?(os) + def os_available? + AVAILABLE_OS.include?(options[:os_name]) + end + + def query_cve + if os_available? response = make_request - parse_json(response) + json = parse_json(response) + os_results = select_os(json) + kbs_for_os(os_results) if os_results else 'Operating system not found.' end end + + def select_os(json) + json.dig('affectedProducts').select do |os| + os['name'] == options[:os_name] + end.first + end + + def kbs_for_os(os_json) + supersedence = os_json.values_at('supersedence') + articles = article_title_keys(os_json) + kbs = articles.map do |article_info| + num = article_info[:article_num] + os_json.values_at("articleTitle#{num}") + end + { + os_name: os_json['name'], + kbs: kbs, + supersedence_kb: supersedence + } + end + + def article_title_keys(json) + # let us know if we have a kb article in our json response data + # the json response is made up of 4 articleTitle keys + # i have this looping through 99 in case there are more articles from the ones ive manually looked at + results = (1..99).map { |index| { article_num: index, has_key?: json.key?("articleTitle#{index}") } } + results.select { |r| r if r[:has_key?] == true } + end end