opennebula 6.6.2 → 6.7.80.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,104 +14,127 @@
14
14
  # limitations under the License. #
15
15
  #--------------------------------------------------------------------------- #
16
16
 
17
-
18
- require 'pp'
19
17
  require 'openssl'
20
18
  require 'base64'
21
19
  require 'fileutils'
20
+ require 'open3'
21
+ require 'tempfile'
22
+
23
+ module OpenNebula
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 SshAuth
29
+
30
+ # Initialize SshAuth object
31
+ #
32
+ # @param [Hash] default options for path
33
+ # @option options [String] :public_key public key for the user
34
+ # @option options [String] :private_key key private key for the user.
35
+ def initialize(options = {})
36
+ @private_key = nil
37
+ @public_key = nil
38
+
39
+ # Initialize the private key
40
+ if options[:private_key]
41
+ begin
42
+ @private_key = File.read(options[:private_key])
43
+ rescue StandardError => e
44
+ raise "Cannot read #{options[:private_key]}\n #{e}"
45
+ end
22
46
 
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
- # Initialize SshAuth object
30
- #
31
- # @param [Hash] default options for path
32
- # @option options [String] :public_key public key for the user
33
- # @option options [String] :private_key key private key for the user.
34
- def initialize(options={})
35
- @private_key = nil
36
- @public_key = nil
37
-
38
- # Initialize the private key
39
- if options[:private_key]
40
- begin
41
- @private_key = File.read(options[:private_key])
42
- rescue Exception => e
43
- raise "Cannot read #{options[:private_key]}"
47
+ begin
48
+ @private_key_rsa = OpenSSL::PKey::RSA.new(@private_key)
49
+ rescue OpenSSL::PKey::RSAError
50
+ private_key_pem = openssh_to_pem(@private_key)
51
+ @private_key_rsa = OpenSSL::PKey::RSA.new(private_key_pem)
52
+ end
53
+ end
54
+
55
+ # Initialize the public key
56
+ if options[:public_key]
57
+ @public_key = options[:public_key]
58
+ elsif !@private_key.nil?
59
+ # Init ssh keys using private key. public key is extracted in a
60
+ # format compatible with openssl. The public key does not contain
61
+ # "---- BEGIN/END PUBLIC KEY ----" and is in a single line
62
+ @public_key = @private_key_rsa.public_key.to_pem.split("\n")
63
+ @public_key = @public_key.reject {|l| l.match(/PUBLIC KEY/) }.join('')
64
+ end
65
+
66
+ if @private_key.nil? && @public_key.nil?
67
+ raise 'You have to define at least one of the keys'
44
68
  end
45
69
 
46
- @private_key_rsa = OpenSSL::PKey::RSA.new(@private_key)
70
+ @public_key_rsa = OpenSSL::PKey::RSA.new(Base64.decode64(@public_key))
47
71
  end
48
72
 
49
- # Initialize the public key
50
- if options[:public_key]
51
- @public_key = options[:public_key]
52
- elsif @private_key != nil
53
- # Init ssh keys using private key. public key is extracted in a
54
- # format compatible with openssl. The public key does not contain
55
- # "---- BEGIN/END PUBLIC KEY ----" and is in a single line
56
- @public_key = @private_key_rsa.public_key.to_pem.split("\n")
57
- @public_key = @public_key.reject {|l| l.match(/PUBLIC KEY/) }.join('')
73
+ # Creates a login token for ssh authentication.
74
+ # By default it is valid for 1 hour but it can be changed to any number
75
+ # of seconds with expire parameter (in seconds)
76
+ def login_token(user, expire = 3600)
77
+ expire ||= 3600
78
+
79
+ return encrypt("#{user}:#{Time.now.to_i + expire.to_i}")
58
80
  end
59
81
 
60
- if @private_key.nil? && @public_key.nil?
61
- raise "You have to define at least one of the keys"
82
+ # Returns a valid password string to create a user using this auth driver.
83
+ # In this case the ssh public key.
84
+ def password
85
+ @public_key
62
86
  end
63
87
 
64
- @public_key_rsa = OpenSSL::PKey::RSA.new(Base64::decode64(@public_key))
65
- end
88
+ # Checks the proxy created with the login method
89
+ def authenticate(user, token)
90
+ begin
91
+ token_plain = decrypt(token)
92
+ t_user, time = token_plain.split(':')
66
93
 
67
- # Creates a login token for ssh authentication.
68
- # By default it is valid for 1 hour but it can be changed to any number
69
- # of seconds with expire parameter (in seconds)
70
- def login_token(user, expire=3600)
71
- expire ||= 3600
94
+ return 'invalid credentials' unless user == t_user
95
+ return 'ssh proxy expired, login again to renew it' if Time.now.to_i >= time.to_i
72
96
 
73
- return encrypt("#{user}:#{Time.now.to_i + expire.to_i}")
74
- end
97
+ return true
98
+ rescue StandardError
99
+ return 'error'
100
+ end
101
+ end
75
102
 
76
- # Returns a valid password string to create a user using this auth driver.
77
- # In this case the ssh public key.
78
- def password
79
- @public_key
80
- end
103
+ private
81
104
 
82
- # Checks the proxy created with the login method
83
- def authenticate(user, token)
84
- begin
85
- token_plain = decrypt(token)
86
- _user, time = token_plain.split(':')
87
-
88
- if user == _user
89
- if Time.now.to_i >= time.to_i
90
- return "ssh proxy expired, login again to renew it"
91
- else
92
- return true
93
- end
94
- else
95
- return "invalid credentials"
96
- end
97
- rescue
98
- return "error"
105
+ def openssh_to_pem(private_key)
106
+ temp_file = Tempfile.new('private_key')
107
+
108
+ File.write(temp_file.path, private_key)
109
+
110
+ # Use ssh-keygen to convert the key
111
+ command = "ssh-keygen -p -N '' -m PEM -f #{temp_file.path}"
112
+
113
+ _out, err, status = Open3.capture3(command)
114
+
115
+ raise "Failed to convert key: #{err}" unless status.success?
116
+
117
+ pem_key = File.read(temp_file.path)
118
+ return pem_key
119
+ ensure
120
+ temp_file.close
121
+ temp_file.unlink if temp_file
122
+ end
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
+ Base64.encode64(@private_key_rsa.private_encrypt(data)).gsub!("\n", '').strip
99
131
  end
100
- end
101
132
 
102
- private
133
+ # Decrypts base 64 encoded data with pub_key (public key)
134
+ def decrypt(data)
135
+ @public_key_rsa.public_decrypt(Base64.decode64(data))
136
+ end
103
137
 
104
- ###########################################################################
105
- # Methods to handle ssh keys
106
- ###########################################################################
107
- # Encrypts data with the private key of the user and returns
108
- # base 64 encoded output in a single line
109
- def encrypt(data)
110
- Base64::encode64(@private_key_rsa.private_encrypt(data)).gsub!(/\n/, '').strip
111
138
  end
112
139
 
113
- # Decrypts base 64 encoded data with pub_key (public key)
114
- def decrypt(data)
115
- @public_key_rsa.public_decrypt(Base64::decode64(data))
116
- end
117
140
  end