Skip to content

Instantly share code, notes, and snippets.

@cjp
Created December 18, 2015 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cjp/2dc77b83f628ac706897 to your computer and use it in GitHub Desktop.
Save cjp/2dc77b83f628ac706897 to your computer and use it in GitHub Desktop.
Take list of assets and classifications in CSV and tag the assets in Nexpose
#!/usr/bin/env ruby
require 'csv'
require 'nexpose'
require 'highline/import'
require 'ipaddr'
class String
# ask String if it's an IPv4 address
def ipv4?
begin
addr = IPAddr.new self
return addr.ipv4?
rescue IPAddr::InvalidAddressError
return false
end
end
end
# Nexpose treats criticality tags different than custom tags
def assign_criticality(nsc, asset, criticality)
tag_id = nsc.list_tags.find { |t| t.name == Nexpose::Tag::Type::Level.const_get(criticality) }.id
unless nsc.asset_tags(asset.id).find { |t| t.id == tag_id }
tag = Nexpose::Tag.load(nsc, tag_id)
tag.add_to_asset(nsc, asset.id)
end
end
def assign_custom(nsc, asset, custom)
tag_id = nsc.list_tags.find { |t| t.name == custom }.id
unless nsc.asset_tags(asset.id).find { |t| t.id == tag_id }
tag = Nexpose::Tag.load(nsc, tag_id)
tag.add_to_asset(nsc, asset.id)
end
end
def nexpose_login
# TODO: change to new nexcli style login
default_host = 'nexpose.example.com'
default_port = 3780
default_name = 'nxadmin'
host = ask('Enter the server name (host) for Nexpose: ') { |q| q.default = default_host }
port = ask('Enter the port for Nexpose: ') { |q| q.default = default_port.to_s }
user = ask('Enter your username: ') { |q| q.default = default_name }
pass = ask('Enter your password: ') { |q| q.echo = '*' }
connection = Nexpose::Connection.new(host, user, pass)
connection.login
return connection
end
# find assets named starting with or by IPv4
def find_assets(connection, name_or_ip)
if name_or_ip.ipv4?
connection.filter(Nexpose::Search::Field::IP_RANGE, Nexpose::Search::Operator::IN, [name_or_ip, name_or_ip])
else
connection.filter(Nexpose::Search::Field::ASSET, Nexpose::Search::Operator::STARTS_WITH, name_or_ip)
end
end
# begin main...
if ARGV.empty?
puts "\nUsage: #{$0} <filename>\n\n"
puts "\t<filename> is a CSV containing at least server_name and "
puts "\tclassification columns.\n\n"
puts "\tserver_name may include names and IPv4 addresses.\n\n"
exit 1
end
nsc = nexpose_login
# load assets from CSV
CSV.foreach(ARGV[0], {:headers => true, :header_converters => :symbol}) do |row|
if row[:classification].downcase == "secret"
assets = find_assets(nsc, row[:server_name])
if assets.empty?
puts "#{row[:server_name]} not found"
else
assets.each do |asset|
puts "#{row[:server_name]}\t#{asset.ip}\t#{asset.name}"
assign_custom(nsc, asset, 'Secret')
assign_criticality(nsc, asset, 'HIGH')
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment