controls 1.5.1 → 1.6.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +9 -0
  5. data/README.md +2 -0
  6. data/Rakefile +6 -1
  7. data/apiary.apib +60 -0
  8. data/controls.gemspec +0 -3
  9. data/lib/controls/client.rb +11 -4
  10. data/lib/controls/client/events.rb +21 -0
  11. data/lib/controls/client/guidance.rb +0 -4
  12. data/lib/controls/client/security_controls.rb +0 -4
  13. data/lib/controls/client/threats.rb +0 -4
  14. data/lib/controls/default.rb +2 -1
  15. data/lib/controls/ext/dish/plate.rb +8 -10
  16. data/lib/controls/objects.rb +4 -0
  17. data/lib/controls/objects/coverage_information.rb +0 -1
  18. data/lib/controls/objects/event.rb +18 -0
  19. data/lib/controls/objects/product_change_event_payload.rb +4 -0
  20. data/lib/controls/objects/security_control_change_event_payload.rb +4 -0
  21. data/lib/controls/objects/site_change_event_payload.rb +4 -0
  22. data/lib/controls/version.rb +1 -1
  23. data/spec/controls/client/assessments_spec.rb +24 -0
  24. data/spec/controls/client/events_spec.rb +54 -0
  25. data/spec/matchers.rb +46 -0
  26. data/spec/spec_helper.rb +14 -0
  27. metadata +17 -71
  28. data/docs/Gemfile +0 -10
  29. data/docs/Rules +0 -31
  30. data/docs/content/index.md +0 -8
  31. data/docs/content/v1.md +0 -8
  32. data/docs/content/v1/authentication.md +0 -3
  33. data/docs/content/v1/search.md +0 -11
  34. data/docs/content/v1/troubleshooting.md +0 -3
  35. data/docs/layouts/default.html +0 -46
  36. data/docs/layouts/home.html +0 -51
  37. data/docs/lib/default.rb +0 -2
  38. data/docs/nanoc.yaml +0 -43
  39. data/docs/static/css/bootstrap-theme.css +0 -397
  40. data/docs/static/css/bootstrap-theme.min.css +0 -7
  41. data/docs/static/css/bootstrap.css +0 -7118
  42. data/docs/static/css/bootstrap.min.css +0 -7
  43. data/docs/static/fonts/glyphicons-halflings-regular.eot +0 -0
  44. data/docs/static/fonts/glyphicons-halflings-regular.svg +0 -229
  45. data/docs/static/fonts/glyphicons-halflings-regular.ttf +0 -0
  46. data/docs/static/fonts/glyphicons-halflings-regular.woff +0 -0
  47. data/docs/static/images/controlsinsight-shield.png +0 -0
  48. data/docs/static/images/controlsinsight.png +0 -0
  49. data/docs/static/js/bootstrap.js +0 -2006
  50. data/docs/static/js/bootstrap.min.js +0 -7
  51. data/spec/controls_spec.rb +0 -22
  52. data/spec/helper.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afef162bcbc4d24e5943361cb4e5b55c4fbe2b06
4
- data.tar.gz: ab9875952d506d826d3464593790a30368ca179a
3
+ metadata.gz: c454bb91456860e8b28060cca709a3955d7e227e
4
+ data.tar.gz: d1069c59e852f48ebb04e6fb3acfa517177dd320
5
5
  SHA512:
6
- metadata.gz: cfd01f6176f85cca3499c7d226d2eed978e26e620a4625ceb700e9f95f4b00858142669065206adbc644946a9712d254cb079b7bb0f458c5fd3aa6e921602308
7
- data.tar.gz: 1ac3ddf95b414e5a3bb3007c149650ae204fde284d08666601711a743c6d5ddb84223bd9c60a5a63aae27450359304217b6aea6cb8cc6c6a509ca97038fc1b17
6
+ metadata.gz: a61b496ef91f6570129fea1491fca80862715227c5a8556dfd9aaa1c46d81d20e3a4273de70fb96b47d6442872951ebdcf3bc99e9cb87f138fe59b67ad5c8153
7
+ data.tar.gz: c2e8ce4004164c97f9650fd6e63c5078a47674f840ee460cfcd7f2075178f0838acfe00e53aea27e3bae40442e6dca7a38a2f8f7988c12c149797ce0062a0762
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ test/version_tmp
17
17
  tmp
