Class: Controls::Client

Inherits:
Object
  • Object
show all
Includes:
Authentication, Assessments, Assets, Configurations, Coverage, Events, Findings, Guidance, PrioritizedGuidance, SecurityControls, ThreatVectors, Threats, Trends, Configurable
Defined in:
lib/controls/client.rb,
lib/controls/client/assets.rb,
lib/controls/client/events.rb,
lib/controls/client/trends.rb,
lib/controls/client/threats.rb,
lib/controls/client/coverage.rb,
lib/controls/client/findings.rb,
lib/controls/client/guidance.rb,
lib/controls/client/assessments.rb,
lib/controls/client/configurations.rb,
lib/controls/client/threat_vectors.rb,
lib/controls/client/security_controls.rb,
lib/controls/client/prioritized_guidance.rb

Overview

A class that handles interactions with the **controls**insight API

Defined Under Namespace

Modules: Assessments, Assets, Configurations, Coverage, Events, Findings, Guidance, PrioritizedGuidance, SecurityControls, ThreatVectors, Threats, Trends

Constant Summary collapse

SSL_WARNING =

A few messages to show the user of Controls::Client in the case that a bad certificate is encountered

[
  'The API endpoint used a self-signed or invalid SSL certificate.',
  'To allow this connection temporarily use `Controls.verify_ssl = false`.',
  'See the Controls.rb wiki on GitHub for more information on SSL verification.'
]

Instance Attribute Summary

Attributes included from Configurable

#api_endpoint, #api_version, #connection_options, #default_media_type, #middleware, #netrc, #netrc_file, #password, #user_agent, #username, #web_endpoint

Instance Method Summary collapse

Methods included from Trends

#configuration_trends, #threat_trends, #threat_vector_trends

Methods included from ThreatVectors

#threat_threat_vectors, #threat_vectors

Methods included from Threats

#threats

Methods included from SecurityControls

#security_controls, #security_controls_coverage, #threat_vector_security_controls, #update_security_controls

Methods included from PrioritizedGuidance

#prioritized_guidance_by_configuration, #prioritized_guidance_by_security_control, #prioritized_guidance_by_threat, #prioritized_guidance_by_threat_vector

Methods included from Guidance

#guidance, #guidance_by_threat

Methods included from Findings

#findings_by_asset_uuid

Methods included from Events

#events

Methods included from Configurations

#security_control_configurations

Methods included from Coverage

#configuration_coverage, #security_control_coverage

Methods included from Assets

#applicable_assets, #asset_search, #assets, #misconfigured_assets, #threat_assets, #uncovered_assets, #undefended_assets

Methods included from Assessments

#assessments

Methods included from Configurable

#configure, keys, #netrc?, #setup

Methods included from Authentication

#basic_authenticated?, #login, #login_from_netrc

Constructor Details

#initialize(options = {}) ⇒ Client

Creates a new Controls::Client object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/controls/client.rb', line 49

def initialize(options = {})
  Controls::Configurable.keys.each do |key|
    value = options[key].nil? ? Controls.instance_variable_get(:"@#{key}") : options[key]
    instance_variable_set(:"@#{key}", value)
  end

  if options[:verify_ssl].nil?
    middleware.ssl[:verify] = if ENV['CONTROLS_VERIFY_SSL'].nil?
                                true
                              else
                                !(ENV['CONTROLS_VERIFY_SSL'] =~ /false/)
                              end
  else
    middleware.ssl[:verify] = !!options[:verify_ssl]
  end

   unless authenticated?

  if basic_authenticated?
    middleware.basic_auth(@username, @password)
  end
end

Instance Method Details

#api_methodsArray<Symbol>

Note:

Any methods defined in a child module will be returned.

A list of methods for API connections available to the Controls::Client



151
152
153
154
155
156
157
158
159
# File 'lib/controls/client.rb', line 151

def api_methods
  mods = Controls::Client.included_modules.map do |mod|
    if mod.to_s =~ /^Controls::Client::/
      mod
    end
  end

  mods.compact.map { |mod| mod.instance_methods(false) }.flatten.sort
end

#exception(message = "HTTP Error") ⇒ Controls::Error

Creates an error from the last request



