diff --git a/lib/fog/hp/compute.rb b/lib/fog/hp/compute.rb index 7f915193b..7bfed3205 100644 --- a/lib/fog/hp/compute.rb +++ b/lib/fog/hp/compute.rb @@ -48,6 +48,7 @@ module Fog request :get_flavor_details request :get_image_details request :get_meta + request :get_windows_password request :get_security_group request :get_server_details request :list_addresses @@ -75,7 +76,50 @@ module Fog request :update_metadata request :update_server + module Utils + + # extract windows password from log + def extract_password_from_log(log_text) + encrypted_text = "" + section = [] + return if log_text.nil? + log_text.each_line do |line| + case line + when /^-----BEGIN (\w+)/ + section.push $1 + next + when /^-----END (\w+)/ + section.pop + next + end + + case section + when ["BASE64"] + encrypted_text << line + end + end + # return the encrypted portion only + encrypted_text + end + + def encrypt_using_public_key(text, public_key_data) + return if (text.nil? || public_key_data.nil?) + public_key = OpenSSL::PKey::RSA.new(public_key_data) + encrypted_text = public_key.public_encrypt(text).strip + Base64.encode64(encrypted_text) + end + + def decrypt_using_private_key(encrypted_text, private_key_data) + return if (encrypted_text.nil? || private_key_data.nil?) + private_key = OpenSSL::PKey::RSA.new(private_key_data) + from_base64 = Base64.decode64(encrypted_text) + private_key.private_decrypt(from_base64).strip + end + + end + class Mock + include Utils def self.data @data ||= Hash.new do |hash, key| @@ -115,6 +159,7 @@ module Fog end class Real + include Utils def initialize(options={}) require 'multi_json' diff --git a/lib/fog/hp/requests/compute/get_windows_password.rb b/lib/fog/hp/requests/compute/get_windows_password.rb new file mode 100644 index 000000000..8c13a5acb --- /dev/null +++ b/lib/fog/hp/requests/compute/get_windows_password.rb @@ -0,0 +1,57 @@ +module Fog + module Compute + class HP + class Real + + def get_windows_password(server_id, private_key_data) + begin + # get console output assuming that the server is already in active state + log_output = get_console_output(server_id, 400).body['output'] + # decrypt the log output to extract the password + encrypted_text = extract_password_from_log(log_output) + if encrypted_text + password = decrypt_using_private_key(encrypted_text, private_key_data) + else + raise "Error in extracting encrypted password from the log." + end + rescue OpenSSL::PKey::RSAError => error + raise "Error in decrypting password. Exception: #{error}" + end + # return the password + password + end + + end + + class Mock + + def get_windows_password(server_id, private_key_data) + # need to mock out the private key as well + private_key = OpenSSL::PKey::RSA.generate(1024) + public_key = private_key.public_key + ### The original password is Passw0rd + encoded_password = encrypt_using_public_key("Passw0rd", public_key) + + if list_servers_detail.body['servers'].detect {|_| _['id'] == server_id} + begin + # mock output for this call get_console_output(server_id, 400).body['output'] + log_output = "start junk [cloud-init] Encrypt random password\n-----BEGIN BASE64-ENCODED ENCRYPTED PASSWORD-----\n#{encoded_password}-----END BASE64-ENCODED ENCRYPTED PASSWORD-----\nend junk [cloud-init] Done\n" + encrypted_text = extract_password_from_log(log_output) + if encrypted_text + password = decrypt_using_private_key(encrypted_text, private_key) + else + raise "Error in extracting encrypted password from the log." + end + rescue OpenSSL::PKey::RSAError => error + raise "Error in decrypting password. Exception: #{error}" + end + # return the password should match Passw0rd + password + else + raise Fog::Compute::HP::NotFound + end + end + end + end + end +end \ No newline at end of file