18
18
  docs/crash.log
19
19
  docs/output/
20
+ .watsonrc
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ env:
5
+ - CONTROLS_API_ENDPOINT="https://controlsinsight.apiary.io/insight/controls/api"
data/Gemfile CHANGED
@@ -2,3 +2,12 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in controls.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem 'rake'
8
+ gem 'rspec'
9
+ end
10
+
11
+ group :documentation do
12
+ gem 'yard'
13
+ end
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # controlsinsight client gem
2
+ [![Build Status](https://travis-ci.org/erran/controls.rb.png?branch=master)](https://travis-ci.org/erran/controls.rb)
3
+
2
4
  The **controls**insight (controls) gem interfaces with [Rapid7's **controls**insight API](http://rapid7.github.io/controlsinsight.rb).
3
5
 
4
6
  ## Installation
data/Rakefile CHANGED
@@ -1,3 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
2
3
 
3
- task :default => :install
4
+ RSpec::Core::RakeTask.new(:spec) do |task|
5
+ task.rspec_opts = "--require ./spec/spec_helper.rb --format documentation --color"
6
+ end
7
+
8
+ task :default => :spec
data/apiary.apib ADDED
@@ -0,0 +1,60 @@
1
+ FORMAT: 1A
2
+ HOST: https://nexpose.local:3780/insight/controls/api/
3
+
4
+ # ControlsInsight
5
+ Notes API is a *short texts saving* service similar to its physical paper presence on your table.
6
+
7
+ # Group Assessments
8
+ ## Assessment Collection [/assessments]
9
+ ### Assessments [GET]
10
+
11
+ + Response 200 (application/json)
12
+
13
+ {
14
+ "id": 1,
15
+ "assessing": false,
16
+ "highRiskAssetCount": 0,
17
+ "mediumRiskAssetCount": 24,
18
+ "lowRiskAssetCount": 0,
19
+ "totalAssetCount": 24,
20
+ "overallRiskScore": 4.004146038088617,
21
+ "timestamp": 1393184605912
22
+ }
23
+
24
+ ## Assessment [/assessments/{assessment_id}]
25
+ ### Assessment by ID [GET]
26
+
27
+ + Parameters
28
+ + assessment_id (optional, integer, `1`) ... The ID of the assessment to retreive.
29
+
30
+ + Response 200 (application/json)
31
+
32
+ {
33
+ "id": 1,
34
+ "assessing": false,
35
+ "highRiskAssetCount": 0,
36
+ "mediumRiskAssetCount": 24,
37
+ "lowRiskAssetCount": 0,
38
+ "totalAssetCount": 24,
39
+ "overallRiskScore": 4.004146038088617,
40
+ "timestamp": 1393184605912
41
+ }
42
+
43
+ # Group Search
44
+ ## Assets [/assets/search?query={query}]
45
+ ### Asset Search [GET]
46
+
47
+ + Parameters
48
+ + query (required, string, `10.4.19`) ... The free text query. This can be a full/partial hostname or IP address.
49
+
50
+ + Response 200 (application/json)
51
+
52
+ [
53
+ {
54
+ "uuid": "db899a57-347c-4df9-9ce2-6932dc4adf38>",
55
+ "riskScore": 5.554266115196547,
56
+ "riskLevel": "MEDIUM",
57
+ "hostName": "CMMNCTR2K7R2-U",
58
+ "ipaddress": "10.4.19.25"
59
+ }
60
+ ]
data/controls.gemspec CHANGED
@@ -24,7 +24,4 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.3'
26
26
  spec.add_development_dependency 'netrc'
27
- spec.add_development_dependency 'rake'
28
- spec.add_development_dependency 'vcr'
29
- spec.add_development_dependency 'yard'
30
27
  end
@@ -1,15 +1,18 @@
1
1
  require 'json'
2
2
  require 'faraday'
3
- require 'nokogiri'
4
3
  require 'rack/utils'
5
4
  require 'controls/authentication'
6
5
  require 'controls/configurable'
7
6
  require 'controls/client/assessments'
8
7
  require 'controls/client/assets'
8
+ require 'controls/client/events'
9
9
  require 'controls/client/coverage'
10
+ require 'controls/client/configurations'
10
11
  require 'controls/client/guidance'
12
+ require 'controls/client/prioritized_guidance'
11
13
  require 'controls/client/security_controls'
12
14
  require 'controls/client/threats'
15
+ require 'controls/client/threat_vectors'
13
16
  require 'controls/client/trends'
14
17
  require 'controls/response'
15
18
 
@@ -20,10 +23,14 @@ module Controls
20
23
  include Controls::Configurable
21
24
  include Controls::Client::Assessments
22
25
  include Controls::Client::Assets
26
+ include Controls::Client::Events
23
27
  include Controls::Client::Coverage
28
+ include Controls::Client::Configurations
24
29
  include Controls::Client::Guidance
30
+ include Controls::Client::PrioritizedGuidance
25
31
  include Controls::Client::SecurityControls
26
32
  include Controls::Client::Threats
33
+ include Controls::Client::ThreatVectors
27
34
  include Controls::Client::Trends
28
35
 
29
36
  # A few messages to show the user of Controls::Client in the case that a bad certificate is encountered
@@ -94,7 +101,7 @@ module Controls
94
101
  path: path
95
102
  }
96
103
 
97
- if !resp.headers['content-type'].eql?("application/json;charset=UTF-8")
104
+ if !resp.headers['content-type'] =~ /^application\/json/
98
105
  fail exception('Invalid content-type error')
99
106
  end
100
107
 
@@ -119,7 +126,7 @@ module Controls
119
126
  path: path
120
127
  }
121
128
 
122
- if !resp.headers['content-type'].eql?("application/json;charset=UTF-8")
129
+ if !resp.headers['content-type'] =~ /^application\/json/
123
130
  fail exception('Invalid content-type error')
124
131
  end
125
132
 
@@ -194,7 +201,7 @@ module Controls
194
201
  path: path
195
202
  }
196
203
 
197
- if !resp.headers['content-type'].eql?("application/json;charset=UTF-8")
204
+ if !resp.headers['content-type'] =~ /^application\/json/
198
205
  fail exception('Invalid content-type error')
199
206
  end
200
207
 
@@ -0,0 +1,21 @@
1
+ module Controls
2
+ class Client
3
+ # A module to encapsulate API methods related to events
4
+ # @since API v1.0
5
+ # @version v1.6.0
6
+ module Events
7
+ # @!group Event Methods
8
+
9
+
10
+ # Either returns a list of all events or all events by type
11
+ #
12
+ # @param [Hash] params the query parameters to send with the request
13
+ # @option params [String] :filter (:all) the event type to filter by
14
+ # @raise [Controls::NotFound] if the uuid didn't match any events
15
+ # @return [Hash] a hash representing the matching event
16
+ def events(params = {})
17
+ get '/events', params
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,13 +1,9 @@
1
- require 'controls/client/prioritized_guidance'
2
-
3
1
  module Controls
4
2
  class Client
5
3
  # A module to encapsulate API methods related to guidance
6
4
  # @since API v1.0
7
5
  # @version v1.0.0
8
6
  module Guidance
9
- include PrioritizedGuidance
10
-
11
7
  # @!group Guidance Methods
12
8
 
13
9
  # @param [String] name the name of the guidance to search for
@@ -1,5 +1,3 @@
1
- require 'controls/client/configurations'
2
-
3
1
  module Controls
4
2
  class Client
5
3
  # A module to encapsulate API methods related to security controls and
@@ -7,8 +5,6 @@ module Controls
7
5
  # @since API v1.0
8
6
  # @version v1.0.0
9
7
  module SecurityControls
10
- include Configurations
11
-
12
8
  #!@group Security Control Methods
13
9
 
14
10
  # @param [String] control the name of the security control name to
@@ -1,13 +1,9 @@
1
- require 'controls/client/threat_vectors'
2
-
3
1
  module Controls
4
2
  class Client
5
3
  # A module to encapsulate API methods related to threats and threat vectors
6
4
  # @since API v1.0
7
5
  # @version v1.0.0
8
6
  module Threats
9
- include ThreatVectors
10
-
11
7
  # @!group Threat Methods
12
8
 
13
9
  # @param [String] threat the threat name to search for
@@ -31,7 +31,8 @@ module Controls
31
31
  # @return [String] the API endpoint's URI as a URL
32
32
  def api_endpoint
33
33
  endpoint = ENV['CONTROLS_API_ENDPOINT'] || API_ENDPOINT
34
- URI.parse(endpoint).to_s
34
+ # [todo] - this raises an exception, it is only used for URI validation so it's being commented out for now
35
+ # URI.parse(endpoint).to_s
35
36
  end
36
37
 
37
38
  # @return [String] the API version to connect to
@@ -5,18 +5,17 @@ module Dish
5
5
  camel_case_key = method.split('_').map(&:capitalize).join
6
6
  camel_case_key[0] = camel_case_key[0].downcase
7
7
 
8
- if method.end_with?('?')
8
+ if method.end_with? '?'
9
9
  key = camel_case_key[0..-2]
10
10
  _check_for_presence(key)
11
- elsif method.end_with?('=')
11
+ elsif method.end_with? '='
12
12
  key = camel_case_key[0..-2]
13
13
  _set_value(key, args.first)
14
14
  else
15
- value = _get_value(camel_case_key)
16
- if value.nil? && !_allowed_keys.include?(camel_case_key)
17
- super(method.to_sym, *args, &block)
15
+ if @_original_hash.key?(camel_case_key)
16
+ _get_value(camel_case_key)
18
17
  else
19
- value
18
+ super(method.to_sym, *args, &block)
20
19
  end
21
20
  end
22
21
  end
@@ -42,18 +41,17 @@ module Dish
42
41
  "#<#{self.class}: #{vars.join(', ')}>"
43
42
  end
44
43
 
44
+ alias_method :to_h, :as_hash
45
+
45
46
  def to_json(*args)
46
47
  as_hash.to_json(*args)
47
48
  end
48
49
 
49
50
  private
51
+
50
52
  def _set_value(key, value)
51
53
  value = _convert_value(value, self.class.coercions[key])
52
54
  @_original_hash[key] = value
53
55
  end
54
-
55
- def _allowed_keys
56
- []
57
- end
58
56
  end
59
57
  end
@@ -2,10 +2,14 @@ require 'dish'
2
2
  require 'controls/ext/dish/plate'
3
3
  require 'controls/objects/assessment'
4
4
  require 'controls/objects/asset'
5
+ require 'controls/objects/event'
6
+ require 'controls/objects/product_change_event_payload'
5
7
  require 'controls/objects/configuration'
6
8
  require 'controls/objects/guidance'
7
9
  require 'controls/objects/security_control'
10
+ require 'controls/objects/security_control_change_event_payload'
8
11
  require 'controls/objects/security_control_coverage'
12
+ require 'controls/objects/site_change_event_payload'
9
13
  require 'controls/objects/threat'
10
14
  require 'controls/objects/threat_vector'
11
15
  require 'controls/objects/trend'
@@ -1,7 +1,6 @@
1
1
  module Controls
2
2
  class CoverageInformation < Dish::Plate
3
3
  def to_s
4
- # [todo] - generate this
5
4
  "#<#{self.class}: total: #{total}, covered: #{covered}, uncovered: #{uncovered}, percent_covered: #{percent_covered}>"
6
5
  end
7
6
  end
@@ -0,0 +1,18 @@
1
+ module Controls
2
+ class Event < Dish::Plate
3
+ coerce :createdAt, ->(value) { Time.at(value / 1000) if value }
4
+
5
+ def payload
6
+ value = _get_value('payload')
7
+ Dish(value, Controls.const_get("#{type}Payload"))
8
+ end
9
+
10
+ def inspect
11
+ super.sub('Event', type)
12
+ end
13
+
14
+ def to_s
15
+ type
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module Controls
2
+ class ProductChangeEventPayload < Dish::Plate
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Controls
2
+ class SecurityControlChangeEventPayload < Dish::Plate
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Controls
2
+ class SiteChangeEventPayload < Dish::Plate
3
+ end
4
+ end
@@ -1,4 +1,4 @@
1
1
  module Controls
2
2
  # The version of the Controls gem
3
- VERSION = '1.5.1'
3
+ VERSION = '1.6.0'
4
4
  end
@@ -0,0 +1,24 @@
1
+ describe '/api/assessments' do
2
+ before do
3
+ login_to_environment
4
+ end
5
+
6
+ context 'GET /api/assessments' do
7
+ it 'returns a list of assessments' do
8
+ assessments = Controls.assessments
9
+
10
+ expect(assessments).to match_assessment_format
11
+ end
12
+ end
13
+
14
+ context 'GET /api/assessments/1' do
15
+ it 'returns a single assessment' do
16
+ assessment = Controls.assessments(1)
17
+
18
+ expect(assessment).to match_assessment_format
19
+ expect(assessment.id).to eq(1)
20
+ expect(assessment.assessing?).to be_false
21
+ expect(assessment.overall_risk_score).to be_within(5.0).of(5.0)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ #describe '/api/events' do
2
+ # before do
3
+ # login_to_environment
4
+ # end
5
+ #
6
+ # context 'GET /api/events' do
7
+ # it 'returns a list of events' do
8
+ # events = Controls.events
9
+ #
10
+ # expect(events).to match_format(event_format)
11
+ # end
12
+ # end
13
+ #
14
+ # context 'GET /api/events?filter=ProductChangeEvent' do
15
+ # it 'returns a list of events' do
16
+ # events = Controls.events filter: 'ProductChangeEvent'
17
+ #
18
+ # expect(events).to match_format(event_format)
19
+ # expect(events.map(&:payload)).to match_format(product_change_format)
20
+ # end
21
+ # end
22
+ #
23
+ # context 'GET /api/events?filter=SecurityControlChangeEvent' do
24
+ # it 'returns a list of events' do
25
+ # events = Controls.events filter: 'SecurityControlChangeEvent'
26
+ # expected_payload_format = security_control_change_format
27
+ #
28
+ # expect(events).to match_format(event_format)
29
+ # expect(events.map(&:payload)).to match_format(expected_payload_format)
30
+ #
31
+ # events.map(&:payload).each do |payload|
32
+ # payload.keys.map(&:to_sym).each do |key|
33
+ # expect(payload.send(key)).to match_format(expected_payload_format[key].last)
34
+ # end
35
+ # end
36
+ # end
37
+ # end
38
+ #
39
+ # context 'GET /api/events?filter=SiteChangeEvent' do
40
+ # it 'returns a list of events' do
41
+ # events = Controls.events filter: 'SiteChangeEvent'
42
+ # expected_payload_format = site_change_format
43
+ #
44
+ # expect(events).to match_format(event_format)
45
+ # expect(events.map(&:payload)).to match_format(expected_payload_format)
46
+ #
47
+ # events.map(&:payload).each do |payload|
48
+ # payload.keys.map(&:to_sym).each do |key|
49
+ # expect(payload.send(key)).to match_format(expected_payload_format[key].last)
50
+ # end
51
+ # end
52
+ # end
53
+ # end
54
+ #end