opennebula 3.9.80.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/LICENSE +202 -0
  2. data/NOTICE +47 -0
  3. data/lib/opennebula.rb +58 -0
  4. data/lib/opennebula/acl.rb +266 -0
  5. data/lib/opennebula/acl_pool.rb +55 -0
  6. data/lib/opennebula/client.rb +119 -0
  7. data/lib/opennebula/cluster.rb +249 -0
  8. data/lib/opennebula/cluster_pool.rb +58 -0
  9. data/lib/opennebula/datastore.rb +171 -0
  10. data/lib/opennebula/datastore_pool.rb +55 -0
  11. data/lib/opennebula/document.rb +261 -0
  12. data/lib/opennebula/document_json.rb +131 -0
  13. data/lib/opennebula/document_pool.rb +102 -0
  14. data/lib/opennebula/document_pool_json.rb +58 -0
  15. data/lib/opennebula/error.rb +52 -0
  16. data/lib/opennebula/group.rb +163 -0
  17. data/lib/opennebula/group_pool.rb +56 -0
  18. data/lib/opennebula/host.rb +201 -0
  19. data/lib/opennebula/host_pool.rb +93 -0
  20. data/lib/opennebula/image.rb +297 -0
  21. data/lib/opennebula/image_pool.rb +79 -0
  22. data/lib/opennebula/ldap_auth.rb +99 -0
  23. data/lib/opennebula/ldap_auth_spec.rb +70 -0
  24. data/lib/opennebula/pool.rb +160 -0
  25. data/lib/opennebula/pool_element.rb +269 -0
  26. data/lib/opennebula/server_cipher_auth.rb +148 -0
  27. data/lib/opennebula/server_x509_auth.rb +104 -0
  28. data/lib/opennebula/ssh_auth.rb +139 -0
  29. data/lib/opennebula/system.rb +141 -0
  30. data/lib/opennebula/template.rb +213 -0
  31. data/lib/opennebula/template_pool.rb +79 -0
  32. data/lib/opennebula/user.rb +174 -0
  33. data/lib/opennebula/user_pool.rb +55 -0
  34. data/lib/opennebula/virtual_machine.rb +560 -0
  35. data/lib/opennebula/virtual_machine_pool.rb +323 -0
  36. data/lib/opennebula/virtual_network.rb +249 -0
  37. data/lib/opennebula/virtual_network_pool.rb +79 -0
  38. data/lib/opennebula/x509_auth.rb +288 -0
  39. data/lib/opennebula/xml_element.rb +427 -0
  40. data/lib/opennebula/xml_pool.rb +45 -0
  41. data/lib/opennebula/xml_utils.rb +34 -0
  42. metadata +118 -0