226
227
228
229
230
231
232
233
234
235
# File 'lib/controls/client.rb', line 226

def exception(message = "HTTP Error")
  last_request = _last_request
  if last_request
    message << ": #{last_request[:response].status} #{Rack::Utils::HTTP_STATUS_CODES[last_request[:response].status]} #{last_request[:path]}"
  else
    message = 'Unknown error'
  end

  Controls::Error.new(message)
end

#get(path, params = {}, headers = {}) ⇒ Array, Hash

A wrapper for GET requests



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/controls/client.rb', line 97

def get(path, params = {}, headers = {})
  headers = connection_options[:headers].merge(headers)
  url = URI.escape(File.join(api_endpoint, path))
  resp = middleware.get(url, params, headers)
  @_last_request = {
    response: resp,
    path: path
  }

  if !resp.headers['content-type'] =~ /^application\/json/
    fail exception('Invalid content-type error')
  end

  Response.parse(resp.body, resp.status, path)
rescue Faraday::Error::ConnectionFailed => e
  if e.message =~ /^SSL_connect/
    warn(*SSL_WARNING)
  else
    raise e
  end
end

#inspectString

Censors the password from the output of #inspect



87
88
89
90
91
92
# File 'lib/controls/client.rb', line 87

def inspect
  raw = super
  raw.sub!(/(@password=")#{@password}(")/, "\\1*********\\2") if @password

  raw
end

#put(path, body = {}, headers = {}, &block) ⇒ Array, Hash

A wrapper for PUT requests



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/controls/client.rb', line 122

def put(path, body = {}, headers = {}, &block)
  headers = connection_options[:headers].merge(headers)
  headers['content-type'] = 'application/json'
  url = URI.escape(File.join(api_endpoint, path))
  resp = middleware.put(url, body, headers, &block)
  @_last_request = {
    response: resp,
    path: path
  }

  if !resp.headers['content-type'] =~ /^application\/json/
    fail exception('Invalid content-type error')
  end

  return resp.status if resp.status == 200

  Response.parse(resp.body, resp.status, path)
rescue Faraday::Error::ConnectionFailed => e
  if e.message =~ /^SSL_connect/
    warn(*SSL_WARNING)
  else
    raise e
  end
end

#references(version = '1.0') ⇒ Object

A set of references from the “documentation” API endpoint /api



164
165
166
167
168
169
170
171
172
173
# File 'lib/controls/client.rb', line 164

def references(version = '1.0')
  version = '1.0' unless version =~ /\d.\d/
  web_get "/api/#{version}"
rescue Faraday::Error::ConnectionFailed => e
  if e.message =~ /^SSL_connect/
    warn(*SSL_WARNING)
  else
    raise e
  end
end

#same_options?(opts) ⇒ Boolean

Compares Controls::Configurable#options or with the given options hash



179
180
181
# File 'lib/controls/client.rb', line 179

def same_options?(opts)
  opts.hash.eql? options.hash
end

#verify_sslObject

Whether the middleware is currently set to verify SSL connections



73
74
75
# File 'lib/controls/client.rb', line 73

def verify_ssl
  middleware.ssl[:verify].nil? || !!middleware.ssl[:verify]
end

#verify_ssl=(verify) ⇒ Object

Sets the middleware to to verify the SSL on true, or disregard it on false



80
81
82
# File 'lib/controls/client.rb', line 80

def verify_ssl=(verify)
  middleware.ssl[:verify] = !!verify
end

#web_get(path, params = {}, headers = {}) ⇒ Array, Hash

A wrapper for GET requests to the Controls endpoint root (web endpoint)



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/controls/client.rb', line 200

def web_get(path, params = {}, headers = {})
  headers = connection_options[:headers].merge(headers)
  url = URI.escape(File.join(web_endpoint, path))
  resp = middleware.get(url, params, headers)
  @_last_request = {
    response: resp,
    path: path
  }

  if !resp.headers['content-type'] =~ /^application\/json/
    fail exception('Invalid content-type error')
  end

  JSON.parse(resp.body)
rescue Faraday::Error::ConnectionFailed => e
  if e.message =~ /^SSL_connect/
    warn(*SSL_WARNING)
  else
    raise e
  end
end