nessus_client 0.1.2 → 0.1.3

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: 34cd232810e228f40b9badc3c3c38cd8ca0a4481baf376df4ff37f9f308af34b
4
- data.tar.gz: 2c9fd0c05537ecf3aad03fb9c4e5f2abf7fde7eb3f1f805edcde53a3a025efe3
3
+ metadata.gz: 9b009898d60e9cf21fbaa66050139ddd5d38cf4aff33b45fae7fc146f56c518b
4
+ data.tar.gz: 7a6b5f73f2030bae2d4d2ddecd058fc088aaddb48da32384af977cfa6ffa0702
5
5
  SHA512:
6
- metadata.gz: 29d460bc57991e7c9d162c77fd7efb247f6a6e68da82867dce865272497ba9b4a95d4214f73518498374cc680b64a4f69c78047d16ebbe85684c8b009066cccc
7
- data.tar.gz: 6d4ce3058ec4c3cf6cf78a5b0041f0f02ce5adb1e02f6f3a3202a5ef5147197d0521d12673cac4976c05d2a97b0d468b8cf784e90fbd7f8414afd7ed100eeee3
6
+ metadata.gz: f1084ca533fe97317ebdf481df3c947e3e63249d7644f10c6428bca0ba0d67873d2eef99b8df4e5aec63d4da2005dfa3d38154a3d7036619c7e915636c9acc12
7
+ data.tar.gz: ab3fdc9d6b87679e4cea96e9efdd0cdd5fe65468649072d1a98c643aec69fdde04f8359b055e56f578d9d0be2aef7fbd8624d159079bc84fa64acaec313a1d29
@@ -0,0 +1,71 @@
1
+ # The NessusClient - Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ All complaints will be reviewed and investigated and will result in a response that
58
+ is deemed necessary and appropriate to the circumstances. The project team is
59
+ obligated to maintain confidentiality with regard to the reporter of an incident.
60
+ Further details of specific enforcement policies may be posted separately.
61
+
62
+ Project maintainers who do not follow or enforce the Code of Conduct in good
63
+ faith may face temporary or permanent repercussions as determined by other
64
+ members of the project's leadership.
65
+
66
+ ## Attribution
67
+
68
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
69
+ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
70
+
71
+ [homepage]: https://www.contributor-covenant.org
data/README.md CHANGED
@@ -1,11 +1,10 @@
1
1
  NessusClient
2
2
  =========
3
3
 
4
- Usable, fast, simple Ruby gem for Tenable Nessus Pro v6.x and v7.x
5
-
4
+ Usable, fast, simple Ruby gem for Tenable Nessus Pro v7.x and v8.x
6
5
  NessusClient was designed to be simple, fast and performant through communication with Nessus over REST interface.
