controls 1.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.md +20 -0
- data/README.md +78 -0
- data/Rakefile +3 -0
- data/controls.gemspec +30 -0
- data/docs/images/controlsinsight+shield.png +0 -0
- data/docs/images/controlsinsight.png +0 -0
- data/lib/controls.rb +42 -0
- data/lib/controls/authentication.rb +46 -0
- data/lib/controls/client.rb +151 -0
- data/lib/controls/client/assessments.rb +17 -0
- data/lib/controls/client/assets.rb +64 -0
- data/lib/controls/client/configurations.rb +31 -0
- data/lib/controls/client/guidance.rb +46 -0
- data/lib/controls/client/prioritized_guidance.rb +34 -0
- data/lib/controls/client/security_controls.rb +36 -0
- data/lib/controls/client/threat_vectors.rb +29 -0
- data/lib/controls/client/threats.rb +26 -0
- data/lib/controls/configurable.rb +83 -0
- data/lib/controls/default.rb +108 -0
- data/lib/controls/error.rb +132 -0
- data/lib/controls/response.rb +76 -0
- data/lib/controls/response/raise_error.rb +21 -0
- data/lib/controls/version.rb +4 -0
- data/spec/controls_spec.rb +22 -0
- data/spec/helper.rb +42 -0
- metadata +187 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module Controls
|
2
|
+
class Client
|
3
|
+
# A module to encapsulate API methods related to security controls and
|
4
|
+
# configurations
|
5
|
+
# @since API v1.0
|
6
|
+
# @version v1.0.0
|
7
|
+
module Configurations
|
8
|
+
# @!group Configuration Methods
|
9
|
+
|
10
|
+
# @param [String] configuration the name of the configuration to search
|
11
|
+
# for
|
12
|
+
# @return [Array<Hash>] a list of hashes representing configurations
|
13
|
+
def configurations(configuration = nil)
|
14
|
+
if configuration
|
15
|
+
get "/configurations/#{configuration}"
|
16
|
+
else
|
17
|
+
get "/configurations"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] control the security control look up configurations for
|
22
|
+
# @return [Array<Hash>] a list of hashes representing configurations
|
23
|
+
def security_control_configurations(control)
|
24
|
+
get "/security_controls/#{control}/configurations"
|
25
|
+
end
|
26
|
+
alias_method :configurations_by_security_control, :security_control_configurations
|
27
|
+
|
28
|
+
# @!endgroup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'controls/client/prioritized_guidance'
|
2
|
+
|
3
|
+
module Controls
|
4
|
+
class Client
|
5
|
+
# A module to encapsulate API methods related to guidance
|
6
|
+
# @since API v1.0
|
7
|
+
# @version v1.0.0
|
8
|
+
module Guidance
|
9
|
+
include PrioritizedGuidance
|
10
|
+
|
11
|
+
# @!group Guidance Methods
|
12
|
+
|
13
|
+
# @param [String] name the name of the guidance to search for
|
14
|
+
# @return [Hash] a hash representing the matching guidance
|
15
|
+
def guidance(name)
|
16
|
+
get "/guidance/#{name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [String] configuration the configuration name to search by
|
20
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
21
|
+
def guidance_by_configuration(security_control, configuration)
|
22
|
+
get "/configurations/#{configuration}/guidance"
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] security_control the security control name to search by
|
26
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
27
|
+
def guidance_by_security_control(security_control)
|
28
|
+
get "/security_controls/#{security_control}/guidance"
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [String] threat the threat name to search by
|
32
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
33
|
+
def guidance_by_threat(threat)
|
34
|
+
get "/threats/#{threat}/guidance"
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [String] threat_vector the threat name to search by
|
38
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
39
|
+
def guidance_by_threat_vector(threat_vector)
|
40
|
+
get "/threat_vectors/#{threat_vector}/guidance"
|
41
|
+
end
|
42
|
+
|
43
|
+
# @!endgroup
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Controls
|
2
|
+
class Client
|
3
|
+
# A module to encapsulate API methods related to guidance
|
4
|
+
# @since API v1.0
|
5
|
+
# @version v1.0.0
|
6
|
+
module PrioritizedGuidance
|
7
|
+
# @!group Prioritized Guidance Methods
|
8
|
+
|
9
|
+
# @param [String] security_control the security control name to search by
|
10
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
11
|
+
def prioritized_guidance_by_security_control(security_control)
|
12
|
+
get "/security_controls/#{security_control}/prioritized_guidance"
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [String] configuration the configuration name to search by
|
16
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
17
|
+
def prioritized_guidance_by_configuration(configuration)
|
18
|
+
get "/configurations/#{configuration}/prioritized_guidance"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] threat the threat name to search by
|
22
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
23
|
+
def prioritized_guidance_by_threat(threat)
|
24
|
+
get "/threats/#{threat}/prioritized_guidance"
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [String] threat_vector the threat name to search by
|
28
|
+
# @return [Array<Hash>] an array of "guidance hashes"
|
29
|
+
def prioritized_guidance_by_threat_vector(threat_vector)
|
30
|
+
get "/threat_vectors/#{threat_vector}/prioritized_guidance"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'controls/client/configurations'
|
2
|
+
|
3
|
+
module Controls
|
4
|
+
class Client
|
5
|
+
# A module to encapsulate API methods related to security controls and
|
6
|
+
# configurations
|
7
|
+
# @since API v1.0
|
8
|
+
# @version v1.0.0
|
9
|
+
module SecurityControls
|
10
|
+
include Configurations
|
11
|
+
|
12
|
+
#!@group Security Control Methods
|
13
|
+
|
14
|
+
# @param [String] control the name of the security control name to
|
15
|
+
# retrieve
|
16
|
+
# @return [Hash] a hash representing a security control
|
17
|
+
def security_controls(control = nil)
|
18
|
+
if control
|
19
|
+
get "/security_controls/#{control}"
|
20
|
+
else
|
21
|
+
get '/security_controls'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] vector the threat vector to search for securuty controls
|
26
|
+
# by
|
27
|
+
# @return [Array<Hash>] a list of hashes representing threats
|
28
|
+
def threat_vector_security_controls(vector)
|
29
|
+
get "/threat_vectors/#{vector}/security_controls"
|
30
|
+
end
|
31
|
+
alias_method :security_controls_by_threat_vector, :threat_vector_security_controls
|
32
|
+
|
33
|
+
# @!endgroup
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Controls
|
2
|
+
class Client
|
3
|
+
# A module to encapsulate API methods related to threats and threat vectors
|
4
|
+
# @since API v1.0
|
5
|
+
# @version v1.0.0
|
6
|
+
module ThreatVectors
|
7
|
+
# @!group Threat Vector Methods
|
8
|
+
|
9
|
+
# @param [String] vector the threat vector to search for
|
10
|
+
# @return [String] a hash representing the specified threat vector
|
11
|
+
def threat_vectors(vector = nil)
|
12
|
+
if vector
|
13
|
+
get "/threat_vectors/#{vector}"
|
14
|
+
else
|
15
|
+
get '/threat_vectors'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [String] threat the threat to search for threat vectors by
|
20
|
+
# @return [Array<Hash>] a list of hashes representing threats
|
21
|
+
def threat_threat_vectors(threat)
|
22
|
+
get "/threats/#{threat}/threat_vectors"
|
23
|
+
end
|
24
|
+
alias_method :threat_vectors_by_threat, :threat_threat_vectors
|
25
|
+
|
26
|
+
# @!endgroup
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'controls/client/threat_vectors'
|
2
|
+
|
3
|
+
module Controls
|
4
|
+
class Client
|
5
|
+
# A module to encapsulate API methods related to threats and threat vectors
|
6
|
+
# @since API v1.0
|
7
|
+
# @version v1.0.0
|
8
|
+
module Threats
|
9
|
+
include ThreatVectors
|
10
|
+
|
11
|
+
# @!group Threat Methods
|
12
|
+
|
13
|
+
# @param [String] threat the threat name to search for
|
14
|
+
# @return [String] a hash representing the specified threat
|
15
|
+
def threats(threat = nil)
|
16
|
+
if threat
|
17
|
+
get "/threats/#{threat}"
|
18
|
+
else
|
19
|
+
get '/threats'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @!endgroup
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Controls
|
2
|
+
# A module to hold configurable options to be used by other classes such as
|
3
|
+
# the {Controls} eigenclass or the {Controls::Client} class
|
4
|
+
module Configurable
|
5
|
+
# @!attribute api_endpoint
|
6
|
+
# @return [String] the endpoint to connect to. default: https://nexpose.local:3780/insight/controls/api/1.0
|
7
|
+
# @!attribute api_endpoint
|
8
|
+
# @return [String] the endpoint to connect to. default: https://nexpose.local:3780/insight/controls/api/1.0
|
9
|
+
# @!attribute connection_options
|
10
|
+
# @return [Hash] the current connection options (headers, etc.)
|
11
|
+
# @!attribute default_media_type
|
12
|
+
# @return [String] the default media type to send with requests. default: application/json
|
13
|
+
# @!attribute middleware
|
14
|
+
# @return [Faraday::Connection] the middleware used to send requests
|
15
|
+
# @!attribute netrc
|
16
|
+
# @return [Boolean] whether to use the netrc credentials to authentcicate with the **controls**insight API
|
17
|
+
# @!attribute netrc_file
|
18
|
+
# @return [String] the path of the .netrc file to look for credentials in. default: ~/.netrc
|
19
|
+
# @!attribute user_agent
|
20
|
+
# @return [String] the user agent to send with API requests. example: "controls/v1.0.0.beta (ruby; 2.0.0p247; [x86_64-darwin12.4.0]; Faraday v0.8.8)"
|
21
|
+
# @!attribute username
|
22
|
+
# @return [String] the username to use for authentication
|
23
|
+
# @!attribute web_endpoint
|
24
|
+
# @return [String] the endpoint to connect to. default: https://nexpose.local:3780/insight/controls
|
25
|
+
attr_accessor :api_endpoint, :api_version, :connection_options,
|
26
|
+
:default_media_type, :middleware, :netrc, :netrc_file,
|
27
|
+
:user_agent, :username, :web_endpoint
|
28
|
+
|
29
|
+
# @!attribute [w] password
|
30
|
+
# @return [String] the password specified on login
|
31
|
+
attr_writer :password
|
32
|
+
|
33
|
+
class << self
|
34
|
+
# @return [Array<Symbol>] a list of configurable keys
|
35
|
+
def keys
|
36
|
+
@keys ||= [
|
37
|
+
:api_endpoint,
|
38
|
+
:api_version,
|
39
|
+
:connection_options,
|
40
|
+
:default_media_type,
|
41
|
+
:middleware,
|
42
|
+
:netrc,
|
43
|
+
:netrc_file,
|
44
|
+
:password,
|
45
|
+
:user_agent,
|
46
|
+
:username,
|
47
|
+
:web_endpoint
|
48
|
+
]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @yield [self]
|
53
|
+
def configure
|
54
|
+
yield self
|
55
|
+
end
|
56
|
+
|
57
|
+
def netrc?
|
58
|
+
!!@netrc
|
59
|
+
end
|
60
|
+
|
61
|
+
# Configures {Controls::Configurable} to use options found in
|
62
|
+
# {Controls::Default}
|
63
|
+
#
|
64
|
+
# @return [self]
|
65
|
+
def setup
|
66
|
+
Controls::Configurable.keys.each do |key|
|
67
|
+
instance_variable_set(:"@#{key}", Controls::Default.options[key])
|
68
|
+
end
|
69
|
+
|
70
|
+
self
|
71
|
+
end
|
72
|
+
# NOTE: This method currently leaves some "updated defaults" intact
|
73
|
+
# alias_method :reset!, :setup
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# @return [Hash] a hash representation of the options mapping key names to
|
78
|
+
# their instance variable counterpart's value
|
79
|
+
def options
|
80
|
+
Hash[Controls::Configurable.keys.map { |key| [key, instance_variable_get(:"@#{key}")] }]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'controls/version'
|
2
|
+
|
3
|
+
module Controls
|
4
|
+
# Default options merged with environment specific overrides to satisfy the
|
5
|
+
# options specified in the {Controls::Configurable} module
|
6
|
+
module Default
|
7
|
+
# @return [String] the API version to connect to. default: 1.0
|
8
|
+
# @since API v1.0.0
|
9
|
+
API_VERSION = '1.0'.freeze
|
10
|
+
|
11
|
+
# @return [String] the API endpoint to connect to. default: https://nexpose.local:3780/insight/controls/api/1.0
|
12
|
+
# @since API v1.0.0
|
13
|
+
API_ENDPOINT = "https://localhost:3780/insight/controls/api/#{API_VERSION}".freeze
|
14
|
+
|
15
|
+
# @return [String] the default media type to send with requests. default: application/json
|
16
|
+
# @since API v1.0.0
|
17
|
+
MEDIA_TYPE = 'application/json'
|
18
|
+
|
19
|
+
# @return [String] the user agent to send with API requests. example: "controls/v1.0.0.beta (ruby; 2.0.0p247; [x86_64-darwin12.4.0]; Faraday v0.8.8)"
|
20
|
+
USER_AGENT = "controls/v#{Controls::VERSION} (#{(RUBY_DESCRIPTION.split[0..1] + [RUBY_DESCRIPTION.split.last]).join('; ')}; Faraday v#{Faraday::VERSION})".freeze
|
21
|
+
|
22
|
+
# @return [String] the web endpoint to connect to. default: https://nexpose.local:3780/insight/controls
|
23
|
+
WEB_ENDPOINT = 'https://localhost:3780/insight/controls'.freeze
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# @return [Hash] options as a Hash, mapped by keys from {Controls::Configurable}
|
27
|
+
def options
|
28
|
+
Hash[Controls::Configurable.keys.map { |key| [key, send(key)] }]
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] the API endpoint's URI as a URL
|
32
|
+
def api_endpoint
|
33
|
+
endpoint = ENV['CONTROLS_API_ENDPOINT'] || API_ENDPOINT
|
34
|
+
URI.parse(endpoint).to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String] the API version to connect to
|
38
|
+
def api_version
|
39
|
+
if ENV['CONTROLS_API_VERSION'].to_s =~ /\d+.\d+/
|
40
|
+
ENV['CONTROLS_API_VERSION']
|
41
|
+
else
|
42
|
+
API_VERSION
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Hash] the current connection options (headers, etc.)
|
47
|
+
def connection_options
|
48
|
+
{
|
49
|
+
headers: {
|
50
|
+
accept: default_media_type,
|
51
|
+
user_agent: user_agent
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [String] the environment specific default media type.
|
57
|
+
# default: {MEDIA_TYPE}
|
58
|
+
def default_media_type
|
59
|
+
ENV['CONTROLS_MEDIA_TYPE'] || MEDIA_TYPE
|
60
|
+
end
|
61
|
+
|
62
|
+
# REVIEW: Ensure that middleware is unique to the client instance
|
63
|
+
# @return [Faraday::Connection] the middleware used to send requests
|
64
|
+
def middleware
|
65
|
+
@middleware ||= Faraday.new(api_endpoint, connection_options) do |conn|
|
66
|
+
conn.adapter Faraday.default_adapter
|
67
|
+
conn.response :logger if ENV['CONTROLS_DEBUG']
|
68
|
+
conn.use Controls::Response::RaiseError
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [Boolean] whether to fallback on authentication using the
|
73
|
+
# specified netrc file
|
74
|
+
def netrc
|
75
|
+
ENV['CONTROLS_NETRC'] || false
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [String] the netrc file to use for authentication.
|
79
|
+
# default: ~/.netrc
|
80
|
+
def netrc_file
|
81
|
+
ENV['CONTROLS_NETRC_FILE'] || File.join(Dir.home, '.netrc')
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# @return [String] the password to use for authentication
|
86
|
+
def password
|
87
|
+
ENV['CONTROLS_PASSWORD']
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [String] the user agent that will be sent along any requests
|
91
|
+
# sent using {#connection_options}
|
92
|
+
def user_agent
|
93
|
+
ENV['CONTROLS_USER_AGENT'] || USER_AGENT
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [String] the username to use for authentication
|
97
|
+
def username
|
98
|
+
ENV['CONTROLS_USERNAME']
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [String] the web endpoint's URI as a URL
|
102
|
+
def web_endpoint
|
103
|
+
endpoint = ENV['CONTROLS_WEB_ENDPOINT'] || WEB_ENDPOINT
|
104
|
+
URI.parse(endpoint).to_s
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Controls
|
2
|
+
# A namespace for errors in the Controls module
|
3
|
+
class Error < StandardError
|
4
|
+
# @!attribute [r] error_message
|
5
|
+
# @return [String] the error message
|
6
|
+
# @!attribute [r] error_status
|
7
|
+
# @return [Fixnum] the error message
|
8
|
+
# @!attribute [r] error_json
|
9
|
+
# @return [Hash] the JSON body from the error message
|
10
|
+
attr_reader :error_json
|
11
|
+
attr_reader :error_message
|
12
|
+
attr_reader :error_status
|
13
|
+
|
14
|
+
# @raise [BadRequest,Unauthorized,NotFound,InternalServerError] a subclass
|
15
|
+
# of {Controls::Error}
|
16
|
+
# @return [nil] if no error was raised
|
17
|
+
def self.from_response(response)
|
18
|
+
error = case response[:status].to_i
|
19
|
+
when 302
|
20
|
+
# TODO: Nexpose/ControlsInsight returns 302 when you either visit a
|
21
|
+
# none existant path (Nexpose) or unauthenticated
|
22
|
+
# (ControlsInsight).
|
23
|
+
Found # if response[:body].empty?
|
24
|
+
when 400 then BadRequest
|
25
|
+
when 401 then Unauthorized
|
26
|
+
when 404 then NotFound
|
27
|
+
when 500 then InternalServerError
|
28
|
+
end
|
29
|
+
|
30
|
+
error.new(response) if error
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [self] generates an error and passes it to super
|
34
|
+
def initialize(response = nil)
|
35
|
+
@response = response
|
36
|
+
super(generate_error)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @return [String] an error message to be used by {#generate_error}
|
42
|
+
def response_message
|
43
|
+
return @response_message if @response_message
|
44
|
+
|
45
|
+
resp = @response[:response]
|
46
|
+
|
47
|
+
if resp.headers['content-type']
|
48
|
+
resp.headers['content-type'][/(\S+);charset=utf-8/i]
|
49
|
+
html = Regexp.last_match && Regexp.last_match[1].eql?('text/html')
|
50
|
+
end
|
51
|
+
|
52
|
+
@response_message = if html
|
53
|
+
doc = Nokogiri::XML.parse(resp.body)
|
54
|
+
|
55
|
+
if doc.css('title').text.eql? 'ControlsInsight'
|
56
|
+
message = ['message'].zip(doc.css('h1').map(&:text))
|
57
|
+
reason = ['reason'].zip([doc.css('p').map(&:text)])
|
58
|
+
Hash[message + reason]
|
59
|
+
else
|
60
|
+
Hash[doc.css('HR').children.map { |elem| elem.text.split(' ', 2) }]
|
61
|
+
end
|
62
|
+
else
|
63
|
+
if resp.body.empty?
|
64
|
+
@error_json = {}
|
65
|
+
else
|
66
|
+
@error_json = JSON.parse(resp.body)
|
67
|
+
@error_message = @error_json['message']
|
68
|
+
@error_status = @error_json['status'].to_i
|
69
|
+
|
70
|
+
@error_json
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [String] the error message passed to super on {#initialize}
|
76
|
+
def generate_error
|
77
|
+
return unless @response
|
78
|
+
|
79
|
+
message = "#{@response[:method]} ".upcase
|
80
|
+
message << "#{@response[:url].path}"
|
81
|
+
|
82
|
+
if response_message.is_a? Hash
|
83
|
+
message << ": #{response_message['message']}\n" if response_message['message']
|
84
|
+
|
85
|
+
if response_message['reason'].respond_to?(:join)
|
86
|
+
message << response_message['reason'].join("\n")
|
87
|
+
elsif response_message['reason']
|
88
|
+
message << response_message['reason'].to_s
|
89
|
+
end
|
90
|
+
elsif response_message.is_a? String
|
91
|
+
message << response_message
|
92
|
+
else
|
93
|
+
message << "#{@response[:status]} -"
|
94
|
+
message << self.class.to_s.split('::', 2).last
|
95
|
+
end
|
96
|
+
|
97
|
+
message.strip
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @!group Generic errors
|
102
|
+
|
103
|
+
# TODO REVIEW: To be raised when a user hasn't explicitly supplied credentials or set up
|
104
|
+
# any environment defaults.
|
105
|
+
Unauthenticated = Class.new(StandardError)
|
106
|
+
|
107
|
+
# @!endgroup
|
108
|
+
|
109
|
+
# @!group HTTP errors
|
110
|
+
|
111
|
+
# @return [Found] an error to be raised when a status code of 401 is
|
112
|
+
# returned by the API
|
113
|
+
Found = Class.new(Error)
|
114
|
+
|
115
|
+
# @return [Unauthorized] an error to be raised when a status code of 401 is
|
116
|
+
# returned by the API
|
117
|
+
Unauthorized = Class.new(Error)
|
118
|
+
|
119
|
+
# @return [BadRequest] an error to be raised when a status code of 400 is
|
120
|
+
# returned by the API
|
121
|
+
BadRequest = Class.new(Error)
|
122
|
+
|
123
|
+
# @return [NotFound] an error to be raised when a status code of 404 is
|
124
|
+
# returned by the API
|
125
|
+
NotFound = Class.new(Error)
|
126
|
+
|
127
|
+
# @return [InternalServerError] an error to be raised when a status code of
|
128
|
+
# 500 is returned by the API
|
129
|
+
InternalServerError = Class.new(Error)
|
130
|
+
|
131
|
+
# @!endgroup
|
132
|
+
end
|