dsv-sdk 0.0.4 → 0.0.6.pre.dev
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/lib/dsv.rb +189 -0
- data/lib/dsv/client.rb +35 -0
- data/lib/{vault → dsv}/role.rb +4 -3
- data/lib/{vault → dsv}/secret.rb +4 -4
- metadata +56 -18
- data/lib/vault.rb +0 -7
- data/lib/vault/client.rb +0 -33
- data/lib/vault/vault.rb +0 -183
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef58849c45425870cb24105d3399712dffc14fe46cbcfc384062acddd34dbb63
|
4
|
+
data.tar.gz: 963dabfba1bad411711c8c95aab628477fafff699cb3a381ffeb38be3abeeeb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dba5aa908ff38e851778cd0664ac14e5fb568a54aaecf97a96ffbc583c04317d01450ce204c409aab763a459bfba2c906e49c2d4d48aa916364456ab0efba1e0
|
7
|
+
data.tar.gz: 1c101637a50f07ba426f197a10a9d90ba2c185305abafd4f85f1df2e530b1265aa876579ad4b5745287f882360f1c84521d5ed2af995e91b3e543afbb421af40
|
data/lib/dsv.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
##
|
6
|
+
# If we're in the +test+ environment just dump logs to Null
|
7
|
+
# Otherwise, use stdout
|
8
|
+
if ENV['test']
|
9
|
+
$logger = Logger.new(IO::NULL)
|
10
|
+
else
|
11
|
+
$logger = Logger.new(STDOUT)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Invoked when the API returns an +API_AccessDenied+ error
|
16
|
+
class AccessDeniedException < StandardError; end;
|
17
|
+
class ResourceNotFoundException < StandardError; end;
|
18
|
+
class InvalidConfigurationException < StandardError; end;
|
19
|
+
class InvalidCredentialsException < StandardError; end;
|
20
|
+
class InvalidMethodTypeException < StandardError; end;
|
21
|
+
class UnrecognizedResourceException < StandardError; end;
|
22
|
+
|
23
|
+
|
24
|
+
module Dsv
|
25
|
+
require_relative 'dsv/client'
|
26
|
+
require_relative 'dsv/secret'
|
27
|
+
require_relative 'dsv/role'
|
28
|
+
|
29
|
+
class Vault
|
30
|
+
DEFAULT_URL_TEMPLATE = "https://%s.secretsvaultcloud.%s/v1/%s%s"
|
31
|
+
DEFAULT_TLD = "com"
|
32
|
+
|
33
|
+
# Initialize a +Vault+ object with provided configuration.
|
34
|
+
#
|
35
|
+
# @param config [Hash]
|
36
|
+
# - client_id: ''
|
37
|
+
# - client_secret: ''
|
38
|
+
# - tld: 'com'
|
39
|
+
# - tenant: ''
|
40
|
+
def initialize(config = nil)
|
41
|
+
|
42
|
+
unless config.nil?
|
43
|
+
@configuration = config.collect{|k,v| [k.to_s, v]}.to_h
|
44
|
+
else
|
45
|
+
@configuration = {}
|
46
|
+
|
47
|
+
@configuration['client_id'] = ENV['DSV_CLIENT_ID']
|
48
|
+
@configuration['client_secret'] = ENV['DSV_CLIENT_SECRET']
|
49
|
+
@configuration['tenant'] = ENV['DSV_TENANT']
|
50
|
+
@configuration['tld'] = ENV['DSV_TLD']
|
51
|
+
end
|
52
|
+
|
53
|
+
if @configuration['client_id'].nil? || @configuration['client_secret'].nil?
|
54
|
+
$logger.error("Must provide client_id and client_secret")
|
55
|
+
raise InvalidConfigurationException
|
56
|
+
end
|
57
|
+
|
58
|
+
$logger.debug("Vault is configured for client_id: #{@configuration['client_id']}")
|
59
|
+
end
|
60
|
+
|
61
|
+
# Helper method to access a resource via API
|
62
|
+
#
|
63
|
+
# @param method [String] HTTP Request Method
|
64
|
+
# @param resource [String] The resource type to invoke
|
65
|
+
# @param path [String] The API Path to request
|
66
|
+
# @param input [String] Input to send via POST/PUT body
|
67
|
+
#
|
68
|
+
# @return [Hash] - return Hash of JSON contents
|
69
|
+
#
|
70
|
+
# - +AccessDeniedException+ is raised if the server responds with an +API_AccessDenied+ error
|
71
|
+
# - +InvalidMethodTypeException+ is raised if a method other than +["GET", "POST", "PUT", "DELETE"]+ is provided
|
72
|
+
# - +UnrecognizedResourceException+ is raised if a resource other than +["clients", "roles", "secrets"]+ is requested
|
73
|
+
def accessResource(method, resource, path, input, parse_json=true)
|
74
|
+
unless ["GET", "POST", "PUT", "DELETE"].include?(method.upcase)
|
75
|
+
$logger.error "Invalid request method: #{method}"
|
76
|
+
raise InvalidMethodTypeException
|
77
|
+
end
|
78
|
+
|
79
|
+
unless ["clients", "roles", "secrets"].include? resource
|
80
|
+
message = "unrecognized resource"
|
81
|
+
$logger.debug "#{message}, #{resource}"
|
82
|
+
|
83
|
+
raise UnrecognizedResourceException
|
84
|
+
end
|
85
|
+
|
86
|
+
body = ""
|
87
|
+
|
88
|
+
unless input.nil?
|
89
|
+
body = input.to_json
|
90
|
+
end
|
91
|
+
|
92
|
+
accessToken = getAccessToken
|
93
|
+
|
94
|
+
# Yikes, normally not a fan of metaprogramming
|
95
|
+
# We first ensured that `method` is legit to prevent
|
96
|
+
# arbitrary method invocation
|
97
|
+
url = urlFor(resource, path)
|
98
|
+
$logger.debug "Sending request to: #{url}"
|
99
|
+
resp = Faraday.send(method.downcase, url) do | req |
|
100
|
+
req.headers['Authorization'] = "Bearer #{accessToken}"
|
101
|
+
req.body = body unless body.empty?
|
102
|
+
|
103
|
+
if ["POST", "PUT"].include?(method.upcase)
|
104
|
+
req.headers['Content-Type'] = 'application/json'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
data = resp.body
|
109
|
+
|
110
|
+
return data unless parse_json
|
111
|
+
|
112
|
+
begin
|
113
|
+
hash = JSON.parse(data)
|
114
|
+
|
115
|
+
if hash['errorCode'] == "API_AccessDenied"
|
116
|
+
raise AccessDeniedException
|
117
|
+
end
|
118
|
+
|
119
|
+
if hash['message'] == "Invalid permissions"
|
120
|
+
raise AccessDeniedException
|
121
|
+
end
|
122
|
+
|
123
|
+
if hash['code'] == 404
|
124
|
+
raise ResourceNotFoundException
|
125
|
+
end
|
126
|
+
|
127
|
+
rescue JSON::ParserError => e
|
128
|
+
$logger.error "Error parsing JSON: #{e.to_s}"
|
129
|
+
raise e
|
130
|
+
end
|
131
|
+
|
132
|
+
return hash
|
133
|
+
end
|
134
|
+
|
135
|
+
# Query API for OAuth token
|
136
|
+
#
|
137
|
+
# - +InvalidCredentialsException+ is returned if the provided credentials are not valid
|
138
|
+
#
|
139
|
+
# @return [String]
|
140
|
+
def getAccessToken
|
141
|
+
grantRequest = {
|
142
|
+
grant_type: "client_credentials",
|
143
|
+
client_id: @configuration['client_id'],
|
144
|
+
client_secret: @configuration['client_secret']
|
145
|
+
}.to_json
|
146
|
+
|
147
|
+
url = urlFor("token")
|
148
|
+
|
149
|
+
$logger.debug "calling #{url} with client_id #{@configuration['client_id']}"
|
150
|
+
|
151
|
+
response = Faraday.post(
|
152
|
+
url,
|
153
|
+
grantRequest,
|
154
|
+
"Content-Type" => "application/json"
|
155
|
+
)
|
156
|
+
|
157
|
+
unless response.status == 200
|
158
|
+
$logger.debug "grant response error: #{response.body}"
|
159
|
+
raise InvalidCredentialsException
|
160
|
+
end
|
161
|
+
|
162
|
+
begin
|
163
|
+
grant = JSON.parse(response.body)
|
164
|
+
return grant['accessToken']
|
165
|
+
rescue JSON::ParserError => e
|
166
|
+
$logger.error "Error parsing JSON: #{e.to_s}"
|
167
|
+
raise e
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Generate the URL for a specific request.
|
172
|
+
# This factors in several configuration options including:
|
173
|
+
# - +tenant+
|
174
|
+
# - +tld+
|
175
|
+
#
|
176
|
+
# @param resource [String] The specific API resource to request
|
177
|
+
# @param path [String] The path to the resource
|
178
|
+
#
|
179
|
+
# @return [String] The generated URL for the request
|
180
|
+
def urlFor(resource, path=nil)
|
181
|
+
|
182
|
+
if path != nil
|
183
|
+
path = "/#{path.delete_prefix("/")}"
|
184
|
+
end
|
185
|
+
|
186
|
+
sprintf(DEFAULT_URL_TEMPLATE, @configuration['tenant'], @configuration['tld'] || DEFAULT_TLD, resource, path)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/lib/dsv/client.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Dsv
|
2
|
+
class Client
|
3
|
+
CLIENTS_RESOURCE = "clients".freeze
|
4
|
+
|
5
|
+
# Fetch desired client information from the specified Vault
|
6
|
+
#
|
7
|
+
# @param vault [Vault] The initialized Vault
|
8
|
+
# @param id [String] The ID of the client
|
9
|
+
#
|
10
|
+
# @return client [Hash]
|
11
|
+
def self.fetch(vault, id)
|
12
|
+
@vault = vault
|
13
|
+
client = @vault.accessResource("GET", CLIENTS_RESOURCE, id, nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Mark the client as ready to be removed
|
17
|
+
#
|
18
|
+
# @param vault [Vault] The initialized Vault
|
19
|
+
# @param id [String] The ID of the client
|
20
|
+
def self.delete(vault, id)
|
21
|
+
vault.accessResource("DELETE", CLIENTS_RESOURCE, id, nil, nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create the client for the desired Vault
|
25
|
+
#
|
26
|
+
# @param vault [Vault] The initialized Vault
|
27
|
+
# @param role_Name [String] Name of the role to create
|
28
|
+
def self.create(vault, role_name)
|
29
|
+
client_data = {
|
30
|
+
role: role_name
|
31
|
+
}
|
32
|
+
vault.accessResource("POST", CLIENTS_RESOURCE, "/", client_data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/{vault → dsv}/role.rb
RENAMED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
class
|
1
|
+
module Dsv
|
2
|
+
class Role
|
3
3
|
ROLES_RESOURCE = "roles".freeze
|
4
4
|
|
5
5
|
# Return the specified role
|
@@ -13,4 +13,5 @@ class Vault::Role
|
|
13
13
|
|
14
14
|
role = @vault.accessResource("GET", ROLES_RESOURCE, name, nil)
|
15
15
|
end
|
16
|
-
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/{vault → dsv}/secret.rb
RENAMED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Vault::Secret
|
1
|
+
module Dsv
|
2
|
+
class Secret
|
4
3
|
SECRETS_RESOURCE = "secrets".freeze
|
5
4
|
|
6
5
|
# Fetch secrets from the server
|
@@ -14,4 +13,5 @@ class Vault::Secret
|
|
14
13
|
|
15
14
|
@secret = @vault.accessResource("GET", SECRETS_RESOURCE, path, nil)
|
16
15
|
end
|
17
|
-
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,16 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dsv-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6.pre.dev
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Poulin
|
8
|
-
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
11
|
date: 2020-04-08 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: logger
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
14
55
|
- !ruby/object:Gem::Dependency
|
15
56
|
name: rspec
|
16
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -26,24 +67,21 @@ dependencies:
|
|
26
67
|
- !ruby/object:Gem::Version
|
27
68
|
version: '3.7'
|
28
69
|
description: The Thycotic DevOps Secrets Vault SDK for Ruby
|
29
|
-
email:
|
30
|
-
- john.m.poulin@gmail.com
|
31
|
-
- adam@migus.org
|
70
|
+
email: john.m.poulin@gmail.com
|
32
71
|
executables: []
|
33
72
|
extensions: []
|
34
73
|
extra_rdoc_files: []
|
35
74
|
files:
|
36
|
-
- lib/
|
37
|
-
- lib/
|
38
|
-
- lib/
|
39
|
-
- lib/
|
40
|
-
|
41
|
-
homepage: https://rubygems.org/gems/hola
|
75
|
+
- lib/dsv.rb
|
76
|
+
- lib/dsv/client.rb
|
77
|
+
- lib/dsv/role.rb
|
78
|
+
- lib/dsv/secret.rb
|
79
|
+
homepage: https://github.com/thycotic/dsv-sdk-ruby
|
42
80
|
licenses:
|
43
81
|
- Apache-2.0
|
44
82
|
metadata:
|
45
83
|
github_repo: ssh://github.com/thycotic/dsv-sdk-ruby
|
46
|
-
post_install_message:
|
84
|
+
post_install_message:
|
47
85
|
rdoc_options: []
|
48
86
|
require_paths:
|
49
87
|
- lib
|
@@ -54,12 +92,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
92
|
version: '0'
|
55
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
94
|
requirements:
|
57
|
-
- - "
|
95
|
+
- - ">"
|
58
96
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
97
|
+
version: 1.3.1
|
60
98
|
requirements: []
|
61
|
-
rubygems_version: 3.0.
|
62
|
-
signing_key:
|
99
|
+
rubygems_version: 3.0.8
|
100
|
+
signing_key:
|
63
101
|
specification_version: 4
|
64
|
-
summary:
|
102
|
+
summary: dsv_sdk
|
65
103
|
test_files: []
|
data/lib/vault.rb
DELETED
data/lib/vault/client.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
class Vault::Client
|
2
|
-
CLIENTS_RESOURCE = "clients".freeze
|
3
|
-
|
4
|
-
# Fetch desired client information from the specified Vault
|
5
|
-
#
|
6
|
-
# @param vault [Vault] The initialized Vault
|
7
|
-
# @param id [String] The ID of the client
|
8
|
-
#
|
9
|
-
# @return client [Hash]
|
10
|
-
def self.fetch(vault, id)
|
11
|
-
@vault = vault
|
12
|
-
client = @vault.accessResource("GET", CLIENTS_RESOURCE, id, nil)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Mark the client as ready to be removed
|
16
|
-
#
|
17
|
-
# @param vault [Vault] The initialized Vault
|
18
|
-
# @param id [String] The ID of the client
|
19
|
-
def self.delete(vault, id)
|
20
|
-
vault.accessResource("DELETE", CLIENTS_RESOURCE, id, nil, nil)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Create the client for the desired Vault
|
24
|
-
#
|
25
|
-
# @param vault [Vault] The initialized Vault
|
26
|
-
# @param role_Name [String] Name of the role to create
|
27
|
-
def self.create(vault, role_name)
|
28
|
-
client_data = {
|
29
|
-
role: role_name
|
30
|
-
}
|
31
|
-
vault.accessResource("POST", CLIENTS_RESOURCE, "/", client_data)
|
32
|
-
end
|
33
|
-
end
|
data/lib/vault/vault.rb
DELETED
@@ -1,183 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'faraday'
|
3
|
-
require 'logger'
|
4
|
-
|
5
|
-
##
|
6
|
-
# If we're in the +test+ environment just dump logs to Null
|
7
|
-
# Otherwise, use stdout
|
8
|
-
if ENV['test']
|
9
|
-
$logger = Logger.new(IO::NULL)
|
10
|
-
else
|
11
|
-
$logger = Logger.new(STDOUT)
|
12
|
-
end
|
13
|
-
|
14
|
-
##
|
15
|
-
# Invoked when the API returns an +API_AccessDenied+ error
|
16
|
-
class AccessDeniedException < StandardError; end;
|
17
|
-
class ResourceNotFoundException < StandardError; end;
|
18
|
-
class InvalidConfigurationException < StandardError; end;
|
19
|
-
class InvalidCredentialsException < StandardError; end;
|
20
|
-
class InvalidMethodTypeException < StandardError; end;
|
21
|
-
class UnrecognizedResourceException < StandardError; end;
|
22
|
-
|
23
|
-
class Vault
|
24
|
-
DEFAULT_URL_TEMPLATE = "https://%s.secretsvaultcloud.%s/v1/%s%s"
|
25
|
-
DEFAULT_TLD = "com"
|
26
|
-
|
27
|
-
# Initialize a +Vault+ object with provided configuration.
|
28
|
-
#
|
29
|
-
# @param config [Hash]
|
30
|
-
# - client_id: ''
|
31
|
-
# - client_secret: ''
|
32
|
-
# - tld: 'com'
|
33
|
-
# - tenant: ''
|
34
|
-
def initialize(config = nil)
|
35
|
-
|
36
|
-
if config
|
37
|
-
@configuration = config.collect{|k,v| [k.to_s, v]}.to_h
|
38
|
-
else
|
39
|
-
@configuration = {}
|
40
|
-
|
41
|
-
@configuration['client_id'] = ENV['DSV_CLIENT_ID']
|
42
|
-
@configuration['client_secret'] = ENV['DSV_CLIENT_SECRET']
|
43
|
-
@configuration['tenant'] = ENV['DSV_TENANT']
|
44
|
-
@configuration['tld'] = ENV['DSV_TLD']
|
45
|
-
end
|
46
|
-
|
47
|
-
if @configuration['client_id'].nil? || @configuration['client_secret'].nil?
|
48
|
-
$logger.error("Must provide client_id and client_secret")
|
49
|
-
raise InvalidConfigurationException
|
50
|
-
end
|
51
|
-
|
52
|
-
$logger.debug("Vault is configured for client_id: #{@configuration['client_id']}")
|
53
|
-
end
|
54
|
-
|
55
|
-
# Helper method to access a resource via API
|
56
|
-
#
|
57
|
-
# @param method [String] HTTP Request Method
|
58
|
-
# @param resource [String] The resource type to invoke
|
59
|
-
# @param path [String] The API Path to request
|
60
|
-
# @param input [String] Input to send via POST/PUT body
|
61
|
-
#
|
62
|
-
# @return [Hash] - return Hash of JSON contents
|
63
|
-
#
|
64
|
-
# - +AccessDeniedException+ is raised if the server responds with an +API_AccessDenied+ error
|
65
|
-
# - +InvalidMethodTypeException+ is raised if a method other than +["GET", "POST", "PUT", "DELETE"]+ is provided
|
66
|
-
# - +UnrecognizedResourceException+ is raised if a resource other than +["clients", "roles", "secrets"]+ is requested
|
67
|
-
def accessResource(method, resource, path, input, parse_json=true)
|
68
|
-
unless ["GET", "POST", "PUT", "DELETE"].include?(method.upcase)
|
69
|
-
$logger.error "Invalid request method: #{method}"
|
70
|
-
raise InvalidMethodTypeException
|
71
|
-
end
|
72
|
-
|
73
|
-
unless ["clients", "roles", "secrets"].include? resource
|
74
|
-
message = "unrecognized resource"
|
75
|
-
$logger.debug "#{message}, #{resource}"
|
76
|
-
|
77
|
-
raise UnrecognizedResourceException
|
78
|
-
end
|
79
|
-
|
80
|
-
body = ""
|
81
|
-
|
82
|
-
unless input.nil?
|
83
|
-
body = input.to_json
|
84
|
-
end
|
85
|
-
|
86
|
-
accessToken = getAccessToken
|
87
|
-
|
88
|
-
# Yikes, normally not a fan of metaprogramming
|
89
|
-
# We first ensured that `method` is legit to prevent
|
90
|
-
# arbitrary method invocation
|
91
|
-
url = urlFor(resource, path)
|
92
|
-
$logger.debug "Sending request to: #{url}"
|
93
|
-
resp = Faraday.send(method.downcase, url) do | req |
|
94
|
-
req.headers['Authorization'] = "Bearer #{accessToken}"
|
95
|
-
req.body = body unless body.empty?
|
96
|
-
|
97
|
-
if ["POST", "PUT"].include?(method.upcase)
|
98
|
-
req.headers['Content-Type'] = 'application/json'
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
data = resp.body
|
103
|
-
|
104
|
-
return data unless parse_json
|
105
|
-
|
106
|
-
begin
|
107
|
-
hash = JSON.parse(data)
|
108
|
-
|
109
|
-
if hash['errorCode'] == "API_AccessDenied"
|
110
|
-
raise AccessDeniedException
|
111
|
-
end
|
112
|
-
|
113
|
-
if hash['message'] == "Invalid permissions"
|
114
|
-
raise AccessDeniedException
|
115
|
-
end
|
116
|
-
|
117
|
-
if hash['code'] == 404
|
118
|
-
raise ResourceNotFoundException
|
119
|
-
end
|
120
|
-
|
121
|
-
rescue JSON::ParserError => e
|
122
|
-
$logger.error "Error parsing JSON: #{e.to_s}"
|
123
|
-
raise e
|
124
|
-
end
|
125
|
-
|
126
|
-
return hash
|
127
|
-
end
|
128
|
-
|
129
|
-
# Query API for OAuth token
|
130
|
-
#
|
131
|
-
# - +InvalidCredentialsException+ is returned if the provided credentials are not valid
|
132
|
-
#
|
133
|
-
# @return [String]
|
134
|
-
def getAccessToken
|
135
|
-
grantRequest = {
|
136
|
-
grant_type: "client_credentials",
|
137
|
-
client_id: @configuration['client_id'],
|
138
|
-
client_secret: @configuration['client_secret']
|
139
|
-
}.to_json
|
140
|
-
|
141
|
-
url = urlFor("token")
|
142
|
-
|
143
|
-
$logger.debug "calling #{url} with client_id #{@configuration['client_id']}"
|
144
|
-
|
145
|
-
response = Faraday.post(
|
146
|
-
url,
|
147
|
-
grantRequest,
|
148
|
-
"Content-Type" => "application/json"
|
149
|
-
)
|
150
|
-
|
151
|
-
unless response.status == 200
|
152
|
-
$logger.debug "grant response error: #{response.body}"
|
153
|
-
raise InvalidCredentialsException
|
154
|
-
end
|
155
|
-
|
156
|
-
begin
|
157
|
-
grant = JSON.parse(response.body)
|
158
|
-
return grant['accessToken']
|
159
|
-
rescue JSON::ParserError => e
|
160
|
-
$logger.error "Error parsing JSON: #{e.to_s}"
|
161
|
-
raise e
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Generate the URL for a specific request.
|
166
|
-
# This factors in several configuration options including:
|
167
|
-
# - +tenant+
|
168
|
-
# - +tld+
|
169
|
-
#
|
170
|
-
# @param resource [String] The specific API resource to request
|
171
|
-
# @param path [String] The path to the resource
|
172
|
-
#
|
173
|
-
# @return [String] The generated URL for the request
|
174
|
-
def urlFor(resource, path=nil)
|
175
|
-
|
176
|
-
if path != nil
|
177
|
-
path = "/#{path.delete_prefix("/")}"
|
178
|
-
end
|
179
|
-
|
180
|
-
sprintf(DEFAULT_URL_TEMPLATE, @configuration['tenant'], @configuration['tld'] || DEFAULT_TLD, resource, path)
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|