tss-sdk 0.0.0 → 0.0.1
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/tss.rb +187 -0
- data/lib/{server → tss}/secret.rb +5 -3
- metadata +50 -9
- data/lib/server.rb +0 -4
- data/lib/server/server.rb +0 -184
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 721d5d13bfe6b37ede36b89c4dc99a06b72142b5f582d120b548e64811f50a94
|
4
|
+
data.tar.gz: 00dc1ba6c06debd7de0858f3ef06fcdb8465cdd179d83d7ce5d4ebc2b8ec3af0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fdbd1fb0238c49c9d3811a85007b49f55cf8e260c1afaff960c902e33d5fbb0a506d9673159705ff7f4464bc73f08e2b9129e7bf6981a47e6c71ea5ef86a969
|
7
|
+
data.tar.gz: 9af2db55bf30fd0b4e3edfd503c8a75065d5bb11678a325d2f3878b5c7abe0126a277a2ac6e67f9887fadeb8ae93163c56d5344d60701f1b898b718d5111b8f5
|
data/lib/tss.rb
ADDED
@@ -0,0 +1,187 @@
|
|
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
|
+
|
18
|
+
class InvalidConfigurationException < StandardError; end;
|
19
|
+
class InvalidCredentialsException < StandardError; end;
|
20
|
+
class InvalidMethodTypeException < StandardError; end;
|
21
|
+
class UnrecognizedResourceException < StandardError; end;
|
22
|
+
|
23
|
+
module Tss
|
24
|
+
require_relative 'tss/secret'
|
25
|
+
|
26
|
+
class Server
|
27
|
+
DEFAULT_URL_TEMPLATE = "https://%s.secretservercloud.%s/"
|
28
|
+
DEFAULT_TLD = "com"
|
29
|
+
DEFAULT_API_PATH_URI = "/api/v1"
|
30
|
+
DEFAULT_TOKEN_PATH_URI = "/oauth2/token"
|
31
|
+
|
32
|
+
# Initialize a +Server+ object with provided configuration.
|
33
|
+
#
|
34
|
+
# @param config [Hash]
|
35
|
+
# - username: ''
|
36
|
+
# - password: ''
|
37
|
+
# - tld: 'com'
|
38
|
+
# - api_path_uri: '/api/v1'
|
39
|
+
# - token_path_uri: '/oauth2/token'
|
40
|
+
# - tenant: ''
|
41
|
+
# - server_url: ''
|
42
|
+
def initialize(config)
|
43
|
+
@configuration = config.collect{|k,v| [k.to_s, v]}.to_h
|
44
|
+
if @configuration['server_url'] == "" && @configuration['tenant'] == ""
|
45
|
+
$logger.error("Either ServerURL or Tenant must be set")
|
46
|
+
raise InvalidConfigurationException
|
47
|
+
end
|
48
|
+
|
49
|
+
if @configuration['username'].nil? || @configuration['password'].nil?
|
50
|
+
$logger.error("Must provide username and password")
|
51
|
+
raise InvalidConfigurationException
|
52
|
+
end
|
53
|
+
|
54
|
+
if @configuration['tld'].nil?
|
55
|
+
@configuration['tld'] = DEFAULT_TLD
|
56
|
+
end
|
57
|
+
|
58
|
+
if @configuration['api_path_uri'].nil?
|
59
|
+
@configuration['api_path_uri'] = DEFAULT_API_PATH_URI
|
60
|
+
end
|
61
|
+
@configuration['api_path_uri'].delete_suffix!("/")
|
62
|
+
|
63
|
+
if @configuration['token_path_uri'].nil?
|
64
|
+
@configuration['token_path_uri'] = DEFAULT_TOKEN_PATH_URI
|
65
|
+
end
|
66
|
+
@configuration['token_path_uri'].delete_suffix!("/")
|
67
|
+
end
|
68
|
+
|
69
|
+
# Helper method to access a resource via API
|
70
|
+
#
|
71
|
+
# @param method [String] HTTP Request Method
|
72
|
+
# @param resource [String] The resource type to invoke
|
73
|
+
# @param path [String] The API Path to request
|
74
|
+
# @param parse_json [Boolean] Determine whether we want to return a hash, or raw output
|
75
|
+
#
|
76
|
+
# @return [Hash] - If +parse_json+, return Hash of JSON contents
|
77
|
+
# @return [String] - Otherwise, return raw HTTP Response Body
|
78
|
+
#
|
79
|
+
# - +AccessDeniedException+ is raised if the server responds with an +API_AccessDenied+ error
|
80
|
+
# - +InvalidMethodTypeException+ is raised if a method other than +["GET", "POST", "PUT", "DELETE"]+ is provided
|
81
|
+
# - +UnrecognizedResourceException+ is raised if a resource other than +["secrets"]+ is requested
|
82
|
+
def accessResource(method, resource, path, parse_json = true)
|
83
|
+
unless ["GET", "POST", "PUT", "DELETE"].include?(method.upcase)
|
84
|
+
$logger.error "Invalid request method: #{method}"
|
85
|
+
raise InvalidMethodTypeException
|
86
|
+
end
|
87
|
+
|
88
|
+
unless ["secrets"].include? resource
|
89
|
+
$logger.debug "unrecognized resource: #{resource}"
|
90
|
+
raise UnrecognizedResourceException
|
91
|
+
end
|
92
|
+
|
93
|
+
accessToken = getAccessToken
|
94
|
+
|
95
|
+
url = urlFor(resource, path)
|
96
|
+
$logger.debug "Sending request to: #{url}"
|
97
|
+
resp = Faraday.send(method.downcase, url) do | req |
|
98
|
+
req.headers['Authorization'] = "Bearer #{accessToken}"
|
99
|
+
|
100
|
+
if ["POST", "PUT"].include?(method.upcase)
|
101
|
+
req.headers['Content-Type'] = 'application/json'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
data = resp.body
|
106
|
+
|
107
|
+
return data unless parse_json
|
108
|
+
|
109
|
+
begin
|
110
|
+
hash = JSON.parse(data)
|
111
|
+
|
112
|
+
if hash['errorCode'] == "API_AccessDenied"
|
113
|
+
raise AccessDeniedException
|
114
|
+
end
|
115
|
+
rescue JSON::ParserError => e
|
116
|
+
$logger.error "Error parsing JSON: #{e.to_s}"
|
117
|
+
raise e
|
118
|
+
end
|
119
|
+
|
120
|
+
return hash
|
121
|
+
end
|
122
|
+
|
123
|
+
# Query API for OAuth token
|
124
|
+
#
|
125
|
+
# - +InvalidCredentialsException+ is returned if the provided credentials are not valid
|
126
|
+
#
|
127
|
+
# @return [String]
|
128
|
+
def getAccessToken
|
129
|
+
grantRequest = {
|
130
|
+
grant_type: 'password',
|
131
|
+
username: @configuration['username'],
|
132
|
+
password: @configuration['password']
|
133
|
+
}
|
134
|
+
|
135
|
+
url = urlFor("token")
|
136
|
+
|
137
|
+
response = Faraday.post(
|
138
|
+
url,
|
139
|
+
grantRequest
|
140
|
+
)
|
141
|
+
|
142
|
+
unless response.status == 200
|
143
|
+
$logger.error "Unable to retrive credentials for username: #{@configuration['username']}"
|
144
|
+
$logger.error "\t #{response.body}"
|
145
|
+
raise InvalidCredentialsException
|
146
|
+
end
|
147
|
+
|
148
|
+
begin
|
149
|
+
grant = JSON.parse(response.body)
|
150
|
+
return grant['access_token']
|
151
|
+
rescue JSON::ParserError => e
|
152
|
+
$logger.error "Error parsing JSON: #{e.to_s}"
|
153
|
+
raise e
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Generate the URL for a specific request.
|
158
|
+
# This factors in several configuration options including:
|
159
|
+
# - +tenant+
|
160
|
+
# - +server_url+
|
161
|
+
# - +token_path_uri+
|
162
|
+
# - +api_path_uri+
|
163
|
+
#
|
164
|
+
# @param resource [String] The specific API resource to request
|
165
|
+
# @param path [String] The path to the resource
|
166
|
+
#
|
167
|
+
# @return [String] The generated URL for the request
|
168
|
+
def urlFor(resource, path=nil)
|
169
|
+
|
170
|
+
if @configuration['server_url'].nil? || @configuration['server_url'] == ""
|
171
|
+
baseURL = sprintf(DEFAULT_URL_TEMPLATE, @configuration['tenant'], @configuration['tld']).delete_suffix("/")
|
172
|
+
else
|
173
|
+
baseURL = @configuration['server_url'].delete_suffix("/")
|
174
|
+
end
|
175
|
+
|
176
|
+
if resource == "token"
|
177
|
+
return sprintf("%s/%s", baseURL, @configuration['token_path_uri'].delete_prefix("/"))
|
178
|
+
end
|
179
|
+
|
180
|
+
if path != "/"
|
181
|
+
path = path.delete_prefix("/")
|
182
|
+
end
|
183
|
+
|
184
|
+
sprintf("%s/%s/%s/%s", baseURL, @configuration['api_path_uri'].delete_prefix("/"), resource.delete_suffix("/").delete_prefix("/"), path)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
|
2
2
|
class InvalidSecretException < StandardError; end;
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Tss
|
5
|
+
# Utilized to fetch secrets from an initialzed +Server+
|
6
|
+
class Secret
|
6
7
|
SECRETS_RESOURCE = "secrets".freeze
|
7
8
|
|
8
9
|
# Fetch secrets from the server
|
@@ -35,4 +36,5 @@ class Server::Secret
|
|
35
36
|
|
36
37
|
return @secret
|
37
38
|
end
|
38
|
-
end
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tss-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Poulin
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2020-04-08 00:00:00.000000000 Z
|
12
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'
|
13
55
|
- !ruby/object:Gem::Dependency
|
14
56
|
name: rspec
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -30,14 +72,13 @@ executables: []
|
|
30
72
|
extensions: []
|
31
73
|
extra_rdoc_files: []
|
32
74
|
files:
|
33
|
-
- lib/
|
34
|
-
- lib/
|
35
|
-
|
36
|
-
homepage: https://rubygems.org/gems/hola
|
75
|
+
- lib/tss.rb
|
76
|
+
- lib/tss/secret.rb
|
77
|
+
homepage: https://github.com/thycotic/tss-sdk-ruby
|
37
78
|
licenses:
|
38
79
|
- Apache-2.0
|
39
80
|
metadata: {}
|
40
|
-
post_install_message:
|
81
|
+
post_install_message:
|
41
82
|
rdoc_options: []
|
42
83
|
require_paths:
|
43
84
|
- lib
|
@@ -52,8 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
93
|
- !ruby/object:Gem::Version
|
53
94
|
version: '0'
|
54
95
|
requirements: []
|
55
|
-
rubygems_version: 3.0.
|
56
|
-
signing_key:
|
96
|
+
rubygems_version: 3.0.8
|
97
|
+
signing_key:
|
57
98
|
specification_version: 4
|
58
99
|
summary: tss-sdk
|
59
100
|
test_files: []
|
data/lib/server.rb
DELETED
data/lib/server/server.rb
DELETED
@@ -1,184 +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
|
-
|
18
|
-
class InvalidConfigurationException < StandardError; end;
|
19
|
-
class InvalidCredentialsException < StandardError; end;
|
20
|
-
class InvalidMethodTypeException < StandardError; end;
|
21
|
-
class UnrecognizedResourceException < StandardError; end;
|
22
|
-
|
23
|
-
class Server
|
24
|
-
DEFAULT_URL_TEMPLATE = "https://%s.secretservercloud.%s/"
|
25
|
-
DEFAULT_TLD = "com"
|
26
|
-
DEFAULT_API_PATH_URI = "/api/v1"
|
27
|
-
DEFAULT_TOKEN_PATH_URI = "/oauth2/token"
|
28
|
-
|
29
|
-
# Initialize a +Server+ object with provided configuration.
|
30
|
-
#
|
31
|
-
# @param config [Hash]
|
32
|
-
# - username: ''
|
33
|
-
# - password: ''
|
34
|
-
# - tld: 'com'
|
35
|
-
# - api_path_uri: '/api/v1'
|
36
|
-
# - token_path_uri: '/oauth2/token'
|
37
|
-
# - tenant: ''
|
38
|
-
# - server_url: ''
|
39
|
-
def initialize(config)
|
40
|
-
@configuration = config.collect{|k,v| [k.to_s, v]}.to_h
|
41
|
-
if @configuration['server_url'] == "" && @configuration['tenant'] == ""
|
42
|
-
$logger.error("Either ServerURL or Tenant must be set")
|
43
|
-
raise InvalidConfigurationException
|
44
|
-
end
|
45
|
-
|
46
|
-
if @configuration['username'].nil? || @configuration['password'].nil?
|
47
|
-
$logger.error("Must provide username and password")
|
48
|
-
raise InvalidConfigurationException
|
49
|
-
end
|
50
|
-
|
51
|
-
if @configuration['tld'].nil?
|
52
|
-
@configuration['tld'] = DEFAULT_TLD
|
53
|
-
end
|
54
|
-
|
55
|
-
if @configuration['api_path_uri'].nil?
|
56
|
-
@configuration['api_path_uri'] = DEFAULT_API_PATH_URI
|
57
|
-
end
|
58
|
-
@configuration['api_path_uri'].delete_suffix!("/")
|
59
|
-
|
60
|
-
if @configuration['token_path_uri'].nil?
|
61
|
-
@configuration['token_path_uri'] = DEFAULT_TOKEN_PATH_URI
|
62
|
-
end
|
63
|
-
@configuration['token_path_uri'].delete_suffix!("/")
|
64
|
-
end
|
65
|
-
|
66
|
-
# Helper method to access a resource via API
|
67
|
-
#
|
68
|
-
# @param method [String] HTTP Request Method
|
69
|
-
# @param resource [String] The resource type to invoke
|
70
|
-
# @param path [String] The API Path to request
|
71
|
-
# @param parse_json [Boolean] Determine whether we want to return a hash, or raw output
|
72
|
-
#
|
73
|
-
# @return [Hash] - If +parse_json+, return Hash of JSON contents
|
74
|
-
# @return [String] - Otherwise, return raw HTTP Response Body
|
75
|
-
#
|
76
|
-
# - +AccessDeniedException+ is raised if the server responds with an +API_AccessDenied+ error
|
77
|
-
# - +InvalidMethodTypeException+ is raised if a method other than +["GET", "POST", "PUT", "DELETE"]+ is provided
|
78
|
-
# - +UnrecognizedResourceException+ is raised if a resource other than +["secrets"]+ is requested
|
79
|
-
def accessResource(method, resource, path, parse_json = true)
|
80
|
-
unless ["GET", "POST", "PUT", "DELETE"].include?(method.upcase)
|
81
|
-
$logger.error "Invalid request method: #{method}"
|
82
|
-
raise InvalidMethodTypeException
|
83
|
-
end
|
84
|
-
|
85
|
-
unless ["secrets"].include? resource
|
86
|
-
$logger.debug "unrecognized resource: #{resource}"
|
87
|
-
raise UnrecognizedResourceException
|
88
|
-
end
|
89
|
-
|
90
|
-
accessToken = getAccessToken
|
91
|
-
|
92
|
-
url = urlFor(resource, path)
|
93
|
-
$logger.debug "Sending request to: #{url}"
|
94
|
-
resp = Faraday.send(method.downcase, url) do | req |
|
95
|
-
req.headers['Authorization'] = "Bearer #{accessToken}"
|
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
|
-
rescue JSON::ParserError => e
|
113
|
-
$logger.error "Error parsing JSON: #{e.to_s}"
|
114
|
-
raise e
|
115
|
-
end
|
116
|
-
|
117
|
-
return hash
|
118
|
-
end
|
119
|
-
|
120
|
-
# Query API for OAuth token
|
121
|
-
#
|
122
|
-
# - +InvalidCredentialsException+ is returned if the provided credentials are not valid
|
123
|
-
#
|
124
|
-
# @return [String]
|
125
|
-
def getAccessToken
|
126
|
-
grantRequest = {
|
127
|
-
grant_type: 'password',
|
128
|
-
username: @configuration['username'],
|
129
|
-
password: @configuration['password']
|
130
|
-
}
|
131
|
-
|
132
|
-
url = urlFor("token")
|
133
|
-
|
134
|
-
response = Faraday.post(
|
135
|
-
url,
|
136
|
-
grantRequest
|
137
|
-
)
|
138
|
-
|
139
|
-
unless response.status == 200
|
140
|
-
$logger.error "Unable to retrive credentials for username: #{@configuration['username']}"
|
141
|
-
$logger.error "\t #{response.body}"
|
142
|
-
raise InvalidCredentialsException
|
143
|
-
end
|
144
|
-
|
145
|
-
begin
|
146
|
-
grant = JSON.parse(response.body)
|
147
|
-
return grant['access_token']
|
148
|
-
rescue JSON::ParserError => e
|
149
|
-
$logger.error "Error parsing JSON: #{e.to_s}"
|
150
|
-
raise e
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# Generate the URL for a specific request.
|
155
|
-
# This factors in several configuration options including:
|
156
|
-
# - +tenant+
|
157
|
-
# - +server_url+
|
158
|
-
# - +token_path_uri+
|
159
|
-
# - +api_path_uri+
|
160
|
-
#
|
161
|
-
# @param resource [String] The specific API resource to request
|
162
|
-
# @param path [String] The path to the resource
|
163
|
-
#
|
164
|
-
# @return [String] The generated URL for the request
|
165
|
-
def urlFor(resource, path=nil)
|
166
|
-
|
167
|
-
if @configuration['server_url'].nil? || @configuration['server_url'] == ""
|
168
|
-
baseURL = sprintf(DEFAULT_URL_TEMPLATE, @configuration['tenant'], @configuration['tld']).delete_suffix("/")
|
169
|
-
else
|
170
|
-
baseURL = @configuration['server_url'].delete_suffix("/")
|
171
|
-
end
|
172
|
-
|
173
|
-
if resource == "token"
|
174
|
-
return sprintf("%s/%s", baseURL, @configuration['token_path_uri'].delete_prefix("/"))
|
175
|
-
end
|
176
|
-
|
177
|
-
if path != "/"
|
178
|
-
path = path.delete_prefix("/")
|
179
|
-
end
|
180
|
-
|
181
|
-
sprintf("%s/%s/%s/%s", baseURL, @configuration['api_path_uri'].delete_prefix("/"), resource.delete_suffix("/").delete_prefix("/"), path)
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|