7
6
 
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)
7
+ [![Gem Version](https://badge.fury.io/rb/nessus_client.svg)](https://badge.fury.io/rb/nessus_client) [![codecov](https://codecov.io/gh/heyder/nessus_client/branch/master/graph/badge.svg)](https://codecov.io/gh/heyder/nessus_client) [![Inline docs](http://inch-ci.org/github/heyder/nessus_client.svg?branch=master)](http://inch-ci.org/github/heyder/nessus_client)
9
8
 
10
9
  **Ruby gem for Nessus API**
11
10
 
@@ -29,30 +28,38 @@ Getting started
29
28
  ```ruby
30
29
  require 'nessus_client'
31
30
 
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 ))
31
+ nc = NessusClient.new( { :uri=>'https://localhost:8834', :username=>'username',:password=> 'password'} )
32
+ status = Oj.load( nc.status )
33
+
34
+ if status['status'] == 'ready'
35
+ scan_id = nc.get_scan_by_name('weekly_scan')
36
+ scan_uuid = Oj.load( nc.launch_by_name( 'weekly_scan' ,['127.0.0.1']) )['scan_uuid']
37
+
38
+ while true do
39
+ puts `clear`
40
+ scan_status = Oj.load( nc.scan_details( scan_id ) )["info"]["status"]
41
+ puts " #{scan_id} - #{scan_uuid} - #{scan_status} "
42
+ sleep 5
43
+ if ["completed","canceled"].include? scan_status
44
+ export_request = Oj.load( nc.export_request( scan_id, "nessus" ))
45
+ puts " export request: #{export_request}"
46
+ while true do
47
+ puts `clear`
48
+ export_status = Oj.load( nc.export_status( export_request['token']) )["status"]
49
+ puts " export status: #{export_status}"
50
+ sleep 5
51
+ if export_status == "ready"
52
+ puts " downloading..."
53
+ open("scan_report", "wb") do |file|
54
+ file.write(nc.export_download( scan_id, export_request['file'] ))
55
+ end
56
+ exit 0
50
57
  end
51
- break
52
58
  end
53
- end
54
- end
59
+ end
60
+ end
55
61
  end
62
+
56
63
  ```
57
64
 
58
65
  ## Installation
@@ -81,11 +88,11 @@ require 'oj'
81
88
  ## Code of Conduct
82
89
 
83
90
  Everyone participating in this project's development, issue trackers and other channels is expected to follow our
84
- [Code of Conduct](./CODE_OF_CONDUCT.md)
91
+ [Code of Conduct](./CODE_OF_CONDUCT.md).
85
92
 
86
93
  ## Contributing
87
94
 
88
- See the [contributing guide](https://github.com/heyder/nessus_client/blob/master/CONTRIBUTING.md).
95
+ See the [contributing guide](./CONTRIBUTING.md).
89
96
 
90
97
  ## Copyright
91
98
 
@@ -1,15 +1,12 @@
1
- # require_relative '../nessus_client/request'
2
-
3
1
  module NessusClient::Exports
4
2
 
5
- # Reques a export of vulnerabilities scan.
3
+ # Request a export of vulnerabilities scan.
6
4
  # @param [String] scan_id The export uuid string.
7
- # @param [String] format The export format.This
8
- # can be `nessus` or `nessus_db`.
5
+ # @param [String] format The file format to use (Nessus, HTML, PDF, CSV, or DB).
9
6
  # @return [JSON]
10
- def export_request( scan_id, format )
11
- params = {:format => format }
12
- self.request.post( "/scans/#{scan_id}/export", params )
7
+ def export_request( scan_id, format="nessus" )
8
+ payload = {:format => format }
9
+ self.request.post( { :path => "/scans/#{scan_id}/export", :payload => payload, :headers => self.headers} )
13
10
  end
14
11
 
15
12
  # Check the status of a export request
@@ -19,19 +16,20 @@ module NessusClient::Exports
19
16
  # export_status = nc.export_status( "73376c41-1508-46b7-8587-483d159cd956" )
20
17
  # return true if export_status["status"] == "ready"
21
18
  def export_status( export_id )
22
- self.request.get( "/tokens/#{export_id}/status" )
19
+ self.request.get( {:path => "/tokens/#{export_id}/status", :headers => self.headers} )
23
20
  end
24
21
 
25
22
  # Download a vulnerabities scan output.
26
- # @param [String] export_id The export uuid string.
23
+ # @param [Integer] scan_id The id of the scan to export.
24
+ # @param [Integer] file_id The id of the file to download (see #export_request).
27
25
  # @return (see #format)
28
26
  # @example Download a ready export.
29
27
  # export = nc.export_download("73376c41-1508-46b7-8587-483d159cd956")
30
28
  # open("scan_report", "wb") do |file|
31
29
  # file.write( export )
32
30
  # end
33
- def export_download( export_id )
34
- self.request.get( "/tokens/#{export_id}/download" )
31
+ def export_download( scan_id, file_id )
32
+ self.request.get( {:path => "/scans/#{scan_id}/export/#{file_id}/download", :headers => self.headers} )
35
33
  end
36
34
 
37
35
  end
@@ -1,16 +1,14 @@
1
- # require_relative '../nessus_client/request'
2
-
3
1
  module NessusClient::Folders
4
2
  # Get the list of folders from the endpoint.
5
3
  # @return [JSON]
6
4
  def list_folders
7
- self.request.get("/folders")
5
+ self.request.get({:path => "/folders", :headers => self.headers})
8
6
  end
9
7
  # Create a folder into the endpoint.
10
8
  # @param [String] folder_name The name of the folder the will be created.
11
9
  # @return [Json]
12
10
  def create_folder( folder_name )
13
- params = {:name => folder_name }.to_json
14
- self.request.post("/folders", params)
11
+ payload = {:name => folder_name }
12
+ self.request.post({:path=>"/folders", :payload => payload, :headers => self.headers})
15
13
  end
16
14
  end
@@ -1,9 +1,7 @@
1
- # require_relative '../nessus_client/request'
2
-
3
1
  module NessusClient::Policies
4
2
  # List the scan polices from the endpoint.
5
3
  # @return [JSON]
6
4
  def policies
7
- self.request.get( "/policies" )
5
+ self.request.get( {:path => "/policies", :headers => self.headers} )
8
6
  end
9
7
  end
@@ -6,7 +6,7 @@ module NessusClient::Scans
6
6
  # @return [JSON]
7
7
  def list_scans( folder_id=nil )
8
8
  query = folder_id.nil? ? nil : { "folder_id" => folder_id }
9
- self.request.get( "/scans", nil, query )
9
+ self.request.get( {:path => "/scans", :query => query, :headers => self.headers} )
10
10
  end
11
11
  alias_method :scans, :list_scans
12
12
 
@@ -16,17 +16,25 @@ module NessusClient::Scans
16
16
  # @return [JSON]
17
17
  def scan_details( scan_id, history_id=nil )
18
18
  query = history_id.nil? ? nil : { "history_id" => history_id }
19
- self.request.get( "/scans/#{scan_id}", nil, query )
19
+ self.request.get( {:path => "/scans/#{scan_id}", :query => query, :headers => self.headers} )
20
+ end
21
+
22
+ # Lauch a scan by its id
23
+ # @param [Integer] scan_id The ID of a alredy created scan.
24
+ # @param [Array<String>] targets comma separeted new target to be scanned.
25
+ # @return [JSON]
26
+ def launch( scan_id, targets=[])
27
+ payload = { :alt_targets => targets } unless targets.empty?
28
+ self.request.post( {:path => "/scans/#{scan_id}/launch", :payload => payload, :headers => self.headers} )
20
29
  end
21
30
 
22
31
  # Lauch a scan by its name
23
32
  # @param [String] scan_name The name of a alredy created scan.
24
- # @param [Array<String>] targets Comma separeted new target to be scanned.
33
+ # @param [Array<String>] targets comma separeted new target to be scanned.
25
34
  # @return [JSON]
26
35
  def launch_by_name( scan_name, targets=[] )
27
36
  scan_id = get_scan_by_name( scan_name )
28
- params = { :alt_targets => targets } unless targets.empty?
29
- self.request.post( "/scans/#{scan_id}/launch", params )
37
+ launch( scan_id, targets )
30
38
  end
31
39
 
32
40
  # Get a scan by its name
@@ -1,56 +1,68 @@
1
1
  require 'oj'
2
- # require_relative 'request'
3
- # require_relative 'exception'
4
-
5
- # Abstract base class for NessusClient Session.
2
+ # Abstract Session class for NessusClient.
6
3
  # @since 0.1.0
7
4
  # @attr_reader [String] token Autentication session token.
8
5
  # @attr_reader [String] api_token Autentication API token.
9
6
  module NessusClient::Session
10
7
 
11
- attr_reader :token, :api_token
8
+ attr_reader :session
12
9
 
13
- @token = @api_token = nil
10
+ @@api_token = nil
11
+ @session = false
14
12
 
15
13
  # Autenticate into Nessus endpoint.
16
14
  # @param [String] username
17
15
  # @param [String] password
16
+ # @return [nil]
18
17
  # @raise [NessusClient::Error] Unable to authenticate.
19
18
  # @todo Validate response token format
20
19
  def set_session( username, password )
21
20
 
22
21
  payload = {
23
22
  username: username,
24
- password: password,
23
+ password: password
25
24
  }
26
25
 
27
- response = self.request.post( '/session', payload )
26
+ response = self.request.post( {:path => '/session', :payload => payload, :headers => self.headers} )
27
+
28
28
  response = Oj.load(response) if response.length > 0
29
29
 
30
30
  raise NessusClient::Error.new( "Unable to authenticate. The response did not include a session token." ) unless response['token']
31
-
32
- @token = response['token']
31
+
32
+ begin
33
+ self.headers.update( 'X-Cookie' => 'token=' + response['token'] )
34
+ @session = true
35
+ self.headers.update( 'X-API-Token' => set_api_token() )
36
+ rescue NessusClient::Error => err
37
+ puts err.message
38
+ else
39
+ @@api_token = true
40
+ ensure
41
+ return
42
+ end
33
43
 
34
44
  end
35
45
  alias_method :session_create, :set_session
36
46
 
47
+ # Destroy the current session from Nessus endpoint
48
+ def destroy
49
+ self.request.delete( '/session', nil, self.headers )
50
+ @session = false
51
+ end
52
+ alias_method :logout , :destroy
53
+
54
+ private
55
+
37
56
  # Set the API Token from legacy Nessus version
38
57
  # @raise [NessusClient::Error] Unable to get API Token.
39
58
  def set_api_token
40
- response = self.request.get( "/nessus6.js" )
59
+ response = self.request.get( {:path => "/nessus6.js", :headers => self.headers} )
41
60
  response.match( %r{return"(\w{8}-(?:\w{4}-){3}\w{12})"\}} )
42
61
 
43
- raise NessusClient::Error.new( "Unable to get API Token. Some features won't work." ) unless $1#.nil?
62
+ raise NessusClient::Error.new( "Unable to get API Token. Some features won't work." ) unless $1
44
63
 
45
- @api_token = $1
64
+ return $1
46
65
 
47
66
  end
48
67
 
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
68
  end
@@ -5,7 +5,7 @@ Dir[File.join(__dir__, 'modules', '*.rb')].each { |file| require file }
5
5
 
6
6
  class NessusClient
7
7
 
8
- attr_reader :request, :session
8
+ attr_reader :request, :session, :headers
9
9
 
10
10
  include NessusClient::Session
11
11
  include NessusClient::Scans
@@ -14,7 +14,6 @@ class NessusClient
14
14
  include NessusClient::Policies
15
15
 
16
16
  autoload :Request, "nessus_client/request"
17
- # autoload :Session, "nessus_client/session"
18
17
 
19
18
  # @param [Hash] params the options to create a NessusClient with.
20
19
  # @option params [String] :uri ('https://localhost:8834/') Nessus endpoint to connect with
@@ -22,46 +21,33 @@ class NessusClient
22
21
  # @option params [String] :password Password (nil) to use in the connection
23
22
  # @option params [String] :ssl_verify_peer (false) should check whether valid SSL certificate
24
23
  def initialize( params = {} )
25
- @has_session = false
24
+
26
25
  default_params = {
27
26
  uri: 'https://localhost:8834/',
28
27
  username: nil,
29
28
  password: nil,
30
- ssl_verify_peer: false
29
+ ssl_verify_peer: true
31
30
  }
32
31
  params = default_params.merge( params )
33
32
  req_params = params.select {|key, value| [:uri, :ssl_verify_peer].include?(key) }
34
33
 
35
34
  @request = NessusClient::Request.new( req_params )
35
+ @headers = NessusClient::Request::DEFAULT_HEADERS.dup
36
36
  self.set_session( params.fetch(:username), params.fetch(:password) )
37
-
38
- if self.token
39
- begin
40
- @has_session = true
41
- @request.headers.update( 'X-Cookie' => 'token=' + self.token )
42
- self.set_api_token
43
- rescue NessusClient::Error => err
44
- puts err.message
45
- else
46
- request.headers.update( 'X-API-Token' => self.api_token )
47
- ensure
48
- return
49
- end
50
37
 
51
- end
52
38
 
53
39
  end
54
40
 
55
41
  # Gets NessusClient::Session authentication status.
56
42
  # @return [Boolean]
57
43
  def has_session?
58
- @has_session
44
+ self.session
59
45
  end
60
46
 
61
47
  # Gets the server status.
62
48
  # @return [Json] Returns the server status (loading, ready, corrupt-db, feed-expired, eval-expired, locked, register, register-locked, download-failed, feed-error).
63
49
  def status
64
- self.request.get( "/server/status" )
50
+ self.request.get( {:path => "/server/status", :headers => self.headers} )
65
51
  end
66
52
 
67
53
  end
@@ -3,51 +3,51 @@ require 'json'
3
3
 
4
4
  class NessusClient
5
5
 
6
- # Abstract base class for NessusClient. Provides some helper methods for
6
+ # Abstract request class for NessusClient. Provides some helper methods for
7
7
  class Request
8
8
 
9
- attr_reader :url, :headers
9
+ attr_reader :url
10
10
 
11
11
  # Default HTTP header to be used on the requests.
12
12
  DEFAULT_HEADERS = {
13
13
  "User-Agent" => "Mozilla/5.0 (Linux x86_64)",
14
14
  "Content-Type" => "application/json"
15
- }
15
+ }.freeze
16
16
 
17
17
  def initialize( params )
18
- params = {:uri => nil, :ssl_verify_peer => false, :headers => {} }.merge( params )
19
- @@ssl_verify_peer = params.fetch(:ssl_verify_peer)
18
+ # @headers = params[:headers] || DEFAULT_HEADERS
19
+ params = {:uri => nil }.merge( params )
20
+ @@ssl_verify_peer = params[:ssl_verify_peer] ? true : false
20
21
  @url = @@url = NessusClient::Request.uri_parse( params.fetch(:uri) )
21
- @headers = params.fetch( :headers ).merge( DEFAULT_HEADERS )
22
22
  end
23
23
 
24
24
  # @raise [NotImplementedError] Use update from Hash insted.
25
- def headers=(value)
26
- raise NotImplementedError.new("Use update from Hash insted.")
27
- end
25
+ # def headers=(value)
26
+ # raise NotImplementedError.new("Use update from Hash insted.")
27
+ # end
28
28
 
29
29
  # Perform a HTTP GET to the endpoint.
30
30
  # @param [String] path The URI path to perform the request.
31
31
  # @param [String] payload The HTTP body to send.
32
32
  # @param [String] query The URI query to send.
33
- def get( path=nil, payload=nil, query=nil )
34
- http_request( :get, path, payload, query )
33
+ def get( opts={} )
34
+ http_request( :get, opts )
35
35
  end
36
36
 
37
37
  # Perform a HTTP POST to the endpoint.
38
38
  # @param [String] path The URI path to perform the request.
39
39
  # @param [String] payload The HTTP body to send.
40
40
  # @param [String] query The URI query to send.
41
- def post( path=nil, payload=nil, query=nil )
42
- http_request( :post, path, payload, query )
41
+ def post( opts={} )
42
+ http_request( :post, opts )
43
43
  end
44
44
 
45
45
  # Perform a HTTP DELETE to the endpoint.
46
46
  # @param [String] path The URI path to perform the request.
47
47
  # @param [String] payload The HTTP body to send.
48
48
  # @param [String] query The URI query to send.
49
- def delete( path=nil, payload=nil, query=nil )
50
- http_request( :delete, path, payload, query )
49
+ def delete( opts={} )
50
+ http_request( :delete, opts )
51
51
  end
52
52
  # Parse a receiveid URI
53
53
  # @param [String] uri A valid URI.
@@ -65,18 +65,23 @@ class NessusClient
65
65
  # @param [String] path The URI path to perform the request.
66
66
  # @param [String] payload The HTTP body to send.
67
67
  # @param [String] query The URI query to send.
68
- def http_request( method=:get, path, payload, query )
69
-
70
- connection = Excon.new( @@url )
68
+ def http_request( method=:get, args )
69
+ opts = {
70
+ :path => nil,
71
+ :payload => nil,
72
+ :query => nil,
73
+ :headers => nil
74
+ }.merge( args )
75
+
76
+ connection = Excon.new( @@url, {ssl_verify_peer: @@ssl_verify_peer} )
71
77
 
72
- body = payload ? payload.to_json : ''
78
+ body = opts[:payload] ? opts[:payload].to_json : ''
73
79
  options = {
74
80
  method: method,
75
- path: path,
81
+ path: opts.fetch(:path),
76
82
  body: body,
77
- query: query,
78
- headers: @headers,
79
- ssl_verify_peer: @@ssl_verify_peer,
83
+ query: opts.fetch(:query),
84
+ headers: opts.fetch(:headers),
80
85
  expects: [200, 201]
81
86
  }
82
87
  response = connection.request( options )
@@ -1,4 +1,4 @@
1
1
  class NessusClient
2
2
  # The current version of the libary.
3
- VERSION = '0.1.2'
3
+ VERSION = '0.1.3'
4
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.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heyder
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.7'
41
- - !ruby/object:Gem::Dependency
42
- name: json
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.1'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.1'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rspec
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -150,7 +136,9 @@ extensions: []
150
136
  extra_rdoc_files:
151
137
  - README.md
152
138
  - CONTRIBUTING.md
139
+ - CODE_OF_CONDUCT.md
153
140
  files:
141
+ - CODE_OF_CONDUCT.md
154
142
  - CONTRIBUTING.md
155
143
  - README.md
156
144
  - lib/modules/exports.rb