Configuration changes

Pulled System.rb out to individual classes.
This commit is contained in:
thomashaw
2016-03-08 18:54:15 +00:00
parent 6a0107ee05
commit ddf8194397
16 changed files with 289 additions and 277 deletions

9
lib/base_manager.rb Normal file
View File

@@ -0,0 +1,9 @@
class BaseManager
def self.generate_base(system,bases)
# takes a sample from bases.xml and then assigns it to system
box = bases.sample
system.basebox = box.vagrantbase
system.url = box.url
return system
end
end

73
lib/configuration.rb Normal file
View File

@@ -0,0 +1,73 @@
require_relative 'systemreader.rb'
class Configuration
# populates the system class with an array of System objects.
def initialize
@systemreader = SystemReader.new
@systems = init_systems()
end
def get_systems
if @systems.empty?
init_systems()
end
return @systems
end
def init_systems()
@systems = @systemreader.parse_systems
end
def self.networks
if defined? @@networks
return @@networks
end
return @@networks = _get_list(NETWORKS_XML, "//networks/network", Network)
end
def self.bases
if defined? @@bases
return @@bases
end
return @@bases = _get_list(BASE_XML, "//bases/base", Basebox)
end
def self.vulnerabilities
if defined? @@vulnerabilities
return @@vulnerabilities
end
return @@vulnerabilities = _get_list(VULN_XML, "//vulnerabilities/vulnerability", Vulnerability)
end
def self.services
if defined? @@services
return @@services
end
return @@services = _get_list(SERVICES_XML, "//services/service", Service)
end
def self._get_list(xmlfile, xpath, cls)
itemlist = []
doc = Nokogiri::XML(File.read(xmlfile))
doc.xpath(xpath).each do |item|
# new class e.g networks
obj = cls.new
# checks to see if there are children puppet and add string to obj.puppets
# move this to vulnerabilities/services classes?
if defined? obj.puppets
item.xpath("puppets/puppet").each { |c| obj.puppets << c.text.strip if not c.text.strip.empty? }
item.xpath("ports/port").each { |c| obj.ports << c.text.strip if not c.text.strip.empty? }
end
# too specific move to vuln class end
item.each do |attr, value|
obj.send "#{attr}=", value
end
# vulnerability item
itemlist << obj
end
return itemlist
end
end

View File

@@ -8,6 +8,7 @@ BASE_XML = "#{ROOT_DIR}/xml/bases.xml"
MOUNT_DIR = "#{ROOT_DIR}/mount/"
BUILD_DIR = "#{ROOT_DIR}/modules/build/"
MOUNT_PUPPET_DIR = "#{ROOT_DIR}/mount/puppet"
PROJECTS_DIR = "#{ROOT_DIR}/projects"
#PATH CONSTANTS
MODULES_PATH = "#{ROOT_DIR}/modules/"
@@ -21,3 +22,5 @@ AVAILABLE_CVE_NUMBERS = []
#VAGRANT_FILE_CONSTANTS
PATH_TO_CLEANUP = "#{ROOT_DIR}/modules/build/puppet/"
VAGRANT_TEMPLATE_FILE = "#{ROOT_DIR}/lib/templates/vagrantbase.erb"
REPORT_TEMPLATE_FILE = "#{ROOT_DIR}/lib/templates/report.erb"

11
lib/erb_controller.rb Normal file
View File

@@ -0,0 +1,11 @@
class ERBController
# ERB Controller initializes the system and returns the binding when mapping .erb files
attr_accessor :systems
def initialize
@systems = []
end
def get_binding
return binding
end
end

View File

