secreto 0.0.6
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 +15 -0
- data/lib/secreto.rb +319 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTJmZjNkNzQyYjVkOTBiMzAxMGQzMmRmY2JkM2E1ZDhjNmRhOGE3Mg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZTk2MTAzZWYyYTkyMGUxZGJhZWI5NGQyYWU5ODRhYzE2NTU1OWRiZA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OTJmM2IxMjBkYjgxYjlkMzE4NTA1ZTIzNzQ4ZDk5OGU5NWZkMjM4NmE2Yjkx
|
10
|
+
OWZkYzE0Nzk5Njk4YTQ5OWNiMzVlYmM5ZWFjOTI5YjRkNTYwN2I4ZWEwZWY5
|
11
|
+
YjA4OTkyOTBmOTQxNzYyZDNiMGMyMTczY2MzYmUwNzJhY2NlNDI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzA2ZmZkMGFjMjZiNzhiZWZhYjg0MTI0NWQ2MDIyYTk5MTMzNGY0ZWZhOGEy
|
14
|
+
NjVkM2QyOTZkZDQzMzkyNjJlMjI2MjQwOGVmMWQ4MWZhZDM1NjM3MmE2YjA0
|
15
|
+
MDkzODg2ZmQ5NDZjYjJhNjAwMzFjMDZkYTI5ZWQwNDVlYTBiZTM=
|
data/lib/secreto.rb
ADDED
@@ -0,0 +1,319 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'crack'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
# Secreto is a ruby class to interact with Thycotic Secret Server
|
7
|
+
# == Supported Operations
|
8
|
+
# * Login
|
9
|
+
# * Retrieve a secret
|
10
|
+
# * Add a Secret
|
11
|
+
# * Add a Folder
|
12
|
+
class Secreto
|
13
|
+
|
14
|
+
# Constructor
|
15
|
+
def initialize(wsdl, ssl_verify_mode, ssl_version)
|
16
|
+
@@wsdl=wsdl
|
17
|
+
@@ssl_verify_mode=ssl_verify_mode
|
18
|
+
@@ssl_version=ssl_version
|
19
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
20
|
+
@@secretTemplates = []
|
21
|
+
end
|
22
|
+
|
23
|
+
# Authenticates with Secret Server
|
24
|
+
#
|
25
|
+
# ==== Attributes
|
26
|
+
#
|
27
|
+
# * +username+ - Username for secret Server
|
28
|
+
# * +password+ - Password
|
29
|
+
# * +domain+ - Domain Name
|
30
|
+
def Authenticate(username, password, domain)
|
31
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
32
|
+
|
33
|
+
response = client.call(:authenticate, message: {
|
34
|
+
username: username,
|
35
|
+
password: password,
|
36
|
+
organization: "",
|
37
|
+
domain: domain
|
38
|
+
})
|
39
|
+
|
40
|
+
@@token = response.to_hash[:authenticate_response][:authenticate_result][:token]
|
41
|
+
getSecretTemplates()
|
42
|
+
return @@token
|
43
|
+
end
|
44
|
+
|
45
|
+
def GetTokenIsValid #:nodoc:
|
46
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
47
|
+
response = client.call(:get_token_is_valid, message: {
|
48
|
+
token: @@token
|
49
|
+
})
|
50
|
+
|
51
|
+
return response
|
52
|
+
end
|
53
|
+
|
54
|
+
def GetSecret(secretId) #:nodoc:
|
55
|
+
thesame = lambda { |key| key }
|
56
|
+
|
57
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none) #, convert_response_tags_to: thesame)
|
58
|
+
response = client.call(:get_secret, message: {
|
59
|
+
token: @@token,
|
60
|
+
secretId: secretId,
|
61
|
+
})
|
62
|
+
doc = Nokogiri::XML.parse(response.to_xml)
|
63
|
+
items = doc.xpath('//foo:SecretItem', 'foo' => 'urn:thesecretserver.com')
|
64
|
+
node = Hash.new
|
65
|
+
node["password"] = getField(items,"Password")
|
66
|
+
node["username"] = getField(items,"Username")
|
67
|
+
node["host"] = getField(items,"Machine")
|
68
|
+
return node
|
69
|
+
end
|
70
|
+
|
71
|
+
def getField(items,field) #:nodoc:
|
72
|
+
for item in items
|
73
|
+
for child in item.children
|
74
|
+
if child.content == field
|
75
|
+
for child1 in item.children
|
76
|
+
if child1.name == "Value"
|
77
|
+
return child1.content
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def UpdateSecret(secret) #:nodoc:
|
86
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
87
|
+
# Nokogiri is stripping the 'xsi' prefix which is required, and it also puts a 'default' prefix in, which is disallowed.
|
88
|
+
fixedXml = secret.to_s.gsub! 'nil=', 'xsi:nil='
|
89
|
+
fixedXml = fixedXml.gsub! 'default:',''
|
90
|
+
|
91
|
+
response = client.call(:update_secret, xml: fixedXml)
|
92
|
+
return response
|
93
|
+
end
|
94
|
+
|
95
|
+
def WhoAmI #:nodoc:
|
96
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
97
|
+
response = client.call(:who_am_i, message: {
|
98
|
+
token: @@token
|
99
|
+
})
|
100
|
+
return response
|
101
|
+
end
|
102
|
+
|
103
|
+
def VersionGet #:nodoc:
|
104
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
105
|
+
response = client.call(:version_get, message: {
|
106
|
+
token: @@token
|
107
|
+
})
|
108
|
+
return response
|
109
|
+
end
|
110
|
+
|
111
|
+
# Retrieve the secret Details
|
112
|
+
#
|
113
|
+
# ==== Attributes
|
114
|
+
#
|
115
|
+
# * +hostName+ - Name of the Secret to search
|
116
|
+
# * +objectType+ - Object Type. For example Machine
|
117
|
+
def GetSecretByHostName(hostName,objectType)
|
118
|
+
thesame = lambda { |key| hostName }
|
119
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none)
|
120
|
+
response = client.call(:get_secrets_by_field_value, message: {
|
121
|
+
token: @@token,
|
122
|
+
fieldName: objectType,
|
123
|
+
searchTerm: hostName,
|
124
|
+
})
|
125
|
+
doc = Nokogiri::XML.parse(response.to_xml)
|
126
|
+
items = doc.xpath('//foo:Id', 'foo' => 'urn:thesecretserver.com')
|
127
|
+
if not items[0].nil?
|
128
|
+
if not items[0].content.nil?
|
129
|
+
return GetSecret(items[0].content)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Create a Folder
|
135
|
+
#
|
136
|
+
# ==== Attributes
|
137
|
+
#
|
138
|
+
# * +folderName+ - Name of the folder you want to create
|
139
|
+
# * +parentFolder+ - Parent Folder Name (Give full path /TOPLEVEL/Folder 1/Folder 2
|
140
|
+
def createFolder(folderName,parentFolder)
|
141
|
+
thesame = lambda { |key| hostName }
|
142
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none)
|
143
|
+
parentId = getFolder(parentFolder)
|
144
|
+
if parentId.nil?
|
145
|
+
print "Parent Folder " + parentFolder + " doesn't exist"
|
146
|
+
return nil
|
147
|
+
else
|
148
|
+
response = client.call(:folder_create, message: {
|
149
|
+
token: @@token,
|
150
|
+
folderName: folderName,
|
151
|
+
parentFolderId: parentId,
|
152
|
+
folderTypeId: 1
|
153
|
+
})
|
154
|
+
doc = Nokogiri::XML.parse(response.to_xml)
|
155
|
+
puts doc
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def getFolder(folderName) #:nodoc:
|
160
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none)
|
161
|
+
response = client.call(:search_folders, message: {
|
162
|
+
token: @@token,
|
163
|
+
folderName: folderName,
|
164
|
+
})
|
165
|
+
doc = Nokogiri::XML.parse(response.to_xml)
|
166
|
+
items = doc.xpath('//foo:Folder', 'foo' => 'urn:thesecretserver.com')
|
167
|
+
if items.length > 1
|
168
|
+
print "The folder " + folderName + " could not be identified uniquely " +
|
169
|
+
"Consider specifying full path like /TOPLEVEL/Level 1/Level 2/Folder Name" + "\n"
|
170
|
+
return nil
|
171
|
+
else
|
172
|
+
if not items[0].nil?
|
173
|
+
node = Hash.new
|
174
|
+
for child in items[0].children
|
175
|
+
if child.name == "Name"
|
176
|
+
node["name"] = child.content
|
177
|
+
elsif child.name == "TypeId"
|
178
|
+
node["typeId"] = child.content
|
179
|
+
elsif child.name == "Id"
|
180
|
+
node["id"] = child.content
|
181
|
+
elsif child.name == "ParentFolderId"
|
182
|
+
node["parentFolderId"] = child.content
|
183
|
+
end
|
184
|
+
end
|
185
|
+
return node["Id"]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
if folderName.include?"/"
|
189
|
+
normalizedFolderName = folderName
|
190
|
+
if folderName.start_with?("/")
|
191
|
+
normalizedFolderName = folderName.sub("/","")
|
192
|
+
end
|
193
|
+
splitted = normalizedFolderName.split("/")
|
194
|
+
$i = 0
|
195
|
+
parentId = -1
|
196
|
+
while $i < splitted.length do
|
197
|
+
parentId = getFolderId(splitted[$i],parentId)
|
198
|
+
$i+=1
|
199
|
+
end
|
200
|
+
return parentId
|
201
|
+
end
|
202
|
+
return nil
|
203
|
+
end
|
204
|
+
|
205
|
+
def getFolderId(folderName,parentFolderId) #:nodoc:
|
206
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none)
|
207
|
+
|
208
|
+
response = client.call(:folder_get_all_children, message: {
|
209
|
+
token: @@token,
|
210
|
+
parentFolderId:parentFolderId,
|
211
|
+
})
|
212
|
+
doc = Nokogiri::XML.parse(response.to_xml)
|
213
|
+
items = doc.xpath('//foo:Folder', 'foo' => 'urn:thesecretserver.com')
|
214
|
+
for item in items
|
215
|
+
node = Hash.new
|
216
|
+
for child in item.children
|
217
|
+
node[child.name] = child.content
|
218
|
+
end
|
219
|
+
if node["Name"] == folderName
|
220
|
+
return node["Id"]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
return nil
|
224
|
+
end
|
225
|
+
|
226
|
+
def getSecretTemplates() #:nodoc:
|
227
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1, convert_request_keys_to: :none)
|
228
|
+
response = client.call(:get_secret_templates, message: {
|
229
|
+
token: @@token,
|
230
|
+
})
|
231
|
+
doc = Nokogiri::XML.parse(response.to_xml)
|
232
|
+
|
233
|
+
secretTemplates = doc.xpath('//foo:SecretTemplates', 'foo' => 'urn:thesecretserver.com')
|
234
|
+
myjson = Crack::XML.parse(secretTemplates.to_xml)
|
235
|
+
@@secretTemplates = myjson["SecretTemplates"]["SecretTemplate"]
|
236
|
+
return nil
|
237
|
+
end
|
238
|
+
|
239
|
+
# Create a Secret
|
240
|
+
#
|
241
|
+
# ==== Attributes
|
242
|
+
#
|
243
|
+
# * +folderName+ - Folder Name where secret will be added (Give full path /TOPLEVEL/Folder 1/Folder 2
|
244
|
+
# * +secretType+ - Secret Type For ex Password/Active Directory Account
|
245
|
+
# * +secretName+ - Name of Secret
|
246
|
+
# * +fieldKeys+ - List of Items in secret
|
247
|
+
# * +fieldValues+ - Value of secret Items
|
248
|
+
def createSecret(folderName,secretType,secretName,fieldKeys,fieldValues)
|
249
|
+
if fieldKeys.length != fieldValues.length
|
250
|
+
print "For each key there should be a value [" + fieldKeys.join(",") + " != " + fieldValues.join(",") + "]\n"
|
251
|
+
return nil
|
252
|
+
end
|
253
|
+
templateFields = nil
|
254
|
+
templateId = nil
|
255
|
+
@@secretTemplates.each { |x|
|
256
|
+
if x['Name'] == secretType
|
257
|
+
templateFields = x['Fields']['SecretField']
|
258
|
+
templateId = x['Id']
|
259
|
+
break
|
260
|
+
end
|
261
|
+
}
|
262
|
+
if templateFields.nil?
|
263
|
+
print "secretType " + secretType + " is not available" + "\n"
|
264
|
+
return nil
|
265
|
+
else
|
266
|
+
#puts templateFields
|
267
|
+
fieldIds = []
|
268
|
+
fieldKeys.each { |fkey|
|
269
|
+
templateFields.each { |field|
|
270
|
+
if field['DisplayName'] == fkey
|
271
|
+
fieldIds.push(field['Id'])
|
272
|
+
end
|
273
|
+
}
|
274
|
+
}
|
275
|
+
if fieldIds.length != fieldKeys.length
|
276
|
+
print "Not all secretField were found [" + fieldKeys.join(",") + "]\n"
|
277
|
+
return nil
|
278
|
+
end
|
279
|
+
# All Found
|
280
|
+
end
|
281
|
+
secretFieldIds = "<ns1:secretFieldIds>"
|
282
|
+
fieldIds.each { |fid|
|
283
|
+
secretFieldIds = secretFieldIds + "<ns1:int>" + fid.to_s + "</ns1:int>"
|
284
|
+
}
|
285
|
+
secretFieldIds = secretFieldIds + "</ns1:secretFieldIds>"
|
286
|
+
|
287
|
+
secretItemValues = "<ns1:secretItemValues>"
|
288
|
+
fieldValues.each { |fval|
|
289
|
+
secretItemValues = secretItemValues + "<ns1:string>" + fval.to_s + "</ns1:string>"
|
290
|
+
}
|
291
|
+
secretItemValues = secretItemValues + "</ns1:secretItemValues>"
|
292
|
+
|
293
|
+
|
294
|
+
folderId=getFolder(folderName)
|
295
|
+
if folderId.nil?
|
296
|
+
print "Folder " + folderName + " is not found"
|
297
|
+
return nil
|
298
|
+
end
|
299
|
+
xmlString = '<?xml version="1.0" encoding="utf-8"?>' +
|
300
|
+
'<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:thesecretserver.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' +
|
301
|
+
'<SOAP-ENV:Header/>' +
|
302
|
+
' <ns0:Body>' +
|
303
|
+
' <ns1:AddSecret>' +
|
304
|
+
' <ns1:token><ns1:token>' + @@token.to_s + '</ns1:token>' +
|
305
|
+
' <ns1:secretTypeId>' + templateId + '</ns1:secretTypeId>' +
|
306
|
+
' <ns1:secretName>' + secretName + '</ns1:secretName>' +
|
307
|
+
secretFieldIds +
|
308
|
+
secretItemValues +
|
309
|
+
' <ns1:folderId>' + folderId + '</ns1:folderId>' +
|
310
|
+
' </ns1:token>' +
|
311
|
+
' </ns1:AddSecret>' +
|
312
|
+
' </ns0:Body>' +
|
313
|
+
'</SOAP-ENV:Envelope>'
|
314
|
+
|
315
|
+
client = Savon.client(wsdl: @@wsdl, ssl_verify_mode: :none, ssl_version: :TLSv1)
|
316
|
+
response = client.call(:add_secret, xml: xmlString)
|
317
|
+
puts response.to_xml
|
318
|
+
end
|
319
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: secreto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- C S P Nanda
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: savon
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: crack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.8'
|
69
|
+
description: Supported operations are create Folder, add Secret, Retrieve a secret
|
70
|
+
from Thycotic Secret Server
|
71
|
+
email: cspnanda@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- lib/secreto.rb
|
77
|
+
homepage: https://github.com/cspnanda/secreto
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.9.3
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.4.8
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Secreto is a gem to interact with Thycotic Secret Server
|
101
|
+
test_files: []
|