tss-sdk 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []