nessus_api 2.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 21bf2c9f1cca3c36a7d49f20cf5d945045754c15
4
+ data.tar.gz: 716f4ffad165197e24db6cebbaba20b43d5f8e0e
5
+ SHA512:
6
+ metadata.gz: 61762f9aa9dc1e1a858c26cd6ce585ce8f83a05be63fc0cf186ffe4e6da4ca4d0b7adb90bd15c0e7c9d564105408c1c4faacc5d90cbdf332461deba6c4c3690c
7
+ data.tar.gz: 8cbbf1276608c843a40ff7a28dc51d76df8dc8b59af1c5a2f7cc7b9acad504258a3732b8506c73286ed91d4cfe1553125ec2ed85ee609c67ec75cfb8b64fce57
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Nicholas Wold
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
File without changes
@@ -0,0 +1,35 @@
1
+ # report.rb
2
+ # A collection of helper functions
3
+ # that make API calls and then return
4
+ # wanted information.
5
+
6
+ module NessusAPI
7
+ module Helpers
8
+ def self.getSeverity(uuid, session=Session.current)
9
+ result = 0
10
+ xml = session.get('report2/hosts', {'report' => uuid})
11
+ xml.css('item').each do |i|
12
+ level = i.css('severityLevel').text.to_i
13
+ threat = i.css('count').text.to_i
14
+ if level > result
15
+ if threat
16
+ result = level
17
+ end
18
+ end
19
+ end
20
+ return result
21
+ end
22
+
23
+ def self.translateSeverity(n)
24
+ if n < 0 or n > 4
25
+ return 'Unknown'
26
+ end
27
+
28
+ return {0 => 'Minimal',
29
+ 1 => 'Low',
30
+ 2 => 'Medium',
31
+ 3 => 'High',
32
+ 4 => 'Critical'}[n]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,55 @@
1
+ # scan.rb
2
+ # Handles all of the scan logic
3
+ # between the API and the installation.
4
+
5
+ module NessusAPI
6
+ class Scan
7
+ # The class that handles API calls
8
+ # for individuals scans.
9
+ def initialize(target, scan_name, policy, session=Session.current)
10
+ # Creates a new scan on the Nessus
11
+ # installation using the given params.
12
+ @target = target
13
+ @name = scan_name
14
+ @policy = policy
15
+ @session = session
16
+ @uuid = @session.get('scan/new', {'target' => @target,
17
+ 'scan_name' => @name, 'policy_id' => @policy}).at_css("uuid").text
18
+ end
19
+
20
+ def stop
21
+ changeStatus('stop')
22
+ end
23
+
24
+ def pause
25
+ # Pauses the current scan.
26
+ changeStatus('pause')
27
+ end
28
+
29
+ def resume
30
+ # Resumes the current scan from being
31
+ # paused.
32
+ changeStatus('resume')
33
+ end
34
+
35
+ def changeStatus(path)
36
+ # Helper function for stop, pause
37
+ # and resume.
38
+ if @session.get("scan/#{path}",
39
+ {'scan_uuid' => @uuid}).css('status').text == 'OK'
40
+ return true
41
+ else
42
+ return false
43
+ end
44
+ end
45
+
46
+ def uuid
47
+ @uuid
48
+ end
49
+
50
+ def self.list(session = Session.current)
51
+ # Returns all currently running scan jobs.
52
+ session.scanList
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,96 @@
1
+ # session.rb
2
+ # Handles all of the session shit between
3
+ # the gem and the Nessus installation.
4
+
5
+ require 'uri'
6
+ require 'net/http'
7
+ require 'nokogiri'
8
+ require 'openssl'
9
+
10
+ module NessusAPI
11
+ class Session
12
+ # Keep that in mind when I start extending
13
+ # the class.
14
+ @@current = nil
15
+
16
+ def initialize(host=ENV['NESSUS_HOST'], user=ENV['NESSUS_USER'],
17
+ pw=ENV['NESSUS_PASS'], port=ENV['NESSUS_PORT'])
18
+ # Attempts to connect with the given instance
19
+ # of Nessus. Returns errors when it cannot reach
20
+ # an installation, or if there are bad credentials
21
+ # given. Returns a token otherwise.
22
+ @host = host
23
+ @port = port
24
+ @token = self.get('login', {'login' => user, 'password' => pw},
25
+ nil).css("token").text
26
+ @@current = self
27
+ end
28
+
29
+ def get(path, args={}, token=@token)
30
+ # Performs an API call using the path and arguments given.
31
+ # Returns a token if there is not already a token.
32
+ # Otherwise, it returns the response from the server.
33
+ args['token'] = @token
34
+ args['seq'] = Random.new.rand(9999).to_s
35
+ url = URI('https://' + @host + ':' + @port + '/' + path)
36
+ request = Net::HTTP::Post.new(url.path)
37
+ request.set_form_data(args)
38
+ conn = Net::HTTP.new(url.host, url.port)
39
+ conn.use_ssl = true
40
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
41
+ begin
42
+ response = conn.request(request)
43
+ if response.is_a?(Net::HTTPSuccess)
44
+ response_xml = Nokogiri::XML(response.body)
45
+ if response_xml.at_css("seq").text != args['seq']
46
+ raise StandardError, "Secret token did not match!"
47
+ elsif response_xml.at_css("status").text != 'OK'
48
+ raise AuthenticationError, "Credentials are not valid!"
49
+ end
50
+ return response_xml
51
+ else
52
+ raise ConnectionError, "Could not connect properly!"
53
+ end
54
+ rescue => e
55
+ raise e
56
+ end
57
+ end
58
+
59
+ def close
60
+ # Logs out of Nessus installation
61
+ # Returns a true, if it works.
62
+ if self.get('logout').css('contents').text == 'OK'
63
+ return true
64
+ else
65
+ return false
66
+ end
67
+ end
68
+
69
+ def self.current
70
+ @@current
71
+ end
72
+
73
+ def current
74
+ @@current
75
+ end
76
+
77
+ def scanList
78
+ get('scan/list', {}).at_css('scanList')
79
+ end
80
+
81
+ def policies
82
+ results = []
83
+ @doc = get('policy/list', {})
84
+ (0..@doc.css("policies policyName").length-1).each do |i|
85
+ results << [@doc.css("policies policyName")[i].text, @doc.css("policies policyID")[i].text]
86
+ end
87
+ return results
88
+ end
89
+ end
90
+
91
+ class AuthenticationError < StandardError
92
+ end
93
+
94
+ class ConnectionError < StandardError
95
+ end
96
+ end
@@ -0,0 +1,60 @@
1
+ # template.rb
2
+ # Does API things with installation.
3
+
4
+ module NessusAPI
5
+ class Template
6
+ # The class that handles the specific
7
+ # calls for templates.
8
+ def initialize(template_name, policy_id, target,
9
+ startTime=nil, rRules=nil,
10
+ session=Session.current)
11
+ @name = template_name
12
+ @policy = policy_id
13
+ @target = target
14
+ @session = session
15
+ @time = startTime
16
+ @rules = rRules
17
+ params = optional({'template_name' => @name, 'policy_id' => @policy,
18
+ 'target' => @target}, @time, @rules)
19
+ @uuid = @session.get('scan/template/new', params).at_css("name").text
20
+ end
21
+
22
+ def edit(old_name, new_name, policy_id, target,
23
+ startTime=nil, rRules=nil)
24
+ params = optional({'template' => old_name, 'template_name' => new_name,
25
+ 'policy_id' => policy_id, 'target' => target})
26
+ if @session.get('scan/template/edit', params).css('status').text == 'OK'
27
+ return true
28
+ else
29
+ return false
30
+ end
31
+ end
32
+
33
+ def launch(uuid=@uuid)
34
+ # Returns the uuid of a template scan.
35
+ return @session.get('scan/template/launch',
36
+ {'template' => uuid}).at_css('uuid').text
37
+ end
38
+
39
+ def delete(uuid=@uuid)
40
+ if @session.get('scan/template/delete',
41
+ {'template' => uuid}).css('status').text == 'OK'
42
+ return true
43
+ else
44
+ return false
45
+ end
46
+ end
47
+
48
+ def optional(params, startTime, rRules)
49
+ # Returns a hash given with a new hash
50
+ # with the optional attributes added.
51
+ if !startTime.nil?
52
+ params['startTime'] = startTime
53
+ end
54
+ if !rRules.nil?
55
+ params['rRules'] = rRules
56
+ end
57
+ return params
58
+ end
59
+ end
60
+ end
data/lib/nessus_api.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'dotenv'
2
+ Dotenv.load()
3
+
4
+ require_relative "nessus_api/scan.rb"
5
+ require_relative "nessus_api/session.rb"
6
+ require_relative "nessus_api/template.rb"
7
+ require_relative "nessus_api/report.rb"
8
+
9
+ module NessusAPI
10
+ VERSION = '2.0.0'
11
+ end
data/spec/api_spec.rb ADDED
@@ -0,0 +1,110 @@
1
+ # session_spec.rb
2
+ require 'factory_girl'
3
+ require_relative '../lib/nessus_api'
4
+ require 'nokogiri'
5
+
6
+ RSpec.configure do |config|
7
+ config.include FactoryGirl::Syntax::Methods
8
+ end
9
+
10
+ describe NessusAPI::Session do
11
+ describe ".new" do
12
+ context 'can connect' do
13
+ it 'does not raise an error' do
14
+ expect{NessusAPI::Session.new().close()}.to_not raise_error()
15
+ end
16
+ end
17
+
18
+ context 'cannot connect' do
19
+ it 'responds with an error' do
20
+ expect{NessusAPI::Session.new('256.256.256.256').close}.to raise_error
21
+ end
22
+ end
23
+
24
+ context 'bad credentials' do
25
+ it 'responds with an error' do
26
+ expect{NessusAPI::Session.new(ENV['NESSUS_HOST'], nil, nil).close}.to raise_error
27
+ end
28
+ end
29
+ end
30
+
31
+ describe ".close" do
32
+ context 'done doing things' do
33
+ it 'returns true' do
34
+ expect{NessusAPI::Session.new.close}.to be_true
35
+ end
36
+ end
37
+ end
38
+
39
+ describe ".list" do
40
+ let(:scan) {NessusAPI::Session.new()}
41
+ it 'returns an xml object' do
42
+ expect {scan.scanList.is_a?(Nokogiri::XML::Document)}.to be_true
43
+ scan.close()
44
+ end
45
+ end
46
+ end
47
+
48
+ describe NessusAPI::Scan do
49
+ let(:session) { NessusAPI::Session.new() }
50
+ let(:scan) { NessusAPI::Scan.new('127.0.0.1', 'API Test Scan', '-9') }
51
+
52
+ describe ".new" do
53
+ it 'to have a uuid' do
54
+ expect{scan.uuid}.to_not be_nil()
55
+ end
56
+ end
57
+
58
+ describe ".pause" do
59
+ it 'returns true' do
60
+ expect {scan.pause}.to be_true
61
+ end
62
+ end
63
+
64
+ describe ".resume" do
65
+ it 'returns true' do
66
+ expect {scan.resume}.to be_true
67
+ end
68
+ end
69
+
70
+ describe ".stop" do
71
+ it 'returns true' do
72
+ expect {scan.stop}.to be_true
73
+ end
74
+ end
75
+
76
+ describe ".list" do
77
+ it 'returns a nokogiri object' do
78
+ expect {NessusAPI::Scan.list.is_a?(Nokogiri::XML::Document)}.to be_true
79
+ end
80
+ end
81
+ end
82
+
83
+ describe NessusAPI::Template do
84
+ let(:session) {NessusAPI::Session.new()}
85
+ let(:template) {NessusAPI::Template.new('Test Template', '-9', '127.0.0.1')}
86
+ describe ".new" do
87
+ it 'does not raise an error' do
88
+ expect {template.is_a?(NessusAPI::Template)}.to be_true
89
+ end
90
+ end
91
+
92
+ describe ".edit" do
93
+ it 'returns true' do
94
+ expect {template.edit('Test Template', 'Test 2: Test Harder', '-9',
95
+ '127.0.0.1')}.to be_true
96
+ end
97
+ end
98
+
99
+ describe '.launch' do
100
+ it 'returns true' do
101
+ expect {template.launch}.to be_true
102
+ end
103
+ end
104
+
105
+ describe '.delete' do
106
+ it 'returns true' do
107
+ expect {template.delete}.to be_true
108
+ end
109
+ end
110
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :scan do
3
+ target '127.0.0.1'
4
+ scan_name 'API Test Scan'
5
+ policy '-9'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nessus_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas Wold
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dotenv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Intelligently allows for use of Nessus API, both with gathering and editing
56
+ information.
57
+ email: nicholas.wold@berkeley.edu
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - lib/nessus_api/report.rb
63
+ - lib/nessus_api/template.rb
64
+ - lib/nessus_api/session.rb
65
+ - lib/nessus_api/scan.rb
66
+ - lib/nessus_api.rb
67
+ - spec/api_spec.rb
68
+ - spec/factories.rb
69
+ - README.md
70
+ - LICENSE.md
71
+ homepage: http://www.nicholaswold.com
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.1.10
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Allows interaction with Nessus REST API.
95
+ test_files: []
96
+ has_rdoc: