controls 1.5.1 → 1.6.0

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