diff --git a/include/Host.h b/include/Host.h index 014374d336..549403e913 100644 --- a/include/Host.h +++ b/include/Host.h @@ -463,6 +463,13 @@ public: return new HostTemplate; } + + /** + * Executed after an update operation to process the new template + * - encrypt VCENTER_PASSWORD attribute. + */ + int post_update_template(string& error); + private: // ------------------------------------------------------------------------- diff --git a/include/NebulaTemplate.h b/include/NebulaTemplate.h index 9998cdf0dc..676e10593e 100644 --- a/include/NebulaTemplate.h +++ b/include/NebulaTemplate.h @@ -154,6 +154,13 @@ public: ~OpenNebulaTemplate(){}; + /** + * Read or Generate the master key file to encrypt DB data when needed + * this key is added to the configuration of OpenNebula and can be obtained + * through one.system.config + */ + int load_key(); + private: /** * Name for the configuration file, oned.conf diff --git a/src/host/Host.cc b/src/host/Host.cc index e9d7322349..2d440d0cdc 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -663,3 +663,36 @@ int Host::from_xml(const string& xml) return 0; } + + +int Host::post_update_template(string& error) +{ + + string vcenter_password; + + erase_template_attribute("VCENTER_PASSWORD", vcenter_password); + + if (!vcenter_password.empty()) + { + Nebula& nd = Nebula::instance(); + string one_key; + string * encrypted; + + nd.get_configuration_attribute("ONE_KEY", one_key); + + if (!one_key.empty()) + { + encrypted = one_util::aes256cbc_encrypt(vcenter_password, one_key); + + add_template_attribute("VCENTER_PASSWORD", *encrypted); + + delete encrypted; + } + else + { + add_template_attribute("VCENTER_PASSWORD", vcenter_password); + } + } + + return 0; +}; diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 6e24fcfc92..c2cdc45bca 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -146,6 +146,17 @@ void Nebula::start(bool bootstrap_only) throw; } + // ----------------------------------------------------------- + // Load the OpenNebula master key and keep it in memory + // ----------------------------------------------------------- + + rc = nebula_configuration->load_key(); + + if ( rc != 0 ) + { + throw runtime_error("Could not load nebula master key file."); + } + // ----------------------------------------------------------- // Initialize the XML library // ----------------------------------------------------------- diff --git a/src/nebula/NebulaTemplate.cc b/src/nebula/NebulaTemplate.cc index d1f71ffe12..5541c40ee8 100644 --- a/src/nebula/NebulaTemplate.cc +++ b/src/nebula/NebulaTemplate.cc @@ -15,6 +15,12 @@ /* -------------------------------------------------------------------------- */ #include "NebulaTemplate.h" +#include "NebulaUtil.h" + +#include +#include + +#include using namespace std; @@ -361,3 +367,69 @@ void OpenNebulaTemplate::set_conf_default() conf_default.insert(make_pair(attribute->name(),attribute)); } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int OpenNebulaTemplate::load_key() +{ + string keyfile = var_location + "/.one/one_key"; + string key; + + if (access(keyfile.c_str(), F_OK) == 0) //Key file exists + { + ifstream ifile; + + ifile.open(keyfile.c_str(), ios::in); + + if ( !ifile.is_open() ) + { + cout << "Could not create OpenNebula keyfile: " << keyfile; + return -1; + } + + ifile >> key; + + ifile.close(); + } + else + { + string dirpath = var_location + "/.one"; + + if (access(dirpath.c_str(), F_OK) != 0) + { + if (mkdir(dirpath.c_str(), S_IRWXU) == -1) + { + cout << "Could not create directory: " << dirpath << endl; + return -1; + } + } + + ofstream ofile; + + ofile.open(keyfile.c_str(), ios::out | ios::trunc); + + if ( !ofile.is_open() ) + { + cout << "Could not create OpenNebula keyfile: " << keyfile; + return -1; + } + + key = one_util::random_password(); + + ofile << key << endl; + + ofile.close(); + + if (chmod(keyfile.c_str(), S_IRUSR | S_IWUSR) != 0) + { + cout << "Could not set access mode to: " << keyfile << endl; + return -1; + } + } + + + SingleAttribute * attribute = new SingleAttribute("ONE_KEY", key); + attributes.insert(make_pair(attribute->name(),attribute)); + + return 0; +} diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 3e7a3f010f..d1a8740a45 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -40,6 +40,7 @@ require 'rbvmomi' require 'yaml' require 'opennebula' require 'base64' +require 'openssl' module VCenterDriver @@ -85,10 +86,26 @@ class VIClient raise "Error getting host information: #{rc.message}" end + password = @one_host["TEMPLATE/VCENTER_PASSWORD"] + + if !@token.nil? + begin + cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc") + + cipher.decrypt + cipher.key = @token + + password = cipher.update(Base64::decode64(password)) + password << cipher.final + rescue + raise "Error decrypting vCenter password" + end + end + connection = { :host => @one_host["TEMPLATE/VCENTER_HOST"], :user => @one_host["TEMPLATE/VCENTER_USER"], - :password => @one_host["TEMPLATE/VCENTER_PASSWORD"] + :password => password } initialize_vim(connection) @@ -216,7 +233,16 @@ class VIClient ############################################################################ def initialize_one begin - @one = ::OpenNebula::Client.new() + @one = ::OpenNebula::Client.new() + system = ::OpenNebula::System.new(@one) + + config = system.get_configuration() + + if ::OpenNebula.is_error?(config) + raise "Error getting oned configuration : #{rc.message}" + end + + @token = config["ONE_KEY"] rescue Exception => e raise "Error initializing OpenNebula client: #{e.message}" end