opennebula-oca 3.9.0.beta → 3.9.90.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README +1 -0
  2. metadata +35 -108
  3. data/LICENSE +0 -202
  4. data/NOTICE +0 -48
  5. data/lib/opennebula/acl.rb +0 -259
  6. data/lib/opennebula/acl_pool.rb +0 -53
  7. data/lib/opennebula/client.rb +0 -102
  8. data/lib/opennebula/cluster.rb +0 -247
  9. data/lib/opennebula/cluster_pool.rb +0 -56
  10. data/lib/opennebula/datastore.rb +0 -169
  11. data/lib/opennebula/datastore_pool.rb +0 -53
  12. data/lib/opennebula/document.rb +0 -259
  13. data/lib/opennebula/document_json.rb +0 -129
  14. data/lib/opennebula/document_pool.rb +0 -97
  15. data/lib/opennebula/document_pool_json.rb +0 -58
  16. data/lib/opennebula/error.rb +0 -52
  17. data/lib/opennebula/group.rb +0 -161
  18. data/lib/opennebula/group_pool.rb +0 -54
  19. data/lib/opennebula/host.rb +0 -199
  20. data/lib/opennebula/host_pool.rb +0 -91
  21. data/lib/opennebula/image.rb +0 -293
  22. data/lib/opennebula/image_pool.rb +0 -74
  23. data/lib/opennebula/ldap_auth.rb +0 -99
  24. data/lib/opennebula/ldap_auth_spec.rb +0 -70
  25. data/lib/opennebula/pool.rb +0 -157
  26. data/lib/opennebula/pool_element.rb +0 -269
  27. data/lib/opennebula/server_cipher_auth.rb +0 -148
  28. data/lib/opennebula/server_x509_auth.rb +0 -104
  29. data/lib/opennebula/ssh_auth.rb +0 -139
  30. data/lib/opennebula/system.rb +0 -141
  31. data/lib/opennebula/template.rb +0 -201
  32. data/lib/opennebula/template_pool.rb +0 -74
  33. data/lib/opennebula/user.rb +0 -172
  34. data/lib/opennebula/user_pool.rb +0 -53
  35. data/lib/opennebula/virtual_machine.rb +0 -426
  36. data/lib/opennebula/virtual_machine_pool.rb +0 -318
  37. data/lib/opennebula/virtual_network.rb +0 -247
  38. data/lib/opennebula/virtual_network_pool.rb +0 -74
  39. data/lib/opennebula/x509_auth.rb +0 -241
  40. data/lib/opennebula/xml_element.rb +0 -427
  41. data/lib/opennebula/xml_pool.rb +0 -45
  42. data/lib/opennebula/xml_utils.rb +0 -34
  43. data/lib/opennebula.rb +0 -58
