diff --git a/.gitignore b/.gitignore index 910b2fe4..1a1a6446 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ templates/* attachments/* config.json plugins/* +!log/blank +log/* \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..660cd2eb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +language: ruby + +rvm: + - 2.1.5 + +branches: + only: + - master + - rack_tests + - dev + +before_install: + - sudo apt-get -qq update + - sudo apt-get install -y libsqlite3-dev libxslt-dev libxml2-dev zlib1g-dev gcc + +install: + - bundle install + +script: + - export RACK_ENV=test + - ruby scripts/first_time.rb --quiet + - rake test diff --git a/Gemfile b/Gemfile index 62daddfb..f14cc4c3 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,12 @@ source 'https://rubygems.org' ruby "2.1.5" +group :test do + gem 'rake' + gem 'rack-test' + gem 'minitest', '5.10.1' +end + gem 'sinatra' gem 'haml' gem 'rubyzip' diff --git a/Gemfile.lock b/Gemfile.lock index 0c0a5cf5..c7ff2814 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,6 +60,7 @@ GEM json_pure (1.8.2) librex (0.0.999) mini_portile (0.6.2) + minitest (5.10.1) msfrpc-client (1.0.3) librex (~> 0.0.70, >= 0.0.70) msgpack (~> 0.6.2, >= 0.6.2) @@ -71,6 +72,9 @@ GEM rack (1.5.5) rack-protection (1.5.3) rack + rack-test (0.7.0) + rack (>= 1.0, < 3) + rake (12.0.0) rubyzip (1.2.1) sinatra (1.4.6) rack (~> 1.4) @@ -89,9 +93,12 @@ DEPENDENCIES do_sqlite3 (= 0.10.17) haml json + minitest (= 5.10.1) msfrpc-client (= 1.0.3) net-ldap (~> 0.11) nokogiri + rack-test + rake rubyzip sinatra @@ -99,4 +106,4 @@ RUBY VERSION ruby 2.1.5p273 BUNDLED WITH - 1.13.6 + 1.15.1 diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..f1ea15a6 --- /dev/null +++ b/Rakefile @@ -0,0 +1,7 @@ +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.pattern = 'test/*_spec.rb' + #https://github.com/hanami/utils/issues/123 + t.warning = false +end diff --git a/db/test.db b/db/test.db new file mode 100644 index 00000000..6bc96aaa Binary files /dev/null and b/db/test.db differ diff --git a/helpers/test_helper.rb b/helpers/test_helper.rb new file mode 100644 index 00000000..ca81bb44 --- /dev/null +++ b/helpers/test_helper.rb @@ -0,0 +1,5 @@ +ENV['RACK_ENV'] = 'test' +require 'minitest/autorun' +require 'rack/test' + +require File.expand_path '../../serpico.rb', __FILE__ \ No newline at end of file diff --git a/model/master.rb b/model/master.rb index 007e9c54..24d65a36 100644 --- a/model/master.rb +++ b/model/master.rb @@ -4,7 +4,11 @@ require 'dm-migrations' # Initialize the Master DB -DataMapper.setup(:default, "sqlite://#{Dir.pwd}/db/master.db") +if ENV['RACK_ENV'] == 'test' + DataMapper.setup(:default, "sqlite://#{Dir.pwd}/db/test.db") +else + DataMapper.setup(:default, "sqlite://#{Dir.pwd}/db/master.db") +end class TemplateFindings @@ -380,4 +384,6 @@ class Xslt # any differences between the data store and the data model should be fixed by this # As discussed in http://datamapper.org/why.html it is limited. Hopefully we never create conflicts. -DataMapper.auto_upgrade! +if ENV['RACK_ENV'] != 'test' + DataMapper.auto_upgrade! +end diff --git a/scripts/first_time.rb b/scripts/first_time.rb index 0c2d06c3..e764238f 100644 --- a/scripts/first_time.rb +++ b/scripts/first_time.rb @@ -2,6 +2,20 @@ require './helpers/xslt_generation' require 'openssl' require 'json' +require 'optparse' + +options = {} +OptionParser.new do |opts| + opts.banner = "Usage: first_time.rb [options]" + opts.on('-q', '--quiet', 'Quiet mode') do |quiet| + options[:quiet] = true; + end + opts.on('-h', '--help', 'Displays Help') do + puts opts + exit + end +end.parse! + userx = User.first @@ -10,7 +24,11 @@ puts "No users in the database, creating a first user. \n" puts "Please enter username (default: administrator): " - username = gets.chomp + if options[:quiet] + username = "administrator" + else + username = gets.chomp + end username = "administrator" if username == "" puts "Generating random password and adding the Administrator with username #{username}..." @@ -39,28 +57,34 @@ puts "Would you like to initialize the database with templated findings? (Y/n)" -find_i = gets.chomp -if (find_i == "" or find_i.downcase == "y" or find_i.downcase == "yes") - puts "Importing Templated Findings template_findings.json..." +if options[:quiet] == nil + find_i = gets.chomp - file = File.new('./templates/template_findings.json',"rb") - json = "" - while(line_j = file.gets) - json = json + line_j - end - line = JSON.parse(json) + if (find_i == "" or find_i.downcase == "y" or find_i.downcase == "yes") + puts "Importing Templated Findings template_findings.json..." - line.each do |j| - j["id"] = nil + file = File.new('./templates/template_findings.json',"rb") + json = "" - finding = TemplateFindings.first(:title => j["title"]) + while(line_j = file.gets) + json = json + line_j + end + line = JSON.parse(json) - j["approved"] = true - f = TemplateFindings.first_or_create(j) - f.save - end + line.each do |j| + j["id"] = nil + + finding = TemplateFindings.first(:title => j["title"]) + + j["approved"] = true + f = TemplateFindings.first_or_create(j) + f.save + end + else + puts "Skipping templated finding import. Use the UI to import templated findings." + end else - puts "Skipping templated finding import. Use the UI to import templated findings." + puts "in quiet mode, skipping importing templates" end # add the Default templates into the DB @@ -109,28 +133,6 @@ report = Xslt.new(datax) report.save - puts "Adding the Default CVSS Report Template" - xslt_file = "./templates/#{rand(36**36).to_s(36)}.xslt" - docx = "./templates/CVSS_Template.docx" - - xslt = generate_xslt(docx) - if xslt =~ /Error file DNE/ - return "ERROR!!!!!!" - end - - # open up a file handle and write the attachment - File.open(xslt_file, 'wb') {|f| f.write(xslt) } - - # delete the file data from the attachment - datax = Hash.new - datax["docx_location"] = "#{docx}" - datax["xslt_location"] = "#{xslt_file}" - datax["description"] = "Default CVSS Report" - datax["report_type"] = "Default CVSS Report" - report = Xslt.new(datax) - report.save - - puts "Adding the Default CVSSv3 Report Template" xslt_file = "./templates/#{rand(36**36).to_s(36)}.xslt" docx = "./templates/Default CVSS 3 Report.docx" diff --git a/serpico.rb b/serpico.rb index c22e3014..8c353fef 100644 --- a/serpico.rb +++ b/serpico.rb @@ -27,4 +27,6 @@ server_options[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_NONE end -Rack::Handler::WEBrick.run Server, server_options \ No newline at end of file +if ENV['RACK_ENV'] != 'test' + Rack::Handler::WEBrick.run Server, server_options +end \ No newline at end of file diff --git a/server.rb b/server.rb index d29e7692..565be7f2 100644 --- a/server.rb +++ b/server.rb @@ -19,12 +19,14 @@ class Server < Sinatra::Application set :show_exceptions, config_options["show_exceptions"] #Set Logging - if(config_options["log_file"] != "") - puts "|+| Started serpico on https://"+config_options["bind_address"]+":"+config_options["port"] - puts "|+| Logging to "+config_options["log_file"] - log = File.new(config_options["log_file"], "a+") - $stdout.reopen(log) - $stderr.reopen(log) + if ENV['RACK_ENV'] != 'test' + if(config_options["log_file"] != "") + puts "|+| Started serpico on https://"+config_options["bind_address"]+":"+config_options["port"] + puts "|+| Logging to "+config_options["log_file"] + log = File.new(config_options["log_file"], "a+") + $stdout.reopen(log) + $stderr.reopen(log) + end end # CVSS diff --git a/test/main_test.rb b/test/main_test.rb deleted file mode 100644 index e0ef2636..00000000 --- a/test/main_test.rb +++ /dev/null @@ -1,229 +0,0 @@ -require 'rubygems' -require 'test/unit' -require 'rack/test' -require './serpico' - -class SerpicoTests < Test::Unit::TestCase - - def test_before_check - browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) - - browser.get '/' - assert_equal browser.last_response.status,302 - - browser.get '/login' - assert_equal browser.last_response.status,302 - - browser.get '/info' - assert_equal browser.last_response.status,302 - - browser.get '/logout' - assert_equal browser.last_response.status,302 - - browser.get '/admin/' - assert_equal browser.last_response.status,302 - - browser.get '/admin/add_user' - assert_equal browser.last_response.status,302 - - browser.get '/admin/pull' - assert_equal browser.last_response.status,302 - - browser.get '/admin/list_user' - assert_equal browser.last_response.status,302 - - browser.get '/admin/edit_user/:id' - assert_equal browser.last_response.status,302 - - browser.get '/admin/delete/:id' - assert_equal browser.last_response.status,302 - - browser.get '/admin/add_user/:id' - assert_equal browser.last_response.status,302 - - browser.get '/admin/del_user_report/:id/:author' - assert_equal browser.last_response.status,302 - - browser.get '/master/findings' - assert_equal browser.last_response.status,302 - - browser.get '/master/findings/f/:type' - assert_equal browser.last_response.status,302 - - browser.get '/master/findings/new' - assert_equal browser.last_response.status,302 - - browser.get '/master/findings/:id/edit' - assert_equal browser.last_response.status,302 - - browser.get '/mapping/:id/nessus/:mappingid/delete' - assert_equal browser.last_response.status,302 - - browser.get '/mapping/:id/burp/:mappingid/delete' - assert_equal browser.last_response.status,302 - - browser.get '/master/findings/:id/delete' - assert_equal browser.last_response.status,302 - - browser.get '/master/findings/:id/preview' - assert_equal browser.last_response.status,302 - - browser.get '/master/export' - assert_equal browser.last_response.status,302 - - browser.get '/master/import' - assert_equal browser.last_response.status,302 - - browser.get '/admin/templates' - assert_equal browser.last_response.status,302 - - browser.get '/admin/templates/add' - assert_equal browser.last_response.status,302 - - browser.get '/admin/templates/:id/download' - assert_equal browser.last_response.status,302 - - browser.get '/admin/delete/templates/:id' - assert_equal browser.last_response.status,302 - - browser.get '/admin/templates/:id/edit' - assert_equal browser.last_response.status,302 - - browser.get '/reports/list' - assert_equal browser.last_response.status,200 - - browser.get '/report/new' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/attachments' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/import_nessus' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/import_burp' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/upload_attachments' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/attachments/:att_id' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/attachments/delete/:att_id' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/remove' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/edit' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/additional_features' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/user_defined_variables' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/status' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings_add' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings/new' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings/:finding_id/edit' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings/:finding_id/upload' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings/:finding_id/remove' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/findings/:finding_id/preview' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/generate' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/export' - assert_equal browser.last_response.status,302 - - browser.get '/report/import' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/text_status' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/asciidoc_status' - assert_equal browser.last_response.status,302 - - browser.get '/report/:id/presentation' - assert_equal browser.last_response.status,302 - - browser.post '/admin/add_user' - assert_equal browser.last_response.status,302 - - browser.post '/info' - assert_equal browser.last_response.status,302 - - browser.post '/login' - assert_equal browser.last_response.status,302 - - browser.post '/admin/add_user' - assert_equal browser.last_response.status,302 - - browser.post '/admin/add_user/:id' - assert_equal browser.last_response.status,302 - - browser.post '/master/findings/new' - assert_equal browser.last_response.status,302 - - browser.post '/master/findings/:id/edit' - assert_equal browser.last_response.status,302 - - browser.post '/master/import' - assert_equal browser.last_response.status,302 - - browser.post '/admin/templates/add' - assert_equal browser.last_response.status,302 - - browser.post '/admin/templates/edit' - assert_equal browser.last_response.status,302 - - browser.post '/report/new' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/import_autoadd' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/upload_attachments' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/edit' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/user_defined_variables' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/findings_add' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/findings/new' - assert_equal browser.last_response.status,302 - - browser.post '/report/:id/findings/:finding_id/edit' - assert_equal browser.last_response.status,302 - - browser.post '/report/import' - assert_equal browser.last_response.status,302 - - end - -end \ No newline at end of file diff --git a/test/main_test_spec.rb b/test/main_test_spec.rb new file mode 100644 index 00000000..e2224cf6 --- /dev/null +++ b/test/main_test_spec.rb @@ -0,0 +1,258 @@ + +require File.expand_path '../../helpers/test_helper.rb', __FILE__ + + +class SerpicoTests < MiniTest::Test + + include Rack::Test::Methods + + # leaving this in here for prep of authd tests + # include FactoryGirl::Syntax::Methods + + # FactoryGirl.define do + # factory :user, class: User do + # username "test" + # password "serpicorulez" + # admin true + # end + # end + + def app + Server.new + end + + def test_before_auth + get '/idontexist' + assert_equal 404,last_response.status + + get '/no_access' + assert_equal 200,last_response.status + + get '/admin/dbbackup' + assert_equal 302,last_response.status + + get '/info' + assert_equal 302,last_response.status + + get '/logout' + assert_equal 302,last_response.status + + get '/admin/' + assert_equal 302,last_response.status + + get '/admin/admin_plugins' + assert_equal 302,last_response.status + + get '/admin/plugins' + assert_equal 302,last_response.status + + get '/report/:id/report_plugins' + assert_equal 302,last_response.status + + get '/admin/add_user' + assert_equal 302,last_response.status + + get '/admin/pull' + assert_equal 302,last_response.status + + get '/admin/list_user' + assert_equal 302,last_response.status + + get '/admin/edit_user/:id' + assert_equal 302,last_response.status + + get '/admin/delete/:id' + assert_equal 302,last_response.status + + get '/admin/add_user/:id' + assert_equal 302,last_response.status + + get '/admin/del_user_report/:id/:author' + assert_equal 302,last_response.status + + get '/master/findings' + assert_equal 302,last_response.status + + get '/master/findings/f/:type' + assert_equal 302,last_response.status + + get '/master/findings/new' + assert_equal 302,last_response.status + + get '/master/findings/:id/edit' + assert_equal 302,last_response.status + + get '/mapping/:id/nessus/:mappingid/delete' + assert_equal 302,last_response.status + + get '/mapping/:id/burp/:mappingid/delete' + assert_equal 302,last_response.status + + get '/mapping/:id/vulnmap/:mappingid/delete' + assert_equal 302,last_response.status + + get '/master/findings/:id/delete' + assert_equal 302,last_response.status + + get '/master/findings/:id/preview' + assert_equal 302,last_response.status + + get '/master/export' + assert_equal 302,last_response.status + + get '/master/import' + assert_equal 302,last_response.status + + get '/admin/templates' + assert_equal 302,last_response.status + + get '/admin/templates/add' + assert_equal 302,last_response.status + + get '/admin/templates/:id/download' + assert_equal 302,last_response.status + + get '/admin/delete/templates/:id' + assert_equal 302,last_response.status + + get '/admin/templates/:id/edit' + assert_equal 302,last_response.status + + get '/report/list' + assert_equal 302,last_response.status + + get '/report/new' + assert_equal 302,last_response.status + + get '/report/:id/attachments' + assert_equal 302,last_response.status + + get '/report/:id/import_nessus' + assert_equal 302,last_response.status + + get '/report/:id/import_burp' + assert_equal 302,last_response.status + + get '/report/:id/upload_attachments' + assert_equal 302,last_response.status + + get '/report/:id/attachments/:att_id' + assert_equal 302,last_response.status + + get '/report/:id/attachments/delete/:att_id' + assert_equal 302,last_response.status + + get '/report/:id/remove' + assert_equal 302,last_response.status + + get '/report/:id/edit' + assert_equal 302,last_response.status + + get '/report/:id/additional_features' + assert_equal 302,last_response.status + + get '/report/:id/user_defined_variables' + assert_equal 302,last_response.status + + get '/report/:id/findings' + assert_equal 302,last_response.status + + get '/report/:id/status' + assert_equal 302,last_response.status + + get '/report/:id/findings_add' + assert_equal 302,last_response.status + + get '/report/:id/findings/new' + assert_equal 302,last_response.status + + get '/report/:id/findings/:finding_id/edit' + assert_equal 302,last_response.status + + get '/report/:id/findings/:finding_id/upload' + assert_equal 302,last_response.status + + get '/report/:id/findings/:finding_id/remove' + assert_equal 302,last_response.status + + get '/report/:id/findings/:finding_id/preview' + assert_equal 302,last_response.status + + get '/report/:id/generate' + assert_equal 302,last_response.status + + get '/report/:id/export' + assert_equal 302,last_response.status + + get '/report/import' + assert_equal 302,last_response.status + + get '/report/:id/text_status' + assert_equal 302,last_response.status + + get '/report/:id/asciidoc_status' + assert_equal 302,last_response.status + + get '/report/:id/presentation' + assert_equal 302,last_response.status + + post '/admin/add_user' + assert_equal 302,last_response.status + + post '/info' + assert_equal 302,last_response.status + + post '/login' + assert_equal 302,last_response.status + + post '/admin/add_user' + assert_equal 302,last_response.status + + post '/admin/add_user/:id' + assert_equal 302,last_response.status + + post '/master/findings/new' + assert_equal 302,last_response.status + + post '/master/findings/:id/edit' + assert_equal 302,last_response.status + + post '/master/import' + assert_equal 302,last_response.status + + post '/admin/templates/add' + assert_equal 302,last_response.status + + post '/admin/templates/edit' + assert_equal 302,last_response.status + + post '/report/new' + assert_equal 302,last_response.status + + post '/report/:id/import_autoadd' + assert_equal 302,last_response.status + + post '/report/:id/upload_attachments' + assert_equal 302,last_response.status + + post '/report/:id/edit' + assert_equal 302,last_response.status + + post '/report/:id/user_defined_variables' + assert_equal 302,last_response.status + + post '/report/:id/findings_add' + assert_equal 302,last_response.status + + post '/report/:id/findings/new' + assert_equal 302,last_response.status + + post '/report/:id/findings/:finding_id/edit' + assert_equal 302,last_response.status + + post '/report/import' + assert_equal 302,last_response.status + + end + +end