NexposeRunner 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3fc954479b13a6d1ee5538438ef4e0e9d155acef
4
- data.tar.gz: 92f8b3905afd4c71bc0f316c42b605d33b2cf2c6
3
+ metadata.gz: 9a8816db77936253046c6e2858d14c794eaa3291
4
+ data.tar.gz: 21121f0ae8c931b390e9ddd239da015a008e7825
5
5
  SHA512:
6
- metadata.gz: faee2b9d52875bb8e2fe4b3112b96a49746953d1784ca29f8cd3b3c9beb00bc215eaf1440f7bfe459393474f564969175440b2a40446680bf1c61f71cafba9f6
7
- data.tar.gz: 4bfb76dc4cf58c81f06c90d2c8ef071c472323b21861d831898c729ce23764e66d5cdc2373255459b21470233582539291f7177a7552f7ff090018b151328f78
6
+ metadata.gz: bfcf436db720bcab7f61126360b0b19056957b1a49a9bb12bed94db7a40c260491da61c46bf6d6e0a754c69f4ac42150a54aab6ad67be8902bda2a45e882f077
7
+ data.tar.gz: 0b5d1dafd6fbe50022a8b0ac8d07a6a774331663d393bb5484678274917beb595b7a37902ff5f7c9bcb4dcf2fcbdb58b3f9aacb5993702430cccc2e36a8edd4b
data/.gitignore CHANGED
@@ -21,3 +21,5 @@ tmp
21
21
  *.a
22
22
  mkmf.log
23
23
  .idea/
24
+ config/scan.yml
25
+ config/scan.yml.bak
data/README.md CHANGED
@@ -33,6 +33,8 @@ EXAMPLE:
33
33
 
34
34
  $ scan "http://test.connection" "rapid7" "password" "3780" "my_cool_software_build-28" "10.5.0.15" "full-audit-widget-corp"
35
35
 
36
+ It is possible to use a YAML file to drive the configuration of this module. An example configuration file is provided in config/scan.yml.example. Simply copy it to config/scan.yml and modify it to work with your environment.
37
+
36
38
  ## Contributing
37
39
 