@@ -1,21 +1,18 @@
require 'erb'
require_relative 'erb_controller'
require_relative 'constants'
VAGRANT_TEMPLATE_FILE = "#{ROOT_DIR}/lib/templates/vagrantbase.erb"
REPORT_TEMPLATE_FILE = "#{ROOT_DIR}/lib/templates/report.erb"
PROJECTS_DIR = "#{ROOT_DIR}/projects"
require_relative 'configuration'
class FileCreator
# Creates project directory, uses .erb files to create a report and the vagrant file that will be used
# to create the virtual machines
def initialize(systems)
@systems = systems
def initialize(config)
@configuration = config
end
def generate(system)
Dir::mkdir("#{PROJECTS_DIR}") unless File.exists?("#{PROJECTS_DIR}")
def generate()
systems = @configuration.get_systems
Dir::mkdir("#{PROJECTS_DIR}") unless File.exists?("#{PROJECTS_DIR}")
count = Dir["#{PROJECTS_DIR}/*"].length
build_number = count.next
@@ -31,7 +28,7 @@ class FileCreator
%x[#{command}]
controller = ERBController.new
controller.systems = system
controller.systems = systems
vagrant_template = ERB.new(File.read(VAGRANT_TEMPLATE_FILE), 0, '<>')
File.delete("#{PROJECTS_DIR}/Project#{build_number}/Vagrantfile")
puts "#{PROJECTS_DIR}/Project#{build_number}/Vagrantfile file has been created"
@@ -44,17 +41,4 @@ class FileCreator
return build_number
end
end
class ERBController
# ERB Controller initializes the system and returns the binding when mapping .erb files
attr_accessor :systems
def initialize
@systems = []
end
def get_binding
return binding
end
end
end

32
lib/network_manager.rb Normal file
View File

@@ -0,0 +1,32 @@
class NetworkManager
# the user will either specify a blank misc type or a knownnetwork type
def self.process(networks,valid_network)
new_networks = {}
# intersection of valid networks / user defined networks
legal_networks = valid_network & networks
networks.each do |network|
# checks to see string is blank if so valid misc into a new hash map of vulnerabilities
if network.name == ""
random = valid_network.sample
new_networks[random.id] = random
else
has_found = false
# shuffle randomly selects first match
legal_networks.shuffle.each do |valid|
if network.name == valid.name
network.range = valid.range unless not network.range.empty?
# valid misc into a new hash map of networks
new_networks[network.id] = network
has_found = true
break
end
end
if not has_found
p "Network was not found please check the xml scenario.xml"
exit
end
end
end
return new_networks.values
end
end

3
lib/objects/base_box.rb Normal file
View File

@@ -0,0 +1,3 @@
class Basebox
attr_accessor :name, :os, :distro, :vagrantbase, :url
end

24
lib/objects/network.rb Normal file
View File

@@ -0,0 +1,24 @@
class Network
attr_accessor :name, :range
def initialize(name="", range="")
@name = name
@range = range
end
def id
hash = @name + @range
return hash
# return string that connects everything to 1 massive string
end
def eql? other
# checks if name matches networks.xml from scenario.xml
other.kind_of?(self.class) && @name == other.name
end
def hash
@type.hash
end
end

22
lib/objects/service.rb Normal file
View File

@@ -0,0 +1,22 @@
class Service
attr_accessor :name, :type, :details, :puppets
def initialize(name="", type="", details="", puppets=[])
@name = name
@type = type
@details = details
@puppets = puppets
end
def eql? other
other.kind_of?(self.class) && @type == other.type
end
def hash
@type.hash
end
def id
return @type
end
end

28
lib/objects/system.rb Normal file
View File

@@ -0,0 +1,28 @@
class System
# can access from outside of class
attr_accessor :id, :os, :url,:basebox, :networks, :vulns, :services
#initalizes system variables
def initialize(id, os, basebox, url, vulns=[], networks=[], services=[])
@id = id
@os = os
@url = url
@basebox = basebox
@vulns = vulns
@networks = networks
@services = services
end
def is_valid_base
valid_base = Configuration.bases
valid_base.each do |b|
if @basebox == b.vagrantbase
@url = b.url
return true
end
end
return false
end
end

View File

@@ -3,11 +3,6 @@ require_relative('../constants.rb')
class Vulnerability
attr_accessor :type, :privilege, :access ,:puppets, :details, :ports, :name, :cve, :files, :scripts
def eql? other
# checks if type matches vulns.xml from scenario.xml
other.kind_of?(self.class) && @type == other.type
end
def initialize(type='', privilege='', access='', puppets=[], details='', ports=[], platform ='', name='', cve='', files=[], scripts=[])
@type = type
@privilege = privilege
@@ -22,6 +17,11 @@ class Vulnerability
@scripts = scripts
end
def eql? other
# checks if type matches vulns.xml from scenario.xml
other.kind_of?(self.class) && @type == other.type
end
def id
return @type + @privilege + @access
end

47
lib/service_manager.rb Normal file
View File

@@ -0,0 +1,47 @@
class ServiceManager
# secure services are randomly selected from the definitions in services.xml (secure_services)
# based on the attributes optionally specified in scenario.xml (want_services)
# However, if the service type has already had a vulnerability assigned (selected_vulns), it is ignored here
def self.process(want_services, secure_services, selected_vulns=[])
return_services = {}
legal_services = secure_services.clone
wanted_services = want_services.clone
# remove all services that have already been selected as vulns (from both the wanted and secure lists)
selected_vulns.each do |a_vuln|
legal_services.delete_if{|x| x.type == a_vuln.type}
wanted_services.delete_if{|x| x.type == a_vuln.type}
end
wanted_services.each do |service_query|
# select based on selected type...
# copy services array
search_list = legal_services.clone
# shuffle order of available secure services
search_list.shuffle!
# remove all the services that don't match the current selection (type, etc)
if service_query.type.length > 0
puts "Searching for service matching type: " + service_query.type
search_list.delete_if{|x| x.type != service_query.type}
end
if search_list.length == 0
STDERR.puts "Matching service was not found please check the xml scenario.xml"
STDERR.puts "(note: you can only have one of each type of service per system)"
exit
else
# use from the top of the top of the randomised list
return_services[service_query.id] = search_list[0]
if search_list[0].type.length > 0
puts "Selected secure service : " + search_list[0].type
end
# enforce only one of any service type (remove from available)
legal_services.delete_if{|x| x.type == service_query.type}
end
end
return return_services.values
end
end

View File

@@ -1,231 +0,0 @@
require 'nokogiri'
require_relative 'constants'
class System
# can access from outside of class
attr_accessor :id, :os, :url,:basebox, :networks, :vulns, :services
#initalizes system variables
def initialize(id, os, basebox, url, vulns=[], networks=[], services=[])
@id = id
@os = os
@url = url
@basebox = basebox
@vulns = vulns
@networks = networks
@services = services
end
def is_valid_base
valid_base = Conf.bases
valid_base.each do |b|
if @basebox == b.vagrantbase
@url = b.url
return true
end
end
return false
end
end
class Network
attr_accessor :name, :range
def initialize(name="", range="")
@name = name
@range = range
end
def id
hash = @name + @range
return hash
# return string that connects everything to 1 massive string
end
def eql? other
# checks if name matches networks.xml from scenario.xml
other.kind_of?(self.class) && @name == other.name
end
def hash
@type.hash
end
end
class Service
attr_accessor :name, :type, :details, :puppets
def initialize(name="", type="", details="", puppets=[])
@name = name
@type = type
@details = details
@puppets = puppets
end
def eql? other
other.kind_of?(self.class) && @type == other.type
end
def hash
@type.hash
end
def id
return @type
end
end
class ServiceManager
# secure services are randomly selected from the definitions in services.xml (secure_services)
# based on the attributes optionally specified in scenario.xml (want_services)
# However, if the service type has already had a vulnerability assigned (selected_vulns), it is ignored here
def self.process(want_services, secure_services, selected_vulns=[])
return_services = {}
legal_services = secure_services.clone
wanted_services = want_services.clone
# remove all services that have already been selected as vulns (from both the wanted and secure lists)
selected_vulns.each do |a_vuln|
legal_services.delete_if{|x| x.type == a_vuln.type}
wanted_services.delete_if{|x| x.type == a_vuln.type}
end
wanted_services.each do |service_query|
# select based on selected type...
# copy services array
search_list = legal_services.clone
# shuffle order of available secure services
search_list.shuffle!
# remove all the services that don't match the current selection (type, etc)
if service_query.type.length > 0
puts "Searching for service matching type: " + service_query.type
search_list.delete_if{|x| x.type != service_query.type}
end
if search_list.length == 0
STDERR.puts "Matching service was not found please check the xml scenario.xml"
STDERR.puts "(note: you can only have one of each type of service per system)"
exit
else
# use from the top of the top of the randomised list
return_services[service_query.id] = search_list[0]
if search_list[0].type.length > 0
puts "Selected secure service : " + search_list[0].type
end
# enforce only one of any service type (remove from available)
legal_services.delete_if{|x| x.type == service_query.type}
end
end
return return_services.values
end
end
class NetworkManager
# the user will either specify a blank misc type or a knownnetwork type
def self.process(networks,valid_network)
new_networks = {}
# intersection of valid networks / user defined networks
legal_networks = valid_network & networks
networks.each do |network|
# checks to see string is blank if so valid misc into a new hash map of vulnerabilities
if network.name == ""
random = valid_network.sample
new_networks[random.id] = random
else
has_found = false
# shuffle randomly selects first match
legal_networks.shuffle.each do |valid|
if network.name == valid.name
network.range = valid.range unless not network.range.empty?
# valid misc into a new hash map of networks
new_networks[network.id] = network
has_found = true
break
end
end
if not has_found
p "Network was not found please check the xml scenario.xml"
exit
end
end
end
return new_networks.values
end
end
class Basebox
attr_accessor :name, :os, :distro, :vagrantbase, :url
end
class BaseManager
def self.generate_base(system,bases)
# takes a sample from bases.xml and then assigns it to system
box = bases.sample
system.basebox = box.vagrantbase
system.url = box.url
return system
end
end
class Conf
# this class uses nokogiri to grab all of the information from misc.xml, bases.xml, and vulns.xml
# then adds them to their specific class to do checking for legal in Manager.process
def self.networks
if defined? @@networks
return @@networks
end
return @@networks = self._get_list(NETWORKS_XML, "//networks/network", Network)
end
def self.bases
if defined? @@bases
return @@bases
end
return @@bases = self._get_list(BASE_XML, "//bases/base", Basebox)
end
def self.vulnerabilities
if defined? @@vulnerabilities
return @@vulnerabilities
end
return @@vulnerabilities = self._get_list(VULN_XML, "//vulnerabilities/vulnerability", Vulnerability)
end
def self.services
if defined? @@services
return @@services
end
return @@services = self._get_list(SERVICES_XML, "//services/service", Service)
end
def self._get_list(xmlfile, xpath, cls)
itemlist = []
doc = Nokogiri::XML(File.read(xmlfile))
doc.xpath(xpath).each do |item|
# new class e.g networks
obj = cls.new
# checks to see if there are children puppet and add string to obj.puppets
# move this to vulnerabilities/services classes?
if defined? obj.puppets
item.xpath("puppets/puppet").each { |c| obj.puppets << c.text.strip if not c.text.strip.empty? }
item.xpath("ports/port").each { |c| obj.ports << c.text.strip if not c.text.strip.empty? }
end
# too specific move to vuln class end
item.each do |attr, value|
obj.send "#{attr}=", value
end
# vulnerability item
itemlist << obj
end
return itemlist
end
end

View File

@@ -1,18 +1,25 @@
require_relative 'system.rb'
require_relative 'objects/vulnerability'
require_relative 'configuration.rb'
require_relative 'network_manager.rb'
require_relative 'service_manager.rb'
require_relative 'base_manager.rb'
require_relative 'helpers/vulnerability_processor'
require_relative 'objects/base_box'
require_relative 'objects/network'
require_relative 'objects/service'
require_relative 'objects/system'
require_relative 'objects/vulnerability'
class SystemReader
# initializes systems xml from BOXES_XML const
def initialize(systems_xml)
@systems_xml = systems_xml
def initialize()
@vulnerability_processor = VulnerabilityProcessor.new
end
# uses nokogiri to extract all system information from scenario.xml will add it to the system class after
# checking if the vulnerabilities / networks exist from system.rb
def systems
def parse_systems
systems = []
doc = Nokogiri::XML(File.read(@systems_xml))
doc = Nokogiri::XML(File.read(SCENARIO_XML))
doc.xpath("//systems/system").each do |system|
id = system["id"]
os = system["os"]
@@ -51,9 +58,9 @@ class SystemReader
new_vulns = @vulnerability_processor.process(vulns)
#puts new_vulns.inspect
new_networks = NetworkManager.process(networks, Conf.networks)
new_networks = NetworkManager.process(networks, Configuration.networks)
# pass in the already selected set of vulnerabilities, and additional secure services to find
new_services = ServiceManager.process(services, Conf.services, new_vulns)
new_services = ServiceManager.process(services, Configuration.services, new_vulns)
s = System.new(id, os, basebox, url, new_vulns, new_networks, new_services)
if s.is_valid_base == false
@@ -64,4 +71,4 @@ class SystemReader
end
return systems
end
end
end

View File

@@ -25,14 +25,14 @@ end
def build_config
puts 'Reading configuration file for virtual machines you want to create'
# uses nokogoiri to grab all the system information from scenario.xml
systems = SystemReader.new(SCENARIO_XML).systems
# Initialise configuration
config = Configuration.new()
puts 'Creating vagrant file'
puts 'Creating vagrant file'
# create's vagrant file / report a starts the vagrant installation'
create_files = FileCreator.new(systems)
build_number = create_files.generate(systems)
return build_number
file_creator = FileCreator.new(config)
build_number = file_creator.generate()
return build_number
end
def build_vms(build_number)

View File

@@ -52,7 +52,7 @@ class TestXMLIsEqual < Test::Unit::TestCase
if empty_type.type == ""
p empty_type
vuln = generate_vulnerability(empty_type,Conf.vulnerabilities,dummy_list)
vuln = generate_vulnerability(empty_type, Configuration.vulnerabilities, dummy_list)
assert_not_match(vuln,"")
end
end