nessus_client 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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