nessus_client 0.1.0 → 0.1.2

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
  SHA256:
3
- metadata.gz: 1dda4cc05fbcee8eac14f8469f106944fa356ec74ecb31e3623c13338ec175f9
4
- data.tar.gz: db9270a96eb7866357754b65e1d3e17c0c67d9fdc98e5d507104a44fee49ef31
3
+ metadata.gz: 34cd232810e228f40b9badc3c3c38cd8ca0a4481baf376df4ff37f9f308af34b
4
+ data.tar.gz: 2c9fd0c05537ecf3aad03fb9c4e5f2abf7fde7eb3f1f805edcde53a3a025efe3
5
5
  SHA512:
6
- metadata.gz: d8c172bec3e3039644a3352dfa279e3799153351936b3d4b9ac86d90e87a31d9d151480e34ef7eb742258b77fdeb28066224216c07ae5a2cf31c9fb5771f8e8b
7
- data.tar.gz: 74dff229a778e97680bde8f690c845e84767b3da1847459577a377d2cfea2febc35f53c8fd1aac1befce5138c450cc7092c3b71d5f35cd840edd516dd4012461
6
+ metadata.gz: 29d460bc57991e7c9d162c77fd7efb247f6a6e68da82867dce865272497ba9b4a95d4214f73518498374cc680b64a4f69c78047d16ebbe85684c8b009066cccc
7
+ data.tar.gz: 6d4ce3058ec4c3cf6cf78a5b0041f0f02ce5adb1e02f6f3a3202a5ef5147197d0521d12673cac4976c05d2a97b0d468b8cf784e90fbd7f8414afd7ed100eeee3
data/CONTRIBUTING.md CHANGED
@@ -0,0 +1,7 @@
1
+
2
+ ## Contributing
3
+ 1. Fork it
4
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
5
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
6
+ 4. Push to the branch (`git push origin my-new-feature`)
7
+ 5. Create new Pull Request
data/README.md CHANGED
@@ -1,14 +1,18 @@
1
- NessusApi
1
+ NessusClient
2
2
  =========
3
- **Ruby wrapper for Nessus API**
4
3
 
5
- * [Source Code]
6
- * [API documentation]
7
- * [Changelog]
8
- * [Rubygem]
4
+ Usable, fast, simple Ruby gem for Tenable Nessus Pro v6.x and v7.x
9
5
 
