Advertisement
Guest User

Untitled

a guest
Aug 13th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 8.52 KB | None | 0 0
  1. require File.expand_path(File.join(File.dirname(__FILE__), 'nexpose.rb'))
  2. require File.expand_path(File.join(File.dirname(__FILE__), 'util.rb'))
  3. require 'rexml/document'
  4. require 'hirb'
  5. require 'ostruct'
  6. require 'optparse'
  7. =begin
  8. require 'rubygems'
  9. require 'nexpose'
  10. =end
  11.  
  12.  
  13. class Options
  14.     def self.parse(args)
  15.       options = OpenStruct.new
  16.  
  17.       option_parser = OptionParser.new  do |option_parser|
  18.         option_parser.on("-h HOST", "The network address of the NeXpose instance - Required") {|arg| options.host=arg}
  19.         option_parser.on("-u USER", "The user name - Required") {|arg| options.user=arg}
  20.         option_parser.on("-p PASSWORD", "The password - Required") {|arg| options.password=arg}
  21.         option_parser.on("--n1", "List all the asset groups") {|arg| options.key=1}
  22.         option_parser.on("--n2 GI", "List an asset groups config. The GI (group id or group name is required)") do |arg|
  23.           options.key=2
  24.           options.args=arg
  25.         end
  26.         option_parser.on("--n3 GID", "Start an asset group scan. The GID (group id is required)") do |arg|
  27.           options.key=3
  28.           options.args=arg
  29.         end
  30.         option_parser.on_tail("--help", "Help") do
  31.           puts option_parser
  32.           exit 0
  33.         end
  34.       end
  35.  
  36.       begin
  37.        option_parser.parse!(args)
  38.         rescue OptionParser::ParseError => e
  39.             puts "#{e}\n\n#{option_parser}"
  40.             exit(1)
  41.       end
  42.  
  43.       options
  44.     end
  45. end
  46.  
  47. class APIUtil
  48.   attr_accessor :user_name, :password, :host
  49.   @api_connection = nil
  50.   @@connected = false
  51.  
  52.   def self.is_connected
  53.     @@connected
  54.   end
  55.  
  56.   def initialize(user_name, password, host)
  57.     @user_name = user_name
  58.     @password = password
  59.     @host = host
  60.   end
  61.  
  62.   private
  63.     def get_asset_group_id
  64.       group_id = -1
  65.       begin
  66.         print("Enter the asset group ID:")
  67.         group_id = gets().chomp()
  68.         if (!Util.is_number?(group_id))
  69.           raise Exception.new("Input is not a number")
  70.         end
  71.         accepted_input = true
  72.       rescue Exception => e
  73.         puts(e.message)
  74.       end until accepted_input == true
  75.  
  76.       group_id;
  77.     end
  78.  
  79.     def get_asset_scan_input()
  80.       max_scans = -1
  81.       scan_template_id = -1
  82.       accepted_input = false
  83.       group_id = get_asset_group_id
  84.  
  85.       accepted_input = false
  86.       begin
  87.         print("Enter the max amount of devices to scan (-1 for unlimitted):")
  88.         max_scans = gets().chomp
  89.         if (!Util.is_number?(max_scans))
  90.           raise Exception.new("Input is not a number")
  91.         end
  92.         accepted_input = true
  93.       rescue Exception => e
  94.         puts(e.message)
  95.       end until accepted_input == true
  96.  
  97. =begin
  98.       accepted_input = false
  99.       begin
  100.         print("Enter the scan template to be used (-1 for default, l to list scan template IDs):")
  101.         input = gets()
  102.         scan_template_id = input.to_i
  103.         accepted_input = true
  104.       rescue Exception => e
  105.         puts(e.message)
  106.       end until accepted_input == true
  107. =end
  108.  
  109.       {:group_id=>group_id, :max_scans=>max_scans}
  110.     end
  111.  
  112.   public
  113.     #-------------------------------------------------------------------
  114.     # Logs in to NeXpose and sets a session key on the connector object.
  115.     #-------------------------------------------------------------------
  116.     def do_login()
  117.       if (!@@connected)
  118.         begin
  119.           @api_connector = Nexpose::Connection.new(host, user_name, password)
  120.           if (@api_connector.login)
  121.             @@connected = true
  122.           end
  123.         rescue Exception => e
  124.           puts(e.message)
  125.         end
  126.       end
  127.     end
  128.  
  129.     #------------------------------------------------------
  130.     # Prints all asset group information in tabular format:
  131.     # | site_id | device_id | address | riskfactor |
  132.     #------------------------------------------------------
  133.     def print_asset_group_info(group_id)
  134.       group_id = group_id != -1 ? group_id : get_asset_group_id
  135.       group_configs = @api_connector.asset_group_config(group_id)
  136.       puts("\nASSET GROUP INFO (id: #{group_id})")
  137.       puts Hirb::Helpers::AutoTable.render(group_configs, :fields => [:site_id, :device_id, :address, :riskfactor])
  138.     end
  139.  
  140.     #----------------------------------------------------------------
  141.     # Prints asset group configuration information in tabular format:
  142.     # | site_id | device_id | address | riskfactor |
  143.     #----------------------------------------------------------------
  144.     def print_asset_groups()
  145.       res = @api_connector.asset_groups_listing
  146.       puts("\nASSET GROUPS:")
  147.       puts Hirb::Helpers::AutoTable.render(res, :fields => [:asset_group_id, :name, :description, :risk_score])
  148.     end
  149.  
  150.     #----------------------------------------------------------------
  151.     # Starts an asset group scan for a particular group ID
  152.     #
  153.     # group_input: A Hash containing the group_id ie: {group_id => 1}
  154.     #----------------------------------------------------------------
  155.     def start_asset_group_scan(group_input)
  156.       input = group_input != -1 ? group_input : get_asset_scan_input
  157.       if (group_input != -1 and (not Util.is_number? input[:group_id]))
  158.         group_name = input[:group_id].chomp
  159.         res = @api_connector.asset_groups_listing
  160.         found = false
  161.         for asset_info in res
  162.           if asset_info[:name].chomp.eql?(group_name)
  163.             input[:group_id] = asset_info[:asset_group_id]
  164.             found = true
  165.             break
  166.           end
  167.         end
  168.  
  169.         if not found
  170.           raise "Unable to find asset group with name: #{group_name}"
  171.         end
  172.  
  173.       end
  174.  
  175.       group_configs = @api_connector.asset_group_config(input[:group_id])
  176.  
  177.       # First build a reverse map to ensure we will not be scanning a device more than once.
  178.       device_to_site = Hash.new("")
  179.       for group_config in group_configs
  180.         key = group_config[:address]
  181.         value = [group_config[:site_id], group_config[:device_id]].flatten
  182.         device_to_site[key] = value;
  183.       end
  184.  
  185.       # Combobulate to a map of site_id->addresses
  186.       site_to_devices = Hash.new("")
  187.       for address in device_to_site.keys
  188.         key = device_to_site[address][0]
  189.         value = device_to_site[address][1]
  190.         if (site_to_devices.has_key?(key))
  191.           site_to_devices[key] = [site_to_devices[key], value].flatten()
  192.         else
  193.           site_to_devices[key] = [value]
  194.         end
  195.       end
  196.  
  197.       # TODO: More intelligent logic needed, ie: scan already started
  198.       for site in site_to_devices.keys
  199.         res = @api_connector.site_device_scan_start(site, site_to_devices[site], nil)
  200.         if (res)
  201.           puts("Scan started scan ID: #{res[:scan_id]}, on engine ID: #{res[:engine_id]}")
  202.         else
  203.           puts("Scan failed for site #{site}")
  204.         end
  205.       end
  206.     end
  207.  
  208.     def do_logout
  209.       @api_connector.logout
  210.     end
  211.  
  212. end
  213.  
  214.  
  215. #---------------------
  216. # MAIN EXECUTION BLOCK
  217. #---------------------
  218.  
  219. begin
  220.  
  221. if ARGV.length > 0
  222.   begin
  223.     options = Options.parse ARGV
  224.     api_util = ::APIUtil.new options.user, options.password, options.host
  225.     api_util.do_login
  226.     case options.key
  227.       when 1 then api_util.print_asset_groups
  228.       when 2 then api_util.print_asset_group_info options.args
  229.       when 3 then api_util.start_asset_group_scan({:group_id => options.args, :max_scans => -1})
  230.       else puts "Invalid Input!"
  231.     end
  232.   rescue Exception => e
  233.     puts e
  234.   end
  235.   exit 0
  236. else
  237.   # Show Main Commands
  238.   commands =
  239. <<CMDS
  240.   SELECT A COMMAND:
  241.   1 - Print asset groups info
  242.   2 - Print an asset group info
  243.   3 - Scan an asset group
  244.   q - Quit
  245. CMDS
  246.  
  247.   while (!APIUtil.is_connected) do
  248.     print("Enter the NeXpose host address:")
  249.     address = gets().chomp()
  250.     print("Enter the user name for this instance:")
  251.     user_name = gets().chomp()
  252.     print("Enter the password for this instance:")
  253.     password = gets().chomp()
  254.     api_util = ::APIUtil.new user_name, password, address
  255.     api_util.do_login
  256.   end
  257.  
  258.   input = ''
  259.   while (input[0] != 'q') do
  260.     puts("\n\n#{commands}")
  261.     print("\nSelect Option:")
  262.     input = gets()
  263.     puts()
  264.  
  265.     if (!APIUtil.is_connected)
  266.       api_util.do_login
  267.     end
  268.  
  269.     case ( input[0] )
  270.       when '1' then api_util.print_asset_groups
  271.       when '2' then api_util.print_asset_group_info -1
  272.       when '3' then api_util.start_asset_group_scan -1
  273.       else if input[0] != 'q' then puts("Invalid Input!") end
  274.     end
  275.   end
  276.  
  277.   puts("Bye")
  278.   if (APIUtil.is_connected)
  279.     api_util.do_logout
  280.   end
  281.  
  282. end
  283.  
  284. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement