tss-sdk 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c4ed8a314a6339abf161455030a68b95b5acdf89c6b776874b49eaa96f27c07c
4
+ data.tar.gz: 8fb041e5ead5023d94ecb87ef7707a171c9801de3b3efb1b7bfe1355f4439385
5
+ SHA512:
6
+ metadata.gz: c06b5b42b1da8a583a0e8c92475e95c574ee8ca5ac4ab88ae5f1abd71ae8bfc9cca50d333fc2b2ee6d01cc6f1f802ec9a6f966880f246d8a0a6d8297d0be857b
7
+ data.tar.gz: 0be9bab6d50434b47a9c5fe1c182bb93bb2ceba248275c698d25f06cba14072d0efba5225ca2ba5b280e7e6ec81da1799711b27427f72b479503638d251ea37a
data/lib/server.rb ADDED
@@ -0,0 +1,4 @@
1
+ class Server
2
+ require 'server/server'
3
+ require 'server/secret'
4
+ end
@@ -0,0 +1,38 @@
1
+
2
+ class InvalidSecretException < StandardError; end;
3
+
4
+ # Utilized to fetch secrets from an initialzed +Server+
5
+ class Server::Secret
6
+ SECRETS_RESOURCE = "secrets".freeze
7
+
8
+ # Fetch secrets from the server
9
+ #
10
+ # @param server [Server]
11
+ #
12
+ # @return [Hash] of the secret and associated file contents
13
+ def self.fetch(server, id)
14
+ @server = server
15
+
16
+ begin
17
+ @secret = @server.accessResource("GET", SECRETS_RESOURCE, id.to_s)
18
+ rescue Exception => e
19
+ $logger.error "Error accessing resource: #{e.to_s}"
20
+ raise InvalidSecretException
21
+ end
22
+
23
+ raise InvalidSecretException if @secret.nil?
24
+
25
+ # automatically download file attachments and substitute them for the
26
+ @secret['items'].each do |item|
27
+ next if item['fileAttachmentId'].nil?
28
+
29
+ path = sprintf("%d/fields/%s", id, item['slug'])
30
+
31
+ item_data = @server.accessResource("GET", SECRETS_RESOURCE, path, false)
32
+
33
+ item['itemValue'] = item_data
34
+ end
35
+
36
+ return @secret
37
+ end
38
+ end
@@ -0,0 +1,184 @@
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
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tss-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John Poulin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.7'
27
+ description: The Thycotic TSS SDK for Ruby
28
+ email: john.m.poulin@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/server.rb
34
+ - lib/server/secret.rb
35
+ - lib/server/server.rb
36
+ homepage: https://rubygems.org/gems/hola
37
+ licenses:
38
+ - Apache-2.0
39
+ metadata: {}
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.0.3
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: tss-sdk
59
+ test_files: []