6
+ NessusClient was designed to be simple, fast and performant through communication with Nessus over REST interface.
7
+
8
+ [![Gem Version](https://badge.fury.io/rb/nessus_client.svg)](https://badge.fury.io/rb/nessus_client) [![codecov](https://codecov.io/gh/heyder/nessus_api/branch/master/graph/badge.svg)](https://codecov.io/gh/heyder/nessus_api) [![Inline docs](http://inch-ci.org/github/heyder/nessus_client.svg?branch=master)](http://inch-ci.org/github/heyder/nessus_client)
9
+
10
+ **Ruby gem for Nessus API**
11
+
12
+ * [Source Code](https://github.com/heyder/nessus_client)
13
+ * [API documentation](https://rubydoc.info/github/heyder/nessus_client/master)
14
+ * [Rubygem](https://rubygems.org/gems/nessus_client)
10
15
 
11
- Ruby wrapper for Nessus API (all verions)
12
16
 
13
17
  ## Contact
14
18
 
@@ -22,8 +26,57 @@ with some common problems to check out before creating an issue.
22
26
  Getting started
23
27
  ---------------
24
28
 
29
+ ```ruby
30
+ require 'nessus_client'
31
+
32
+ nc = NessusClient.new(
33
+ {
34
+ :uri=>'https://localhost:8834',
35
+ :username=>'user',
36
+ :password=> 'password'
37
+ }
38
+ )
39
+ scan_uuid = nc.launch_by_name('scan_name',['192.168.10.0/28'])
40
+
41
+ while true do
42
+ scan_status = Oj.load( nc.scan_details( scan_uuid ) )["info"]["status"]
43
+ if scan_status == "done"
44
+ export_id = nc.export_request( scan_uuid )
45
+ while true do
46
+ export_status = Oj.load( nc.export_status( export_id ) )["status"]
47
+ if export_status == "ready"
48
+ open("scan_report", "wb") do |file|
49
+ file.write(nc.export_download( scan_uuid ))
50
+ end
51
+ break
52
+ end
53
+ end
54
+ end
55
+ end
56
+ ```
57
+
58
+ ## Installation
59
+
60
+ Add this line to your application's Gemfile:
61
+
62
+ gem 'nessus_client'
63
+
64
+ And then execute:
65
+
66
+ $ bundle
67
+
68
+ Or install it yourself as:
69
+
70
+ $ gem install nessus_client
71
+
72
+ ## Requirements
25
73
 
74
+ Requirements are Exon for HTTP(S) and Oj parsing:
26
75
 
76
+ ```ruby
77
+ require 'excon'
78
+ require 'oj'
79
+ ```
27
80
 
28
81
  ## Code of Conduct
29
82
 
@@ -1,15 +1,37 @@
1
1
  # require_relative '../nessus_client/request'
2
2
 
3
3
  module NessusClient::Exports
4
- # export scans
4
+
5
+ # Reques a export of vulnerabilities scan.
6
+ # @param [String] scan_id The export uuid string.
7
+ # @param [String] format The export format.This
8
+ # can be `nessus` or `nessus_db`.
9
+ # @return [JSON]
5
10
  def export_request( scan_id, format )
6
11
  params = {:format => format }
7
- self.request.post("/scans/#{scan_id}/export", params)
12
+ self.request.post( "/scans/#{scan_id}/export", params )
8
13
  end
14
+
15
+ # Check the status of a export request
16
+ # @param [String] export_id The export uuid string.
17
+ # @return [JSON]
18
+ # @example Checking the status of a export.
19
+ # export_status = nc.export_status( "73376c41-1508-46b7-8587-483d159cd956" )
20
+ # return true if export_status["status"] == "ready"
9
21
  def export_status( export_id )
10
- self.request.get("/tokens/#{export_id}/status")
22
+ self.request.get( "/tokens/#{export_id}/status" )
11
23
  end
24
+
25
+ # Download a vulnerabities scan output.
26
+ # @param [String] export_id The export uuid string.
27
+ # @return (see #format)
28
+ # @example Download a ready export.
29
+ # export = nc.export_download("73376c41-1508-46b7-8587-483d159cd956")
30
+ # open("scan_report", "wb") do |file|
31
+ # file.write( export )
32
+ # end
12
33
  def export_download( export_id )
13
- self.request.get("/tokens/#{export_id}/download")
34
+ self.request.get( "/tokens/#{export_id}/download" )
14
35
  end
36
+
15
37
  end
@@ -1,10 +1,14 @@
1
1
  # require_relative '../nessus_client/request'
2
2
 
3
3
  module NessusClient::Folders
4
- # folders
4
+ # Get the list of folders from the endpoint.
5
+ # @return [JSON]
5
6
  def list_folders
6
7
  self.request.get("/folders")
7
8
  end
9
+ # Create a folder into the endpoint.
10
+ # @param [String] folder_name The name of the folder the will be created.
11
+ # @return [Json]
8
12
  def create_folder( folder_name )
9
13
  params = {:name => folder_name }.to_json
10
14
  self.request.post("/folders", params)
@@ -1,6 +1,8 @@
1
1
  # require_relative '../nessus_client/request'
2
2
 
3
3
  module NessusClient::Policies
4
+ # List the scan polices from the endpoint.
5
+ # @return [JSON]
4
6
  def policies
5
7
  self.request.get( "/policies" )
6
8
  end
data/lib/modules/scans.rb CHANGED
@@ -1,26 +1,41 @@
1
1
 
2
2
  module NessusClient::Scans
3
3
 
4
+ # List scans from the endpoint.
5
+ # @param [String] folder_id (nil) The name of a alredy created scan.
6
+ # @return [JSON]
4
7
  def list_scans( folder_id=nil )
5
8
  query = folder_id.nil? ? nil : { "folder_id" => folder_id }
6
9
  self.request.get( "/scans", nil, query )
7
10
  end
8
11
  alias_method :scans, :list_scans
9
12
 
13
+ # See details of a scan.
14
+ # @param [String] scan_id The `uuid` of a scan.
15
+ # @param [String] history_id (nil) The `history_id` of a scan.
16
+ # @return [JSON]
10
17
  def scan_details( scan_id, history_id=nil )
11
18
  query = history_id.nil? ? nil : { "history_id" => history_id }
12
19
  self.request.get( "/scans/#{scan_id}", nil, query )
13
20
  end
14
21
 
22
+ # Lauch a scan by its name
23
+ # @param [String] scan_name The name of a alredy created scan.
24
+ # @param [Array<String>] targets Comma separeted new target to be scanned.
25
+ # @return [JSON]
15
26
  def launch_by_name( scan_name, targets=[] )
16
27
  scan_id = get_scan_by_name( scan_name )
17
28
  params = { :alt_targets => targets } unless targets.empty?
18
29
  self.request.post( "/scans/#{scan_id}/launch", params )
19
30
  end
20
31
 
21
- def get_scan_by_name( folder_id=nil, name )
32
+ # Get a scan by its name
33
+ # @param [String] folder_id The id of the folder to look into.
34
+ # @param [String] scan_name The name of the scan to look for.
35
+ # @return [String, nil] The uuid of the scan.
36
+ def get_scan_by_name( folder_id=nil, scan_name )
22
37
  Oj.load(list_scans( folder_id ))["scans"].each do |scan|
23
- return scan['id'] if scan['name'] == name
38
+ return scan['id'] if scan['name'] == scan_name
24
39
  end
25
40
  end
26
41
 
@@ -0,0 +1,56 @@
1
+ require 'oj'
2
+ # require_relative 'request'
3
+ # require_relative 'exception'
4
+
5
+ # Abstract base class for NessusClient Session.
6
+ # @since 0.1.0
7
+ # @attr_reader [String] token Autentication session token.
8
+ # @attr_reader [String] api_token Autentication API token.
9
+ module NessusClient::Session
10
+
11
+ attr_reader :token, :api_token
12
+
13
+ @token = @api_token = nil
14
+
15
+ # Autenticate into Nessus endpoint.
16
+ # @param [String] username
17
+ # @param [String] password
18
+ # @raise [NessusClient::Error] Unable to authenticate.
19
+ # @todo Validate response token format
20
+ def set_session( username, password )
21
+
22
+ payload = {
23
+ username: username,
24
+ password: password,
25
+ }
26
+
27
+ response = self.request.post( '/session', payload )
28
+ response = Oj.load(response) if response.length > 0
29
+
30
+ raise NessusClient::Error.new( "Unable to authenticate. The response did not include a session token." ) unless response['token']
31
+
32
+ @token = response['token']
33
+
34
+ end
35
+ alias_method :session_create, :set_session
36
+
37
+ # Set the API Token from legacy Nessus version
38
+ # @raise [NessusClient::Error] Unable to get API Token.
39
+ def set_api_token
40
+ response = self.request.get( "/nessus6.js" )
41
+ response.match( %r{return"(\w{8}-(?:\w{4}-){3}\w{12})"\}} )
42
+
43
+ raise NessusClient::Error.new( "Unable to get API Token. Some features won't work." ) unless $1#.nil?
44
+
45
+ @api_token = $1
46
+
47
+ end
48
+
49
+ # Destroy the current session from Nessus endpoint
50
+ def destroy
51
+ self.request.delete( '/session', nil )
52
+ @token = nil
53
+ end
54
+ alias_method :logout , :destroy
55
+
56
+ end
data/lib/nessus_client.rb CHANGED
@@ -1,4 +1,3 @@
1
- # require 'pry'
2
1
  require_relative 'nessus_client/version'
3
2
  require_relative 'nessus_client/exception'
4
3
 
@@ -8,32 +7,43 @@ class NessusClient
8
7
 
9
8
  attr_reader :request, :session
10
9
 
10
+ include NessusClient::Session
11
11
  include NessusClient::Scans
12
12
  include NessusClient::Exports
13
13
  include NessusClient::Folders
14
14
  include NessusClient::Policies
15
15
 
16
16
  autoload :Request, "nessus_client/request"
17
- autoload :Session, "nessus_client/session"
17
+ # autoload :Session, "nessus_client/session"
18
18
 
19
- def initialize( params={uri: nil, username: nil, password: nil, :ssl_verify_peer => false} )
19
+ # @param [Hash] params the options to create a NessusClient with.
20
+ # @option params [String] :uri ('https://localhost:8834/') Nessus endpoint to connect with
21
+ # @option params [String] :username Username (nil) to use in the connection
22
+ # @option params [String] :password Password (nil) to use in the connection
23
+ # @option params [String] :ssl_verify_peer (false) should check whether valid SSL certificate
24
+ def initialize( params = {} )
20
25
  @has_session = false
26
+ default_params = {
27
+ uri: 'https://localhost:8834/',
28
+ username: nil,
29
+ password: nil,
30
+ ssl_verify_peer: false
31
+ }
32
+ params = default_params.merge( params )
21
33
  req_params = params.select {|key, value| [:uri, :ssl_verify_peer].include?(key) }
22
- # session_params = params.select {|key, value| [:username, :password].include?(key) }
23
34
 
24
35
  @request = NessusClient::Request.new( req_params )
25
- @session = NessusClient::Session.create( params.fetch(:username), params.fetch(:password) )
36
+ self.set_session( params.fetch(:username), params.fetch(:password) )
26
37
 
27
- if @session.token
38
+ if self.token
28
39
  begin
29
40
  @has_session = true
30
- # NessusClient::Request.headers.update( 'X-Cookie' => 'token=' + api_session.token )
31
- @request.headers.update( 'X-Cookie' => 'token=' + @session.token )
32
- @session.set_api_token
41
+ @request.headers.update( 'X-Cookie' => 'token=' + self.token )
42
+ self.set_api_token
33
43
  rescue NessusClient::Error => err
34
44
  puts err.message
35
45
  else
36
- request.headers.update( 'X-API-Token' => @session.api_token )
46
+ request.headers.update( 'X-API-Token' => self.api_token )
37
47
  ensure
38
48
  return
39
49
  end
@@ -42,10 +52,14 @@ class NessusClient
42
52
 
43
53
  end
44
54
 
55
+ # Gets NessusClient::Session authentication status.
56
+ # @return [Boolean]
45
57
  def has_session?
46
58
  @has_session
47
59
  end
48
60
 
61
+ # Gets the server status.
62
+ # @return [Json] Returns the server status (loading, ready, corrupt-db, feed-expired, eval-expired, locked, register, register-locked, download-failed, feed-error).
49
63
  def status
50
64
  self.request.get( "/server/status" )
51
65
  end
@@ -1,4 +1,5 @@
1
1
  class NessusClient
2
+ # Abstract Error class for NessusClient.
2
3
  class Error < ::StandardError
3
4
  def initialize(msg="message")
4
5
  super
@@ -1,15 +1,14 @@
1
1
  require 'excon'
2
2
  require 'json'
3
- # require 'pry'
3
+
4
4
  class NessusClient
5
5
 
6
- # Excon.defaults[:ssl_verify_peer] = false
7
- # This class should be used to in all requests classes
8
-
6
+ # Abstract base class for NessusClient. Provides some helper methods for
9
7
  class Request
10
- # attr_accessor :headers
8
+
11
9
  attr_reader :url, :headers
12
10
 
11
+ # Default HTTP header to be used on the requests.
13
12
  DEFAULT_HEADERS = {
14
13
  "User-Agent" => "Mozilla/5.0 (Linux x86_64)",
15
14
  "Content-Type" => "application/json"
@@ -20,27 +19,39 @@ class NessusClient
20
19
  @@ssl_verify_peer = params.fetch(:ssl_verify_peer)
21
20
  @url = @@url = NessusClient::Request.uri_parse( params.fetch(:uri) )
22
21
  @headers = params.fetch( :headers ).merge( DEFAULT_HEADERS )
23
- end
22
+ end
24
23
 
25
- # def self.headers
26
- # @@headers
27
- # end
24
+ # @raise [NotImplementedError] Use update from Hash insted.
28
25
  def headers=(value)
29
26
  raise NotImplementedError.new("Use update from Hash insted.")
30
27
  end
31
-
28
+
29
+ # Perform a HTTP GET to the endpoint.
30
+ # @param [String] path The URI path to perform the request.
31
+ # @param [String] payload The HTTP body to send.
32
+ # @param [String] query The URI query to send.
32
33
  def get( path=nil, payload=nil, query=nil )
33
34
  http_request( :get, path, payload, query )
34
35
  end
35
36
 
37
+ # Perform a HTTP POST to the endpoint.
38
+ # @param [String] path The URI path to perform the request.
39
+ # @param [String] payload The HTTP body to send.
40
+ # @param [String] query The URI query to send.
36
41
  def post( path=nil, payload=nil, query=nil )
37
42
  http_request( :post, path, payload, query )
38
43
  end
39
44
 
45
+ # Perform a HTTP DELETE to the endpoint.
46
+ # @param [String] path The URI path to perform the request.
47
+ # @param [String] payload The HTTP body to send.
48
+ # @param [String] query The URI query to send.
40
49
  def delete( path=nil, payload=nil, query=nil )
41
50
  http_request( :delete, path, payload, query )
42
51
  end
43
-
52
+ # Parse a receiveid URI
53
+ # @param [String] uri A valid URI.
54
+ # @return [String] A string uri.
44
55
  def self.uri_parse( uri )
45
56
  url = URI.parse( uri )
46
57
  raise URI::InvalidURIError unless url.scheme
@@ -49,8 +60,13 @@ class NessusClient
49
60
 
50
61
  private
51
62
 
63
+ # @private HTTP request abstraction to be used.
64
+ # @param [Symbol] method A HTTP method to be used could be `:get`, `:post` or `:delete`.
65
+ # @param [String] path The URI path to perform the request.
66
+ # @param [String] payload The HTTP body to send.
67
+ # @param [String] query The URI query to send.
52
68
  def http_request( method=:get, path, payload, query )
53
- # binding.pry
69
+
54
70
  connection = Excon.new( @@url )
55
71
 
56
72
  body = payload ? payload.to_json : ''
@@ -61,8 +77,6 @@ class NessusClient
61
77
  query: query,
62
78
  headers: @headers,
63
79
  ssl_verify_peer: @@ssl_verify_peer,
64
- #idempotent: true,
65
- #proxy: "http://127.0.0.1:8080",
66
80
  expects: [200, 201]
67
81
  }
68
82
  response = connection.request( options )
@@ -1,3 +1,4 @@
1
1
  class NessusClient
2
- VERSION = '0.1.0'
2
+ # The current version of the libary.
3
+ VERSION = '0.1.2'
3
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nessus_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heyder
@@ -108,7 +108,42 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.17.0
111
- description: Ruby wrapper for Nessus API (all verions)
111
+ - !ruby/object:Gem::Dependency
112
+ name: codecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.1.14
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.1.14
125
+ - !ruby/object:Gem::Dependency
126
+ name: yard
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.9'
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 0.9.20
135
+ type: :development
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: '0.9'
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 0.9.20
145
+ description: NessusClient was designed to be simple, fast and performant through communication
146
+ with Nessus over REST interface.
112
147
  email: eu@heyderandrade.org
113
148
  executables: []
114
149
  extensions: []
@@ -122,15 +157,16 @@ files:
122
157
  - lib/modules/folders.rb
123
158
  - lib/modules/policies.rb
124
159
  - lib/modules/scans.rb
160
+ - lib/modules/session.rb
125
161
  - lib/nessus_client.rb
126
162
  - lib/nessus_client/exception.rb
127
163
  - lib/nessus_client/request.rb
128
- - lib/nessus_client/session.rb
129
164
  - lib/nessus_client/version.rb
130
- homepage: https://rubygemspec.org/gems/nessus_client
165
+ homepage: https://github.com/heyder/nessus_client
131
166
  licenses:
132
167
  - MIT
133
168
  metadata:
169
+ documentation_uri: https://rubydoc.info/github/heyder/nessus_client/
134
170
  source_code_uri: https://github.com/heyder/nessus_client
135
171
  post_install_message:
136
172
  rdoc_options: []
@@ -150,5 +186,5 @@ requirements: []
150
186
  rubygems_version: 3.0.3
151
187
  signing_key:
152
188
  specification_version: 4
153
- summary: Ruby wrapper for Nessus API
189
+ summary: Usable, fast, simple Ruby gem for Tenable Nessus Pro v6.x and v7.x
154
190
  test_files: []
@@ -1,56 +0,0 @@
1
- require 'oj'
2
- require_relative 'request'
3
- require_relative 'exception'
4
-
5
- class NessusClient
6
-
7
- # This class should be used to get an access token
8
- # for use with the main client class.
9
- class Session
10
- attr_reader :token, :api_token
11
-
12
- @token = @api_token = nil
13
-
14
- # @param [String] username
15
- # @param [String] password
16
- def self.create( username, password )
17
-
18
- payload = {
19
- username: username,
20
- password: password,
21
- }
22
-
23
- response = NessusClient::Request.post( '/session', payload )
24
- response = Oj.load(response) if response.length > 0
25
-
26
- if response['token']
27
- return self.new( response['token'] )
28
- else
29
- raise NessusClient::Error.new "#{__method__}::Response did not include a session token."
30
- end
31
-
32
- end
33
-
34
- def initialize( token )
35
- @token = token
36
- end
37
-
38
- def set_api_token
39
- response = NessusClient::Request.get( "/nessus6.js" )
40
- response.match( %r{return"(\w{8}-(?:\w{4}-){3}\w{12})"\}} )
41
-
42
- raise NessusClient::Error.new( "Unable to get API Token. Some features won't work." ) unless $1#.nil?
43
-
44
- @api_token = $1
45
-
46
- end
47
-
48
- def destroy
49
- NessusClient::Request.delete( '/session', nil )
50
- @token = nil
51
- end
52
- alias_method :logout , :destroy
53
-
54
- end
55
-
56
- end