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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +9 -0
- data/README.md +2 -0
- data/Rakefile +6 -1
- data/apiary.apib +60 -0
- data/controls.gemspec +0 -3
- data/lib/controls/client.rb +11 -4
- data/lib/controls/client/events.rb +21 -0
- data/lib/controls/client/guidance.rb +0 -4
- data/lib/controls/client/security_controls.rb +0 -4
- data/lib/controls/client/threats.rb +0 -4
- data/lib/controls/default.rb +2 -1
- data/lib/controls/ext/dish/plate.rb +8 -10
- data/lib/controls/objects.rb +4 -0
- data/lib/controls/objects/coverage_information.rb +0 -1
- data/lib/controls/objects/event.rb +18 -0
- data/lib/controls/objects/product_change_event_payload.rb +4 -0
- data/lib/controls/objects/security_control_change_event_payload.rb +4 -0
- data/lib/controls/objects/site_change_event_payload.rb +4 -0
- data/lib/controls/version.rb +1 -1
- data/spec/controls/client/assessments_spec.rb +24 -0
- data/spec/controls/client/events_spec.rb +54 -0
- data/spec/matchers.rb +46 -0
- data/spec/spec_helper.rb +14 -0
- metadata +17 -71
- data/docs/Gemfile +0 -10
- data/docs/Rules +0 -31
- data/docs/content/index.md +0 -8
- data/docs/content/v1.md +0 -8
- data/docs/content/v1/authentication.md +0 -3
- data/docs/content/v1/search.md +0 -11
- data/docs/content/v1/troubleshooting.md +0 -3
- data/docs/layouts/default.html +0 -46
- data/docs/layouts/home.html +0 -51
- data/docs/lib/default.rb +0 -2
- data/docs/nanoc.yaml +0 -43
- data/docs/static/css/bootstrap-theme.css +0 -397
- data/docs/static/css/bootstrap-theme.min.css +0 -7
- data/docs/static/css/bootstrap.css +0 -7118
- data/docs/static/css/bootstrap.min.css +0 -7
- data/docs/static/fonts/glyphicons-halflings-regular.eot +0 -0
- data/docs/static/fonts/glyphicons-halflings-regular.svg +0 -229
- data/docs/static/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/docs/static/fonts/glyphicons-halflings-regular.woff +0 -0
- data/docs/static/images/controlsinsight-shield.png +0 -0
- data/docs/static/images/controlsinsight.png +0 -0
- data/docs/static/js/bootstrap.js +0 -2006
- data/docs/static/js/bootstrap.min.js +0 -7
- data/spec/controls_spec.rb +0 -22
- data/spec/helper.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c454bb91456860e8b28060cca709a3955d7e227e
|
4
|
+
data.tar.gz: d1069c59e852f48ebb04e6fb3acfa517177dd320
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a61b496ef91f6570129fea1491fca80862715227c5a8556dfd9aaa1c46d81d20e3a4273de70fb96b47d6442872951ebdcf3bc99e9cb87f138fe59b67ad5c8153
|
7
|
+
data.tar.gz: c2e8ce4004164c97f9650fd6e63c5078a47674f840ee460cfcd7f2075178f0838acfe00e53aea27e3bae40442e6dca7a38a2f8f7988c12c149797ce0062a0762
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# controlsinsight client gem
|
2
|
+
[](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
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
|
data/lib/controls/client.rb
CHANGED
@@ -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']
|
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']
|
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']
|
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
|
data/lib/controls/default.rb
CHANGED
@@ -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
|
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
|
-
|
16
|
-
|
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
|
-
|
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
|
data/lib/controls/objects.rb
CHANGED
@@ -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'
|
@@ -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
|
data/lib/controls/version.rb
CHANGED
@@ -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
|