@@ -0,0 +1,148 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
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 'digest/sha1'
19
+
20
+ require 'base64'
21
+ require 'fileutils'
22
+
23
+ module OpenNebula; end
24
+
25
+ # Server authentication class. This method can be used by OpenNebula services
26
+ # to let access authenticated users by other means. It is based on OpenSSL
27
+ # symmetric ciphers
28
+ class OpenNebula::ServerCipherAuth
29
+ ###########################################################################
30
+ #Constants with paths to relevant files and defaults
31
+ ###########################################################################
32
+
33
+ CIPHER = "aes-256-cbc"
34
+
35
+ ###########################################################################
36
+
37
+ def initialize(srv_user, srv_passwd)
38
+ @srv_user = srv_user
39
+ @srv_passwd = srv_passwd
40
+
41
+ if !srv_passwd.empty?
42
+ @key = Digest::SHA1.hexdigest(@srv_passwd)
43
+ else
44
+ @key = ""
45
+ end
46
+
47
+ @cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
48
+ end
49
+
50
+ ###########################################################################
51
+ # Client side
52
+ ###########################################################################
53
+
54
+ # Creates a ServerCipher for client usage
55
+ def self.new_client(srv_user=nil, srv_passwd=nil)
56
+ if ( srv_user == nil || srv_passwd == nil )
57
+ begin
58
+ if ENV["ONE_CIPHER_AUTH"] and !ENV["ONE_CIPHER_AUTH"].empty?
59
+ one_auth = File.read(ENV["ONE_CIPHER_AUTH"])
60
+ else
61
+ raise "ONE_CIPHER_AUTH environment variable not set"
62
+ end
63
+
64
+ one_auth.rstrip!
65
+
66
+ rc = one_auth.match(/(.*?):(.*)/)
67
+
68
+ if rc.nil?
69
+ raise "Bad format for one_auth token (<user>:<passwd>)"
70
+ else
71
+ srv_user = rc[1]
72
+ srv_passwd = rc[2]
73
+ end
74
+ rescue => e
75
+ raise e.message
76
+ end
77
+ end
78
+
79
+ self.new(srv_user, srv_passwd)
80
+ end
81
+
82
+ # Generates a login token in the form:
83
+ # - server_user:target_user:time_expires
84
+ # The token is then encrypted with the contents of one_auth
85
+ def login_token(expire, target_user=nil)
86
+ target_user ||= @srv_user
87
+ token_txt = "#{@srv_user}:#{target_user}:#{expire}"
88
+
89
+ token = encrypt(token_txt)
90
+ token64 = Base64::encode64(token).strip.delete("\n")
91
+
92
+ return "#{@srv_user}:#{target_user}:#{token64}"
93
+ end
94
+
95
+ # Returns a valid password string to create a user using this auth driver
96
+ def password
97
+ return @srv_passwd
98
+ end
99
+
100
+ ###########################################################################
101
+ # Driver side
102
+ ###########################################################################
103
+
104
+ # Creates a ServerCipher for driver usage
105
+ def self.new_driver()
106
+ self.new("","")
107
+ end
108
+
109
+ # auth method for auth_mad
110
+ def authenticate(srv_user,srv_pass, signed_text)
111
+ begin
112
+ @key = srv_pass
113
+
114
+ s_user, t_user, expires = decrypt(signed_text).split(':')
115
+
116
+ return "User name missmatch" if s_user != srv_user
117
+
118
+ return "login token expired" if Time.now.to_i >= expires.to_i
119
+
120
+ return true
121
+ rescue => e
122
+ return e.message
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ def encrypt(data)
129
+ @cipher.encrypt
130
+ @cipher.key = @key
131
+
132
+ rc = @cipher.update(data)
133
+ rc << @cipher.final
134
+
135
+ return rc
136
+ end
137
+
138
+ def decrypt(data)
139
+ @cipher.decrypt
140
+ @cipher.key = @key
141
+
142
+ rc = @cipher.update(Base64::decode64(data))
143
+ rc << @cipher.final
144
+
145
+ return rc
146
+ end
147
+ end
148
+
@@ -0,0 +1,104 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
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
+
21
+ require 'opennebula/x509_auth'
22
+
23
+ module OpenNebula; end
24
+
25
+ # Server authentication class. This authmethod can be used by opennebula services
26
+ # to let access authenticated users by other means. It is based on x509 server
27
+ # certificates
28
+ class OpenNebula::ServerX509Auth < OpenNebula::X509Auth
29
+ ###########################################################################
30
+ #Constants with paths to relevant files and defaults
31
+ ###########################################################################
32
+
33
+ SERVER_AUTH_CONF_PATH = ETC_LOCATION + "/auth/server_x509_auth.conf"
34
+
35
+ SERVER_DEFAULTS = {
36
+ :one_cert => ETC_LOCATION + "/auth/cert.pem",
37
+ :one_key => ETC_LOCATION + "/auth/key.pem"
38
+ }
39
+
40
+ ###########################################################################
41
+
42
+ def initialize()
43
+ @options = SERVER_DEFAULTS
44
+
45
+ load_options(SERVER_AUTH_CONF_PATH)
46
+
47
+ begin
48
+ certs = [ File.read(@options[:one_cert]) ]
49
+ key = File.read(@options[:one_key])
50
+
51
+ super(:certs_pem => certs, :key_pem => key)
52
+ rescue
53
+ raise
54
+ end
55
+
56
+ if @options[:srv_user] == nil || @options[:srv_user].empty?
57
+ raise "User for x509 server not defined"
58
+ end
59
+ end
60
+
61
+ ###########################################################################
62
+ # Client side
63
+ ###########################################################################
64
+
65
+ # Creates a ServerCipher for client and driver sage
66
+ class << OpenNebula::ServerX509Auth
67
+ alias :new_client :new
68
+ alias :new_driver :new
69
+ end
70
+
71
+ # Generates a login token in the form:
72
+ # - server_user:target_user:time_expires
73
+ def login_token(expire, target_user=nil)
74
+ target_user ||= @options[:srv_user]
75
+ token_txt = "#{@options[:srv_user]}:#{target_user}:#{expire}"
76
+
77
+ token = encrypt(token_txt)
78
+ token64 = Base64::encode64(token).strip.delete("\n")
79
+
80
+ return "#{@options[:srv_user]}:#{target_user}:#{token64}"
81
+ end
82
+
83
+ ###########################################################################
84
+ # Server side
85
+ ###########################################################################
86
+
87
+ # auth method for auth_mad
88
+ def authenticate(server_user, server_pass, signed_text)
89
+ begin
90
+ s_user, t_user, expires = decrypt(signed_text).split(':')
91
+
92
+ return "Server password missmatch" if server_pass != password
93
+
94
+ return "User name missmatch" if ( s_user != server_user ||
95
+ s_user != @options[:srv_user] )
96
+
97
+ return "login token expired" if Time.now.to_i >= expires.to_i
98
+
99
+ return true
100
+ rescue => e
101
+ return e.message
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,139 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
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
+ require 'pp'
19
+ require 'openssl'
20
+ require 'base64'
21
+ require 'fileutils'
22
+
23
+ module OpenNebula; end
24
+
25
+ # SSH key authentication class. It can be used as a driver for auth_mad
26
+ # as auth method is defined. It also holds some helper methods to be used
27
+ # by oneauth command
28
+ class OpenNebula::SshAuth
29
+ LOGIN_PATH = ENV['HOME']+'/.one/one_ssh'
30
+
31
+ # Initialize SshAuth object
32
+ #
33
+ # @param [Hash] default options for path
34
+ # @option options [String] :public_key public key for the user
35
+ # @option options [String] :private_key key private key for the user.
36
+ def initialize(options={})
37
+ @private_key = nil
38
+ @public_key = nil
39
+
40
+ if options[:private_key]
41
+ begin
42
+ @private_key = File.read(options[:private_key])
43
+ rescue Exception => e
44
+ raise "Cannot read #{options[:private_key]}"
45
+ end
46
+ end
47
+
48
+ if options[:public_key]
49
+ @public_key = options[:public_key]
50
+ elsif @private_key != nil
51
+ # Init ssh keys using private key. public key is extracted in a
52
+ # format compatible with openssl. The public key does not contain
53
+ # "---- BEGIN/END RSA PUBLIC KEY ----" and is in a single line
54
+ key = OpenSSL::PKey::RSA.new(@private_key)
55
+
56
+ @public_key = key.public_key.to_pem.split("\n")
57
+ @public_key = @public_key.reject {|l| l.match(/RSA PUBLIC KEY/) }.join('')
58
+ end
59
+
60
+ if @private_key.nil? && @public_key.nil?
61
+ raise "You have to define at least one of the keys"
62
+ end
63
+ end
64
+
65
+ # Creates the login file for ssh authentication at ~/.one/one_ssh.
66
+ # By default it is valid for 1 hour but it can be changed to any number
67
+ # of seconds with expire parameter (in seconds)
68
+ def login(user, expire=3600)
69
+ expire ||= 3600
70
+
71
+ # Init proxy file path and creates ~/.one directory if needed
72
+ proxy_dir = File.dirname(LOGIN_PATH)
73
+
74
+ begin
75
+ FileUtils.mkdir_p(proxy_dir)
76
+ rescue Errno::EEXIST
77
+ end
78
+
79
+ # Generate security token
80
+ time = Time.now.to_i + expire.to_i
81
+
82
+ secret_plain = "#{user}:#{time}"
83
+ secret_crypted = encrypt(secret_plain)
84
+
85
+ proxy = "#{user}:#{secret_crypted}"
86
+
87
+ file = File.open(LOGIN_PATH, "w")
88
+ file.write(proxy)
89
+ file.close
90
+
91
+ File.chmod(0600,LOGIN_PATH)
92
+
93
+ secret_crypted
94
+ end
95
+
96
+ # Returns a valid password string to create a user using this auth driver.
97
+ # In this case the ssh public key.
98
+ def password
99
+ @public_key
100
+ end
101
+
102
+ # Checks the proxy created with the login method
103
+ def authenticate(user, token)
104
+ begin
105
+ token_plain = decrypt(token)
106
+ _user, time = token_plain.split(':')
107
+
108
+ if user == _user
109
+ if Time.now.to_i >= time.to_i
110
+ return "ssh proxy expired, login again to renew it"
111
+ else
112
+ return true
113
+ end
114
+ else
115
+ return "invalid credentials"
116
+ end
117
+ rescue
118
+ return "error"
119
+ end
120
+ end
121
+
122
+ private
123
+
124
+ ###########################################################################
125
+ # Methods to handle ssh keys
126
+ ###########################################################################
127
+ # Encrypts data with the private key of the user and returns
128
+ # base 64 encoded output in a single line
129
+ def encrypt(data)
130
+ rsa=OpenSSL::PKey::RSA.new(@private_key)
131
+ Base64::encode64(rsa.private_encrypt(data)).gsub!(/\n/, '').strip
132
+ end
133
+
134
+ # Decrypts base 64 encoded data with pub_key (public key)
135
+ def decrypt(data)
136
+ rsa=OpenSSL::PKey::RSA.new(Base64::decode64(@public_key))
137
+ rsa.public_decrypt(Base64::decode64(data))
138
+ end
139
+ end
@@ -0,0 +1,141 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
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
+ require 'opennebula/pool'
19
+
20
+ module OpenNebula
21
+ class System
22
+ #######################################################################
23
+ # Constants and Class attribute accessors
24
+ #######################################################################
25
+
26
+ SYSTEM_METHODS = {
27
+ :userquotainfo => "userquota.info",
28
+ :userquotaupdate => "userquota.update",
29
+ :groupquotainfo => "groupquota.info",
30
+ :groupquotaupdate => "groupquota.update",
31
+ :version => "system.version",
32
+ :config => "system.config"
33
+ }
34
+
35
+ #######################################################################
36
+ # Class constructor
37
+ #######################################################################
38
+
39
+ # Constructor
40
+ # @param [Client] client that represents a XML-RPC connection
41
+ def initialize(client)
42
+ @client = client
43
+ end
44
+
45
+ #######################################################################
46
+ # XML-RPC Methods
47
+ #######################################################################
48
+
49
+ # Gets the oned version
50
+ #
51
+ # @return [String, OpenNebula::Error] the oned version in case
52
+ # of success, Error otherwise
53
+ def get_oned_version()
54
+ return @client.call("system.version")
55
+ end
56
+
57
+ # Returns whether of not the oned version is the same as the OCA version
58
+ #
59
+ # @return [true, false, OpenNebula::Error] true if oned is the same
60
+ # version
61
+ def compatible_version()
62
+ no_revision = VERSION[/^\d+\.\d+\./]
63
+ oned_v = get_oned_version
64
+
65
+ if OpenNebula.is_error?(oned_v)
66
+ return oned_v
67
+ end
68
+
69
+ return (oned_v =~ /#{no_revision}/) != nil
70
+ end
71
+
72
+ # Gets the oned configuration
73
+ #
74
+ # @return [XMLElement, OpenNebula::Error] the oned configuration in case
75
+ # of success, Error otherwise
76
+ def get_configuration()
77
+ rc = @client.call(SYSTEM_METHODS[:config])
78
+
79
+ if OpenNebula.is_error?(rc)
80
+ return rc
81
+ end
82
+
83
+ config = XMLElement.new
84
+ config.initialize_xml(rc, 'TEMPLATE')
85
+
86
+ return config
87
+ end
88
+
89
+ # Gets the default user quota limits
90
+ #
91
+ # @return [XMLElement, OpenNebula::Error] the default user quota in case
92
+ # of success, Error otherwise
93
+ def get_user_quotas()
94
+ rc = @client.call(SYSTEM_METHODS[:userquotainfo])
95
+
96
+ if OpenNebula.is_error?(rc)
97
+ return rc
98
+ end
99
+
100
+ default_quotas = XMLElement.new
101
+ default_quotas.initialize_xml(rc, 'DEFAULT_USER_QUOTAS')
102
+
103
+ return default_quotas
104
+ end
105
+
106
+ # Sets the default user quota limits
107
+ # @param quota [String] a template (XML or txt) with the new quota limits
108
+ #
109
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
110
+ # otherwise
111
+ def set_user_quotas(quota)
112
+ return @client.call(SYSTEM_METHODS[:userquotaupdate], quota)
113
+ end
114
+
115
+ # Gets the default group quota limits
116
+ #
117
+ # @return [XMLElement, OpenNebula::Error] the default group quota in case
118
+ # of success, Error otherwise
119
+ def get_group_quotas()
120
+ rc = @client.call(SYSTEM_METHODS[:groupquotainfo])
121
+
122
+ if OpenNebula.is_error?(rc)
123
+ return rc
124
+ end
125
+
126
+ default_quotas = XMLElement.new
127
+ default_quotas.initialize_xml(rc, 'DEFAULT_GROUP_QUOTAS')
128
+
129
+ return default_quotas
130
+ end
131
+
132
+ # Sets the default group quota limits
133
+ # @param quota [String] a template (XML or txt) with the new quota limits
134
+ #
135
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
136
+ # otherwise
137
+ def set_group_quotas(quota)
138
+ return @client.call(SYSTEM_METHODS[:groupquotaupdate], quota)
139
+ end
140
+ end
141
+ end