38
40
  1. Fork it ( https://github.com/[my-github-username]/nexpose-scan/fork )
@@ -0,0 +1,7 @@
1
+ connection_url: ''
2
+ username: ''
3
+ password: ''
4
+ port: '3780'
5
+ site_name: ''
6
+ ip_addresses: ''
7
+ scan_template: ''
@@ -1,4 +1,4 @@
1
1
  module NexposeRunner
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.7'
3
3
  end
4
4
 
@@ -10,6 +10,7 @@ module CONSTANTS
10
10
  VULNERABILITY_REPORT_NAME = 'nexpose-vulnerability-report.csv'
11
11
  SOFTWARE_REPORT_NAME = 'nexpose-software-report.csv'
12
12
  POLICY_REPORT_NAME = 'nexpose-policy-report.csv'
13
+ AUDIT_REPORT_NAME = 'nexpose-audit-report.html'
13
14
 
14
15
  VULNERABILITY_REPORT_QUERY = 'SELECT DISTINCT
15
16
  ip_address,
@@ -61,4 +62,4 @@ module CONSTANTS
61
62
  LEFT JOIN dim_policy_rule dpr on dpr.policy_id = fapr.policy_id and fapr.rule_id = dpr.rule_id
62
63
  LEFT JOIN dim_asset da on da.asset_id = fapr.asset_id
63
64
  ORDER BY da.ip_address'
64
- end
65
+ end
@@ -35,6 +35,9 @@ module NexposeRunner
35
35
  policies = generate_report(CONSTANTS::POLICY_REPORT_QUERY, site.id, nsc)
36
36
  generate_csv(policies, CONSTANTS::POLICY_REPORT_NAME)
37
37
 
38
+ puts "Scan complete for #{run_details.site_name}, Generating Audit Report"
39
+ generate_audit_report(site.id, nsc, CONSTANTS::AUDIT_REPORT_NAME)
40
+
38
41
  [vulnerbilities, software, policies]
39
42
  end
40
43
 
@@ -51,8 +54,9 @@ module NexposeRunner
51
54
 
52
55
  begin
53
56
  sleep(3)
54
- status = nsc.scan_status(scan.id)
55
- puts "Current #{run_details.site_name} scan status: #{status.to_s}"
57
+ stats = nsc.scan_statistics(scan.id)
58
+ status = stats.status
59
+ puts "Current #{run_details.site_name} scan status: #{status.to_s} -- PENDING: #{stats.tasks.pending.to_s} ACTIVE: #{stats.tasks.active.to_s} COMPLETED #{stats.tasks.completed.to_s}"
56
60
  end while status == Nexpose::Scan::Status::RUNNING
57
61
  end
58
62
 
@@ -83,6 +87,12 @@ module NexposeRunner
83
87
  CSV.parse(report_output.chomp, {:headers => :first_row})
84
88
  end
85
89
 
90
+ def self.generate_audit_report(site, nsc, name)
91
+ adhoc = Nexpose::AdhocReportConfig.new('audit-report', 'html', site)
92
+ data = adhoc.generate(nsc)
93
+ File.open(name, 'w') { |file| file.write(data) }
94
+ end
95
+
86
96
  def self.generate_csv(csv_output, name)
87
97
  CSV.open(name, 'w') do |csv_file|
88
98
  csv_file << csv_output.headers
@@ -1,9 +1,15 @@
1
+ require 'yaml'
2
+
1
3
  class ScanRunDescription
2
4
  attr_accessor :connection_url, :username, :password, :port, :site_name, :ip_addresses, :scan_template
3
5
  @@port_value = ''
4
6
  @@ip_addresses = ''
5
7
 
6
8
  def initialize(options)
9
+ if File.file?('config/scan.yml')
10
+ options = YAML.load_file('config/scan.yml')
11
+ end
12
+
7
13
  self.connection_url = options['connection_url']
8
14
  self.username = options['username']
9
15
  self.password = options['password']
@@ -0,0 +1,57 @@
1
+ require 'nexpose-runner/scan_run_description'
2
+ require 'yaml'
3
+
4
+ file_path = 'config/scan.yml'
5
+ describe 'scan_user_config_file_tests' do
6
+ if File.file?('config/scan.yml')
7
+ File.rename('config/scan.yml','config/scan.yml.bak')
8
+ end
9
+
10
+ describe 'start' do
11
+ before(:each) do
12
+ config_file = File.new(file_path, 'w')
13
+ config_file.puts("connection_url: 'mydomain.wat'")
14
+ config_file.puts("ip_addresses: ''")
15
+ config_file.close
16
+ @scan_run_description = ScanRunDescription.new({})
17
+ end
18
+
19
+ after(:each) do
20
+ File.delete(file_path) if File.exist?(file_path)
21
+ end
22
+
23
+ it 'should get configuration from the config/scan.yaml when provided' do
24
+ expect(@scan_run_description.connection_url).to eq('mydomain.wat')
25
+ end
26
+ end
27
+
28
+ if File.file?('config/scan.yml.bak')
29
+ File.rename('config/scan.yml.bak', 'config/scan.yml')
30
+ end
31
+
32
+ end
33
+
34
+ describe 'scan_default_config_tests' do
35
+ if File.file?('config/scan.yml')
36
+ File.rename('config/scan.yml', 'config/scan.yml.bak')
37
+ end
38
+
39
+ describe 'start' do
40
+ before(:each) do
41
+ @options = {
42
+ 'connection_url' => 'foo.bar',
43
+ 'ip_addresses' => ''
44
+ }
45
+ @scan_run_description = ScanRunDescription.new(@options)
46
+ end
47
+
48
+ it 'should get configuration from the command line options' do
49
+ expect(@scan_run_description.connection_url).to eq('foo.bar')
50
+ end
51
+ end
52
+
53
+ if File.file?('config/scan.yml.bak')
54
+ File.rename('config/scan.yml.bak', 'config/scan.yml')
55
+ end
56
+
57
+ end
data/spec/scan_spec.rb CHANGED
@@ -1,7 +1,13 @@
1
1
  require 'nexpose-runner/scan'
2
2
  require 'nexpose-runner/constants'
3
+ require 'ostruct'
3
4
 
4
5
  describe 'nexpose-runner' do
6
+
7
+ if File.file?('config/exploit.yml')
8
+ File.rename('config/exploit.yml', 'config/exploit.yml.bak')
9
+ end
10
+
5
11
  before(:each) do
6
12
  allow(NexposeRunner::Scan).to receive(:sleep)
7
13
  end
@@ -39,10 +45,12 @@ describe 'nexpose-runner' do
39
45
 
40
46
 
41
47
  @mock_scan = get_mock_scan
48
+ @mock_scan_summary = get_mock_scan_summary
42
49
  @mock_nexpose_client = get_mock_nexpose_client
43
50
  @mock_nexpose_site = get_mock_nexpose_site
44
51
  @mock_report = get_mock_report
45
52
 
53
+
46
54
  @options = {
47
55
  'connection_url' => @expected_connection,
48
56
  'username' => @expected_username,
@@ -163,20 +171,18 @@ describe 'nexpose-runner' do
163
171
 
164
172
  describe 'wait for the Nexpose Scan to complete' do
165
173
  it 'should call to check the status of the scan' do
166
- expect(@mock_nexpose_client).to receive(:scan_status).with(@mock_scan_id)
174
+ expect(@mock_nexpose_client).to receive(:scan_statistics).with(@mock_scan_id)
167
175
 
168
176
  NexposeRunner::Scan.start(@options)
169
177
  end
170
178
 
171
179
  it 'should call to check the status until it is not running' do
172
- expect(@mock_nexpose_client).to receive(:scan_status)
173
- .with(@mock_scan_id)
180
+ expect(@mock_scan_summary).to receive(:status)
174
181
  .and_return(Nexpose::Scan::Status::RUNNING)
175
182
  .exactly(3).times
176
183
  .ordered
177
184
 
178
- expect(@mock_nexpose_client).to receive(:scan_status)
179
- .with(@mock_scan_id)
185
+ expect(@mock_scan_summary).to receive(:status)
180
186
  .and_return(Nexpose::Scan::Status::FINISHED)
181
187
  .once
182
188
  .ordered
@@ -185,14 +191,12 @@ describe 'nexpose-runner' do
185
191
  end
186
192
 
187
193
  it 'should sleep for 3 seconds if the status is still running' do
188
- expect(@mock_nexpose_client).to receive(:scan_status)
189
- .with(@mock_scan_id)
194
+ expect(@mock_scan_summary).to receive(:status)
190
195
  .and_return(Nexpose::Scan::Status::RUNNING)
191
196
  .exactly(3).times
192
197
  .ordered
193
198
 
194
- expect(@mock_nexpose_client).to receive(:scan_status)
195
- .with(@mock_scan_id)
199
+ expect(@mock_scan_summary).to receive(:status)
196
200
  .and_return(Nexpose::Scan::Status::FINISHED)
197
201
  .once
198
202
  .ordered
@@ -227,6 +231,10 @@ describe 'nexpose-runner' do
227
231
  }.to raise_error(StandardError, CONSTANTS::VULNERABILITY_FOUND_MESSAGE)
228
232
  end
229
233
  end
234
+
235
+ if File.file?('config/exploit.yml.bak')
236
+ File.rename('config/exploit.yml.bak', 'config/exploit.yml')
237
+ end
230
238
  end
231
239
 
232
240
  def expect_report_to_be_called_with(report_name, report_query, report_response)
@@ -249,8 +257,9 @@ def get_mock_nexpose_client
249
257
 
250
258
  allow(mock_nexpose_client).to receive(:call).with(any_args).and_return({})
251
259
 
252
- allow(mock_nexpose_client).to receive(:scan_status)
260
+ allow(mock_nexpose_client).to receive(:scan_statistics)
253
261
  .with(@mock_scan_id)
262
+ .and_return(@mock_scan_summary)
254
263
 
255
264
  allow(mock_nexpose_client).to receive(:login)
256
265
  .and_return(true)
@@ -261,6 +270,20 @@ def get_mock_nexpose_client
261
270
  mock_nexpose_client
262
271
  end
263
272
 
273
+ def get_mock_scan_summary
274
+ mock_scan_summary = double(Nexpose::ScanSummary)
275
+
276
+ tasks = OpenStruct.new(:completed => 1, :pending => 1)
277
+ allow(mock_scan_summary).to receive(:tasks).and_return(tasks)
278
+
279
+ allow(mock_scan_summary).to receive(:status).and_return(
280
+ Nexpose::Scan::Status::RUNNING,
281
+ Nexpose::Scan::Status::RUNNING,
282
+ Nexpose::Scan::Status::RUNNING,
283
+ Nexpose::Scan::Status::FINISHED)
284
+ mock_scan_summary
285
+ end
286
+
264
287
  def get_mock_nexpose_site
265
288
  mock_nexpose_site = double(Nexpose::Site)
266
289
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: NexposeRunner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Gibson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-10 00:00:00.000000000 Z
11
+ date: 2015-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nexpose
@@ -83,11 +83,13 @@ files:
83
83
  - README.md
84
84
  - Rakefile
85
85
  - bin/scan
86
+ - config/scan.yml.example
86
87
  - lib/NexposeRunner.rb
87
88
  - lib/NexposeRunner/version.rb
88
89
  - lib/nexpose-runner/constants.rb
89
90
  - lib/nexpose-runner/scan.rb
90
91
  - lib/nexpose-runner/scan_run_description.rb
92
+ - spec/scan_config_spec.rb
91
93
  - spec/scan_spec.rb
92
94
  - spec/spec_helper.rb
93
95
  homepage: ''
@@ -110,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
112
  version: '0'
111
113
  requirements: []
112
114
  rubyforge_project:
113
- rubygems_version: 2.2.2
115
+ rubygems_version: 2.4.8
114
116
  signing_key:
115
117
  specification_version: 4
116
118
  summary: This is a gem that provides the ability to create a new site, add an IP to
@@ -118,5 +120,6 @@ summary: This is a gem that provides the ability to create a new site, add an IP
118
120
  and finally produce a reports for vulnerabilities, installed software, and policy
119
121
  compliance.
120
122
  test_files:
123
+ - spec/scan_config_spec.rb
121
124
  - spec/scan_spec.rb
122
125
  - spec/spec_helper.rb