@@ -1,241 +0,0 @@
1
- # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
3
- # #
4
- # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
- # not use this file except in compliance with the License. You may obtain #
6
- # a copy of the License at #
7
- # #
8
- # http://www.apache.org/licenses/LICENSE-2.0 #
9
- # #
10
- # Unless required by applicable law or agreed to in writing, software #
11
- # distributed under the License is distributed on an "AS IS" BASIS, #
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
- # See the License for the specific language governing permissions and #
14
- # limitations under the License. #
15
- #--------------------------------------------------------------------------- #
16
-
17
- require 'openssl'
18
- require 'base64'
19
- require 'fileutils'
20
- require 'yaml'
21
-
22
- module OpenNebula; end
23
-
24
- # X509 authentication class. It can be used as a driver for auth_mad
25
- # as auth method is defined. It also holds some helper methods to be used
26
- # by oneauth command
27
- class OpenNebula::X509Auth
28
- ###########################################################################
29
- #Constants with paths to relevant files and defaults
30
- ###########################################################################
31
- if !ENV["ONE_LOCATION"]
32
- ETC_LOCATION = "/etc/one"
33
- else
34
- ETC_LOCATION = ENV["ONE_LOCATION"] + "/etc"
35
- end
36
-
37
- LOGIN_PATH = ENV['HOME']+'/.one/one_x509'
38
-
39
- X509_AUTH_CONF_PATH = ETC_LOCATION + "/auth/x509_auth.conf"
40
-
41
- X509_DEFAULTS = {
42
- :ca_dir => ETC_LOCATION + "/auth/certificates"
43
- }
44
-
45
- ###########################################################################
46
- # Initialize x509Auth object
47
- #
48
- # @param [Hash] default options for path
49
- # @option options [String] :certs_pem
50
- # cert chain array in colon-separated pem format
51
- # @option options [String] :key_pem
52
- # key in pem format
53
- # @option options [String] :ca_dir
54
- # directory of trusted CA's. Needed for auth method, not for login.
55
- def initialize(options={})
56
- @options ||= X509_DEFAULTS
57
- @options.merge!(options)
58
-
59
- load_options(X509_AUTH_CONF_PATH)
60
-
61
- @cert_chain = @options[:certs_pem].collect do |cert_pem|
62
- OpenSSL::X509::Certificate.new(cert_pem)
63
- end
64
-
65
- if @options[:key_pem]
66
- @key = OpenSSL::PKey::RSA.new(@options[:key_pem])
67
- end
68
- end
69
-
70
- ###########################################################################
71
- # Client side
72
- ###########################################################################
73
-
74
- # Creates the login file for x509 authentication at ~/.one/one_x509.
75
- # By default it is valid as long as the certificate is valid. It can
76
- # be changed to any number of seconds with expire parameter (sec.)
77
- def login(user, expire=0)
78
- write_login(login_token(user,expire))
79
- end
80
-
81
- # Returns a valid password string to create a user using this auth driver.
82
- # In this case the dn of the user certificate.
83
- def password
84
- @cert_chain[0].subject.to_s.delete("\s")
85
- end
86
-
87
- # Generates a login token in the form:
88
- # user_name:x509:user_name:time_expires:cert_chain
89
- # - user_name:time_expires is encrypted with the user certificate
90
- # - user_name:time_expires:cert_chain is base64 encoded
91
- def login_token(user, expire)
92
- if expire != 0
93
- expires = Time.now.to_i + expire.to_i
94
- else
95
- expires = @cert_chain[0].not_after.to_i
96
- end
97
-
98
- text_to_sign = "#{user}:#{expires}"
99
- signed_text = encrypt(text_to_sign)
100
-
101
- certs_pem = @cert_chain.collect{|cert| cert.to_pem}.join(":")
102
-
103
- token = "#{signed_text}:#{certs_pem}"
104
- token64 = Base64::encode64(token).strip.delete("\n")
105
-
106
- login_out = "#{user}:#{token64}"
107
-
108
- login_out
109
- end
110
-
111
- ###########################################################################
112
- # Server side
113
- ###########################################################################
114
- # auth method for auth_mad
115
- def authenticate(user, pass, signed_text)
116
- begin
117
- # Decryption demonstrates that the user posessed the private key.
118
- _user, expires = decrypt(signed_text).split(':')
119
-
120
- return "User name missmatch" if user != _user
121
-
122
- return "x509 proxy expired" if Time.now.to_i >= expires.to_i
123
-
124
- # Some DN in the chain must match a DN in the password
125
- dn_ok = @cert_chain.each do |cert|
126
- if pass.split('|').include?(cert.subject.to_s.delete("\s"))
127
- break true
128
- end
129
- end
130
-
131
- unless dn_ok == true
132
- return "Certificate subject missmatch"
133
- end
134
-
135
- validate
136
-
137
- return true
138
- rescue => e
139
- return e.message
140
- end
141
- end
142
-
143
- private
144
- # Writes a login_txt to the login file as defined in LOGIN_PATH
145
- # constant
146
- def write_login(login_txt)
147
- # Inits login file path and creates ~/.one directory if needed
148
- # Set instance variables
149
- login_dir = File.dirname(LOGIN_PATH)
150
-
151
- begin
152
- FileUtils.mkdir_p(login_dir)
153
- rescue Errno::EEXIST
154
- end
155
-
156
- file = File.open(LOGIN_PATH, "w")
157
- file.write(login_txt)
158
- file.close
159
-
160
- File.chmod(0600,LOGIN_PATH)
161
- end
162
-
163
- # Load class options form a configuration file (yaml syntax)
164
- def load_options(conf_file)
165
- if File.readable?(conf_file)
166
- conf_txt = File.read(conf_file)
167
- conf_opt = YAML::load(conf_txt)
168
-
169
- @options.merge!(conf_opt) if conf_opt != false
170
- end
171
- end
172
-
173
- ###########################################################################
174
- # Methods to encrpyt/decrypt keys
175
- ###########################################################################
176
- # Encrypts data with the private key of the user and returns
177
- # base 64 encoded output in a single line
178
- def encrypt(data)
179
- return nil if !@key
180
- Base64::encode64(@key.private_encrypt(data)).delete("\n").strip
181
- end
182
-
183
- # Decrypts base 64 encoded data with pub_key (public key)
184
- def decrypt(data)
185
- @cert_chain[0].public_key.public_decrypt(Base64::decode64(data))
186
- end
187
-
188
- ###########################################################################
189
- # Validate the user certificate
190
- ###########################################################################
191
- def validate
192
- now = Time.now
193
- failed = "Could not validate user credentials: "
194
-
195
- # Check start time and end time of certificates
196
- @cert_chain.each do |cert|
197
- if cert.not_before > now || cert.not_after < now
198
- raise failed + "Certificate not valid. Current time is " +
199
- now.localtime.to_s + "."
200
- end
201
- end
202
-
203
- begin
204
- # Validate the proxy certifcates
205
- signee = @cert_chain[0]
206
-
207
- @cert_chain[1..-1].each do |cert|
208
- if !((signee.issuer.to_s == cert.subject.to_s) &&
209
- (signee.verify(cert.public_key)))
210
- raise failed + signee.subject.to_s + " with issuer " +
211
- signee.issuer.to_s + " was not verified by " +
212
- cert.subject.to_s + "."
213
- end
214
- signee = cert
215
- end
216
-
217
- # Validate the End Entity certificate
218
- if !@options[:ca_dir]
219
- raise failed + "No certifcate authority directory was specified."
220
- end
221
-
222
- begin
223
- ca_hash = signee.issuer.hash.to_s(16)
224
- ca_path = @options[:ca_dir] + '/' + ca_hash + '.0'
225
-
226
- ca_cert = OpenSSL::X509::Certificate.new(File.read(ca_path))
227
-
228
- if !((signee.issuer.to_s == ca_cert.subject.to_s) &&
229
- (signee.verify(ca_cert.public_key)))
230
- raise failed + signee.subject.to_s + " with issuer " +
231
- signee.issuer.to_s + " was not verified by " +
232
- ca_cert.subject.to_s + "."
233
- end
234
-
235
- signee = ca_cert
236
- end while ca_cert.subject.to_s != ca_cert.issuer.to_s
237
- rescue
238
- raise
239
- end
240
- end
241
- end
@@ -1,427 +0,0 @@
1
- # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
3
- # #
4
- # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
- # not use this file except in compliance with the License. You may obtain #
6
- # a copy of the License at #
7
- # #
8
- # http://www.apache.org/licenses/LICENSE-2.0 #
9
- # #
10
- # Unless required by applicable law or agreed to in writing, software #
11
- # distributed under the License is distributed on an "AS IS" BASIS, #
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
- # See the License for the specific language governing permissions and #
14
- # limitations under the License. #
15
- #--------------------------------------------------------------------------- #
16
-
17
-
18
- module OpenNebula
19
- # The XMLElement class provides an abstraction of the underlying
20
- # XML parser engine. It provides XML-related methods for the Pool and
21
- # PoolElement classes
22
- class XMLElement
23
-
24
- # xml:: _opaque xml object_ an xml object as returned by build_xml
25
- def initialize(xml=nil)
26
- @xml = xml
27
- end
28
-
29
- # Initialize a XML document for the element
30
- # xml:: _String_ the XML document of the object
31
- # root_element:: _String_ Base xml element
32
- def initialize_xml(xml, root_element)
33
- @xml = XMLElement.build_xml(xml, root_element)
34
-
35
- if OpenNebula.is_error?(@xml)
36
- @xml = nil
37
- else
38
- if NOKOGIRI
39
- if @xml.size == 0
40
- @xml = nil
41
- end
42
- else
43
- if @xml.name != root_element
44
- @xml = nil
45
- end
46
- end
47
- end
48
- end
49
-
50
- # Builds a XML document
51
- # xml:: _String_ the XML document of the object
52
- # root_element:: _String_ Base xml element
53
- # [return] _XML_ object for the underlying XML engine
54
- def self.build_xml(xml, root_element)
55
- begin
56
- if NOKOGIRI
57
- doc = Nokogiri::XML(xml).xpath("/#{root_element}")
58
- else
59
- doc = REXML::Document.new(xml).root
60
- end
61
- rescue Exception => e
62
- return OpenNebula::Error.new(e.message)
63
- end
64
-
65
- return doc
66
- end
67
-
68
- # Extract a text element from the XML description of the PoolElement.
69
- #
70
- # @param [String] key Xpath expression
71
- #
72
- # @return [String, nil] If a text element is found, the element's
73
- # text value. Otherwise, an empty string or nil, depending
74
- # on the backend
75
- #
76
- # @example
77
- # vm['VID'] # gets VM id
78
- # vm['HISTORY/HOSTNAME'] # get the hostname from the history
79
- def [](key)
80
- if NOKOGIRI
81
- element=@xml.xpath(key.to_s)
82
-
83
- return nil if element.size == 0
84
- else
85
- element=@xml.elements[key.to_s]
86
-
87
- return "" if element && !element.has_text?
88
- end
89
-
90
- element.text if element
91
- end
92
-
93
- # Delete an element from the xml
94
- # xpath::_String_ xpath expression that selects the elemnts to be deleted
95
- def delete_element(xpath)
96
- if NOKOGIRI
97
- @xml.xpath(xpath.to_s).remove
98
- else
99
- @xml.delete_element(xpath.to_s)
100
- end
101
- end
102
-
103
- # Add a new element to the xml
104
- # xpath::_String_ xpath xpression where the elemente will be added
105
- # elems::_Hash_ Hash containing the pairs key-value to be included
106
- # Examples:
107
- # add_element('VM', 'NEW_ITEM' => 'NEW_VALUE')
108
- # <VM><NEW_ITEM>NEW_VALUE</NEW_ITEM>...</VM>
109
- #
110
- # add_element('VM/TEMPLATE', 'V1' => {'X1' => 'A1', 'Y2' => 'A2'})
111
- # <VM><TEMPLATE><V1><X1>A1</X1><Y2>A2</Y2>...</TEMPLATE></VM>
112
- def add_element(xpath, elems)
113
- elems.each { |key, value|
114
- if value.instance_of?(Hash)
115
- if NOKOGIRI
116
- elem = Nokogiri::XML::Node.new key, @xml.document
117
- value.each { |k2, v2|
118
- child = Nokogiri::XML::Node.new k2, elem
119
- child.content = v2
120
- elem.add_child(child)
121
- }
122
- @xml.xpath(xpath.to_s).first.add_child(elem)
123
- else
124
- elem = REXML::Element.new(key)
125
- value.each { |k2, v2|
126
- elem.add_element(k2).text = v2
127
- }
128
- @xml.elements[xpath].add_element(elem)
129
- end
130
- else
131
- if NOKOGIRI
132
- elem = Nokogiri::XML::Node.new key, @xml.document
133
- elem.content = value
134
- @xml.xpath(xpath.to_s).first.add_child(elem)
135
- else
136
- @xml.elements[xpath].add_element(key).text = value
137
- end
138
- end
139
- }
140
- end
141
-
142
- # Gets an array of text from elemenets extracted
143
- # using the XPATH expression passed as filter
144
- def retrieve_elements(filter)
145
- elements_array = Array.new
146
-
147
- if NOKOGIRI
148
- @xml.xpath(filter.to_s).each { |pelem|
149
- elements_array << pelem.text if pelem.text
150
- }
151
- else
152
- @xml.elements.each(filter.to_s) { |pelem|
153
- elements_array << pelem.text if pelem.text
154
- }
155
- end
156
-
157
- if elements_array.size == 0
158
- return nil
159
- else
160
- return elements_array
161
- end
162
-
163
- end
164
-
165
- # Gets an attribute from an elemenT
166
- # key:: _String_ xpath for the element
167
- # name:: _String_ name of the attribute
168
- def attr(key,name)
169
- value = nil
170
-
171
- if NOKOGIRI
172
- element=@xml.xpath(key.to_s.upcase)
173
- if element.size == 0
174
- return nil
175
- end
176
-
177
- attribute = element.attr(name)
178
-
179
- value = attribute.text if attribute != nil
180
- else
181
- element=@xml.elements[key.to_s.upcase]
182
-
183
- value = element.attributes[name] if element != nil
184
- end
185
-
186
- return value
187
- end
188
-
189
- # Iterates over every Element in the XPath and calls the block with a
190
- # a XMLElement
191
- # block:: _Block_
192
- def each(xpath_str,&block)
193
- if NOKOGIRI
194
- @xml.xpath(xpath_str).each { |pelem|
195
- block.call XMLElement.new(pelem)
196
- }
197
- else
198
- @xml.elements.each(xpath_str) { |pelem|
199
- block.call XMLElement.new(pelem)
200
- }
201
- end
202
- end
203
-
204
- def each_xpath(xpath_str,&block)
205
- if NOKOGIRI
206
- @xml.xpath(xpath_str).each { |pelem|
207
- block.call pelem.text
208
- }
209
- else
210
- @xml.elements.each(xpath_str) { |pelem|
211
- block.call pelem.text
212
- }
213
- end
214
- end
215
-
216
- def name
217
- @xml.name
218
- end
219
-
220
- def text
221
- if NOKOGIRI
222
- @xml.content
223
- else
224
- @xml.text
225
- end
226
- end
227
-
228
- # Returns wheter there are elements for a given XPath
229
- # xpath_str:: _String_ XPath expression to locate the element
230
- def has_elements?(xpath_str)
231
- if NOKOGIRI
232
- element = @xml.xpath(xpath_str.to_s.upcase)
233
- return element != nil && element.children.size > 0
234
- else
235
- element = @xml.elements[xpath_str.to_s]
236
- return element != nil && element.has_elements?
237
- end
238
- end
239
-
240
- # Returns the <TEMPLATE> element in text form
241
- # indent:: _Boolean_ indents the resulting string, default true
242
- def template_str(indent=true)
243
- template_like_str('TEMPLATE', indent)
244
- end
245
-
246
- # Returns the <TEMPLATE> element in XML form
247
- def template_xml
248
- if NOKOGIRI
249
- @xml.xpath('TEMPLATE').to_s
250
- else
251
- @xml.elements['TEMPLATE'].to_s
252
- end
253
- end
254
-
255
- # Returns the xml of an element
256
- def element_xml(xpath)
257
- if NOKOGIRI
258
- @xml.xpath(xpath).to_s
259
- else
260
- @xml.elements[xpath].to_s
261
- end
262
- end
263
-
264
- # Returns elements in text form
265
- # root_element:: _String_ base element
266
- # indent:: _Boolean_ indents the resulting string, default true
267
- # xpath_exp:: _String_ filter elements with a XPath
268
- def template_like_str(root_element, indent=true, xpath_exp=nil)
269
- if NOKOGIRI
270
- xml_template = @xml.xpath(root_element).to_s
271
- rexml = REXML::Document.new(xml_template).root
272
- else
273
- rexml = @xml.elements[root_element]
274
- end
275
-
276
- if indent
277
- ind_enter = "\n"
278
- ind_tab = ' '
279
- else
280
- ind_enter = ''
281
- ind_tab = ' '
282
- end
283
-
284
- str = rexml.elements.collect(xpath_exp) {|n|
285
- next if n.class != REXML::Element
286
-
287
- str_line = ""
288
-
289
- if n.has_elements?
290
- str_line << "#{n.name}=[#{ind_enter}" << n.collect { |n2|
291
-
292
- next if n2.class != REXML::Element or !n2.has_text?
293
-
294
- str = "#{ind_tab}#{n2.name}=#{attr_to_str(n2.text)}"
295
-
296
- }.compact.join(",#{ind_enter}") << " ]"
297
- else
298
- next if !n.has_text?
299
-
300
- str_line << "#{n.name}=#{attr_to_str(n.text)}"
301
- end
302
-
303
- str_line
304
- }.compact.join("\n")
305
-
306
- return str
307
- end
308
-
309
- #
310
- #
311
- #
312
- def to_xml(pretty=false)
313
- if NOKOGIRI && pretty
314
- str = @xml.to_xml
315
- elsif REXML_FORMATTERS && pretty
316
- str = String.new
317
-
318
- formatter = REXML::Formatters::Pretty.new
319
- formatter.compact = true
320
-
321
- formatter.write(@xml,str)
322
- else
323
- str = @xml.to_s
324
- end
325
-
326
- return str
327
- end
328
-
329
- # @return [Hash] a hash representing the resource
330
- def to_hash
331
- hash = {}
332
-
333
- if NOKOGIRI
334
- if @xml.instance_of?(Nokogiri::XML::NodeSet)
335
- @xml.each { |c|
336
- if c.element?
337
- build_hash(hash, c)
338
- end
339
- }
340
- else
341
- build_hash(hash, @xml)
342
- end
343
- else
344
- build_hash(hash, @xml)
345
- end
346
-
347
- hash
348
- end
349
-
350
- private
351
-
352
- #
353
- #
354
- #
355
- def build_hash(hash, element)
356
- if NOKOGIRI
357
- array = element.children
358
- if array.length==1 and (array.first.text? or array.first.cdata?)
359
- r = array.first.text
360
- else
361
- r = {}
362
- array.each { |c|
363
- if c.element?
364
- build_hash(r, c)
365
- end
366
- }
367
- end
368
- else
369
- r = {}
370
- if element.has_elements?
371
- element.each_element { |c| build_hash(r, c) }
372
- elsif element.has_text?
373
- r = element.text
374
- end
375
- end
376
-
377
- key = element.name
378
- if hash.has_key?(key)
379
- if hash[key].instance_of?(Array)
380
- hash[key] << r
381
- else
382
- hash[key] = [hash[key], r]
383
- end
384
- else
385
- hash[key] = r
386
- end
387
-
388
- hash
389
- end
390
-
391
- #
392
- #
393
- #
394
- def attr_to_str(attr)
395
- attr.gsub!('"',"\\\"")
396
- attr = "\"#{attr}\""
397
-
398
- return attr
399
- end
400
- end
401
-
402
- # The XMLUtilsPool module provides an abstraction of the underlying
403
- # XML parser engine. It provides XML-related methods for the Pools
404
- class XMLPool < XMLElement
405
-
406
- def initialize(xml=nil)
407
- super(xml)
408
- end
409
-
410
- #Executes the given block for each element of the Pool
411
- #block:: _Block_
412
- def each_element(block)
413
- if NOKOGIRI
414
- @xml.xpath(
415
- "#{@element_name}").each {|pelem|
416
- block.call self.factory(pelem)
417
- }
418
- else
419
- @xml.elements.each(
420
- "#{@element_name}") {|pelem|
421
- block.call self.factory(pelem)
422
- }
423
- end
424
- end
425
- end
426
-
427
- end