From bfaabf357db896002a28e6c67275e550aceeb838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 22 Jun 2011 19:22:52 +0200 Subject: [PATCH 01/75] Feature #687: Start work on ACL rules --- include/AclManager.h | 137 +++++++++++++++++++++++++++++ include/AclRule.h | 109 +++++++++++++++++++++++ include/AuthManager.h | 65 ++++++++++---- include/Nebula.h | 14 ++- include/Request.h | 2 +- include/RequestManagerAcl.h | 123 ++++++++++++++++++++++++++ install.sh | 5 +- src/authm/AclManager.cc | 108 +++++++++++++++++++++++ src/authm/AclRule.cc | 151 ++++++++++++++++++++++++++++++++ src/authm/AuthManager.cc | 123 +++----------------------- src/authm/SConstruct | 4 +- src/cli/oneacl | 102 ++++++++++++++++++++++ src/nebula/Nebula.cc | 3 + src/oca/ruby/OpenNebula.rb | 1 + src/oca/ruby/OpenNebula/Acl.rb | 87 +++++++++++++++++++ src/rm/RequestManager.cc | 11 +++ src/rm/RequestManagerAcl.cc | 152 +++++++++++++++++++++++++++++++++ src/rm/SConstruct | 31 +------ 18 files changed, 1066 insertions(+), 162 deletions(-) create mode 100644 include/AclManager.h create mode 100644 include/AclRule.h create mode 100644 include/RequestManagerAcl.h create mode 100644 src/authm/AclManager.cc create mode 100644 src/authm/AclRule.cc create mode 100755 src/cli/oneacl create mode 100644 src/oca/ruby/OpenNebula/Acl.rb create mode 100644 src/rm/RequestManagerAcl.cc diff --git a/include/AclManager.h b/include/AclManager.h new file mode 100644 index 0000000000..d8e97fe059 --- /dev/null +++ b/include/AclManager.h @@ -0,0 +1,137 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef ACL_MANAGER_H_ +#define ACL_MANAGER_H_ + +#include + +#include "AuthManager.h" +#include "AclRule.h" + +using namespace std; + +class AclManager : public ObjectSQL +{ +public: + AclManager(){}; + + /* ---------------------------------------------------------------------- */ + /* Rule management */ + /* ---------------------------------------------------------------------- */ + + bool authorize(int uid, const set &user_groups, + AuthRequest::Object obj_type, int obj_id, int obj_gid, + AuthRequest::Operation op); + + /* ---------------------------------------------------------------------- */ + + int add_rule(long long user, long long resource, long long rights) + { + AclRule rule(user, resource, rights); + return add_rule(rule); + }; + + int add_rule(const AclRule &rule) + { + pair::iterator,bool> ret; + + ret = acl_set.insert(rule); + + if( !ret.second ) + { + return -1; + } + + return 0; + }; + + /* ---------------------------------------------------------------------- */ + + int del_rule(long long user, long long resource, long long rights) + { + AclRule rule(user, resource, rights); + return del_rule(rule); + }; + + int del_rule(AclRule &rule) + { + if( acl_set.erase(rule) != 1 ) + { + return -1; + } + + return 0; + }; + + /* ---------------------------------------------------------------------- */ + /* DB management */ + /* ---------------------------------------------------------------------- */ + + /** + * Callback function to unmarshall a PoolObjectSQL + * @param num the number of columns read from the DB + * @param names the column names + * @param vaues the column values + * @return 0 on success + */ + int select_cb(void *nil, int num, char **values, char **names) + { + if ( (!values[0]) || (num != 1) ) + { + return -1; + } + + // TODO: from_xml + + return 0; + }; + + /** + * Reads the ACL rule set from the database. + * @param db pointer to the db + * @return 0 on success + */ + int select(SqlDB *db) + { + return 0; + }; + + int insert(SqlDB*, std::string&) + { + return 0; + }; + + int update(SqlDB*) + { + return 0; + }; + + int drop(SqlDB*) + { + return 0; + }; + + /* ---------------------------------------------------------------------- */ + + int dump(ostringstream& oss); + +private: + set acl_set; +}; + +#endif /*ACL_MANAGER_H*/ + diff --git a/include/AclRule.h b/include/AclRule.h new file mode 100644 index 0000000000..37c786bf7a --- /dev/null +++ b/include/AclRule.h @@ -0,0 +1,109 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef ACL_RULE_H_ +#define ACL_RULE_H_ + +#include + +#include "ObjectSQL.h" + +using namespace std; + +class AclRule +{ +public: + + static const long long INDIVIDUAL_ID; + static const long long GROUP_ID; + static const long long ALL_ID; + + AclRule(long long _user, long long _resource, long long _rights): + user(_user), resource(_resource), rights(_rights) + {}; + + AclRule& operator=(AclRule const& o) + { + user = o.user; + resource = o.resource; + rights = o.rights; + + return *this; + }; + + bool operator ==(const AclRule& other) const + { + return (user == other.user && + resource == other.resource && + rights == other.rights); + }; + + bool operator!=(const AclRule& other) const + { + return !(*this == other); + }; + + bool operator <(const AclRule& other) const + { + return user < other.user; + }; + + string to_str() const; + + string& to_xml(string& xml) const; + + int user_id() const + { + return user; + }; + + long long user_code() const + { + return user & 0xFFFFFFFF00000000LL; + }; + + int resource_id() const + { + return resource; + }; + + long long resource_code() const + { + return resource & 0xFFFFFFFF00000000LL; + }; + +private: + + friend class AclManager; + + /** + * + */ + long long user; + + /** + * + */ + long long resource; + + /** + * + */ + long long rights; +}; + +#endif /*ACL_RULE_H*/ + diff --git a/include/AuthManager.h b/include/AuthManager.h index 106497d2ee..0aebd3e405 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -276,15 +276,32 @@ public: */ enum Operation { - CREATE, /** Authorization to create an object */ - DELETE, /** Authorization to delete an object */ - USE, /** Authorization to use an object */ - MANAGE, /** Authorization to manage an object */ - INFO, /** Authorization to view an object */ - INFO_POOL, /** Authorization to view any object in the pool */ - INFO_POOL_MINE, /** Authorization to view user and/or group objects */ - INSTANTIATE, /** Authorization to instantiate a VM from a TEMPLATE */ - CHOWN /** Authorization to change ownership of an object */ + CREATE = 0x1LL, /**< Auth. to create an object */ + DELETE = 0x2LL, /**< Auth. to delete an object */ + USE = 0x4LL, /**< Auth. to use an object */ + MANAGE = 0x8LL, /**< Auth. to manage an object */ + INFO = 0x10LL, /**< Auth. to view an object */ + INFO_POOL = 0x20LL, /**< Auth. to view any object in the pool */ + INFO_POOL_MINE= 0x40LL, /**< Auth. to view user and/or group objects */ + INSTANTIATE = 0x80LL, /**< Auth. to instantiate a VM from a TEMPLATE*/ + CHOWN = 0x100LL /**< Auth. to change ownership of an object */ + }; + + static string Operation_to_str(Operation op) + { + switch (op) + { + case CREATE: return "CREATE"; + case DELETE: return "DELETE"; + case USE: return "USE"; + case MANAGE: return "MANAGE"; + case INFO: return "INFO"; + case INFO_POOL: return "INFO_POOL"; + case INFO_POOL_MINE: return "INFO_POOL_MINE"; + case INSTANTIATE: return "INSTANTIATE"; + case CHOWN: return "CHOWN"; + default: return ""; + } }; /** @@ -292,13 +309,29 @@ public: */ enum Object { - VM, - HOST, - NET, - IMAGE, - USER, - TEMPLATE, - GROUP + VM = 0x1000000000LL, + HOST = 0x2000000000LL, + NET = 0x4000000000LL, + IMAGE = 0x8000000000LL, + USER = 0x10000000000LL, + TEMPLATE = 0x20000000000LL, + GROUP = 0x40000000000LL, + ACL = 0x80000000000LL + }; + + static string Object_to_str(Object ob) + { + switch (ob) + { + case VM: return "VM" ; break; + case HOST: return "HOST" ; break; + case NET: return "NET" ; break; + case IMAGE: return "IMAGE" ; break; + case USER: return "USER" ; break; + case TEMPLATE: return "TEMPLATE" ; break; + case GROUP: return "GROUP" ; break; + default: return ""; + } }; /** diff --git a/include/Nebula.h b/include/Nebula.h index bbb69f126e..7ac0e3513c 100644 --- a/include/Nebula.h +++ b/include/Nebula.h @@ -36,6 +36,7 @@ #include "RequestManager.h" #include "HookManager.h" #include "AuthManager.h" +#include "AclManager.h" #include "ImageManager.h" #include "Callbackable.h" @@ -134,6 +135,11 @@ public: return imagem; }; + AclManager * get_aclm() + { + return aclm; + }; + // -------------------------------------------------------------- // Environment & Configuration // -------------------------------------------------------------- @@ -249,7 +255,7 @@ private: Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0), upool(0),ipool(0),gpool(0),tpool(0),lcm(0),vmm(0),im(0),tm(0), - dm(0),rm(0),hm(0),authm(0),imagem(0) + dm(0),rm(0),hm(0),authm(0),aclm(0),imagem(0) { const char * nl = getenv("ONE_LOCATION"); @@ -359,6 +365,11 @@ private: delete authm; } + if ( aclm != 0) + { + delete aclm; + } + if ( imagem != 0) { delete imagem; @@ -425,6 +436,7 @@ private: RequestManager * rm; HookManager * hm; AuthManager * authm; + AclManager * aclm; ImageManager * imagem; // --------------------------------------------------------------- diff --git a/include/Request.h b/include/Request.h index 25a21811f4..a649deda6e 100644 --- a/include/Request.h +++ b/include/Request.h @@ -88,7 +88,7 @@ protected: /* -------------------------------------------------------------------- */ /** - * Performs a basic autorization for this request using the uid/gid + * Performs a basic authorization for this request using the uid/gid * from the request. The function gets the object from the pool to get * the public attribute and its owner. The authorization is based on * object and type of operation for the request. diff --git a/include/RequestManagerAcl.h b/include/RequestManagerAcl.h new file mode 100644 index 0000000000..3ce9501f87 --- /dev/null +++ b/include/RequestManagerAcl.h @@ -0,0 +1,123 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef REQUEST_MANAGER_ACL_H +#define REQUEST_MANAGER_ACL_H + +#include "Request.h" +#include "Nebula.h" + +using namespace std; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class RequestManagerAcl: public Request +{ +protected: + RequestManagerAcl( const string& method_name, + const string& help, + const string& params) + :Request(method_name,params,help) + { + auth_object = AuthRequest::ACL; + }; + + ~RequestManagerAcl(){}; + + /* -------------------------------------------------------------------- */ + + virtual void request_execute(xmlrpc_c::paramList const& _paramList); + + /* -------------------------------------------------------------------- */ + + virtual int perform_operation(string& error_msg) + { + return 0; + }; + + /* -------------------------------------------------------------------- */ + + long long user; + long long resource; + long long rights; + + AclManager * aclm; +}; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class AclAddRule : public RequestManagerAcl +{ +public: + AclAddRule(): + RequestManagerAcl("AclAddRule", + "Adds a new ACL rule", + "A:ssss") + { + // TODO: auth_op ? + }; + + ~AclAddRule(){}; + + int perform_operation(string& error_msg); +}; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class AclDelRule : public RequestManagerAcl +{ +public: + AclDelRule(): + RequestManagerAcl("AclDelRule", + "Deletes an existing ACL rule", + "A:ssss") + { + // TODO: auth_op ? + }; + + ~AclDelRule(){}; + + int perform_operation(string& error_msg); +}; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class AclInfo: public RequestManagerAcl +{ +public: + AclInfo(): + RequestManagerAcl("AclInfo", + "Returns the ACL rule set", + "A:s") + { + // TODO: auth_op ? + }; + + ~AclInfo(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList); +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +#endif diff --git a/install.sh b/install.sh index 1e5f47b9d4..98c3333e51 100755 --- a/install.sh +++ b/install.sh @@ -371,6 +371,7 @@ BIN_FILES="src/nebula/oned \ src/cli/oneimage \ src/cli/onegroup \ src/cli/onetemplate \ + src/cli/oneacl \ src/onedb/onedb \ share/scripts/one \ src/authm_mad/oneauth" @@ -653,6 +654,7 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \ src/oca/ruby/OpenNebula/TemplatePool.rb \ src/oca/ruby/OpenNebula/Group.rb \ src/oca/ruby/OpenNebula/GroupPool.rb \ + src/oca/ruby/OpenNebula/Acl.rb \ src/oca/ruby/OpenNebula/XMLUtils.rb" #------------------------------------------------------------------------------- @@ -756,7 +758,8 @@ CLI_BIN_FILES="src/cli/onevm \ src/cli/oneuser \ src/cli/oneimage \ src/cli/onetemplate \ - src/cli/onegroup" + src/cli/onegroup \ + src/cli/oneacl" CLI_CONF_FILES="src/cli/etc/onegroup.yaml \ src/cli/etc/onehost.yaml \ diff --git a/src/authm/AclManager.cc b/src/authm/AclManager.cc new file mode 100644 index 0000000000..aad2efb809 --- /dev/null +++ b/src/authm/AclManager.cc @@ -0,0 +1,108 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "AclManager.h" +#include "NebulaLog.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +bool AclManager::authorize(int uid, const set &user_groups, + AuthRequest::Object obj_type, int obj_id, int obj_gid, + AuthRequest::Operation op) +{ + ostringstream oss; + + bool auth = false; + + // Build masks for request + long long user_req = AclRule::INDIVIDUAL_ID + uid; + long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; + long long resource_gid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_gid; + long long rights_req = op; + + long long individual_obj_type = + ( obj_type | AclRule::INDIVIDUAL_ID | 0xFFFFFFFF ); + + long long group_obj_type = + ( obj_type | AclRule::GROUP_ID | 0xFFFFFFFF ); + + AclRule request_rule(user_req, resource_oid_req, rights_req); + oss << "Request " << request_rule.to_str(); + NebulaLog::log("ACL",Log::DEBUG,oss); + + + set::iterator rule; + + for ( rule = acl_set.begin() ; rule != acl_set.end(); rule++ ) + { + oss.str(""); + oss << "> Rule " << rule->to_str(); + NebulaLog::log("ACL",Log::DEBUG,oss); + + // TODO: This only works for individual uid + + auth = + // This rule applies to this individual user ID + ( rule->user == user_req ) + && + ( + // Rule's object type and individual object ID match + ( ( rule->resource & individual_obj_type ) == resource_oid_req ) + || + // Or rule's object type and group object ID match + ( ( rule->resource & group_obj_type ) == resource_gid_req ) + ) + && + ( ( rule->rights & rights_req ) == rights_req ); + + if ( auth == true ) + { + oss.str("Permission granted"); + NebulaLog::log("ACL",Log::DEBUG,oss); + + return true; + } + } + + oss.str("No more rules, permission not granted "); + NebulaLog::log("ACL",Log::DEBUG,oss); + + return false; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::dump(ostringstream& oss) +{ + set::iterator rule; + string xml; + + oss << ""; + + for ( rule = acl_set.begin() ; rule != acl_set.end(); rule++ ) + { + oss << rule->to_xml(xml); + } + + oss << ""; + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/authm/AclRule.cc b/src/authm/AclRule.cc new file mode 100644 index 0000000000..fccefba478 --- /dev/null +++ b/src/authm/AclRule.cc @@ -0,0 +1,151 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "AclRule.h" +#include "AuthManager.h" +#include "NebulaLog.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +const long long AclRule::INDIVIDUAL_ID = 0x100000000LL; +const long long AclRule::GROUP_ID = 0x200000000LL; +const long long AclRule::ALL_ID = 0x400000000LL; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string AclRule::to_str() const +{ + ostringstream oss; + + oss << "USER:"; + if ( (user & GROUP_ID) != 0 ) + { + oss << "@" << user_id(); + } + else if ( (user & INDIVIDUAL_ID) != 0 ) + { + oss << "#" << user_id(); + } + else + { + oss << "*"; + } + + oss << " RESOURCE:"; + + AuthRequest::Object objects[] = { + AuthRequest::VM, + AuthRequest::HOST, + AuthRequest::NET, + AuthRequest::IMAGE, + AuthRequest::USER, + AuthRequest::TEMPLATE, + AuthRequest::GROUP, + AuthRequest::ACL + }; + + bool prefix = false; + + for ( int i = 0; i < 8; i++ ) + { + if ( (resource & objects[i]) != 0 ) + { + if ( prefix ) + { + oss << "+"; + } + + oss << AuthRequest::Object_to_str( objects[i] ); + prefix = true; + } + } + + oss << "/"; + + if ( (resource & GROUP_ID) != 0 ) + { + oss << "@" << resource_id(); + } + else if ( (resource & INDIVIDUAL_ID) != 0 ) + { + oss << "#" << resource_id(); + } + else + { + oss << "*"; + } + + oss << " OPERATION:"; + + + AuthRequest::Operation operations[] = { + AuthRequest::CREATE, + AuthRequest::DELETE, + AuthRequest::USE, + AuthRequest::MANAGE, + AuthRequest::INFO, + AuthRequest::INFO_POOL, + AuthRequest::INFO_POOL_MINE, + AuthRequest::INSTANTIATE, + AuthRequest::CHOWN + }; + + prefix = false; + + for ( int i = 0; i < 10; i++ ) + { + if ( (rights & operations[i]) != 0 ) + { + if ( prefix ) + { + oss << "+"; + } + + oss << AuthRequest::Operation_to_str( operations[i] ); + prefix = true; + } + } + + return oss.str(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string& AclRule::to_xml(string& xml) const +{ + ostringstream oss; + + oss << + "" + "" << hex << user << "" << + "" << hex << resource << "" << + "" << hex << rights << "" << + + // TODO: Element DEBUG contains a human friendly string + "" << to_str() << "" << + + ""; + + xml = oss.str(); + + return xml; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index 0753d69f85..2fde223c11 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -39,16 +39,7 @@ void AuthRequest::add_auth(Object ob, ostringstream oss; bool auth; - switch (ob) - { - case VM: oss << "VM:" ; break; - case HOST: oss << "HOST:" ; break; - case NET: oss << "NET:" ; break; - case IMAGE: oss << "IMAGE:" ; break; - case USER: oss << "USER:" ; break; - case TEMPLATE: oss << "TEMPLATE:" ; break; - case GROUP: oss << "GROUP:" ; break; - } + oss << Object_to_str(ob) << ":"; if (op == CREATE || op == INSTANTIATE) //encode the ob_id, it is a template { @@ -69,44 +60,7 @@ void AuthRequest::add_auth(Object ob, oss << ob_id << ":"; } - switch (op) - { - case CREATE: - oss << "CREATE:" ; - break; - - case DELETE: - oss << "DELETE:" ; - break; - - case USE: - oss << "USE:" ; - break; - - case MANAGE: - oss << "MANAGE:" ; - break; - - case INFO: - oss << "INFO:" ; - break; - - case INFO_POOL: - oss << "INFO_POOL:" ; - break; - - case INFO_POOL_MINE: - oss << "INFO_POOL_MINE:" ; - break; - - case INSTANTIATE: - oss << "INSTANTIATE:" ; - break; - - case CHOWN: - oss << "CHOWN:" ; - break; - } + oss << Operation_to_str(op) << ":"; oss << owner << ":" << pub; @@ -120,75 +74,20 @@ void AuthRequest::add_auth(Object ob, } else { - auth = false; + // TODO, the set of object ids is needed + set emtpy_set; - switch (op) - { - case CREATE: - if ( ob == VM || ob == NET || ob == IMAGE || ob == TEMPLATE ) - { - auth = true; - } - break; + int ob_gid = 0; - case INSTANTIATE: - if ( ob == VM ) - { - auth = true; - } - break; + istringstream iss(ob_id); + int ob_id_int; - case DELETE: - auth = owner == uid; - break; + iss >> ob_id_int; - case USE: - if (ob == NET || ob == IMAGE || ob == TEMPLATE) - { - auth = (owner == uid) || pub; - } - else if (ob == HOST) - { - auth = true; - } - break; + Nebula& nd = Nebula::instance(); + AclManager* aclm = nd.get_aclm(); - case MANAGE: - auth = owner == uid; - break; - - case INFO: - if ( ob != USER ) // User info only for root or owner - { - auth = true; - } - else - { - istringstream iss(ob_id); - int ob_id_int; - - iss >> ob_id_int; - - if (ob_id_int == uid) - { - auth = true; - } - } - break; - - case INFO_POOL: - if ( ob != USER ) // User pool only for oneadmin - { - auth = true; - } - break; - - case INFO_POOL_MINE: - auth = true; - break; - case CHOWN: //true only for oneadmin - break; - } + auth = aclm->authorize(uid, emtpy_set, ob, ob_id_int, ob_gid, op); } self_authorize = self_authorize && auth; diff --git a/src/authm/SConstruct b/src/authm/SConstruct index ea9531a972..035670d9b4 100644 --- a/src/authm/SConstruct +++ b/src/authm/SConstruct @@ -23,7 +23,9 @@ lib_name='nebula_authm' # Sources to generate the library source_files=[ 'AuthManager.cc', - 'AuthManagerDriver.cc' + 'AuthManagerDriver.cc', + 'AclManager.cc', + 'AclRule.cc' ] # Build library diff --git a/src/cli/oneacl b/src/cli/oneacl new file mode 100755 index 0000000000..b1fdb3941f --- /dev/null +++ b/src/cli/oneacl @@ -0,0 +1,102 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +ONE_LOCATION=ENV["ONE_LOCATION"] + +if !ONE_LOCATION + RUBY_LIB_LOCATION="/usr/lib/one/ruby" +else + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" +end + +$: << RUBY_LIB_LOCATION +$: << RUBY_LIB_LOCATION+"/cli" + +require 'command_parser' +require 'one_helper' + +cmd = CommandParser::CmdParser.new(ARGV) do + usage "oneacl COMMAND [args..] [options..]" + version OpenNebulaHelper::ONE_VERSION + + ######################################################################## + # Global Options + ######################################################################## + set :option, CommandParser::OPTIONS + + ######################################################################## + # Formatters for arguments + ######################################################################## + # TODO + + ######################################################################## + # Commands + ######################################################################## + + addrule_desc = <<-EOT.unindent + Adds a new ACL rule + EOT + + command :addrule, addrule_desc, :user, :resource, :rights do + acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) + + rc = acl.addrule( args[0], args[1], args[2] ) + + if OpenNebula.is_error?(rc) + [-1, rc.message] + else + puts "Rule added" if options[:verbose] + 0 + end + end + + delrule_desc = <<-EOT.unindent + Deletes an existing ACL rule + EOT + + command :delrule, delrule_desc, :user, :resource, :rights do + acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) + + rc = acl.delrule( args[0], args[1], args[2] ) + + if OpenNebula.is_error?(rc) + [-1, rc.message] + else + puts "Rule deleted" if options[:verbose] + 0 + end + + end + + list_desc = <<-EOT.unindent + Lists the ACL rule set + EOT + + command :list, list_desc,:options=>OpenNebulaHelper::XML do + acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) + + rc = acl.info() + + if OpenNebula.is_error?(rc) + [-1, rc.message] + else + puts acl.to_xml + 0 + end + end +end diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 251afffc46..0f4e9f6434 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -515,6 +515,9 @@ void Nebula::start() } } + // ---- ACL Manager ---- + aclm = new AclManager(); + // ---- Image Manager ---- try { diff --git a/src/oca/ruby/OpenNebula.rb b/src/oca/ruby/OpenNebula.rb index 6f1ffa281e..98f2bcec04 100644 --- a/src/oca/ruby/OpenNebula.rb +++ b/src/oca/ruby/OpenNebula.rb @@ -39,6 +39,7 @@ require 'OpenNebula/Template' require 'OpenNebula/TemplatePool' require 'OpenNebula/Group' require 'OpenNebula/GroupPool' +require 'OpenNebula/Acl' module OpenNebula diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb new file mode 100644 index 0000000000..abac2ff8bb --- /dev/null +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -0,0 +1,87 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +require 'OpenNebula/Pool' + +module OpenNebula + class Acl < XMLElement + + ####################################################################### + # Constants and Class Methods + ####################################################################### + ACL_METHODS = { + :info => "acl.info", + :addrule => "acl.addrule", + :delrule => "acl.delrule" + } + + ####################################################################### + # Class constructor + ####################################################################### + def initialize(client) + @client = client + end + + ####################################################################### + # XML-RPC Methods + ####################################################################### + + # Retrieves the ACL rule set + def info() + rc = @client.call( ACL_METHODS[:info] ) + + if !OpenNebula.is_error?(rc) + initialize_xml(rc, 'ACL') + rc = nil + end + + return rc + end + + # Adds a new ACL rule. + # + # +user+ A hex number, e.g. 0x100000001 + # +resource+ A hex number, e.g. 0x2100000001 + # +rights+ A hex number, e.g. 0x10 + def addrule(user, resource, rights) + rc = @client.call( ACL_METHODS[:addrule], user, resource, rights ) + + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + + # Deletes an existing ACL rule. + # + # +user+ A hex number, e.g. 0x100000001 + # +resource+ A hex number, e.g. 0x2100000001 + # +rights+ A hex number, e.g. 0x10 + def delrule(user, resource, rights) + rc = @client.call( ACL_METHODS[:delrule], user, resource, rights ) + + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + + ####################################################################### + # Helpers + ####################################################################### + + private + + end +end diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index e8fca245bf..9cbf9401cc 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -33,6 +33,7 @@ #include "RequestManagerHost.h" #include "RequestManagerImage.h" #include "RequestManagerUser.h" +#include "RequestManagerAcl.h" #include #include @@ -310,6 +311,11 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr image_chown(new ImageChown()); xmlrpc_c::methodPtr user_chown(new UserChown()); + // ACL Methods + xmlrpc_c::methodPtr acl_addrule(new AclAddRule()); + xmlrpc_c::methodPtr acl_delrule(new AclDelRule()); + xmlrpc_c::methodPtr acl_info(new AclInfo()); + /* VM related methods */ RequestManagerRegistry.addMethod("one.vm.deploy", vm_deploy); RequestManagerRegistry.addMethod("one.vm.action", vm_action); @@ -383,6 +389,11 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.image.chown", image_chown); RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info); + + /* ACL related methods */ + RequestManagerRegistry.addMethod("one.acl.addrule", acl_addrule); + RequestManagerRegistry.addMethod("one.acl.delrule", acl_delrule); + RequestManagerRegistry.addMethod("one.acl.info", acl_info); }; /* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerAcl.cc b/src/rm/RequestManagerAcl.cc new file mode 100644 index 0000000000..c50d73d2f8 --- /dev/null +++ b/src/rm/RequestManagerAcl.cc @@ -0,0 +1,152 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "RequestManagerAcl.h" + +using namespace std; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) +{ +/* + xmlrpc-c version 1.07 can manage 64 bit numbers, but not all distros. ship + the latest version. + + user = xmlrpc_c::value_i8(paramList.getI8(1)); + resource = xmlrpc_c::value_i8(paramList.getI8(2)); + rights = xmlrpc_c::value_i8(paramList.getI8(3)); +*/ + + istringstream iss; + + iss.str( xmlrpc_c::value_string(paramList.getString(1)) ); + iss >> hex >> user; + + iss.clear(); + iss.str( xmlrpc_c::value_string(paramList.getString(2)) ); + iss >> hex >> resource; + + iss.clear(); + iss.str( xmlrpc_c::value_string(paramList.getString(3)) ); + iss >> hex >> rights; + + + + // TODO, debug +/* + int iu, id, it; + + iss.clear(); + iss.str( xmlrpc_c::value_string(paramList.getString(1)) ); + iss >> iu; + + iss.clear(); + iss.str( xmlrpc_c::value_string(paramList.getString(2)) ); + iss >> id; + + iss.clear(); + iss.str( xmlrpc_c::value_string(paramList.getString(3)) ); + iss >> it; + + + + ostringstream oss; + string u = xmlrpc_c::value_string(paramList.getString(1)); + string d = xmlrpc_c::value_string(paramList.getString(2)); + string t = xmlrpc_c::value_string(paramList.getString(3)); + + oss << "\n"; + oss << "User : " << u << ", " << iu << ", dec: " << dec << user << "\n"; + oss << "Resource : " << d << ", " << id << ", dec: " << dec << resource << "\n"; + oss << "Rights : " << t << ", " << it << ", dec: " << dec << rights << "\n"; + NebulaLog::log("ACL-RM",Log::DEBUG,oss); +*/ + + Nebula& nd = Nebula::instance(); + aclm = nd.get_aclm(); + + string error_msg; + + // TODO: Only oneadmin can manage ACL + if ( uid != 0 ) + { + failure_response(AUTHORIZATION, + authorization_error("Only oneadmin can manage ACL rules")); + return; + } + + int rc = perform_operation(error_msg); + + if ( rc != 0 ) + { + failure_response(INTERNAL, request_error(error_msg, "")); + return; + } + + success_response(""); + + return; +} + +/* ------------------------------------------------------------------------- */ + +int AclAddRule::perform_operation(string& error_msg) +{ + return aclm->add_rule(user, resource, rights); +} + +/* ------------------------------------------------------------------------- */ + +int AclDelRule::perform_operation(string& error_msg) +{ + return aclm->del_rule(user, resource, rights); +} + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void AclInfo::request_execute(xmlrpc_c::paramList const& paramList) +{ + Nebula& nd = Nebula::instance(); + aclm = nd.get_aclm(); + + ostringstream oss; + int rc; + + // TODO: Only oneadmin can manage ACL + if ( uid != 0 ) + { + failure_response(AUTHORIZATION, + authorization_error("Only oneadmin can manage ACL rules")); + return; + } + + rc = aclm->dump(oss); + + if ( rc != 0 ) + { + failure_response(INTERNAL, request_error("Internal Error","")); + return; + } + + success_response( oss.str() ); + + return; +} + +/* ------------------------------------------------------------------------- */ diff --git a/src/rm/SConstruct b/src/rm/SConstruct index a025765a41..b6880c9758 100644 --- a/src/rm/SConstruct +++ b/src/rm/SConstruct @@ -38,36 +38,7 @@ source_files=[ 'RequestManagerHost.cc', 'RequestManagerImage.cc', 'RequestManagerChown.cc', - -# 'RequestManagerAction.cc', -# 'RequestManagerAllocate.cc', -# 'RequestManagerDeploy.cc', -# 'RequestManagerMigrate.cc', -# 'RequestManagerSaveDisk.cc', -# 'RequestManagerHostAllocate.cc', -# 'RequestManagerHostEnable.cc', -# 'RequestManagerImageAllocate.cc', -# 'RequestManagerImageUpdate.cc', -# 'RequestManagerImageRemoveAttribute.cc', -# 'RequestManagerImagePublish.cc', -# 'RequestManagerImagePersistent.cc', -# 'RequestManagerImageEnable.cc', -# 'RequestManagerClusterAdd.cc', -# 'RequestManagerClusterAllocate.cc', -# 'RequestManagerClusterRemove.cc', -# 'RequestManagerGroupAllocate.cc', -# 'RequestManagerVirtualNetworkAllocate.cc', -# 'RequestManagerVirtualNetworkInfo.cc', -# 'RequestManagerVirtualNetworkPublish.cc', -# 'RequestManagerVirtualNetworkAddLeases.cc', -# 'RequestManagerVirtualNetworkRemoveLeases.cc', -# 'RequestManagerUserAllocate.cc', -# 'RequestManagerUserChangePassword.cc', -# 'RequestManagerTemplateAllocate.cc', -# 'RequestManagerTemplateUpdate.cc', -# 'RequestManagerTemplateRemoveAttribute.cc', -# 'RequestManagerTemplatePublish.cc', -# 'RequestManagerChown.cc', + 'RequestManagerAcl.cc', ] # Build library From 94d1615e582f4c63c6719231ff3a389b6d8b0ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 24 Jun 2011 13:22:17 +0200 Subject: [PATCH 02/75] Feature #687: Store acl rules in a multimap. Add error messages when adding/deleting a wrong rule --- include/AclManager.h | 46 +++--------- src/authm/AclManager.cc | 138 +++++++++++++++++++++++++++++++----- src/authm/AclRule.cc | 2 +- src/rm/RequestManagerAcl.cc | 4 +- 4 files changed, 133 insertions(+), 57 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index d8e97fe059..76ea596844 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -17,8 +17,6 @@ #ifndef ACL_MANAGER_H_ #define ACL_MANAGER_H_ -#include - #include "AuthManager.h" #include "AclRule.h" @@ -29,53 +27,25 @@ class AclManager : public ObjectSQL public: AclManager(){}; + ~AclManager(); + /* ---------------------------------------------------------------------- */ /* Rule management */ /* ---------------------------------------------------------------------- */ - bool authorize(int uid, const set &user_groups, + const bool authorize(int uid, const set &user_groups, AuthRequest::Object obj_type, int obj_id, int obj_gid, AuthRequest::Operation op); /* ---------------------------------------------------------------------- */ - int add_rule(long long user, long long resource, long long rights) - { - AclRule rule(user, resource, rights); - return add_rule(rule); - }; - - int add_rule(const AclRule &rule) - { - pair::iterator,bool> ret; - - ret = acl_set.insert(rule); - - if( !ret.second ) - { - return -1; - } - - return 0; - }; + int add_rule(long long user, long long resource, long long rights, + string& error_str); /* ---------------------------------------------------------------------- */ - int del_rule(long long user, long long resource, long long rights) - { - AclRule rule(user, resource, rights); - return del_rule(rule); - }; - - int del_rule(AclRule &rule) - { - if( acl_set.erase(rule) != 1 ) - { - return -1; - } - - return 0; - }; + int del_rule(long long user, long long resource, long long rights, + string& error_str); /* ---------------------------------------------------------------------- */ /* DB management */ @@ -130,7 +100,7 @@ public: int dump(ostringstream& oss); private: - set acl_set; + multimap acl_rules; }; #endif /*ACL_MANAGER_H*/ diff --git a/src/authm/AclManager.cc b/src/authm/AclManager.cc index aad2efb809..013c190cc7 100644 --- a/src/authm/AclManager.cc +++ b/src/authm/AclManager.cc @@ -20,18 +20,35 @@ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -bool AclManager::authorize(int uid, const set &user_groups, +AclManager::~AclManager() +{ + multimap::iterator it; + + for ( it = acl_rules.begin(); it != acl_rules.end(); it++ ) + { + delete it->second; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +const bool AclManager::authorize(int uid, const set &user_groups, AuthRequest::Object obj_type, int obj_id, int obj_gid, AuthRequest::Operation op) { ostringstream oss; + multimap::iterator it; + pair::iterator, + multimap::iterator> index; + bool auth = false; // Build masks for request long long user_req = AclRule::INDIVIDUAL_ID + uid; long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; - long long resource_gid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_gid; + long long resource_gid_req = obj_type + AclRule::GROUP_ID + obj_gid; long long rights_req = op; long long individual_obj_type = @@ -45,29 +62,25 @@ bool AclManager::authorize(int uid, const set &user_groups, NebulaLog::log("ACL",Log::DEBUG,oss); - set::iterator rule; + // TODO: This only works for individual uid + index = acl_rules.equal_range( user_req ); - for ( rule = acl_set.begin() ; rule != acl_set.end(); rule++ ) + for ( it = index.first; it != index.second; it++) { oss.str(""); - oss << "> Rule " << rule->to_str(); + oss << "> Rule " << it->second->to_str(); NebulaLog::log("ACL",Log::DEBUG,oss); - // TODO: This only works for individual uid - auth = - // This rule applies to this individual user ID - ( rule->user == user_req ) - && ( // Rule's object type and individual object ID match - ( ( rule->resource & individual_obj_type ) == resource_oid_req ) + ( ( it->second->resource & individual_obj_type ) == resource_oid_req ) || // Or rule's object type and group object ID match - ( ( rule->resource & group_obj_type ) == resource_gid_req ) + ( ( it->second->resource & group_obj_type ) == resource_gid_req ) ) && - ( ( rule->rights & rights_req ) == rights_req ); + ( ( it->second->rights & rights_req ) == rights_req ); if ( auth == true ) { @@ -87,16 +100,109 @@ bool AclManager::authorize(int uid, const set &user_groups, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int AclManager::add_rule(long long user, long long resource, long long rights, + string& error_str) +{ + AclRule * rule = new AclRule(user, resource, rights); + + ostringstream oss; + + multimap::iterator it; + pair::iterator, + multimap::iterator> index; + + bool found = false; + + index = acl_rules.equal_range( user ); + + for ( it = index.first; (it != index.second && !found); it++) + { + found = *(it->second) == *rule; + if ( it->second->resource == resource && + it->second->rights == rights ) + { + found = true; + } + } + + if ( found ) + { + oss << "Rule " << rule->to_str() << " already exists"; + error_str = oss.str(); + + delete rule; + return -1; + } + +/* + if ( rule->malformed() ) + { + delete rule; + NebulaLog::log("ACL", Log::INFO, "TODO"); + return -2; + } +*/ + + acl_rules.insert( make_pair(rule->user, rule) ); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::del_rule(long long user, long long resource, long long rights, + string& error_str) +{ + multimap::iterator it; + pair::iterator, + multimap::iterator> index; + + bool found = false; + + index = acl_rules.equal_range( user ); + + for ( it = index.first; (it != index.second && !found); it++) + { + if ( it->second->resource == resource && + it->second->rights == rights ) + { + delete it->second; + acl_rules.erase( it ); + + found = true; + } + } + + if ( found ) + { + return 0; + } + else + { + AclRule rule(user, resource, rights); + + ostringstream oss; + oss << "Rule " << rule.to_str() << " does not exist"; + error_str = oss.str(); + + return -1; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int AclManager::dump(ostringstream& oss) { - set::iterator rule; + multimap::iterator it; string xml; oss << ""; - for ( rule = acl_set.begin() ; rule != acl_set.end(); rule++ ) + for ( it = acl_rules.begin() ; it != acl_rules.end(); it++ ) { - oss << rule->to_xml(xml); + oss << it->second->to_xml(xml); } oss << ""; diff --git a/src/authm/AclRule.cc b/src/authm/AclRule.cc index fccefba478..efede82ac4 100644 --- a/src/authm/AclRule.cc +++ b/src/authm/AclRule.cc @@ -107,7 +107,7 @@ string AclRule::to_str() const prefix = false; - for ( int i = 0; i < 10; i++ ) + for ( int i = 0; i < 9; i++ ) { if ( (rights & operations[i]) != 0 ) { diff --git a/src/rm/RequestManagerAcl.cc b/src/rm/RequestManagerAcl.cc index c50d73d2f8..fce1eb6c63 100644 --- a/src/rm/RequestManagerAcl.cc +++ b/src/rm/RequestManagerAcl.cc @@ -107,14 +107,14 @@ void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) int AclAddRule::perform_operation(string& error_msg) { - return aclm->add_rule(user, resource, rights); + return aclm->add_rule(user, resource, rights, error_msg); } /* ------------------------------------------------------------------------- */ int AclDelRule::perform_operation(string& error_msg) { - return aclm->del_rule(user, resource, rights); + return aclm->del_rule(user, resource, rights, error_msg); } /* ------------------------------------------------------------------------- */ From edcfcb8c1752781c56b95268b199db815109ed99 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 24 Jun 2011 17:50:03 +0200 Subject: [PATCH 03/75] feature #696: Tests now can be executed with Ruby 1.9 --- src/oca/ruby/test/HostPool_spec.rb | 5 +++-- src/oca/ruby/test/Host_spec.rb | 5 +++-- src/oca/ruby/test/UserPool_spec.rb | 5 +++-- src/oca/ruby/test/User_spec.rb | 5 +++-- src/oca/ruby/test/VirtualMachinePool_spec.rb | 5 +++-- src/oca/ruby/test/VirtualMachine_spec.rb | 5 +++-- src/oca/ruby/test/VirtualNetworkPool_spec.rb | 5 +++-- src/oca/ruby/test/VirtualNetwork_spec.rb | 5 +++-- 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/oca/ruby/test/HostPool_spec.rb b/src/oca/ruby/test/HostPool_spec.rb index 5d08319618..7c2d083330 100644 --- a/src/oca/ruby/test/HostPool_spec.rb +++ b/src/oca/ruby/test/HostPool_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -78,4 +79,4 @@ module OpenNebula } end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/Host_spec.rb b/src/oca/ruby/test/Host_spec.rb index e2d8cb39e4..5d0a585b19 100644 --- a/src/oca/ruby/test/Host_spec.rb +++ b/src/oca/ruby/test/Host_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -216,4 +217,4 @@ module OpenNebula end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/UserPool_spec.rb b/src/oca/ruby/test/UserPool_spec.rb index 7465cfc485..22f208b6af 100644 --- a/src/oca/ruby/test/UserPool_spec.rb +++ b/src/oca/ruby/test/UserPool_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -62,4 +63,4 @@ module OpenNebula } end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/User_spec.rb b/src/oca/ruby/test/User_spec.rb index a02911f03e..c3f25fdbc6 100644 --- a/src/oca/ruby/test/User_spec.rb +++ b/src/oca/ruby/test/User_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -142,4 +143,4 @@ module OpenNebula end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/VirtualMachinePool_spec.rb b/src/oca/ruby/test/VirtualMachinePool_spec.rb index cd138b5d2f..5d08cce65f 100644 --- a/src/oca/ruby/test/VirtualMachinePool_spec.rb +++ b/src/oca/ruby/test/VirtualMachinePool_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -114,4 +115,4 @@ module OpenNebula } end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/VirtualMachine_spec.rb b/src/oca/ruby/test/VirtualMachine_spec.rb index 4fc6c90996..982916fa5a 100644 --- a/src/oca/ruby/test/VirtualMachine_spec.rb +++ b/src/oca/ruby/test/VirtualMachine_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -469,4 +470,4 @@ module OpenNebula @vm.name.should eql(nil) end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/VirtualNetworkPool_spec.rb b/src/oca/ruby/test/VirtualNetworkPool_spec.rb index fd107827c6..5bebce9fa0 100644 --- a/src/oca/ruby/test/VirtualNetworkPool_spec.rb +++ b/src/oca/ruby/test/VirtualNetworkPool_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -84,4 +85,4 @@ module OpenNebula } end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/test/VirtualNetwork_spec.rb b/src/oca/ruby/test/VirtualNetwork_spec.rb index b74982bf52..3d3431da2f 100644 --- a/src/oca/ruby/test/VirtualNetwork_spec.rb +++ b/src/oca/ruby/test/VirtualNetwork_spec.rb @@ -1,4 +1,5 @@ -$: << '../' +$: << '../' \ + << './' require 'OpenNebula' require 'helpers/MockClient' @@ -152,4 +153,4 @@ module OpenNebula end end -end \ No newline at end of file +end From 9e21a2adc618dda0a0448dec914364b0893799d2 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 24 Jun 2011 17:50:50 +0200 Subject: [PATCH 04/75] feature #696: filter pool methods can specify start and end ids of resources --- include/RequestManagerPoolInfoFilter.h | 2 +- src/rm/RequestManagerPoolInfoFilter.cc | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h index 102d24845d..8c8296a7e8 100644 --- a/include/RequestManagerPoolInfoFilter.h +++ b/include/RequestManagerPoolInfoFilter.h @@ -32,7 +32,7 @@ class RequestManagerPoolInfoFilter: public Request protected: RequestManagerPoolInfoFilter(const string& method_name, const string& help) - :Request(method_name,"A:si",help) + :Request(method_name,"A:siii",help) { auth_op = AuthRequest::INFO_POOL; }; diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc index 88a4fe2647..524b2466ea 100644 --- a/src/rm/RequestManagerPoolInfoFilter.cc +++ b/src/rm/RequestManagerPoolInfoFilter.cc @@ -33,6 +33,8 @@ const int RequestManagerPoolInfoFilter::MINE_GROUP = -1; void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& paramList) { int filter_flag = xmlrpc_c::value_int(paramList.getInt(1)); + int start_id = xmlrpc_c::value_int(paramList.getInt(2)); + int end_id = xmlrpc_c::value_int(paramList.getInt(3)); ostringstream oss, where_string; @@ -47,7 +49,7 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa switch(filter_flag) { case MINE: - where_string << "UID=" << uid; + where_string << "uid = " << uid; auth_op = AuthRequest::INFO_POOL_MINE; break; @@ -55,15 +57,29 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa break; case MINE_GROUP: - where_string << "UID=" << uid << " OR GID=" << gid; + where_string << "( uid = " << uid << " OR gid= " << gid << " )"; auth_op = AuthRequest::INFO_POOL_MINE; break; default: - where_string << "UID=" << filter_flag; + where_string << "uid = " << filter_flag; break; } + if ( start_id != -1 ) + { + where_string << "AND ( oid >= " << start_id; + + if ( end_id != -1 ) + { + where_string << " AND oid <= " << end_id << " )"; + } + else + { + where_string << " )"; + } + } + if ( basic_authorization(-1) == false ) { return; From 953c02c79235069b64200b7290f0dd44aeb8d704 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 24 Jun 2011 17:51:30 +0200 Subject: [PATCH 05/75] Feature #696: Upgraded OCA (Ruby) API to match new filter functionality in pool.info methods --- src/oca/ruby/OpenNebula/ImagePool.rb | 23 +++++++++++++-- src/oca/ruby/OpenNebula/Pool.rb | 29 ++++++++++++++++++- src/oca/ruby/OpenNebula/TemplatePool.rb | 24 ++++++++++++--- src/oca/ruby/OpenNebula/VirtualMachinePool.rb | 21 ++++++++++++-- src/oca/ruby/OpenNebula/VirtualNetworkPool.rb | 23 +++++++++++++-- 5 files changed, 107 insertions(+), 13 deletions(-) diff --git a/src/oca/ruby/OpenNebula/ImagePool.rb b/src/oca/ruby/OpenNebula/ImagePool.rb index 2d60908b63..4cec6b3840 100644 --- a/src/oca/ruby/OpenNebula/ImagePool.rb +++ b/src/oca/ruby/OpenNebula/ImagePool.rb @@ -47,9 +47,26 @@ module OpenNebula # XML-RPC Methods for the Image Object ####################################################################### - # Retrieves all or part of the Images in the pool. - def info() - super(IMAGE_POOL_METHODS[:info],@user_id) + # Retrieves all or part of the VirtualMachines in the pool. + def info(*args) + case args.size + when 0 + info_filter(IMAGE_POOL_METHODS[:info],@user_id,-1,-1) + when 3 + info_filter(IMAGE_POOL_METHODS[:info],args[0],args[1],args[2]) + end + end + + def info_all() + return super(IMAGE_POOL_METHODS[:info]) + end + + def info_mine() + return super(IMAGE_POOL_METHODS[:info]) + end + + def info_group() + return super(IMAGE_POOL_METHODS[:info]) end end end diff --git a/src/oca/ruby/OpenNebula/Pool.rb b/src/oca/ruby/OpenNebula/Pool.rb index 30fa180c51..58c342e547 100644 --- a/src/oca/ruby/OpenNebula/Pool.rb +++ b/src/oca/ruby/OpenNebula/Pool.rb @@ -22,6 +22,10 @@ module OpenNebula include Enumerable protected + # Constants for info queries (include/RequestManagerPoolInfoFilter.h) + INFO_GROUP = -1 + INFO_ALL = -2 + INFO_MINE = -3 #pool:: _String_ XML name of the root element #element:: _String_ XML name of the Pool elements @@ -48,13 +52,36 @@ module OpenNebula ####################################################################### # Common XML-RPC Methods for all the Pool Types ####################################################################### + + #Gets the pool without any filter. Host, Group and User Pools + # xml_method:: _String_ the name of the XML-RPC method + def info(xml_method) + return xmlrpc_info(xml_method) + end + def info_all(xml_method) + return xmlrpc_info(xml_method,INFO_ALL,-1,-1) + end + + def info_mine(xml_method) + return xmlrpc_info(xml_method,INFO_MINE,-1,-1) + end + + def info_group(xml_method) + return xmlrpc_info(xml_method,INFO_GROUP,-1,-1) + end + + def info_filter(xml_method, who, start_id, end_id) + return xmlrpc_info(xml_method,who, start_id, end_id) + end + + private # Calls to the corresponding info method to retreive the pool # representation in XML format # xml_method:: _String_ the name of the XML-RPC method # args:: _Array_ with additional arguments for the info call # [return] nil in case of success or an Error object - def info(xml_method,*args) + def xmlrpc_info(xml_method,*args) rc = @client.call(xml_method,*args) if !OpenNebula.is_error?(rc) diff --git a/src/oca/ruby/OpenNebula/TemplatePool.rb b/src/oca/ruby/OpenNebula/TemplatePool.rb index 8cebdd8877..c5174036bc 100644 --- a/src/oca/ruby/OpenNebula/TemplatePool.rb +++ b/src/oca/ruby/OpenNebula/TemplatePool.rb @@ -46,10 +46,26 @@ module OpenNebula # --------------------------------------------------------------------- # XML-RPC Methods for the Template Object # --------------------------------------------------------------------- + # Retrieves all or part of the VirtualMachines in the pool. + def info(*args) + case args.size + when 0 + info_filter(TEMPLATE_POOL_METHODS[:info],@user_id,-1,-1) + when 3 + info_filter(TEMPLATE_POOL_METHODS[:info],args[0],args[1],args[2]) + end + end - # Retrieves all the Templates in the pool. - def info() - super(TEMPLATE_POOL_METHODS[:info], @user_id) + def info_all() + return super(TEMPLATE_POOL_METHODS[:info]) + end + + def info_mine() + return super(TEMPLATE_POOL_METHODS[:info]) + end + + def info_group() + return super(TEMPLATE_POOL_METHODS[:info]) end end -end \ No newline at end of file +end diff --git a/src/oca/ruby/OpenNebula/VirtualMachinePool.rb b/src/oca/ruby/OpenNebula/VirtualMachinePool.rb index 766fd202dc..7a61c1ae98 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachinePool.rb +++ b/src/oca/ruby/OpenNebula/VirtualMachinePool.rb @@ -48,8 +48,25 @@ module OpenNebula ####################################################################### # Retrieves all or part of the VirtualMachines in the pool. - def info() - super(VM_POOL_METHODS[:info],@user_id) + def info(*args) + case args.size + when 0 + info_filter(VM_POOL_METHODS[:info],@user_id,-1,-1) + when 3 + info_filter(VM_POOL_METHODS[:info],args[0],args[1],args[2]) + end + end + + def info_all() + return super(VM_POOL_METHODS[:info]) + end + + def info_mine() + return super(VM_POOL_METHODS[:info]) + end + + def info_group() + return super(VM_POOL_METHODS[:info]) end end end diff --git a/src/oca/ruby/OpenNebula/VirtualNetworkPool.rb b/src/oca/ruby/OpenNebula/VirtualNetworkPool.rb index 0e41cc99ba..4267ac1830 100644 --- a/src/oca/ruby/OpenNebula/VirtualNetworkPool.rb +++ b/src/oca/ruby/OpenNebula/VirtualNetworkPool.rb @@ -47,9 +47,26 @@ module OpenNebula # XML-RPC Methods for the Virtual Network Object ####################################################################### - # Retrieves all or part of the VirtualNetwork in the pool. - def info() - super(VN_POOL_METHODS[:info],@user_id) + # Retrieves all or part of the VirtualMachines in the pool. + def info(*args) + case args.size + when 0 + info_filter(VN_POOL_METHODS[:info],@user_id,-1,-1) + when 3 + info_filter(VN_POOL_METHODS[:info],args[0],args[1],args[2]) + end + end + + def info_all() + return super(VN_POOL_METHODS[:info]) + end + + def info_mine() + return super(VN_POOL_METHODS[:info]) + end + + def info_group() + return super(VN_POOL_METHODS[:info]) end end end From 7e7c2451ecb9c461e830bd7711bd0ab9e0094fd8 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 24 Jun 2011 18:43:20 +0200 Subject: [PATCH 06/75] feature #696: Fixes minor bugs --- src/oca/ruby/OpenNebula/Pool.rb | 9 ++++----- src/rm/RequestManagerPoolInfoFilter.cc | 10 ++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/oca/ruby/OpenNebula/Pool.rb b/src/oca/ruby/OpenNebula/Pool.rb index 58c342e547..2608848e84 100644 --- a/src/oca/ruby/OpenNebula/Pool.rb +++ b/src/oca/ruby/OpenNebula/Pool.rb @@ -22,11 +22,6 @@ module OpenNebula include Enumerable protected - # Constants for info queries (include/RequestManagerPoolInfoFilter.h) - INFO_GROUP = -1 - INFO_ALL = -2 - INFO_MINE = -3 - #pool:: _String_ XML name of the root element #element:: _String_ XML name of the Pool elements #client:: _Client_ represents a XML-RPC connection @@ -93,6 +88,10 @@ module OpenNebula end public + # Constants for info queries (include/RequestManagerPoolInfoFilter.h) + INFO_GROUP = -1 + INFO_ALL = -2 + INFO_MINE = -3 # Iterates over every PoolElement in the Pool and calls the block with a # a PoolElement obtained calling the factory method diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc index 524b2466ea..9b1ac59444 100644 --- a/src/rm/RequestManagerPoolInfoFilter.cc +++ b/src/rm/RequestManagerPoolInfoFilter.cc @@ -68,7 +68,12 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa if ( start_id != -1 ) { - where_string << "AND ( oid >= " << start_id; + if (filter_flag != ALL) + { + where_string << " AND "; + } + + where_string << "( oid >= " << start_id; if ( end_id != -1 ) { @@ -84,7 +89,8 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa { return; } - + + auth_object = AuthRequest::VM; // Call the template pool dump rc = pool->dump(oss,where_string.str()); From 9cea16cd5efa8167f3c2b3861d11336155302029 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 25 Jun 2011 01:29:44 +0200 Subject: [PATCH 07/75] feature #696: Virtual Machine info method now returns the full history of the VM. --- include/RequestManagerInfo.h | 8 ++ include/VirtualMachine.h | 23 ++++++ src/vm/VirtualMachine.cc | 107 ++++++++++++++++---------- src/vm/test/VirtualMachinePoolTest.cc | 3 +- 4 files changed, 100 insertions(+), 41 deletions(-) diff --git a/include/RequestManagerInfo.h b/include/RequestManagerInfo.h index cc91e86ee3..a9416f68b9 100644 --- a/include/RequestManagerInfo.h +++ b/include/RequestManagerInfo.h @@ -66,6 +66,14 @@ public: }; ~VirtualMachineInfo(){}; + + /* -------------------------------------------------------------------- */ + + void to_xml(PoolObjectSQL * object, string& str) + { + VirtualMachine * vm = static_cast(object); + vm->to_xml_extended(str); + }; }; /* ------------------------------------------------------------------------- */ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index ff0e436ac5..1aa10ac1ed 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -124,6 +124,14 @@ public: */ string& to_xml(string& xml) const; + /** + * Function to print the VirtualMachine object into a string in + * XML format, with extended information (full history records) + * @param xml the resulting XML string + * @return a reference to the generated string + */ + string& to_xml_extended(string& xml) const; + /** * Rebuilds the object from an xml formatted string * @param xml_str The xml-formatted string @@ -752,6 +760,12 @@ private: */ History * previous_history; + + /** + * Complete set of history records for the VM + */ + vector history_records; + // ------------------------------------------------------------------------- // Logging // ------------------------------------------------------------------------- @@ -859,6 +873,15 @@ private: */ void parse_graphics(); + /** + * Function that renders the VM in XML format optinally including + * extended information (all history records) + * @param xml the resulting XML string + * @param extended include additional info if true + * @return a reference to the generated string + */ + string& to_xml_extended(string& xml, bool extended) const; + protected: //************************************************************************** diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index d6a505fc4c..06a6139c44 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -68,14 +68,9 @@ VirtualMachine::VirtualMachine(int id, VirtualMachine::~VirtualMachine() { - if ( history != 0 ) + for (unsigned int i=0 ; i < history_records.size() ; i++) { - delete history; - } - - if ( previous_history != 0 ) - { - delete previous_history; + delete history_records[i]; } if ( _log != 0 ) @@ -126,18 +121,26 @@ int VirtualMachine::select(SqlDB * db) //Get History Records. Current history is built in from_xml() (if any). if( hasHistory() ) { - last_seq = history->seq; + last_seq = history->seq - 1; - if ( last_seq > 0 ) + for (int i = last_seq; i >= 0; i--) { - previous_history = new History(oid, last_seq - 1); + History * hp; - rc = previous_history->select(db); + hp = new History(oid, i); + rc = hp->select(db); if ( rc != 0) { goto error_previous_history; } + + history_records[i] = hp; + + if ( i == last_seq ) + { + previous_history = hp; + } } } @@ -166,6 +169,7 @@ int VirtualMachine::select(SqlDB * db) error_previous_history: ose << "Can not get previous history record (seq:" << history->seq << ") for VM id: " << oid; + log("ONE", Log::ERROR, ose); return -1; } @@ -558,15 +562,12 @@ void VirtualMachine::add_history( { seq = history->seq + 1; - if (previous_history != 0) - { - delete previous_history; - } - previous_history = history; } history = new History(oid,seq,hid,hostname,vm_dir,vmm_mad,tm_mad); + + history_records.push_back(history); }; /* -------------------------------------------------------------------------- */ @@ -582,21 +583,18 @@ void VirtualMachine::cp_history() } htmp = new History(oid, - history->seq + 1, - history->hid, - history->hostname, - history->vm_dir, - history->vmm_mad_name, - history->tm_mad_name); + history->seq + 1, + history->hid, + history->hostname, + history->vm_dir, + history->vmm_mad_name, + history->tm_mad_name); - if ( previous_history != 0 ) - { - delete previous_history; - } previous_history = history; + history = htmp; - history = htmp; + history_records.push_back(history); } /* -------------------------------------------------------------------------- */ @@ -612,18 +610,17 @@ void VirtualMachine::cp_previous_history() } htmp = new History(oid, - history->seq + 1, - previous_history->hid, - previous_history->hostname, - previous_history->vm_dir, - previous_history->vmm_mad_name, - previous_history->tm_mad_name); - - delete previous_history; + history->seq + 1, + previous_history->hid, + previous_history->hostname, + previous_history->vm_dir, + previous_history->vmm_mad_name, + previous_history->tm_mad_name); previous_history = history; + history = htmp; - history = htmp; + history_records.push_back(history); } /* -------------------------------------------------------------------------- */ @@ -1137,11 +1134,26 @@ error_yy: pthread_mutex_unlock(&lex_mutex); return -1; } - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ string& VirtualMachine::to_xml(string& xml) const +{ + return to_xml_extended(xml,false); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string& VirtualMachine::to_xml_extended(string& xml) const +{ + return to_xml_extended(xml,true); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string& VirtualMachine::to_xml_extended(string& xml, bool extended) const { string template_xml; @@ -1168,7 +1180,21 @@ string& VirtualMachine::to_xml(string& xml) const if ( hasHistory() ) { - oss << history->to_xml(history_xml); + oss << ""; + + if ( extended ) + { + for (unsigned int i=0; i < history_records.size(); i++) + { + oss << history_records[i]->to_xml(history_xml); + } + } + else + { + oss << history->to_xml(history_xml); + } + + oss << ""; } oss << ""; @@ -1227,12 +1253,15 @@ int VirtualMachine::from_xml(const string &xml_str) // Last history entry content.clear(); - ObjectXML::get_nodes("/VM/HISTORY", content); + ObjectXML::get_nodes("/VM/HISTORY_RECORDS/HISTORY", content); if( !content.empty() ) { history = new History(oid); rc += history->from_xml_node(content[0]); + + history_records.resize(history->seq + 1); + history_records[history->seq] = history; } if (rc != 0) diff --git a/src/vm/test/VirtualMachinePoolTest.cc b/src/vm/test/VirtualMachinePoolTest.cc index aeb53b41b7..6e636d0065 100644 --- a/src/vm/test/VirtualMachinePoolTest.cc +++ b/src/vm/test/VirtualMachinePoolTest.cc @@ -76,8 +76,7 @@ const string xml_dump_where = "011VM one010000000000000000"; const string xml_history_dump = - "001VM one010000000000000000101Second VM0200000000000000000A_hostnameA_vm_dir000A_vmm_madA_tm_mad0000000201VM one0200000000000000001C_hostnameC_vm_dir200C_vmm_madC_tm_mad0000000"; - + "001VM one010000000000000000101Second VM0200000000000000000A_hostnameA_vm_dir000A_vmm_madA_tm_mad0000000201VM one0200000000000000001C_hostnameC_vm_dir200C_vmm_madC_tm_mad0000000"; /* ************************************************************************* */ /* ************************************************************************* */ From d5bd0e16bdff8451d81d6a4baef25c519bef2aa3 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 27 Jun 2011 13:19:03 +0200 Subject: [PATCH 08/75] feature #696: Added state flag for VM pool info. Removed uneeded dummps in VMPool --- include/RequestManagerPoolInfoFilter.h | 26 ++++-- include/VirtualMachinePool.h | 15 +--- src/rm/RequestManagerPoolInfoFilter.cc | 109 +++++++++++++++++++++---- src/vm/VirtualMachinePool.cc | 26 ------ 4 files changed, 110 insertions(+), 66 deletions(-) diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h index 8c8296a7e8..88e829cec3 100644 --- a/include/RequestManagerPoolInfoFilter.h +++ b/include/RequestManagerPoolInfoFilter.h @@ -31,8 +31,9 @@ class RequestManagerPoolInfoFilter: public Request { protected: RequestManagerPoolInfoFilter(const string& method_name, - const string& help) - :Request(method_name,"A:siii",help) + const string& help, + const string& signature) + :Request(method_name,signature,help) { auth_op = AuthRequest::INFO_POOL; }; @@ -56,9 +57,17 @@ protected: class VirtualMachinePoolInfo : public RequestManagerPoolInfoFilter { public: + /* -------------------------------------------------------------------- */ + + static const int ALL_VM; /**< VMs in any state (-2) */ + static const int ACTIVE; /**< VMs in any state expect DONE (-1)*/ + + /* -------------------------------------------------------------------- */ + VirtualMachinePoolInfo(): RequestManagerPoolInfoFilter("VirtualMachinePoolInfo", - "Returns the virtual machine instances pool") + "Returns the virtual machine instances pool", + "A:siii") { Nebula& nd = Nebula::instance(); pool = nd.get_vmpool(); @@ -76,7 +85,8 @@ class TemplatePoolInfo : public RequestManagerPoolInfoFilter public: TemplatePoolInfo(): RequestManagerPoolInfoFilter("TemplatePoolInfo", - "Returns the virtual machine template pool") + "Returns the virtual machine template pool", + "A:siii") { Nebula& nd = Nebula::instance(); pool = nd.get_tpool(); @@ -89,13 +99,13 @@ public: /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ - class VirtualNetworkPoolInfo: public RequestManagerPoolInfoFilter { public: VirtualNetworkPoolInfo(): RequestManagerPoolInfoFilter("VirtualNetworkPoolInfo", - "Returns the virtual network pool") + "Returns the virtual network pool", + "A:siii") { Nebula& nd = Nebula::instance(); pool = nd.get_vnpool(); @@ -113,7 +123,8 @@ class ImagePoolInfo: public RequestManagerPoolInfoFilter public: ImagePoolInfo(): RequestManagerPoolInfoFilter("ImagePoolInfo", - "Returns the image pool") + "Returns the image pool", + "A:siii") { Nebula& nd = Nebula::instance(); pool = nd.get_ipool(); @@ -123,7 +134,6 @@ public: ~ImagePoolInfo(){}; }; - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index f84723259c..1ec27adb95 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -137,22 +137,9 @@ public: */ int dump(ostringstream& oss, const string& where) { - return dump(oss, -1, where); + return PoolSQL::dump(oss, "VM_POOL", VirtualMachine::table, where); } - /** - * Dumps the VM pool in XML format. A filter can be also added to the query - * Also the hostname where the VirtualMachine is running is added to the - * pool - * @param oss the output stream to dump the pool contents - * @param where filter for the objects, defaults to all - * @param state include only VMs in this state. -1 means any state, - * except DONE - * - * @return 0 on success - */ - int dump(ostringstream& oss, int state, const string& where); - private: /** * Factory method to produce VM objects diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc index 9b1ac59444..41ea783cdc 100644 --- a/src/rm/RequestManagerPoolInfoFilter.cc +++ b/src/rm/RequestManagerPoolInfoFilter.cc @@ -27,6 +27,12 @@ const int RequestManagerPoolInfoFilter::MINE = -3; const int RequestManagerPoolInfoFilter::MINE_GROUP = -1; +/* ------------------------------------------------------------------------- */ + +const int VirtualMachinePoolInfo::ALL_VM = -2; + +const int VirtualMachinePoolInfo::ACTIVE = -1; + /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ @@ -36,20 +42,33 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa int start_id = xmlrpc_c::value_int(paramList.getInt(2)); int end_id = xmlrpc_c::value_int(paramList.getInt(3)); - ostringstream oss, where_string; + ostringstream oss; + + bool empty = true; + ostringstream where_string; + + ostringstream uid_filter; + ostringstream state_filter; + ostringstream id_filter; + + string uid_str; + string state_str; + string id_str; int rc; + // ------------ User ID filter -------------- + if ( filter_flag < MINE ) { - failure_response(XML_RPC_API, request_error("Incorrect filter_flag","")); + failure_response(XML_RPC_API,request_error("Incorrect filter_flag","")); return; } - + switch(filter_flag) { case MINE: - where_string << "uid = " << uid; + uid_filter << "uid = " << uid; auth_op = AuthRequest::INFO_POOL_MINE; break; @@ -57,40 +76,94 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa break; case MINE_GROUP: - where_string << "( uid = " << uid << " OR gid= " << gid << " )"; + uid_filter << "uid = " << uid << " OR gid = " << gid; auth_op = AuthRequest::INFO_POOL_MINE; break; default: - where_string << "uid = " << filter_flag; + uid_filter << "uid = " << filter_flag; break; } + uid_str = uid_filter.str(); + + // ------------ Resource ID filter -------------- if ( start_id != -1 ) { - if (filter_flag != ALL) + id_filter << "oid >= " << start_id; + + if ( end_id != -1 ) + { + id_filter << " AND oid <= " << end_id; + } + } + + id_str = id_filter.str(); + + // ------------ State filter for VM -------------- + if ( auth_object == AuthRequest::VM ) + { + int state = xmlrpc_c::value_int(paramList.getInt(4)); + + if (( state < MINE ) || ( state > VirtualMachine::FAILED )) + { + failure_response(XML_RPC_API, + request_error("Incorrect filter_flag, state","")); + return; + } + + switch(state) + { + case VirtualMachinePoolInfo::ALL_VM: + break; + + case VirtualMachinePoolInfo::ACTIVE: + state_filter << "state <> " << VirtualMachine::DONE; + break; + + default: + state_filter << "state = " << state; + break; + } + } + + state_str = state_filter.str(); + + // ------------ Compound WHERE clause -------------- + + if (!uid_str.empty()) + { + where_string << "(" << uid_str << ")" ; + empty = false; + } + + if (!id_str.empty()) + { + if (!empty) { where_string << " AND "; } - where_string << "( oid >= " << start_id; - - if ( end_id != -1 ) - { - where_string << " AND oid <= " << end_id << " )"; - } - else - { - where_string << " )"; - } + where_string << "(" << id_str << ")"; + empty = false; } + if (!state_str.empty()) + { + if (!empty) + { + where_string << " AND "; + } + + where_string << "(" << state_str << ")"; + } + + if ( basic_authorization(-1) == false ) { return; } - auth_object = AuthRequest::VM; // Call the template pool dump rc = pool->dump(oss,where_string.str()); diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 9bb3bdd4fb..e50be9bd95 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -248,29 +248,3 @@ int VirtualMachinePool::get_pending( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - -int VirtualMachinePool::dump( ostringstream& oss, - int state, - const string& where) -{ - ostringstream where_oss; - - if ( state != -1 ) - { - where_oss << VirtualMachine::table << ".state = " << state; - } - else - { - where_oss << VirtualMachine::table << ".state <> 6"; - } - - if ( !where.empty() ) - { - where_oss << " AND " << where; - } - - return PoolSQL::dump(oss, "VM_POOL", VirtualMachine::table,where_oss.str()); -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ From 1c1cb98400007e43ce2b43037ed5f4d22910fe12 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 27 Jun 2011 16:20:31 +0200 Subject: [PATCH 09/75] feature #696: OCA now supports state filter for VMs --- include/RequestManagerPoolInfoFilter.h | 4 +- src/oca/ruby/OpenNebula/VirtualMachinePool.rb | 43 ++++++++++++++++--- src/rm/RequestManagerPoolInfoFilter.cc | 6 +-- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h index 88e829cec3..1281c5f6c5 100644 --- a/include/RequestManagerPoolInfoFilter.h +++ b/include/RequestManagerPoolInfoFilter.h @@ -59,8 +59,8 @@ class VirtualMachinePoolInfo : public RequestManagerPoolInfoFilter public: /* -------------------------------------------------------------------- */ - static const int ALL_VM; /**< VMs in any state (-2) */ - static const int ACTIVE; /**< VMs in any state expect DONE (-1)*/ + static const int ALL_VM; /**< VMs in any state (-2) */ + static const int NOT_DONE; /**< VMs in any state expect DONE (-1)*/ /* -------------------------------------------------------------------- */ diff --git a/src/oca/ruby/OpenNebula/VirtualMachinePool.rb b/src/oca/ruby/OpenNebula/VirtualMachinePool.rb index 7a61c1ae98..4613da0c2b 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachinePool.rb +++ b/src/oca/ruby/OpenNebula/VirtualMachinePool.rb @@ -26,6 +26,10 @@ module OpenNebula :info => "vmpool.info" } + # Constants for info queries (include/RequestManagerPoolInfoFilter.h) + INFO_NOT_DONE = -1 + INFO_ALL_VM = -2 + ####################################################################### # Class constructor & Pool Methods ####################################################################### @@ -48,25 +52,54 @@ module OpenNebula ####################################################################### # Retrieves all or part of the VirtualMachines in the pool. + # No arguments, returns the not-in-done VMs for the user + # [user_id, start_id, end_id] + # [user_id, start_id, end_id, state] def info(*args) case args.size when 0 - info_filter(VM_POOL_METHODS[:info],@user_id,-1,-1) + info_filter(VM_POOL_METHODS[:info], + @user_id, + -1, + -1, + INFO_NOT_DONE) when 3 - info_filter(VM_POOL_METHODS[:info],args[0],args[1],args[2]) + info_filter(VM_POOL_METHODS[:info], + args[0], + args[1], + args[2], + INFO_NOT_DONE) + when 4 + info_filter(VM_POOL_METHODS[:info], + args[0], + args[1], + args[2], + args[3]) end end def info_all() - return super(VM_POOL_METHODS[:info]) + return info_filter(VM_POOL_METHODS[:info], + INFO_ALL, + -1, + -1, + INFO_NOT_DONE) end def info_mine() - return super(VM_POOL_METHODS[:info]) + return info_filter(VM_POOL_METHODS[:info], + INFO_MINE, + -1, + -1, + INFO_NOT_DONE) end def info_group() - return super(VM_POOL_METHODS[:info]) + return info_filter(VM_POOL_METHODS[:info], + INFO_GROUP, + -1, + -1, + INFO_NOT_DONE) end end end diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc index 41ea783cdc..2a2bc6c2dd 100644 --- a/src/rm/RequestManagerPoolInfoFilter.cc +++ b/src/rm/RequestManagerPoolInfoFilter.cc @@ -29,9 +29,9 @@ const int RequestManagerPoolInfoFilter::MINE_GROUP = -1; /* ------------------------------------------------------------------------- */ -const int VirtualMachinePoolInfo::ALL_VM = -2; +const int VirtualMachinePoolInfo::ALL_VM = -2; -const int VirtualMachinePoolInfo::ACTIVE = -1; +const int VirtualMachinePoolInfo::NOT_DONE = -1; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ @@ -117,7 +117,7 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa case VirtualMachinePoolInfo::ALL_VM: break; - case VirtualMachinePoolInfo::ACTIVE: + case VirtualMachinePoolInfo::NOT_DONE: state_filter << "state <> " << VirtualMachine::DONE; break; From c1a0fa6f7db388f9e085d360dbb02e0ac0868801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 27 Jun 2011 18:41:16 +0200 Subject: [PATCH 10/75] Feature #687: Add DB persistence to ACL rules --- include/AclManager.h | 133 +++++++++++++++++++++++--------- include/AclRule.h | 46 ++++++++++- src/authm/AclManager.cc | 167 ++++++++++++++++++++++++++++++++++++---- src/authm/AclRule.cc | 14 ++-- src/nebula/Nebula.cc | 17 +++- 5 files changed, 313 insertions(+), 64 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index 76ea596844..7ea235f07f 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -22,28 +22,69 @@ using namespace std; -class AclManager : public ObjectSQL +/** + * This class manages the ACL rules and the authorization engine + */ +class AclManager : public Callbackable { public: - AclManager(){}; + AclManager(SqlDB * _db) + :db(_db) + {}; ~AclManager(); + /** + * Loads the ACL rule set from the DB + * @return 0 on success. + */ + int start(); + /* ---------------------------------------------------------------------- */ /* Rule management */ /* ---------------------------------------------------------------------- */ + /** + * Takes an authorization request and checks if any rule in the ACL + * authorizes the operation. + * + * @param uid The user ID requesting to be authorized + * @param user_groups Set of group IDs that the user is part of + * @param obj_type The object over which the operation will be performed + * @param obj_id The object ID + * @param obj_gid The object's group ID + * @param op The operation to be authorized + * @return true if the authorization is granted by any rule + */ const bool authorize(int uid, const set &user_groups, AuthRequest::Object obj_type, int obj_id, int obj_gid, AuthRequest::Operation op); /* ---------------------------------------------------------------------- */ + /** + * Adds a new rule to the ACL rule set + * + * @param user 64 bit ID and flags + * @param resource 64 bit ID and flags + * @param rights 64 bit flags + * @param error_str Returns the error reason, if any + * @return 0 on success + */ int add_rule(long long user, long long resource, long long rights, string& error_str); /* ---------------------------------------------------------------------- */ + /** + * Deletes a rule from the ACL rule set + * + * @param user 64 bit ID and flags + * @param resource 64 bit ID and flags + * @param rights 64 bit flags + * @param error_str Returns the error reason, if any + * @return 0 on success + */ int del_rule(long long user, long long resource, long long rights, string& error_str); @@ -52,55 +93,71 @@ public: /* ---------------------------------------------------------------------- */ /** - * Callback function to unmarshall a PoolObjectSQL + * Bootstraps the database table(s) associated to the ACL Manager + */ + static void bootstrap(SqlDB * _db) + { + ostringstream oss(db_bootstrap); + + _db->exec(oss); + }; + + /* ---------------------------------------------------------------------- */ + + /** + * Dumps the rule set in XML format. + * @param oss The output stream to dump the rule set contents + * @return 0 on success + */ + int dump(ostringstream& oss); + +private: + multimap acl_rules; + + // ---------------------------------------- + // DataBase implementation variables + // ---------------------------------------- + + /** + * Pointer to the database. + */ + SqlDB * db; + + static const char * table; + + static const char * db_names; + + static const char * db_bootstrap; + + /** + * Callback function to unmarshall the ACL rules * @param num the number of columns read from the DB * @param names the column names * @param vaues the column values * @return 0 on success */ - int select_cb(void *nil, int num, char **values, char **names) - { - if ( (!values[0]) || (num != 1) ) - { - return -1; - } - - // TODO: from_xml - - return 0; - }; + int select_cb(void *nil, int num, char **values, char **names); /** * Reads the ACL rule set from the database. * @param db pointer to the db * @return 0 on success */ - int select(SqlDB *db) - { - return 0; - }; + int select(); - int insert(SqlDB*, std::string&) - { - return 0; - }; + /** + * Inserts the ACL rule in the database. + * @param rule to insert + * @return 0 on success + */ + int insert(AclRule * rule); - int update(SqlDB*) - { - return 0; - }; - - int drop(SqlDB*) - { - return 0; - }; - - /* ---------------------------------------------------------------------- */ - - int dump(ostringstream& oss); - -private: - multimap acl_rules; + /** + * Drops an ACL rule from the database + * @param rule to drop + * @return 0 on success + */ + int drop(AclRule * rule); }; #endif /*ACL_MANAGER_H*/ diff --git a/include/AclRule.h b/include/AclRule.h index 37c786bf7a..e2f341ef9c 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -23,6 +23,10 @@ using namespace std; +/** + * An ACL Rule is composed of three 64 bit numbers: user, resource and rights. + * These attributes store a combination of IDs and flags + */ class AclRule { public: @@ -61,25 +65,59 @@ public: return user < other.user; }; + /** + * Returns a human readable string for this rule + * + * @return a human readable string for this rule + */ string to_str() const; + + /** + * Function to print the object into a string in XML format + * + * @param xml the resulting XML string + * @return a reference to the generated string + */ string& to_xml(string& xml) const; + /** + * Returns the 32 less significant bits of the user long long attribute + * + * @return the user or group ID + */ int user_id() const { return user; }; + /** + * Returns the 64 bit user attribute with the ID cleared (the 32 less + * significant bits are set to 0) + * + * @return the user flags + */ long long user_code() const { return user & 0xFFFFFFFF00000000LL; }; + /** + * Returns the 32 less significant bits of the resource long long attribute + * + * @return the resource ID + */ int resource_id() const { return resource; }; + /** + * Returns the 64 bit resource attribute with the ID cleared (the 32 less + * significant bits are set to 0) + * + * @return the resource flags + */ long long resource_code() const { return resource & 0xFFFFFFFF00000000LL; @@ -90,17 +128,19 @@ private: friend class AclManager; /** - * + * 64 bit integer holding a user ID in the 32 less significant bits, + * and a flag indicating the kind of ID in the other 32 */ long long user; /** - * + * 64 bit integer holding an object ID in the 32 less significant bits, + * and flags indicanting the kind of ID and object in the other 32 */ long long resource; /** - * + * 64 bit integer containing the rights flags */ long long rights; }; diff --git a/src/authm/AclManager.cc b/src/authm/AclManager.cc index 013c190cc7..732ab354f9 100644 --- a/src/authm/AclManager.cc +++ b/src/authm/AclManager.cc @@ -20,6 +20,24 @@ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +const char * AclManager::table = "acl"; + +const char * AclManager::db_names = "user, resource, rights"; + +const char * AclManager::db_bootstrap = "CREATE TABLE IF NOT EXISTS " + "acl (user BIGINT, resource BIGINT, rights BIGINT)"; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::start() +{ + return select(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + AclManager::~AclManager() { multimap::iterator it; @@ -105,7 +123,8 @@ int AclManager::add_rule(long long user, long long resource, long long rights, { AclRule * rule = new AclRule(user, resource, rights); - ostringstream oss; + ostringstream oss; + int rc; multimap::iterator it; pair::iterator, @@ -143,6 +162,14 @@ int AclManager::add_rule(long long user, long long resource, long long rights, } */ + rc = insert(rule); + + if ( rc != 0 ) + { + error_str = "Error inserting rule in DB"; + return -1; + } + acl_rules.insert( make_pair(rule->user, rule) ); return 0; @@ -156,29 +183,26 @@ int AclManager::del_rule(long long user, long long resource, long long rights, { multimap::iterator it; pair::iterator, - multimap::iterator> index; + multimap::iterator> index; + int rc; bool found = false; index = acl_rules.equal_range( user ); - for ( it = index.first; (it != index.second && !found); it++) + it = index.first; + while ( !found && it != index.second ) { - if ( it->second->resource == resource && - it->second->rights == rights ) - { - delete it->second; - acl_rules.erase( it ); + found = ( it->second->resource == resource && + it->second->rights == rights ); - found = true; + if ( !found ) + { + it++; } } - if ( found ) - { - return 0; - } - else + if ( !found ) { AclRule rule(user, resource, rights); @@ -188,6 +212,121 @@ int AclManager::del_rule(long long user, long long resource, long long rights, return -1; } + + rc = drop( it->second ); + + if ( rc != 0 ) + { + error_str = "SQL DB error"; + return -1; + } + + delete it->second; + acl_rules.erase( it ); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::select_cb(void *nil, int num, char **values, char **names) +{ + if ( (num != 3) || + (!values[0]) || + (!values[1]) || + (!values[2]) ) + { + return -1; + } + + ostringstream oss; + istringstream iss; + + long long rule_values[3]; + + for ( int i = 0; i < 3; i++ ) + { + iss.str( values[i] ); + + iss >> rule_values[i]; + + if ( iss.fail() == true ) + { + return -1; + } + + iss.clear(); + } + + // TODO: Use add_rule() instead, to check possible errors, or assume + // that anything that was stored into the DB is trustworthy? + AclRule * rule = new AclRule(rule_values[0], rule_values[1], rule_values[2]); + + + oss << "Loading ACL Rule " << rule->to_str(); + NebulaLog::log("ACL",Log::DEBUG,oss); + + acl_rules.insert( make_pair(rule->user, rule) ); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::select() +{ + ostringstream oss; + int rc; + + oss << "SELECT " << db_names << " FROM " << table; + + set_callback(static_cast(&AclManager::select_cb)); + + rc = db->exec(oss,this); + + unset_callback(); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::insert(AclRule * rule) +{ + ostringstream oss; + int rc; + + // Construct the SQL statement to Insert + + oss << "INSERT INTO " << table <<" ("<< db_names <<") VALUES (" + << rule->user << "," + << rule->resource << "," + << rule->rights << ")"; + + rc = db->exec(oss); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::drop(AclRule * rule) +{ + ostringstream oss; + int rc; + + oss << "DELETE FROM " << table << " WHERE " + << "user=" << rule->user << "AND" + << "resource=" << rule->resource << "AND" + << "rights=" << rule->rights; + + rc = db->exec(oss); + + return rc; } /* -------------------------------------------------------------------------- */ diff --git a/src/authm/AclRule.cc b/src/authm/AclRule.cc index efede82ac4..fb20d3aa9f 100644 --- a/src/authm/AclRule.cc +++ b/src/authm/AclRule.cc @@ -16,7 +16,6 @@ #include "AclRule.h" #include "AuthManager.h" -#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -133,14 +132,13 @@ string& AclRule::to_xml(string& xml) const oss << "" - "" << hex << user << "" << - "" << hex << resource << "" << - "" << hex << rights << "" << + "" << hex << user << "" << + "" << hex << resource << "" << + "" << hex << rights << "" << - // TODO: Element DEBUG contains a human friendly string - "" << to_str() << "" << - - ""; + // TODO: Element DEBUG contains a human friendly string + "" << to_str() << "" << + ""; xml = oss.str(); diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 0f4e9f6434..deb5e5675d 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -247,6 +247,7 @@ void Nebula::start() UserPool::bootstrap(db); ImagePool::bootstrap(db); VMTemplatePool::bootstrap(db); + AclManager::bootstrap(db); } } catch (exception&) @@ -516,7 +517,21 @@ void Nebula::start() } // ---- ACL Manager ---- - aclm = new AclManager(); + try + { + aclm = new AclManager(db); + } + catch (bad_alloc&) + { + throw; + } + + rc = aclm->start(); + + if ( rc != 0 ) + { + throw runtime_error("Could not start the ACL Manager"); + } // ---- Image Manager ---- try From 99088df9b5cc56b9a2d466ec6e83db7d1b5cec42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 27 Jun 2011 19:11:34 +0200 Subject: [PATCH 11/75] Feature #687: Move acl classes to their own source dir --- SConstruct | 2 ++ src/{authm => acl}/AclManager.cc | 0 src/{authm => acl}/AclRule.cc | 0 src/acl/SConstruct | 30 ++++++++++++++++++++++++++++++ src/authm/SConstruct | 4 +--- src/group/test/SConstruct | 1 + src/host/test/SConstruct | 1 + src/image/test/SConstruct | 1 + src/lcm/test/SConstruct | 1 + src/nebula/SConstruct | 1 + src/um/test/SConstruct | 1 + src/vm/test/SConstruct | 1 + src/vm_template/test/SConstruct | 1 + src/vnm/test/SConstruct | 1 + 14 files changed, 42 insertions(+), 3 deletions(-) rename src/{authm => acl}/AclManager.cc (100%) rename src/{authm => acl}/AclRule.cc (100%) create mode 100644 src/acl/SConstruct diff --git a/SConstruct b/SConstruct index 6492bb173e..506738d5e5 100644 --- a/SConstruct +++ b/SConstruct @@ -75,6 +75,7 @@ main_env.Append(LIBPATH=[ cwd+'/src/hm', cwd+'/src/um', cwd+'/src/authm', + cwd+'/src/acl', cwd+'/src/xml', ]) @@ -204,6 +205,7 @@ build_scripts=[ 'src/hm/SConstruct', 'src/um/SConstruct', 'src/authm/SConstruct', + 'src/acl/SConstruct', 'src/xml/SConstruct', 'share/man/SConstruct' ] diff --git a/src/authm/AclManager.cc b/src/acl/AclManager.cc similarity index 100% rename from src/authm/AclManager.cc rename to src/acl/AclManager.cc diff --git a/src/authm/AclRule.cc b/src/acl/AclRule.cc similarity index 100% rename from src/authm/AclRule.cc rename to src/acl/AclRule.cc diff --git a/src/acl/SConstruct b/src/acl/SConstruct new file mode 100644 index 0000000000..f96ccd19bc --- /dev/null +++ b/src/acl/SConstruct @@ -0,0 +1,30 @@ +# SConstruct for src/authm + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +Import('env') + +lib_name='nebula_acl' + +# Sources to generate the library +source_files=[ + 'AclManager.cc', + 'AclRule.cc' +] + +# Build library +env.StaticLibrary(lib_name, source_files) diff --git a/src/authm/SConstruct b/src/authm/SConstruct index 035670d9b4..ea9531a972 100644 --- a/src/authm/SConstruct +++ b/src/authm/SConstruct @@ -23,9 +23,7 @@ lib_name='nebula_authm' # Sources to generate the library source_files=[ 'AuthManager.cc', - 'AuthManagerDriver.cc', - 'AclManager.cc', - 'AclRule.cc' + 'AuthManagerDriver.cc' ] # Build library diff --git a/src/group/test/SConstruct b/src/group/test/SConstruct index d7ed958024..01dc379f17 100644 --- a/src/group/test/SConstruct +++ b/src/group/test/SConstruct @@ -44,6 +44,7 @@ env.Prepend(LIBS=[ 'nebula_pool', 'nebula_hm', 'nebula_authm', + 'nebula_acl', 'nebula_common', 'nebula_lcm', 'nebula_dm', diff --git a/src/host/test/SConstruct b/src/host/test/SConstruct index 9f12682dc5..03184e77b6 100644 --- a/src/host/test/SConstruct +++ b/src/host/test/SConstruct @@ -37,6 +37,7 @@ env.Prepend(LIBS=[ 'nebula_pool', 'nebula_hm', 'nebula_authm', + 'nebula_acl', 'nebula_common', 'nebula_lcm', 'nebula_dm', diff --git a/src/image/test/SConstruct b/src/image/test/SConstruct index 8827054f90..391d3cce93 100644 --- a/src/image/test/SConstruct +++ b/src/image/test/SConstruct @@ -36,6 +36,7 @@ env.Prepend(LIBS=[ 'nebula_pool', 'nebula_hm', 'nebula_authm', + 'nebula_acl', 'nebula_common', 'nebula_lcm', 'nebula_dm', diff --git a/src/lcm/test/SConstruct b/src/lcm/test/SConstruct index 41597fac76..bb9131fff1 100644 --- a/src/lcm/test/SConstruct +++ b/src/lcm/test/SConstruct @@ -36,6 +36,7 @@ env.Prepend(LIBS=[ 'nebula_xml', 'nebula_hm', 'nebula_authm', + 'nebula_acl', 'nebula_common', 'nebula_sql', 'nebula_log', diff --git a/src/nebula/SConstruct b/src/nebula/SConstruct index 93b154eb77..4bb8e393a7 100644 --- a/src/nebula/SConstruct +++ b/src/nebula/SConstruct @@ -43,6 +43,7 @@ env.Prepend(LIBS=[ 'nebula_um', 'nebula_group', 'nebula_authm', + 'nebula_acl', 'nebula_mad', 'nebula_template', 'nebula_image', diff --git a/src/um/test/SConstruct b/src/um/test/SConstruct index a766dc55aa..f74e3c2d93 100644 --- a/src/um/test/SConstruct +++ b/src/um/test/SConstruct @@ -44,6 +44,7 @@ env.Prepend(LIBS=[ 'nebula_pool', 'nebula_hm', 'nebula_authm', + 'nebula_acl', 'nebula_common', 'nebula_lcm', 'nebula_dm', diff --git a/src/vm/test/SConstruct b/src/vm/test/SConstruct index bd2813a595..7876b88735 100644 --- a/src/vm/test/SConstruct +++ b/src/vm/test/SConstruct @@ -22,6 +22,7 @@ env.Prepend(LIBS=[ 'nebula_hm', 'nebula_vnm', 'nebula_authm', + 'nebula_acl', 'nebula_template', 'nebula_pool', 'nebula_xml', diff --git a/src/vm_template/test/SConstruct b/src/vm_template/test/SConstruct index 6ab70ef56e..6945476a24 100644 --- a/src/vm_template/test/SConstruct +++ b/src/vm_template/test/SConstruct @@ -24,6 +24,7 @@ env.Prepend(LIBS=[ 'nebula_hm', 'nebula_vnm', 'nebula_authm', + 'nebula_acl', 'nebula_template', 'nebula_pool', 'nebula_mad', diff --git a/src/vnm/test/SConstruct b/src/vnm/test/SConstruct index a01df7d274..d645885a0b 100644 --- a/src/vnm/test/SConstruct +++ b/src/vnm/test/SConstruct @@ -21,6 +21,7 @@ env.Prepend(LIBS=[ 'nebula_um', 'nebula_vnm', 'nebula_authm', + 'nebula_acl', 'nebula_template', 'nebula_pool', 'nebula_xml', From 2da4877c8c9623ec36b64056878c82bd9a1540ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 28 Jun 2011 11:43:14 +0200 Subject: [PATCH 12/75] Feature #687: AuthRequest::add_auth extracts the object int id only if it is not a string template --- src/authm/AuthManager.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index 2fde223c11..eb843fbdad 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -39,6 +39,8 @@ void AuthRequest::add_auth(Object ob, ostringstream oss; bool auth; + int ob_id_int = 0; + oss << Object_to_str(ob) << ":"; if (op == CREATE || op == INSTANTIATE) //encode the ob_id, it is a template @@ -58,6 +60,9 @@ void AuthRequest::add_auth(Object ob, else { oss << ob_id << ":"; + + istringstream iss(ob_id); + iss >> ob_id_int; } oss << Operation_to_str(op) << ":"; @@ -79,11 +84,6 @@ void AuthRequest::add_auth(Object ob, int ob_gid = 0; - istringstream iss(ob_id); - int ob_id_int; - - iss >> ob_id_int; - Nebula& nd = Nebula::instance(); AclManager* aclm = nd.get_aclm(); From 05ea353f24cbb625b903b347b4c341787ab76d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 28 Jun 2011 12:56:37 +0200 Subject: [PATCH 13/75] Feature #687: ACL rules now check the object's group --- include/AuthManager.h | 4 +++- src/authm/AuthManager.cc | 5 ++--- src/image/ImagePool.cc | 1 + src/rm/Request.cc | 8 +++++--- src/rm/RequestManagerAllocate.cc | 6 +++--- src/rm/RequestManagerVMTemplate.cc | 5 +++-- src/rm/RequestManagerVirtualMachine.cc | 7 +++++-- src/vnm/VirtualNetworkPool.cc | 1 + 8 files changed, 23 insertions(+), 14 deletions(-) diff --git a/include/AuthManager.h b/include/AuthManager.h index 0aebd3e405..d34761c3e0 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -361,6 +361,7 @@ public: */ void add_auth(Object ob, const string& ob_id, + int ob_gid, Operation op, int owner, bool pub); @@ -370,6 +371,7 @@ public: */ void add_auth(Object ob, int ob_id, + int ob_gid, Operation op, int owner, bool pub) @@ -377,7 +379,7 @@ public: ostringstream oss; oss << ob_id; - add_auth(ob,oss.str(),op,owner,pub); + add_auth(ob,oss.str(),ob_gid,op,owner,pub); }; /** diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index eb843fbdad..e386185e23 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -32,6 +32,7 @@ const char * AuthManager::auth_driver_name = "auth_exe"; void AuthRequest::add_auth(Object ob, const string& ob_id, + int ob_gid, Operation op, int owner, bool pub) @@ -39,7 +40,7 @@ void AuthRequest::add_auth(Object ob, ostringstream oss; bool auth; - int ob_id_int = 0; + int ob_id_int = -1; oss << Object_to_str(ob) << ":"; @@ -82,8 +83,6 @@ void AuthRequest::add_auth(Object ob, // TODO, the set of object ids is needed set emtpy_set; - int ob_gid = 0; - Nebula& nd = Nebula::instance(); AclManager* aclm = nd.get_aclm(); diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index 19313b552d..b728fc2f0b 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -252,6 +252,7 @@ void ImagePool::authorize_disk(VectorAttribute * disk,int uid, AuthRequest * ar) ar->add_auth(AuthRequest::IMAGE, img->get_oid(), + img->get_gid(), AuthRequest::USE, img->get_uid(), img->isPublic()); diff --git a/src/rm/Request.cc b/src/rm/Request.cc index a204af1e4a..90aa0ee167 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -52,6 +52,7 @@ bool Request::basic_authorization(int oid) bool pub; int ouid; + int ogid; if ( uid == 0 ) { @@ -74,6 +75,7 @@ bool Request::basic_authorization(int oid) } ouid = object->get_uid(); + ogid = object->get_gid(); pub = object->isPublic(); object->unlock(); @@ -81,10 +83,10 @@ bool Request::basic_authorization(int oid) AuthRequest ar(uid); - ar.add_auth(auth_object, oid, auth_op, ouid, pub); + ar.add_auth(auth_object, oid, ogid, auth_op, ouid, pub); - if (UserPool::authorize(ar) == -1) - { + if (UserPool::authorize(ar) == -1) + { failure_response(AUTHORIZATION, authorization_error(ar.message)); return false; diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc index 551c156703..f5821e300b 100644 --- a/src/rm/RequestManagerAllocate.cc +++ b/src/rm/RequestManagerAllocate.cc @@ -34,13 +34,13 @@ bool RequestManagerAllocate::allocate_authorization(Template * tmpl) if ( tmpl == 0 ) { - ar.add_auth(auth_object,-1,auth_op,uid,false); + ar.add_auth(auth_object,-1,-1,auth_op,uid,false); } else { string t64; - ar.add_auth(auth_object,tmpl->to_xml(t64),auth_op,uid,false); + ar.add_auth(auth_object,tmpl->to_xml(t64),-1,auth_op,uid,false); } if (UserPool::authorize(ar) == -1) @@ -67,7 +67,7 @@ bool VirtualMachineAllocate::allocate_authorization(Template * tmpl) VirtualMachineTemplate * ttmpl = static_cast(tmpl); - ar.add_auth(auth_object,tmpl->to_xml(t64),auth_op,uid,false); + ar.add_auth(auth_object,tmpl->to_xml(t64),-1,auth_op,uid,false); VirtualMachine::set_auth_request(uid, ar, ttmpl); diff --git a/src/rm/RequestManagerVMTemplate.cc b/src/rm/RequestManagerVMTemplate.cc index b93ca5f202..757d7db435 100644 --- a/src/rm/RequestManagerVMTemplate.cc +++ b/src/rm/RequestManagerVMTemplate.cc @@ -25,7 +25,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList int id = xmlrpc_c::value_int(paramList.getInt(1)); string name = xmlrpc_c::value_string(paramList.getString(2)); - int rc, ouid, vid; + int rc, ouid, ogid, vid; Nebula& nd = Nebula::instance(); VirtualMachinePool* vmpool = nd.get_vmpool(); @@ -46,6 +46,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList tmpl = rtmpl->clone_template(); ouid = rtmpl->get_uid(); + ogid = rtmpl->get_gid(); rtmpl->unlock(); @@ -56,7 +57,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList { AuthRequest ar(uid); - ar.add_auth(auth_object, id, auth_op, ouid, false); + ar.add_auth(auth_object, id, ogid, auth_op, ouid, false); VirtualMachine::set_auth_request(uid, ar, tmpl); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 10142230c0..65eedc431e 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -25,6 +25,7 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl PoolObjectSQL * object; int ouid; + int ogid; if ( uid == 0 ) { @@ -40,16 +41,17 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl } ouid = object->get_uid(); + ogid = object->get_gid(); object->unlock(); AuthRequest ar(uid); - ar.add_auth(auth_object, oid, auth_op, ouid, false); + ar.add_auth(auth_object, oid, ogid, auth_op, ouid, false); if (hid != -1) { - ar.add_auth(AuthRequest::HOST,hid,AuthRequest::USE,0,false); + ar.add_auth(AuthRequest::HOST,hid,-1,AuthRequest::USE,0,false); } else if (tmpl != 0) { @@ -57,6 +59,7 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl ar.add_auth(AuthRequest::IMAGE, tmpl->to_xml(t64), + -1, AuthRequest::CREATE, uid, false); diff --git a/src/vnm/VirtualNetworkPool.cc b/src/vnm/VirtualNetworkPool.cc index 8cee60727a..e24464b33c 100644 --- a/src/vnm/VirtualNetworkPool.cc +++ b/src/vnm/VirtualNetworkPool.cc @@ -196,6 +196,7 @@ void VirtualNetworkPool::authorize_nic(VectorAttribute * nic, ar->add_auth(AuthRequest::NET, vnet->get_oid(), + vnet->get_gid(), AuthRequest::USE, vnet->get_uid(), vnet->isPublic()); From 303db36d95765e14575fcef91b5d9b5684aaa06d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 29 Jun 2011 12:50:16 +0200 Subject: [PATCH 14/75] Feature #687: ACL Manager looks for rules that apply to any of the user's groups --- include/AclManager.h | 23 ++++++ include/AuthManager.h | 9 ++- include/Request.h | 4 +- include/RequestManagerAllocate.h | 6 +- include/UserPool.h | 5 +- src/acl/AclManager.cc | 102 +++++++++++++++++++++---- src/authm/AuthManager.cc | 5 +- src/cli/oneuser | 2 +- src/rm/Request.cc | 4 +- src/rm/RequestManagerAcl.cc | 31 -------- src/rm/RequestManagerAllocate.cc | 5 +- src/rm/RequestManagerVMTemplate.cc | 2 +- src/rm/RequestManagerVirtualMachine.cc | 2 +- src/um/UserPool.cc | 9 ++- 14 files changed, 144 insertions(+), 65 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index 7ea235f07f..6e617e2a6e 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -114,6 +114,29 @@ public: private: multimap acl_rules; + /** + * Gets all rules that apply to the user_req and, if any of them grants + * permission, returns true. + * + * @param user_req user/group id and flags + * @param resource_oid_req 64 bit request, ob. type and individual oid + * @param resource_gid_req 64 bit request, ob. type and group id + * @param resource_all_req 64 bit request, ob. type and all flag + * @param rights_req Requested rights + * @param individual_obj_type Mask with ob. type and individual flags + * @param group_obj_type Mask with ob. type and gropu flags + * + * @return true if any rule grants permission + */ + bool match_rules( + long long user_req, + long long resource_oid_req, + long long resource_gid_req, + long long resource_all_req, + long long rights_req, + long long individual_obj_type, + long long group_obj_type); + // ---------------------------------------- // DataBase implementation variables // ---------------------------------------- diff --git a/include/AuthManager.h b/include/AuthManager.h index d34761c3e0..d8d5f6c206 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -18,6 +18,7 @@ #define AUTH_MANAGER_H_ #include +#include #include "MadManager.h" #include "ActionManager.h" @@ -259,10 +260,11 @@ private: class AuthRequest : public ActionListener { public: - AuthRequest(int _uid): + AuthRequest(int _uid, set _gids): result(false), timeout(false), uid(_uid), + gids(_gids), time_out(0), self_authorize(true) { @@ -460,6 +462,11 @@ private: */ int uid; + /** + * The user groups ID set + */ + set gids; + /** * Timeout for this request */ diff --git a/include/Request.h b/include/Request.h index a649deda6e..2f68ba3dbb 100644 --- a/include/Request.h +++ b/include/Request.h @@ -60,9 +60,11 @@ protected: /* ------------------- Attributes of the Request ---------------------- */ int uid; /**< id of the user performing the request */ - + int gid; /**< id of the user's group */ + set group_ids; /**< set of user's group ids */ + PoolSQL * pool; /**< Pool of objects */ string method_name; /**< The name of the XML-RPC method */ diff --git a/include/RequestManagerAllocate.h b/include/RequestManagerAllocate.h index 15d2f975cf..1106e31df7 100644 --- a/include/RequestManagerAllocate.h +++ b/include/RequestManagerAllocate.h @@ -104,7 +104,7 @@ class VirtualNetworkAllocate: public RequestManagerAllocate { public: VirtualNetworkAllocate(): - RequestManagerAllocate("VirtualNetworkInfo", + RequestManagerAllocate("VirtualNetworkAllocate", "Allocates a new virtual network", "A:ss", true) @@ -200,7 +200,7 @@ class HostAllocate : public RequestManagerAllocate { public: HostAllocate(): - RequestManagerAllocate("HostInfo", + RequestManagerAllocate("HostAllocate", "Allocates a new host", "A:sssss", false) @@ -225,7 +225,7 @@ class UserAllocate: public RequestManagerAllocate { public: UserAllocate(): - RequestManagerAllocate("UserInfo", + RequestManagerAllocate("UserAllocate", "Returns user information", "A:sss", false) diff --git a/include/UserPool.h b/include/UserPool.h index 5154067aa4..59db2b0a50 100644 --- a/include/UserPool.h +++ b/include/UserPool.h @@ -102,9 +102,12 @@ public: * @param session, colon separated username and password string * @param uid of the user if authN succeeded -1 otherwise * @param gid of the user if authN succeeded -1 otherwise + * @param group_ids the user groups if authN succeeded, is empty otherwise * @return false if authn failed, true otherwise */ - bool authenticate(const string& session, int& uid, int& gid); + bool authenticate(const string& session, int& uid, int& gid, + set& group_ids); + /** * Returns whether there is a user with given username/password or not diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index 732ab354f9..5440e20ee4 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -64,9 +64,10 @@ const bool AclManager::authorize(int uid, const set &user_groups, bool auth = false; // Build masks for request - long long user_req = AclRule::INDIVIDUAL_ID + uid; + long long user_req; long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; long long resource_gid_req = obj_type + AclRule::GROUP_ID + obj_gid; + long long resource_all_req = obj_type + AclRule::ALL_ID; long long rights_req = op; long long individual_obj_type = @@ -75,12 +76,82 @@ const bool AclManager::authorize(int uid, const set &user_groups, long long group_obj_type = ( obj_type | AclRule::GROUP_ID | 0xFFFFFFFF ); - AclRule request_rule(user_req, resource_oid_req, rights_req); + + + AclRule request_rule(AclRule::INDIVIDUAL_ID + uid, resource_oid_req, rights_req); oss << "Request " << request_rule.to_str(); NebulaLog::log("ACL",Log::DEBUG,oss); - // TODO: This only works for individual uid + // Look for rules that apply to everyone + + user_req = AclRule::ALL_ID; + auth = match_rules(user_req, resource_oid_req, resource_gid_req, + resource_all_req, rights_req, individual_obj_type, group_obj_type); + + if ( auth == true ) + { + return true; + } + + // Look for rules that apply to the individual user id + user_req = AclRule::INDIVIDUAL_ID + uid; + + auth = match_rules(user_req, resource_oid_req, resource_gid_req, + resource_all_req, rights_req, individual_obj_type, group_obj_type); + + if ( auth == true ) + { + return true; + } + + + // Look for rules that apply to each one of the user's groups + + set::iterator g_it; + + for (g_it = user_groups.begin(); g_it != user_groups.end(); g_it++) + { + user_req = AclRule::GROUP_ID + *g_it; + + auth = match_rules(user_req, resource_oid_req, resource_gid_req, + resource_all_req, rights_req, individual_obj_type, + group_obj_type); + + if ( auth == true ) + { + return true; + } + } + + + oss.str("No more rules, permission not granted "); + NebulaLog::log("ACL",Log::DEBUG,oss); + + return false; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +bool AclManager::match_rules( + long long user_req, + long long resource_oid_req, + long long resource_gid_req, + long long resource_all_req, + long long rights_req, + long long individual_obj_type, + long long group_obj_type) + +{ + bool auth; + ostringstream oss; + + multimap::iterator it; + + pair::iterator, + multimap::iterator> index; + index = acl_rules.equal_range( user_req ); for ( it = index.first; it != index.second; it++) @@ -90,15 +161,19 @@ const bool AclManager::authorize(int uid, const set &user_groups, NebulaLog::log("ACL",Log::DEBUG,oss); auth = - ( - // Rule's object type and individual object ID match - ( ( it->second->resource & individual_obj_type ) == resource_oid_req ) - || - // Or rule's object type and group object ID match - ( ( it->second->resource & group_obj_type ) == resource_gid_req ) - ) - && - ( ( it->second->rights & rights_req ) == rights_req ); + // Rule grants the requested rights + ( ( it->second->rights & rights_req ) == rights_req ) + && + ( + // Rule grants permission for all objects of this type + ( it->second->resource == resource_all_req ) + || + // Or rule's object type and group object ID match + ( ( it->second->resource & group_obj_type ) == resource_gid_req ) + || + // Or rule's object type and individual object ID match + ( ( it->second->resource & individual_obj_type ) == resource_oid_req ) + ); if ( auth == true ) { @@ -109,9 +184,6 @@ const bool AclManager::authorize(int uid, const set &user_groups, } } - oss.str("No more rules, permission not granted "); - NebulaLog::log("ACL",Log::DEBUG,oss); - return false; } diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index e386185e23..be132d650f 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -80,13 +80,10 @@ void AuthRequest::add_auth(Object ob, } else { - // TODO, the set of object ids is needed - set emtpy_set; - Nebula& nd = Nebula::instance(); AclManager* aclm = nd.get_aclm(); - auth = aclm->authorize(uid, emtpy_set, ob, ob_id_int, ob_gid, op); + auth = aclm->authorize(uid, gids, ob, ob_id_int, ob_gid, op); } self_authorize = self_authorize && auth; diff --git a/src/cli/oneuser b/src/cli/oneuser index bfc2a45fd8..f91d6ef9d0 100755 --- a/src/cli/oneuser +++ b/src/cli/oneuser @@ -120,7 +120,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do command :chgrp, chgrp_desc, [:range, :userid_list], :groupid do helper.perform_actions(args[0],options,"Group changed") do |user| - user.chown(-1, args[1].to_i) + user.chgrp(args[1].to_i) end end diff --git a/src/rm/Request.cc b/src/rm/Request.cc index 90aa0ee167..c3866b4d76 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -33,7 +33,7 @@ void Request::execute( NebulaLog::log("ReM",Log::DEBUG, method_name + " method invoked"); - if ( upool->authenticate(session, uid, gid) == false ) + if ( upool->authenticate(session, uid, gid, group_ids) == false ) { failure_response(AUTHENTICATION, authenticate_error()); } @@ -81,7 +81,7 @@ bool Request::basic_authorization(int oid) object->unlock(); } - AuthRequest ar(uid); + AuthRequest ar(uid, group_ids); ar.add_auth(auth_object, oid, ogid, auth_op, ouid, pub); diff --git a/src/rm/RequestManagerAcl.cc b/src/rm/RequestManagerAcl.cc index fce1eb6c63..34838210d7 100644 --- a/src/rm/RequestManagerAcl.cc +++ b/src/rm/RequestManagerAcl.cc @@ -46,37 +46,6 @@ void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) iss >> hex >> rights; - - // TODO, debug -/* - int iu, id, it; - - iss.clear(); - iss.str( xmlrpc_c::value_string(paramList.getString(1)) ); - iss >> iu; - - iss.clear(); - iss.str( xmlrpc_c::value_string(paramList.getString(2)) ); - iss >> id; - - iss.clear(); - iss.str( xmlrpc_c::value_string(paramList.getString(3)) ); - iss >> it; - - - - ostringstream oss; - string u = xmlrpc_c::value_string(paramList.getString(1)); - string d = xmlrpc_c::value_string(paramList.getString(2)); - string t = xmlrpc_c::value_string(paramList.getString(3)); - - oss << "\n"; - oss << "User : " << u << ", " << iu << ", dec: " << dec << user << "\n"; - oss << "Resource : " << d << ", " << id << ", dec: " << dec << resource << "\n"; - oss << "Rights : " << t << ", " << it << ", dec: " << dec << rights << "\n"; - NebulaLog::log("ACL-RM",Log::DEBUG,oss); -*/ - Nebula& nd = Nebula::instance(); aclm = nd.get_aclm(); diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc index f5821e300b..ccbbf9675a 100644 --- a/src/rm/RequestManagerAllocate.cc +++ b/src/rm/RequestManagerAllocate.cc @@ -30,7 +30,7 @@ bool RequestManagerAllocate::allocate_authorization(Template * tmpl) return true; } - AuthRequest ar(uid); + AuthRequest ar(uid, group_ids); if ( tmpl == 0 ) { @@ -62,7 +62,8 @@ bool VirtualMachineAllocate::allocate_authorization(Template * tmpl) return true; } - AuthRequest ar(uid); + AuthRequest ar(uid, group_ids); + string t64; VirtualMachineTemplate * ttmpl = static_cast(tmpl); diff --git a/src/rm/RequestManagerVMTemplate.cc b/src/rm/RequestManagerVMTemplate.cc index 757d7db435..eac3224f2a 100644 --- a/src/rm/RequestManagerVMTemplate.cc +++ b/src/rm/RequestManagerVMTemplate.cc @@ -55,7 +55,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList if ( uid != 0 ) { - AuthRequest ar(uid); + AuthRequest ar(uid, group_ids); ar.add_auth(auth_object, id, ogid, auth_op, ouid, false); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 65eedc431e..cb93f988aa 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -45,7 +45,7 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl object->unlock(); - AuthRequest ar(uid); + AuthRequest ar(uid, group_ids); ar.add_auth(auth_object, oid, ogid, auth_op, ouid, false); diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index ae896b742b..19a404a534 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -190,7 +190,9 @@ error_common: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -bool UserPool::authenticate(const string& session, int& user_id, int& group_id) +//bool UserPool::authenticate(const string& session, int& user_id, int& group_id) +bool UserPool::authenticate(const string& session, int& user_id, int& group_id, + set& group_ids) { map::iterator index; @@ -224,6 +226,8 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id) uid = user->oid; gid = user->gid; + group_ids = user->get_groups(); + user->unlock(); } else //External User @@ -233,7 +237,7 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id) gid = -1; } - AuthRequest ar(uid); + AuthRequest ar(uid, group_ids); ar.add_authenticate(username,u_pass,secret); @@ -302,6 +306,7 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id) } else { + group_ids.insert( GroupPool::USERS_ID ); group_id = GroupPool::USERS_ID; result = true; } From 773f5f0881b2dd7b68e44a8ca040a5a38beb0553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 29 Jun 2011 12:56:12 +0200 Subject: [PATCH 15/75] Feature #687: Remove unneeded operators in AclRule --- include/AclRule.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/include/AclRule.h b/include/AclRule.h index e2f341ef9c..507e30b3da 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -39,15 +39,6 @@ public: user(_user), resource(_resource), rights(_rights) {}; - AclRule& operator=(AclRule const& o) - { - user = o.user; - resource = o.resource; - rights = o.rights; - - return *this; - }; - bool operator ==(const AclRule& other) const { return (user == other.user && @@ -55,16 +46,6 @@ public: rights == other.rights); }; - bool operator!=(const AclRule& other) const - { - return !(*this == other); - }; - - bool operator <(const AclRule& other) const - { - return user < other.user; - }; - /** * Returns a human readable string for this rule * From 85fa48e604802d71a9ce703fb97e25bda07a70e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 29 Jun 2011 13:09:29 +0200 Subject: [PATCH 16/75] Feature #687: Change the way the rule string representation is built --- include/AclRule.h | 17 ++++++++++++++--- src/acl/AclRule.cc | 13 +++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include/AclRule.h b/include/AclRule.h index 507e30b3da..ed6d402bf3 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -37,7 +37,9 @@ public: AclRule(long long _user, long long _resource, long long _rights): user(_user), resource(_resource), rights(_rights) - {}; + { + build_str(); + }; bool operator ==(const AclRule& other) const { @@ -51,8 +53,10 @@ public: * * @return a human readable string for this rule */ - string to_str() const; - + const string& to_str() const + { + return str; + }; /** * Function to print the object into a string in XML format @@ -124,6 +128,13 @@ private: * 64 bit integer containing the rights flags */ long long rights; + + /** + * Human readable representation + */ + string str; + + void build_str(); }; #endif /*ACL_RULE_H*/ diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index fb20d3aa9f..de9e3686ca 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -27,11 +27,10 @@ const long long AclRule::ALL_ID = 0x400000000LL; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -string AclRule::to_str() const +void AclRule::build_str() { ostringstream oss; - oss << "USER:"; if ( (user & GROUP_ID) != 0 ) { oss << "@" << user_id(); @@ -45,7 +44,7 @@ string AclRule::to_str() const oss << "*"; } - oss << " RESOURCE:"; + oss << " "; AuthRequest::Object objects[] = { AuthRequest::VM, @@ -89,7 +88,7 @@ string AclRule::to_str() const oss << "*"; } - oss << " OPERATION:"; + oss << " "; AuthRequest::Operation operations[] = { @@ -120,7 +119,7 @@ string AclRule::to_str() const } } - return oss.str(); + str = oss.str(); } /* -------------------------------------------------------------------------- */ @@ -135,9 +134,7 @@ string& AclRule::to_xml(string& xml) const "" << hex << user << "" << "" << hex << resource << "" << "" << hex << rights << "" << - - // TODO: Element DEBUG contains a human friendly string - "" << to_str() << "" << + "" << str << "" << ""; xml = oss.str(); From 8d4fec645b731879ae37a4ae618e64a5b67607f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tino=20V=C3=A1zquez?= Date: Wed, 29 Jun 2011 14:46:55 +0200 Subject: [PATCH 17/75] feature #687: Add Rule class in OCA --- src/oca/ruby/OpenNebula/Acl.rb | 206 +++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index abac2ff8bb..df9b0362de 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -63,6 +63,21 @@ module OpenNebula return rc end + + # Adds a new ACL rule. + # + # +rule+ Rule class + def addrule(rule) + return rule.error if rule.is_error? + + rc = @client.call( ACL_METHODS[:addrule], rule.user, + user.resources, + user.rights ) + + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end # Deletes an existing ACL rule. # @@ -84,4 +99,195 @@ module OpenNebula private end + + + # Abstract rules of the type USER RESOURCE RIGHTS + # which are: + # USER -> # + # @ + # ALL + # RESOURCE -> + separated list and "/{#,@}|ALL" + # VM, + # HOST + # NET + # IMAGE + # USER + # TEMPLATE + # GROUP + # ACL + # RIGHTS -> + separated list + # CREATE + # DELETE + # USE + # MANAGE + # INFO + # INFO_POOL + # INFO_POOL_MINE + # INSTANTIATE + # CHOWN + class Rule + + USERS = { + "UID" => 4294967296, + "GID" => 8589934592, + "ALL" => 17179869184 + } + + + RESOURCES = { + "VM" => 68719476736, + "HOST" => 137438953472, + "NET" => 274877906944, + "IMAGE" => 549755813888, + "USER" => 1099511627776, + "TEMPLATE" => 2199023255552, + "GROUP" => 4398046511104, + "ACL" => 8796093022208 + } + + RIGHTS = { + "CREATE" => 1, # Auth. to create an object + "DELETE" => 2, # Auth. to delete an object + "USE" => 4, # Auth. to use an object + "MANAGE" => 8, # Auth. to manage an object + "INFO" => 16, # Auth. to view an object + "INFO_POOL" => 32, # Auth. to view any object in the pool + "INFO_POOL_MINE"=> 64, # Auth. to view user and/or group objects + "INSTANTIATE" => 128,# Auth. to instantiate a VM from a TEMPLATE + "CHOWN" => 256 # Auth. to change ownership of an object + } + + + def initialize(rule_str=nil) + @content = { + :users => 0, + :resources => 0, + :rights => 0 + } + + parse_rule(rule_str) if rule_str + end + + def set_hex_rule(users,resources,rights) + set_hex_users users + set_hex_resources resources + set_hex_rights rights + end + + def set_hex_users(users) + @content[:users] = users + end + + def set_hex_resources(resources) + @content[:resources] = resources + end + + def set_hex_rights(rights) + @content[:rights] = rights + end + + def parse_rule(rule_str) + begin + rule_str = rule_str.split(" ") + parse_users(rule_str[0]) + parse_resource(rule_str[1]) + parse_rights(rule_str[2]) + rescue Exception => e + @content[:users] = OpenNebula::Error.new(e.message) + end + end + + def parse_users(users) + begin + @content[:users] = calculate_users(users) + rescue Exception => e + @content[:resources] = OpenNebula::Error.new(e.message) + end + end + + def parse_resources(resources) + begin + resources = resources.split("/") + + if resources.size != 2 + @content[:resources] = OpenNebula::Error.new( + "Resource #{resources} not well formed") + return + end + + resources[0].each{ |resource| + next if !RESOURCES[resource.upcase] + + @content[:resources] = @content[:resources] + + RESOURCES[resource.upcase] + } + + @content[:resources] = @content[:resources] + + calculate_user(resources[1]) + + @content[:resources] = @content[:resources].to_s(16) + rescue Exception => e + @content[:resources] = OpenNebula::Error.new(e.message) + end + end + + def parse_rights(rights) + begin + rights = rights.split("+") + + rights.each{ |right| + next if !RIGHTS[right.upcase] + + @content[:rights] = @content[:rights] + RIGHTS[right.upcase] + } + + @content[:rights] = @content[:rights].to_s(16) + rescue Exception => e + @content[:rights] = OpenNebula::Error.new(e.message) + end + end + + + def calculate_users(users_str) + if users == "*" + return USERS["ALL"] + end + + value = 0 + + case users[0..0] + when "#" + value = USERS["UID"] + when "@" + value = USERS["GID"] + end + + return value + users[1..-1].to_i + end + + def users + @content[:users] + end + + def resources + @content[:resources] + end + + def rights + @content[:rights] + end + + def is_error? + OpenNebula.is_error?(@content[:users]) || + OpenNebula.is_error?(@content[:resources]) || + OpenNebula.is_error?(@content[:rights]) + end + + def error + @content.each{ |part| + return part if OpenNebula.is_error?(part) + } + end + + end end From 84f874bfc29f3e8a6f8baf09e304f7466b547539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 29 Jun 2011 16:22:54 +0200 Subject: [PATCH 18/75] Feature #687: Add correctness check for new rules --- include/AclRule.h | 8 +++ src/acl/AclManager.cc | 9 +-- src/acl/AclRule.cc | 152 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 162 insertions(+), 7 deletions(-) diff --git a/include/AclRule.h b/include/AclRule.h index ed6d402bf3..3b59536292 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -58,6 +58,14 @@ public: return str; }; + /** + * Returns whether or not the rule is malformed. + * + * @param error_str Returns the error message, if any + * @return true if the rule is wrong + */ + bool malformed(string& error_str) const; + /** * Function to print the object into a string in XML format * diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index 5440e20ee4..ece77c188a 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -225,14 +225,15 @@ int AclManager::add_rule(long long user, long long resource, long long rights, return -1; } -/* - if ( rule->malformed() ) + if ( rule->malformed(error_str) ) { + oss << "Rule " << rule->to_str() << " is malformed: " << error_str; + error_str = oss.str(); + delete rule; - NebulaLog::log("ACL", Log::INFO, "TODO"); return -2; } -*/ + rc = insert(rule); diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index de9e3686ca..fc2e877b68 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -27,6 +27,153 @@ const long long AclRule::ALL_ID = 0x400000000LL; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +bool AclRule::malformed(string& error_str) const +{ + ostringstream oss; + bool error = false; + + // Check user + + if ( (user & INDIVIDUAL_ID) != 0 && (user & GROUP_ID) != 0 ) + { + error = true; + oss << "[user] INDIVIDUAL (#) and GROUP (@) bits are exclusive"; + } + + if ( (user & INDIVIDUAL_ID) != 0 && (user & ALL_ID) != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[user] INDIVIDUAL (#) and ALL (*) bits are exclusive"; + } + + if ( (user & GROUP_ID) != 0 && (user & ALL_ID) != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[user] GROUP (@) and ALL (*) bits are exclusive"; + } + + if ( user_id() < 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[user] ID cannot be negative"; + } + + if ( (user & ALL_ID) != 0 && user_id() != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "when using the ALL bit, [user] ID must be 0"; + } + + // Check resource + + if ( (resource & INDIVIDUAL_ID) != 0 && (resource & GROUP_ID) != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[resource] INDIVIDUAL (#) and GROUP (@) bits are exclusive"; + } + + if ( (resource & INDIVIDUAL_ID) != 0 && (resource & ALL_ID) != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[resource] INDIVIDUAL (#) and ALL (*) bits are exclusive"; + } + + if ( (resource & GROUP_ID) != 0 && (resource & ALL_ID) != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[resource] GROUP (@) and ALL (*) bits are exclusive"; + } + + if ( resource_id() < 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[resource] ID cannot be negative"; + } + + if ( (resource & ALL_ID) != 0 && resource_id() != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "when using the ALL bit, [resource] ID must be 0"; + } + + if ( (resource & 0xFF000000000LL) == 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[resource] type is missing"; + } + + if ( (resource & 0xFFFFF00000000000LL) != 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "wrong [resource] type"; + } + + if ( error ) + { + error_str = oss.str(); + } + + return error; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void AclRule::build_str() { ostringstream oss; @@ -53,13 +200,12 @@ void AclRule::build_str() AuthRequest::IMAGE, AuthRequest::USER, AuthRequest::TEMPLATE, - AuthRequest::GROUP, - AuthRequest::ACL + AuthRequest::GROUP }; bool prefix = false; - for ( int i = 0; i < 8; i++ ) + for ( int i = 0; i < 7; i++ ) { if ( (resource & objects[i]) != 0 ) { From 165a8fb74b269aceb0ee91d346e594314ebd00d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 29 Jun 2011 18:41:49 +0200 Subject: [PATCH 19/75] Feature #687: Add oid to ACL Rules, one.acl.delrule now expects that ID. Modify XML to look similar to a pool --- include/AclManager.h | 50 +++++++-- include/AclRule.h | 9 +- include/RequestManagerAcl.h | 19 +--- src/acl/AclManager.cc | 194 ++++++++++++++++++++++++++------- src/acl/AclRule.cc | 5 +- src/cli/oneacl | 4 +- src/oca/ruby/OpenNebula/Acl.rb | 8 +- src/rm/RequestManagerAcl.cc | 58 +++++++--- 8 files changed, 251 insertions(+), 96 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index 6e617e2a6e..3de8710902 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -28,9 +28,7 @@ using namespace std; class AclManager : public Callbackable { public: - AclManager(SqlDB * _db) - :db(_db) - {}; + AclManager(SqlDB * _db); ~AclManager(); @@ -69,7 +67,11 @@ public: * @param resource 64 bit ID and flags * @param rights 64 bit flags * @param error_str Returns the error reason, if any - * @return 0 on success + * + * @return the oid assigned to the rule on success, + * -1 if the rule exists, + * -2 if the rule is malformed, + * -3 if the DB insert failed */ int add_rule(long long user, long long resource, long long rights, string& error_str); @@ -79,14 +81,11 @@ public: /** * Deletes a rule from the ACL rule set * - * @param user 64 bit ID and flags - * @param resource 64 bit ID and flags - * @param rights 64 bit flags + * @param oid Rule id * @param error_str Returns the error reason, if any * @return 0 on success */ - int del_rule(long long user, long long resource, long long rights, - string& error_str); + int del_rule(int oid, string& error_str); /* ---------------------------------------------------------------------- */ /* DB management */ @@ -112,8 +111,18 @@ public: int dump(ostringstream& oss); private: + + /** + * ACL rules. Each rule is indexed by its 'user' long long attibute, + * several rules can apply to the same user + */ multimap acl_rules; + /** + * Rules indexed by oid. Stores the same rules as acl_rules + */ + map acl_rules_oids; + /** * Gets all rules that apply to the user_req and, if any of them grants * permission, returns true. @@ -146,12 +155,25 @@ private: */ SqlDB * db; + /** + * Last object ID assigned to a rule. + */ + int lastOID; + + /** + * Tablename for the ACL rules + */ static const char * table; static const char * db_names; static const char * db_bootstrap; + /** + * Inserts the last oid into the pool_control table + */ + void update_lastOID(); + /** * Callback function to unmarshall the ACL rules * @param num the number of columns read from the DB @@ -177,10 +199,16 @@ private: /** * Drops an ACL rule from the database - * @param rule to drop + * + * @param oid Rule id * @return 0 on success */ - int drop(AclRule * rule); + int drop(int oid); + + /** + * Callback to set the lastOID + */ + int init_cb(void *nil, int num, char **values, char **names); }; #endif /*ACL_MANAGER_H*/ diff --git a/include/AclRule.h b/include/AclRule.h index 3b59536292..ebcc11b317 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -35,8 +35,8 @@ public: static const long long GROUP_ID; static const long long ALL_ID; - AclRule(long long _user, long long _resource, long long _rights): - user(_user), resource(_resource), rights(_rights) + AclRule(int _oid, long long _user, long long _resource, long long _rights): + oid(_oid), user(_user), resource(_resource), rights(_rights) { build_str(); }; @@ -120,6 +120,11 @@ private: friend class AclManager; + /** + * Rule unique identifier + */ + int oid; + /** * 64 bit integer holding a user ID in the 32 less significant bits, * and a flag indicating the kind of ID in the other 32 diff --git a/include/RequestManagerAcl.h b/include/RequestManagerAcl.h index 3ce9501f87..fce48369a6 100644 --- a/include/RequestManagerAcl.h +++ b/include/RequestManagerAcl.h @@ -41,21 +41,10 @@ protected: /* -------------------------------------------------------------------- */ - virtual void request_execute(xmlrpc_c::paramList const& _paramList); + virtual void request_execute(xmlrpc_c::paramList const& _paramList) = 0; /* -------------------------------------------------------------------- */ - virtual int perform_operation(string& error_msg) - { - return 0; - }; - - /* -------------------------------------------------------------------- */ - - long long user; - long long resource; - long long rights; - AclManager * aclm; }; @@ -75,7 +64,7 @@ public: ~AclAddRule(){}; - int perform_operation(string& error_msg); + void request_execute(xmlrpc_c::paramList const& _paramList); }; /* ------------------------------------------------------------------------- */ @@ -87,14 +76,14 @@ public: AclDelRule(): RequestManagerAcl("AclDelRule", "Deletes an existing ACL rule", - "A:ssss") + "A:si") { // TODO: auth_op ? }; ~AclDelRule(){}; - int perform_operation(string& error_msg); + void request_execute(xmlrpc_c::paramList const& _paramList); }; /* ------------------------------------------------------------------------- */ diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index ece77c188a..010cf7178a 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -14,6 +14,8 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ +#include + #include "AclManager.h" #include "NebulaLog.h" @@ -22,10 +24,46 @@ const char * AclManager::table = "acl"; -const char * AclManager::db_names = "user, resource, rights"; +const char * AclManager::db_names = "oid, user, resource, rights"; const char * AclManager::db_bootstrap = "CREATE TABLE IF NOT EXISTS " - "acl (user BIGINT, resource BIGINT, rights BIGINT)"; + "acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, rights BIGINT)"; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int AclManager::init_cb(void *nil, int num, char **values, char **names) +{ + lastOID = -1; + + if ( values[0] != 0 ) + { + lastOID = atoi(values[0]); + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +AclManager::AclManager(SqlDB * _db) : + db(_db), lastOID(-1) +{ + ostringstream oss; + + // TODO: + // pthread_mutex_init(&mutex, 0); + + set_callback(static_cast (&AclManager::init_cb)); + + oss << "SELECT last_oid FROM pool_control WHERE tablename='" << table + << "'"; + + db->exec(oss, this); + + unset_callback(); +} +; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -78,7 +116,8 @@ const bool AclManager::authorize(int uid, const set &user_groups, - AclRule request_rule(AclRule::INDIVIDUAL_ID + uid, resource_oid_req, rights_req); + AclRule request_rule(-1, AclRule::INDIVIDUAL_ID + uid, resource_oid_req, + rights_req); oss << "Request " << request_rule.to_str(); NebulaLog::log("ACL",Log::DEBUG,oss); @@ -193,7 +232,12 @@ bool AclManager::match_rules( int AclManager::add_rule(long long user, long long resource, long long rights, string& error_str) { - AclRule * rule = new AclRule(user, resource, rights); + if (lastOID == INT_MAX) + { + lastOID = -1; + } + + AclRule * rule = new AclRule(++lastOID, user, resource, rights); ostringstream oss; int rc; @@ -218,20 +262,12 @@ int AclManager::add_rule(long long user, long long resource, long long rights, if ( found ) { - oss << "Rule " << rule->to_str() << " already exists"; - error_str = oss.str(); - - delete rule; - return -1; + goto error_duplicated; } if ( rule->malformed(error_str) ) { - oss << "Rule " << rule->to_str() << " is malformed: " << error_str; - error_str = oss.str(); - - delete rule; - return -2; + goto error_malformed; } @@ -239,35 +275,84 @@ int AclManager::add_rule(long long user, long long resource, long long rights, if ( rc != 0 ) { - error_str = "Error inserting rule in DB"; - return -1; + goto error_insert; } acl_rules.insert( make_pair(rule->user, rule) ); + acl_rules_oids.insert( make_pair(rule->oid, rule) ); - return 0; + update_lastOID(); + + return lastOID; + + +error_duplicated: + oss << "Rule " << rule->to_str() << " already exists"; + rc = -1; + + goto error_common; + +error_malformed: + oss << "Rule " << rule->to_str() << " is malformed: " << error_str; + rc = -2; + + goto error_common; + +error_insert: + oss << "Error inserting rule in DB"; + rc = -3; + + goto error_common; + +error_common: + error_str = oss.str(); + + delete rule; + lastOID--; + + return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int AclManager::del_rule(long long user, long long resource, long long rights, - string& error_str) + +int AclManager::del_rule(int oid, string& error_str) { + multimap::iterator it; pair::iterator, multimap::iterator> index; - int rc; - bool found = false; + AclRule * rule; + int rc; + bool found = false; - index = acl_rules.equal_range( user ); + // Check the rule exists + found = acl_rules_oids.count(oid) > 0; + + if ( !found ) + { + ostringstream oss; + oss << "Rule " << oid << " does not exist"; + error_str = oss.str(); + + return -1; + } + + rule = acl_rules_oids[oid]; + + // Look for it in the multimap + + found = false; + + index = acl_rules.equal_range( rule->user ); it = index.first; while ( !found && it != index.second ) { - found = ( it->second->resource == resource && - it->second->rights == rights ); + found = *rule == *(it->second); + if ( !found ) { @@ -277,16 +362,17 @@ int AclManager::del_rule(long long user, long long resource, long long rights, if ( !found ) { - AclRule rule(user, resource, rights); - ostringstream oss; - oss << "Rule " << rule.to_str() << " does not exist"; - error_str = oss.str(); + oss << "Internal error: ACL Rule " << oid + << " indexed by oid, but not in by user attribute"; + + NebulaLog::log("ACL",Log::ERROR,oss); return -1; } - rc = drop( it->second ); + + rc = drop( oid ); if ( rc != 0 ) { @@ -295,7 +381,9 @@ int AclManager::del_rule(long long user, long long resource, long long rights, } delete it->second; + acl_rules.erase( it ); + acl_rules_oids.erase( oid ); return 0; } @@ -303,12 +391,30 @@ int AclManager::del_rule(long long user, long long resource, long long rights, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +void AclManager::update_lastOID() +{ + // db->escape_str is not used for 'table' since its name can't be set in + // any way by the user, it is hardcoded. + + ostringstream oss; + + oss << "REPLACE INTO pool_control (tablename, last_oid) VALUES (" + << "'" << table << "'," + << lastOID << ")"; + + db->exec(oss); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int AclManager::select_cb(void *nil, int num, char **values, char **names) { - if ( (num != 3) || + if ( (num != 4) || (!values[0]) || (!values[1]) || - (!values[2]) ) + (!values[2]) || + (!values[3]) ) { return -1; } @@ -316,11 +422,13 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names) ostringstream oss; istringstream iss; + int oid = atoi(values[0]); + long long rule_values[3]; for ( int i = 0; i < 3; i++ ) { - iss.str( values[i] ); + iss.str( values[i+1] ); iss >> rule_values[i]; @@ -334,13 +442,15 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names) // TODO: Use add_rule() instead, to check possible errors, or assume // that anything that was stored into the DB is trustworthy? - AclRule * rule = new AclRule(rule_values[0], rule_values[1], rule_values[2]); + AclRule * rule = new AclRule(oid, rule_values[0], rule_values[1], + rule_values[2]); oss << "Loading ACL Rule " << rule->to_str(); - NebulaLog::log("ACL",Log::DEBUG,oss); + NebulaLog::log("ACL",Log::DDEBUG,oss); acl_rules.insert( make_pair(rule->user, rule) ); + acl_rules_oids.insert( make_pair(rule->oid, rule) ); return 0; } @@ -375,6 +485,7 @@ int AclManager::insert(AclRule * rule) // Construct the SQL statement to Insert oss << "INSERT INTO " << table <<" ("<< db_names <<") VALUES (" + << rule->oid << "," << rule->user << "," << rule->resource << "," << rule->rights << ")"; @@ -387,15 +498,14 @@ int AclManager::insert(AclRule * rule) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int AclManager::drop(AclRule * rule) + +int AclManager::drop(int oid) { ostringstream oss; int rc; oss << "DELETE FROM " << table << " WHERE " - << "user=" << rule->user << "AND" - << "resource=" << rule->resource << "AND" - << "rights=" << rule->rights; + << "oid=" << oid; rc = db->exec(oss); @@ -407,17 +517,17 @@ int AclManager::drop(AclRule * rule) int AclManager::dump(ostringstream& oss) { - multimap::iterator it; + map::iterator it; string xml; - oss << ""; + oss << ""; - for ( it = acl_rules.begin() ; it != acl_rules.end(); it++ ) + for ( it = acl_rules_oids.begin() ; it != acl_rules_oids.end(); it++ ) { oss << it->second->to_xml(xml); } - oss << ""; + oss << ""; return 0; } diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index fc2e877b68..24dd9b7e25 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -276,12 +276,13 @@ string& AclRule::to_xml(string& xml) const ostringstream oss; oss << - "" + "" + "" << oid << "" << "" << hex << user << "" << "" << hex << resource << "" << "" << hex << rights << "" << "" << str << "" << - ""; + ""; xml = oss.str(); diff --git a/src/cli/oneacl b/src/cli/oneacl index b1fdb3941f..318284dae1 100755 --- a/src/cli/oneacl +++ b/src/cli/oneacl @@ -69,10 +69,10 @@ cmd = CommandParser::CmdParser.new(ARGV) do Deletes an existing ACL rule EOT - command :delrule, delrule_desc, :user, :resource, :rights do + command :delrule, delrule_desc, :id do acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) - rc = acl.delrule( args[0], args[1], args[2] ) + rc = acl.delrule( args[0] ) if OpenNebula.is_error?(rc) [-1, rc.message] diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index df9b0362de..f61bbed424 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -81,11 +81,9 @@ module OpenNebula # Deletes an existing ACL rule. # - # +user+ A hex number, e.g. 0x100000001 - # +resource+ A hex number, e.g. 0x2100000001 - # +rights+ A hex number, e.g. 0x10 - def delrule(user, resource, rights) - rc = @client.call( ACL_METHODS[:delrule], user, resource, rights ) + # +id+ Rule id + def delrule(id) + rc = @client.call( ACL_METHODS[:delrule], id.to_i ) rc = nil if !OpenNebula.is_error?(rc) diff --git a/src/rm/RequestManagerAcl.cc b/src/rm/RequestManagerAcl.cc index 34838210d7..aa30f041e1 100644 --- a/src/rm/RequestManagerAcl.cc +++ b/src/rm/RequestManagerAcl.cc @@ -21,7 +21,7 @@ using namespace std; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ -void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) +void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList) { /* xmlrpc-c version 1.07 can manage 64 bit numbers, but not all distros. ship @@ -32,6 +32,10 @@ void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) rights = xmlrpc_c::value_i8(paramList.getI8(3)); */ + long long user; + long long resource; + long long rights; + istringstream iss; iss.str( xmlrpc_c::value_string(paramList.getString(1)) ); @@ -59,9 +63,43 @@ void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) return; } - int rc = perform_operation(error_msg); + int rc = aclm->add_rule(user, resource, rights, error_msg); - if ( rc != 0 ) + + if ( rc < 0 ) + { + failure_response(INTERNAL, request_error(error_msg, "")); + return; + } + + success_response(rc); + + return; +} + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList) +{ + int oid = xmlrpc_c::value_int(paramList.getInt(1)); + + Nebula& nd = Nebula::instance(); + aclm = nd.get_aclm(); + + string error_msg; + + // TODO: Only oneadmin can manage ACL + if ( uid != 0 ) + { + failure_response(AUTHORIZATION, + authorization_error("Only oneadmin can manage ACL rules")); + return; + } + + int rc = aclm->del_rule(oid, error_msg); + + if ( rc < 0 ) { failure_response(INTERNAL, request_error(error_msg, "")); return; @@ -72,20 +110,6 @@ void RequestManagerAcl::request_execute(xmlrpc_c::paramList const& paramList) return; } -/* ------------------------------------------------------------------------- */ - -int AclAddRule::perform_operation(string& error_msg) -{ - return aclm->add_rule(user, resource, rights, error_msg); -} - -/* ------------------------------------------------------------------------- */ - -int AclDelRule::perform_operation(string& error_msg) -{ - return aclm->del_rule(user, resource, rights, error_msg); -} - /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ From 3a321321b54e7b0e12c221f00ceda7bde6fdc518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tino=20V=C3=A1zquez?= Date: Wed, 29 Jun 2011 19:32:10 +0200 Subject: [PATCH 20/75] feature #687: Human readable output for oneacl list --- src/cli/etc/oneacl.yaml | 25 ++++++ src/cli/one_helper/oneacl_helper.rb | 118 +++++++++++++++++++++++++++ src/cli/oneacl | 17 ++-- src/oca/ruby/OpenNebula.rb | 1 + src/oca/ruby/OpenNebula/Acl.rb | 121 ++++++++-------------------- src/oca/ruby/OpenNebula/AclPool.rb | 109 +++++++++++++++++++++++++ 6 files changed, 290 insertions(+), 101 deletions(-) create mode 100644 src/cli/etc/oneacl.yaml create mode 100644 src/cli/one_helper/oneacl_helper.rb create mode 100644 src/oca/ruby/OpenNebula/AclPool.rb diff --git a/src/cli/etc/oneacl.yaml b/src/cli/etc/oneacl.yaml new file mode 100644 index 0000000000..e53a1bad8e --- /dev/null +++ b/src/cli/etc/oneacl.yaml @@ -0,0 +1,25 @@ +--- +:USER: + :desc: To which resource owner the rule applies to + :size: 4 + :right: true + +:RESOURCE_VHNIUTG: + :desc: Which resource the rule applies to + :size: 16 + +:RID: + :desc: Resource ID + :size: 4 + :right: true + +:OPERATION_CDUMIPpTW: + :desc: Operation to which the rule applies + :size: 19 + :right: true + +:default: +- :USER +- :RESOURCE_VHNIUTG +- :RID +- :OPERATION_CDUMIPpTW diff --git a/src/cli/one_helper/oneacl_helper.rb b/src/cli/one_helper/oneacl_helper.rb new file mode 100644 index 0000000000..916d4be256 --- /dev/null +++ b/src/cli/one_helper/oneacl_helper.rb @@ -0,0 +1,118 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +require 'one_helper' + +class OneAclHelper < OpenNebulaHelper::OneHelper + def self.rname + "ACL" + end + + def self.conf_file + "oneacl.yaml" + end + + private + + def factory_pool(filter) + OpenNebula::AclPool.new(@client) + end + + # TODO check that @content[:resources_str] is valid + def self.resource_mask(str) + resource_type=str.split("/")[0] + + mask = "-------" + + resource_type.split("+").each{|type| + case type + when "VM" + mask[0] = "V" + when "HOST" + mask[1] = "H" + when "NET" + mask[2] = "N" + when "IMAGE" + mask[3] = "I" + when "USER" + mask[4] = "U" + when "TEMPLATE" + mask[5] = "T" + when "GROUP" + mask[6] = "G" + end + } + mask + end + + # TODO check that @content[:resources_str] is valid + def self.right_mask(str) + mask = "---------" + + str.split("+").each{|type| + case type + when "CREATE" + mask[0] = "C" + when "DELETE" + mask[1] = "D" + when "USE" + mask[2] = "U" + when "MANAGE" + mask[3] = "M" + when "INFO" + mask[4] = "I" + when "INFO_POOL" + mask[5] = "P" + when "INFO_POOL_MINE" + mask[6] = "p" + when "INSTANTIATE" + mask[8] = "T" + when "CHOWN" + mask[9] = "W" + end + } + + mask + end + + def format_pool(pool, options, top=false) + config_file=self.class.table_conf + + table=CLIHelper::ShowTable.new(config_file, self) do + column :USER, "To which resource owner the rule applies to", + :size=>4 do |d| + d['STRING'].split(" ")[0] + end + + column :RESOURCE_VHNIUTG, "Resource to which the rule applies" do |d| + OneAclHelper::resource_mask d['STRING'].split(" ")[1] + end + + column :RID, "Resource ID", :right, :size=>4 do |d| + d['STRING'].split(" ")[1].split("/")[1] + end + + column :OPERATION_CDUMIPpTW, "Operation to which the rule applies" do |d| + OneAclHelper::right_mask d['STRING'].split(" ")[2] + end + + default :USER, :RESOURCE_VHNIUTG, :RID, :OPERATION_CDUMIPpTW + end + + table.show(pool, options) + + end +end \ No newline at end of file diff --git a/src/cli/oneacl b/src/cli/oneacl index 318284dae1..d4001ffac1 100755 --- a/src/cli/oneacl +++ b/src/cli/oneacl @@ -28,11 +28,13 @@ $: << RUBY_LIB_LOCATION $: << RUBY_LIB_LOCATION+"/cli" require 'command_parser' -require 'one_helper' +require 'one_helper/oneacl_helper' cmd = CommandParser::CmdParser.new(ARGV) do usage "oneacl COMMAND [args..] [options..]" version OpenNebulaHelper::ONE_VERSION + + helper = OneAclHelper.new ######################################################################## # Global Options @@ -53,7 +55,7 @@ cmd = CommandParser::CmdParser.new(ARGV) do EOT command :addrule, addrule_desc, :user, :resource, :rights do - acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) + acl = OpenNebula::AclPool.new( OpenNebula::Client.new() ) rc = acl.addrule( args[0], args[1], args[2] ) @@ -88,15 +90,6 @@ cmd = CommandParser::CmdParser.new(ARGV) do EOT command :list, list_desc,:options=>OpenNebulaHelper::XML do - acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) - - rc = acl.info() - - if OpenNebula.is_error?(rc) - [-1, rc.message] - else - puts acl.to_xml - 0 - end + helper.list_pool(options) end end diff --git a/src/oca/ruby/OpenNebula.rb b/src/oca/ruby/OpenNebula.rb index 98f2bcec04..c536eefe7a 100644 --- a/src/oca/ruby/OpenNebula.rb +++ b/src/oca/ruby/OpenNebula.rb @@ -40,6 +40,7 @@ require 'OpenNebula/TemplatePool' require 'OpenNebula/Group' require 'OpenNebula/GroupPool' require 'OpenNebula/Acl' +require 'OpenNebula/AclPool' module OpenNebula diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index f61bbed424..52698f1d9a 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -14,91 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' - module OpenNebula - class Acl < XMLElement - - ####################################################################### - # Constants and Class Methods - ####################################################################### - ACL_METHODS = { - :info => "acl.info", - :addrule => "acl.addrule", - :delrule => "acl.delrule" - } - - ####################################################################### - # Class constructor - ####################################################################### - def initialize(client) - @client = client - end - - ####################################################################### - # XML-RPC Methods - ####################################################################### - - # Retrieves the ACL rule set - def info() - rc = @client.call( ACL_METHODS[:info] ) - - if !OpenNebula.is_error?(rc) - initialize_xml(rc, 'ACL') - rc = nil - end - - return rc - end - - # Adds a new ACL rule. - # - # +user+ A hex number, e.g. 0x100000001 - # +resource+ A hex number, e.g. 0x2100000001 - # +rights+ A hex number, e.g. 0x10 - def addrule(user, resource, rights) - rc = @client.call( ACL_METHODS[:addrule], user, resource, rights ) - - rc = nil if !OpenNebula.is_error?(rc) - - return rc - end - - # Adds a new ACL rule. - # - # +rule+ Rule class - def addrule(rule) - return rule.error if rule.is_error? - - rc = @client.call( ACL_METHODS[:addrule], rule.user, - user.resources, - user.rights ) - - rc = nil if !OpenNebula.is_error?(rc) - - return rc - end - - # Deletes an existing ACL rule. - # - # +id+ Rule id - def delrule(id) - rc = @client.call( ACL_METHODS[:delrule], id.to_i ) - - rc = nil if !OpenNebula.is_error?(rc) - - return rc - end - - ####################################################################### - # Helpers - ####################################################################### - - private - - end - - # Abstract rules of the type USER RESOURCE RIGHTS # which are: # USER -> # @@ -123,7 +39,7 @@ module OpenNebula # INFO_POOL_MINE # INSTANTIATE # CHOWN - class Rule + class Acl USERS = { "UID" => 4294967296, @@ -156,14 +72,27 @@ module OpenNebula } - def initialize(rule_str=nil) + def initialize(rule_xml=nil) @content = { :users => 0, :resources => 0, :rights => 0 } - parse_rule(rule_str) if rule_str + parse_rule(rule_xml) + end + + def initialize(users,resources,rights, str) + str=str.split(" ") + + @content = { + :users => users, + :resources => resources, + :rights => rights, + :users_str => str.size==3?str[0]:0, + :resources_str => str.size==3?str[1]:0, + :rights_str => str.size==3?str[2]:0 + } end def set_hex_rule(users,resources,rights) @@ -184,6 +113,17 @@ module OpenNebula @content[:rights] = rights end + def set_users(users) + @content[:users] = users.to_s(10) + end + + def set_resources(resources) + @content[:resources] = resources.to_s(10) + end + + def set_rights(rights) + @content[:rights] = rights.to_s(10) + end def parse_rule(rule_str) begin rule_str = rule_str.split(" ") @@ -278,7 +218,10 @@ module OpenNebula def is_error? OpenNebula.is_error?(@content[:users]) || OpenNebula.is_error?(@content[:resources]) || - OpenNebula.is_error?(@content[:rights]) + OpenNebula.is_error?(@content[:rights]) || + @content[:users] == 0 || + @content[:resources] == 0 || + @content[:rights] == 0 end def error @@ -286,6 +229,6 @@ module OpenNebula return part if OpenNebula.is_error?(part) } end - + end end diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/OpenNebula/AclPool.rb new file mode 100644 index 0000000000..8b49b898c5 --- /dev/null +++ b/src/oca/ruby/OpenNebula/AclPool.rb @@ -0,0 +1,109 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +require 'OpenNebula/Pool' + +module OpenNebula + class AclPool < Pool + + ####################################################################### + # Constants and Class Methods + ####################################################################### + ACL_POOL_METHODS = { + :info => "acl.info", + :addrule => "acl.addrule", + :delrule => "acl.delrule" + } + + ####################################################################### + # Class constructor + ####################################################################### + def initialize(client) + super('ACL_POOL','ACL',client) + end + + def factory(element_xml) + acl=REXML::Document.new(element_xml).root + OpenNebula::Acl.new(acl['USER'], acl['RESOURCE'], acl['RIGHTS']) + end + + ####################################################################### + # XML-RPC Methods + ####################################################################### + + # Retrieves the ACL Pool + def info() + # Retrieves all the Acls in the pool. + super(ACL_POOL_METHODS[:info]) + end + + # Adds a new ACL rule. + # + # +user+ A hex number, e.g. 0x100000001 + # +resource+ A hex number, e.g. 0x2100000001 + # +rights+ A hex number, e.g. 0x10 + def addrule(user, resource, rights) + rc = @client.call( ACL_POOL_METHODS[:addrule], + user, + resource, + rights ) + + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + + # Adds a new ACL rule. + # + # +rule+ Rule class + def addrule_with_class(rule) + return rule.error if rule.is_error? + + rc = @client.call( ACL_POOL_METHODS[:addrule], + rule.user, + rule.resources, + rule.rights ) + + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + + # Deletes an existing ACL rule. + # + # +user+ A hex number, e.g. 0x100000001 + # +resource+ A hex number, e.g. 0x2100000001 + # +rights+ A hex number, e.g. 0x10 + def delrule(user, resource, rights) + rc = @client.call( ACL_POOL_METHODS[:delrule], + user, + resource, + rights ) + + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + + ####################################################################### + # Helpers + ####################################################################### + + private + + end + +end From 759d05c2f2df859c7dea2ac63af4c3447868ed88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 11:04:07 +0200 Subject: [PATCH 21/75] Feature #687: Remove duplicated search test in AclManager::add_rule --- src/acl/AclManager.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index 010cf7178a..efc5611ed9 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -253,11 +253,6 @@ int AclManager::add_rule(long long user, long long resource, long long rights, for ( it = index.first; (it != index.second && !found); it++) { found = *(it->second) == *rule; - if ( it->second->resource == resource && - it->second->rights == rights ) - { - found = true; - } } if ( found ) From 42ae602e99e8e2e2dc3ff582196cf4a26fb1a689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 11:17:22 +0200 Subject: [PATCH 22/75] Feature #687: Add missing CLI files to install.sh --- install.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index f8201c9b28..dbc4e993db 100755 --- a/install.sh +++ b/install.sh @@ -674,6 +674,7 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \ src/oca/ruby/OpenNebula/Group.rb \ src/oca/ruby/OpenNebula/GroupPool.rb \ src/oca/ruby/OpenNebula/Acl.rb \ + src/oca/ruby/OpenNebula/AclPool.rb \ src/oca/ruby/OpenNebula/XMLUtils.rb" #------------------------------------------------------------------------------- @@ -769,7 +770,8 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \ src/cli/one_helper/onetemplate_helper.rb \ src/cli/one_helper/oneuser_helper.rb \ src/cli/one_helper/onevm_helper.rb \ - src/cli/one_helper/onevnet_helper.rb" + src/cli/one_helper/onevnet_helper.rb \ + src/cli/one_helper/oneacl_helper.rb" CLI_BIN_FILES="src/cli/onevm \ src/cli/onehost \ @@ -786,7 +788,8 @@ CLI_CONF_FILES="src/cli/etc/onegroup.yaml \ src/cli/etc/onetemplate.yaml \ src/cli/etc/oneuser.yaml \ src/cli/etc/onevm.yaml \ - src/cli/etc/onevnet.yaml" + src/cli/etc/onevnet.yaml \ + src/cli/etc/oneacl.yaml" #----------------------------------------------------------------------------- # Sunstone files From 8e33e4cded8326ee52af38e87060dae4d4c40a52 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 30 Jun 2011 11:31:00 +0200 Subject: [PATCH 23/75] feature #687: Resources now stores the name of the owner and the group --- include/Group.h | 2 +- include/Image.h | 2 + include/ImagePool.h | 6 ++- include/PoolObjectSQL.h | 34 ++++++++++++--- include/Request.h | 9 ++-- include/User.h | 13 ++++-- include/UserPool.h | 19 +++++---- include/VMTemplate.h | 6 ++- include/VMTemplatePool.h | 17 ++------ include/VirtualMachine.h | 8 +++- include/VirtualMachinePool.h | 4 +- include/VirtualNetwork.h | 2 + include/VirtualNetworkPool.h | 4 +- src/host/Host.cc | 2 +- src/image/Image.cc | 4 +- src/image/ImagePool.cc | 4 +- src/rm/Request.cc | 7 +++- src/rm/RequestManagerAllocate.cc | 21 ++++++---- src/rm/RequestManagerVMTemplate.cc | 2 +- src/rm/RequestManagerVirtualMachine.cc | 2 +- src/um/UserPool.cc | 58 ++++++++++++++++++++------ src/vm/VirtualMachine.cc | 10 +++-- src/vm/VirtualMachinePool.cc | 4 +- src/vm_template/VMTemplate.cc | 4 +- src/vm_template/VMTemplatePool.cc | 4 +- src/vnm/VirtualNetwork.cc | 10 +++-- src/vnm/VirtualNetworkPool.cc | 4 +- 27 files changed, 182 insertions(+), 80 deletions(-) diff --git a/include/Group.h b/include/Group.h index 860d883e87..f732811b33 100644 --- a/include/Group.h +++ b/include/Group.h @@ -78,7 +78,7 @@ private: // ************************************************************************* Group(int id, const string& name): - PoolObjectSQL(id,name,-1,-1,table), + PoolObjectSQL(id,name,-1,-1,"","",table), ObjectCollection("USERS"){}; virtual ~Group(){}; diff --git a/include/Image.h b/include/Image.h index ad40595233..6c60ac4ab5 100644 --- a/include/Image.h +++ b/include/Image.h @@ -332,6 +332,8 @@ protected: Image(int uid, int gid, + const string& uname, + const string& gname, ImageTemplate* img_template); virtual ~Image(); diff --git a/include/ImagePool.h b/include/ImagePool.h index 6a5df81d8c..1c192997ec 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -48,6 +48,8 @@ public: * Function to allocate a new Image object * @param uid the user id of the image's owner * @param gid the id of the group this object is assigned to + * @param uname name of the user + * @param gname name of the group * @param img_template template associated with the image * @param oid the id assigned to the Image * @param error_str Returns the error reason, if any @@ -58,6 +60,8 @@ public: int allocate ( int uid, int gid, + const string& uname, + const string& gname, ImageTemplate * img_template, int * oid, string& error_str); @@ -172,7 +176,7 @@ private: */ PoolObjectSQL * create() { - return new Image(-1,-1,0); + return new Image(-1,-1,"","",0); }; }; diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index 58794da920..b12b16107b 100644 --- a/include/PoolObjectSQL.h +++ b/include/PoolObjectSQL.h @@ -36,11 +36,25 @@ using namespace std; class PoolObjectSQL : public ObjectSQL, public ObjectXML { public: - - PoolObjectSQL(int id, const string& _name, int _uid, - int _gid, const char *_table) - :ObjectSQL(),ObjectXML(),oid(id),name(_name),uid(_uid),gid(_gid), - valid(true),public_obj(0),obj_template(0),table(_table) + PoolObjectSQL(int id, + const string& _name, + int _uid, + int _gid, + const string& _uname, + const string& _gname, + const char * _table) + :ObjectSQL(), + ObjectXML(), + oid(id), + name(_name), + uid(_uid), + gid(_gid), + uname(_uname), + gname(_gname), + valid(true), + public_obj(0), + obj_template(0), + table(_table) { pthread_mutex_init(&mutex,0); }; @@ -360,6 +374,16 @@ protected: */ int gid; + /** + * Name of the object's owner, empty if owner is not used + */ + string uname; + + /** + * Name of the object's group,, empty if group is not used + */ + string gname; + /** * The contents of this object are valid */ diff --git a/include/Request.h b/include/Request.h index 2f68ba3dbb..4a7d7121df 100644 --- a/include/Request.h +++ b/include/Request.h @@ -59,10 +59,12 @@ protected: /* ------------------- Attributes of the Request ---------------------- */ - int uid; /**< id of the user performing the request */ - + int uid; /**< id of the user */ int gid; /**< id of the user's group */ + string uname; /**< name of the user */ + string gname; /**< name of the user's group */ + set group_ids; /**< set of user's group ids */ PoolSQL * pool; /**< Pool of objects */ @@ -70,8 +72,7 @@ protected: string method_name; /**< The name of the XML-RPC method */ AuthRequest::Object auth_object; /**< Auth object for the request */ - - AuthRequest::Operation auth_op; /**< Auth operation for the request */ + AuthRequest::Operation auth_op; /**< Auth operation for the request */ /* -------------------- Constructors ---------------------------------- */ diff --git a/include/User.h b/include/User.h index ee57ed35ba..b7b94775ee 100644 --- a/include/User.h +++ b/include/User.h @@ -189,11 +189,16 @@ protected: // Constructor // ************************************************************************* - User(int id, int _gid, const string& _username, const string& _password, bool _enabled): - PoolObjectSQL(id,_username,-1,_gid,table), + User(int id, + int _gid, + const string& _uname, + const string& _gname, + const string& _password, + bool _enabled): + PoolObjectSQL(id,_uname,-1,_gid,"",_gname,table), ObjectCollection("GROUPS"), - password(_password), enabled(_enabled) - { }; + password(_password), + enabled(_enabled){}; virtual ~User(){}; diff --git a/include/UserPool.h b/include/UserPool.h index 59db2b0a50..e543e65cde 100644 --- a/include/UserPool.h +++ b/include/UserPool.h @@ -51,8 +51,9 @@ public: int allocate ( int * oid, int gid, - string username, - string password, + const string& uname, + const string& gname, + const string& password, bool enabled, string& error_str); @@ -102,13 +103,17 @@ public: * @param session, colon separated username and password string * @param uid of the user if authN succeeded -1 otherwise * @param gid of the user if authN succeeded -1 otherwise + * @param uname of the user if authN succeeded "" otherwise + * @param gname of the group if authN succeeded "" otherwise * @param group_ids the user groups if authN succeeded, is empty otherwise * @return false if authn failed, true otherwise */ - bool authenticate(const string& session, int& uid, int& gid, - set& group_ids); - - + bool authenticate(const string& session, + int& uid, + int& gid, + string& uname, + string& gname, + set& group_ids); /** * Returns whether there is a user with given username/password or not * @param ar, an Authorization Request @@ -136,7 +141,7 @@ private: */ PoolObjectSQL * create() { - return new User(-1,-1,"","",true); + return new User(-1,-1,"","","",true); }; }; diff --git a/include/VMTemplate.h b/include/VMTemplate.h index b47a6fd705..819eb29c01 100644 --- a/include/VMTemplate.h +++ b/include/VMTemplate.h @@ -129,7 +129,11 @@ protected: // ************************************************************************* // Constructor // ************************************************************************* - VMTemplate(int id, int uid, int gid, + VMTemplate(int id, + int uid, + int gid, + const string& uname, + const string& gname, VirtualMachineTemplate * _template_contents); ~VMTemplate(); diff --git a/include/VMTemplatePool.h b/include/VMTemplatePool.h index 4ebb5a0280..0b66952bfd 100644 --- a/include/VMTemplatePool.h +++ b/include/VMTemplatePool.h @@ -44,6 +44,8 @@ public: */ int allocate(int uid, int gid, + const string& uname, + const string& gname, VirtualMachineTemplate * template_contents, int * oid, string& error_str); @@ -109,26 +111,13 @@ public: }; private: - //-------------------------------------------------------------------------- - // Configuration Attributes for Images - // ------------------------------------------------------------------------- - - // TODO - - //-------------------------------------------------------------------------- - // Pool Attributes - // ------------------------------------------------------------------------- - - // TODO - - /** * Factory method to produce Image objects * @return a pointer to the new Image */ PoolObjectSQL * create() { - return new VMTemplate(-1,-1,-1,0); + return new VMTemplate(-1,-1,-1,"","",0); }; }; diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index ff0e436ac5..3f52feb54a 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -865,8 +865,12 @@ protected: // Constructor //************************************************************************** - VirtualMachine(int id, int uid, - int gid, VirtualMachineTemplate * _vm_template); + VirtualMachine(int id, + int uid, + int gid, + const string& uname, + const string& gname, + VirtualMachineTemplate * _vm_template); virtual ~VirtualMachine(); diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index f84723259c..873e6de3d9 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -52,6 +52,8 @@ public: int allocate ( int uid, int gid, + const string& uname, + const string& gname, VirtualMachineTemplate * vm_template, int * oid, string& error_str, @@ -160,7 +162,7 @@ private: */ PoolObjectSQL * create() { - return new VirtualMachine(-1,-1,-1,0); + return new VirtualMachine(-1,-1,-1,"","",0); }; }; diff --git a/include/VirtualNetwork.h b/include/VirtualNetwork.h index a6d056854a..dc78655908 100644 --- a/include/VirtualNetwork.h +++ b/include/VirtualNetwork.h @@ -269,6 +269,8 @@ private: VirtualNetwork(int uid, int gid, + const string& _uname, + const string& _gname, VirtualNetworkTemplate * _vn_template = 0); ~VirtualNetwork(); diff --git a/include/VirtualNetworkPool.h b/include/VirtualNetworkPool.h index 1f6f2d3724..ff0fe2aed6 100644 --- a/include/VirtualNetworkPool.h +++ b/include/VirtualNetworkPool.h @@ -51,6 +51,8 @@ public: int allocate ( int uid, int gid, + const string& uname, + const string& gname, VirtualNetworkTemplate * vn_template, int * oid, string& error_str); @@ -156,7 +158,7 @@ private: */ PoolObjectSQL * create() { - return new VirtualNetwork(-1,-1, 0); + return new VirtualNetwork(-1,-1,"","",0); }; }; diff --git a/src/host/Host.cc b/src/host/Host.cc index 992f0d87d3..062c456024 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -34,7 +34,7 @@ Host::Host( const string& _im_mad_name, const string& _vmm_mad_name, const string& _tm_mad_name): - PoolObjectSQL(id,_hostname,-1,-1,table), + PoolObjectSQL(id,_hostname,-1,-1,"","",table), state(INIT), im_mad_name(_im_mad_name), vmm_mad_name(_vmm_mad_name), diff --git a/src/image/Image.cc b/src/image/Image.cc index 928d371b3c..1b77775f3f 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -36,8 +36,10 @@ Image::Image(int _uid, int _gid, + const string& _uname, + const string& _gname, ImageTemplate * _image_template): - PoolObjectSQL(-1,"",_uid,_gid,table), + PoolObjectSQL(-1,"",_uid,_gid,_uname,_gname,table), type(OS), regtime(time(0)), source("-"), diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index b728fc2f0b..980715b6b9 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -57,6 +57,8 @@ ImagePool::ImagePool(SqlDB * db, int ImagePool::allocate ( int uid, int gid, + const string& uname, + const string& gname, ImageTemplate* img_template, int * oid, string& error_str) @@ -66,7 +68,7 @@ int ImagePool::allocate ( string name; ostringstream oss; - img = new Image(uid, gid, img_template); + img = new Image(uid, gid, uname, gname, img_template); // Check name img->get_template_attribute("NAME", name); diff --git a/src/rm/Request.cc b/src/rm/Request.cc index c3866b4d76..19f3584012 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -33,7 +33,12 @@ void Request::execute( NebulaLog::log("ReM",Log::DEBUG, method_name + " method invoked"); - if ( upool->authenticate(session, uid, gid, group_ids) == false ) + if ( upool->authenticate(session, + uid, + gid, + uname, + gname, + group_ids) == false ) { failure_response(AUTHENTICATION, authenticate_error()); } diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc index ccbbf9675a..175c92b5b0 100644 --- a/src/rm/RequestManagerAllocate.cc +++ b/src/rm/RequestManagerAllocate.cc @@ -133,10 +133,10 @@ int VirtualMachineAllocate::pool_allocate(xmlrpc_c::paramList const& paramList, int& id, string& error_str) { - VirtualMachineTemplate * ttmpl = static_cast(tmpl); - VirtualMachinePool * vmpool = static_cast(pool); + VirtualMachineTemplate * ttmpl= static_cast(tmpl); + VirtualMachinePool * vmpool = static_cast(pool); - return vmpool->allocate(uid, gid, ttmpl, &id, error_str, false); + return vmpool->allocate(uid, gid, uname, gname, ttmpl, &id,error_str,false); } @@ -151,7 +151,7 @@ int VirtualNetworkAllocate::pool_allocate(xmlrpc_c::paramList const& _paramList, VirtualNetworkPool * vpool = static_cast(pool); VirtualNetworkTemplate * vtmpl=static_cast(tmpl); - return vpool->allocate(uid, gid, vtmpl, &id, error_str); + return vpool->allocate(uid, gid, uname, gname, vtmpl, &id, error_str); } /* -------------------------------------------------------------------------- */ @@ -165,7 +165,7 @@ int ImageAllocate::pool_allocate(xmlrpc_c::paramList const& _paramList, ImagePool * ipool = static_cast(pool); ImageTemplate * itmpl = static_cast(tmpl); - return ipool->allocate(uid, gid, itmpl, &id, error_str); + return ipool->allocate(uid, gid, uname, gname, itmpl, &id, error_str); } /* -------------------------------------------------------------------------- */ @@ -180,7 +180,7 @@ int TemplateAllocate::pool_allocate(xmlrpc_c::paramList const& _paramList, VirtualMachineTemplate * ttmpl=static_cast(tmpl); - return tpool->allocate(uid, gid, ttmpl, &id, error_str); + return tpool->allocate(uid, gid, uname, gname, ttmpl, &id, error_str); } /* -------------------------------------------------------------------------- */ @@ -213,14 +213,17 @@ int UserAllocate::pool_allocate(xmlrpc_c::paramList const& paramList, string passwd = xmlrpc_c::value_string(paramList.getString(2)); UserPool * upool = static_cast(pool); - int users_group = gid; + + int ugid = gid; + string ugname = gname; if ( gid == GroupPool::ONEADMIN_ID ) { - users_group = GroupPool::USERS_ID; + ugid = GroupPool::USERS_ID; + ugname = GroupPool::USERS_NAME; } - return upool->allocate(&id,users_group,uname,passwd,true,error_str); + return upool->allocate(&id,ugid,uname,ugname,passwd,true,error_str); } /* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerVMTemplate.cc b/src/rm/RequestManagerVMTemplate.cc index eac3224f2a..39e9e0aea0 100644 --- a/src/rm/RequestManagerVMTemplate.cc +++ b/src/rm/RequestManagerVMTemplate.cc @@ -69,7 +69,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList } } - rc = vmpool->allocate(uid, gid, tmpl, &vid, error_str, false); + rc = vmpool->allocate(uid, gid, uname, gname, tmpl, &vid, error_str, false); if ( rc < 0 ) { diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index cb93f988aa..de02b00f1b 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -398,7 +398,7 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis // ------------------ Create the image ------------------ - rc = ipool->allocate(uid, gid, itemplate, &iid,error_str); + rc = ipool->allocate(uid, gid, uname, gname, itemplate, &iid,error_str); if ( rc < 0 ) { diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index 19a404a534..467263ab08 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -88,8 +88,13 @@ UserPool::UserPool(SqlDB * db):PoolSQL(db,User::table) string error_str; string sha1_pass = SSLTools::sha1_digest(one_pass); - allocate(&one_uid,GroupPool::ONEADMIN_ID,one_name,sha1_pass, - true, error_str); + allocate(&one_uid, + GroupPool::ONEADMIN_ID, + one_name, + GroupPool::ONEADMIN_NAME, + sha1_pass, + true, + error_str); } else { @@ -117,8 +122,9 @@ UserPool::UserPool(SqlDB * db):PoolSQL(db,User::table) int UserPool::allocate ( int * oid, int gid, - string username, - string password, + const string& uname, + const string& gname, + const string& password, bool enabled, string& error_str) { @@ -130,12 +136,12 @@ int UserPool::allocate ( ostringstream oss; - if ( username.empty() ) + if ( uname.empty() ) { goto error_name; } - user = get(username,false); + user = get(uname,false); if ( user !=0 ) { @@ -143,7 +149,7 @@ int UserPool::allocate ( } // Build a new User object - user = new User(-1, gid, username, password, enabled); + user = new User(-1, gid, uname, gname, password, enabled); user->add_collection_id(gid); //Adds the primary group to the collection @@ -190,9 +196,12 @@ error_common: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -//bool UserPool::authenticate(const string& session, int& user_id, int& group_id) -bool UserPool::authenticate(const string& session, int& user_id, int& group_id, - set& group_ids) +bool UserPool::authenticate(const string& session, + int& user_id, + int& group_id, + string& uname, + string& gname, + set& group_ids) { map::iterator index; @@ -200,6 +209,9 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, string username; string secret, u_pass; + string tuname; + string tgname; + int uid, gid; int rc; bool result; @@ -209,6 +221,8 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, user_id = -1; group_id = -1; + uname = ""; + gname = ""; result = false; rc = User::split_secret(session,username,secret); @@ -226,6 +240,9 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, uid = user->oid; gid = user->gid; + tuname = user->name; + tgname = user->gname; + group_ids = user->get_groups(); user->unlock(); @@ -245,8 +262,12 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, { if (ar.plain_authenticate()) { - user_id = 0; - group_id = GroupPool::ONEADMIN_ID; + user_id = uid; + group_id = gid; + + uname = tuname; + gname = tgname; + result = true; } } @@ -256,6 +277,10 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, { user_id = uid; group_id = gid; + + uname = tuname; + gname = tgname; + result = true; } } @@ -270,6 +295,10 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, { user_id = uid; group_id = gid; + + uname = tuname; + gname = tgname; + result = true; } else //External user, username & pass in driver message @@ -290,6 +319,7 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, allocate(&user_id, GroupPool::USERS_ID, mad_name, + GroupPool::USERS_NAME, mad_pass, true, error_str); @@ -308,6 +338,10 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id, { group_ids.insert( GroupPool::USERS_ID ); group_id = GroupPool::USERS_ID; + + uname = mad_name; + gname = GroupPool::USERS_NAME; + result = true; } } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index d6a505fc4c..ef8e3ba6b0 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -37,11 +37,13 @@ /* Virtual Machine :: Constructor/Destructor */ /* ************************************************************************** */ -VirtualMachine::VirtualMachine(int id, - int _uid, - int _gid, +VirtualMachine::VirtualMachine(int id, + int _uid, + int _gid, + const string& _uname, + const string& _gname, VirtualMachineTemplate * _vm_template): - PoolObjectSQL(id,"",_uid,_gid,table), + PoolObjectSQL(id,"",_uid,_gid,_uname,_gname,table), last_poll(0), state(INIT), lcm_state(LCM_INIT), diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 9bb3bdd4fb..eae0cb0fde 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -178,6 +178,8 @@ VirtualMachinePool::VirtualMachinePool(SqlDB * db, int VirtualMachinePool::allocate ( int uid, int gid, + const string& uname, + const string& gname, VirtualMachineTemplate * vm_template, int * oid, string& error_str, @@ -188,7 +190,7 @@ int VirtualMachinePool::allocate ( // ------------------------------------------------------------------------ // Build a new Virtual Machine object // ------------------------------------------------------------------------ - vm = new VirtualMachine(-1, uid, gid, vm_template); + vm = new VirtualMachine(-1, uid, gid, uname, gname, vm_template); if (on_hold == true) { diff --git a/src/vm_template/VMTemplate.cc b/src/vm_template/VMTemplate.cc index 2ee020c124..a39f5c5638 100644 --- a/src/vm_template/VMTemplate.cc +++ b/src/vm_template/VMTemplate.cc @@ -26,8 +26,10 @@ VMTemplate::VMTemplate(int id, int _uid, int _gid, + const string& _uname, + const string& _gname, VirtualMachineTemplate * _template_contents): - PoolObjectSQL(id,"",_uid,_gid,table), + PoolObjectSQL(id,"",_uid,_gid,_uname,_gname,table), regtime(time(0)) { if (_template_contents != 0) diff --git a/src/vm_template/VMTemplatePool.cc b/src/vm_template/VMTemplatePool.cc index 24a84a6713..e0d330a4f2 100644 --- a/src/vm_template/VMTemplatePool.cc +++ b/src/vm_template/VMTemplatePool.cc @@ -26,6 +26,8 @@ int VMTemplatePool::allocate ( int uid, int gid, + const string& uname, + const string& gname, VirtualMachineTemplate * template_contents, int * oid, string& error_str) @@ -38,7 +40,7 @@ int VMTemplatePool::allocate ( // ------------------------------------------------------------------------ // Build a new VMTemplate object // ------------------------------------------------------------------------ - vm_template = new VMTemplate(-1, uid, gid, template_contents); + vm_template = new VMTemplate(-1, uid, gid, uname, gname,template_contents); // Check name vm_template->get_template_attribute("NAME", name); diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index c6326d018b..43f10ae834 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -29,10 +29,12 @@ /* Virtual Network :: Constructor/Destructor */ /* ************************************************************************** */ -VirtualNetwork::VirtualNetwork(int _uid, - int _gid, - VirtualNetworkTemplate *_vn_template): - PoolObjectSQL(-1,"",_uid,_gid,table), +VirtualNetwork::VirtualNetwork(int _uid, + int _gid, + const string& _uname, + const string& _gname, + VirtualNetworkTemplate * _vn_template): + PoolObjectSQL(-1,"",_uid,_gid,_uname,_gname,table), bridge(""), type(UNINITIALIZED), leases(0) diff --git a/src/vnm/VirtualNetworkPool.cc b/src/vnm/VirtualNetworkPool.cc index e24464b33c..f292d9397b 100644 --- a/src/vnm/VirtualNetworkPool.cc +++ b/src/vnm/VirtualNetworkPool.cc @@ -72,6 +72,8 @@ VirtualNetworkPool::VirtualNetworkPool(SqlDB * db, int VirtualNetworkPool::allocate ( int uid, int gid, + const string& uname, + const string& gname, VirtualNetworkTemplate * vn_template, int * oid, string& error_str) @@ -80,7 +82,7 @@ int VirtualNetworkPool::allocate ( VirtualNetwork * vn_aux; string name; - vn = new VirtualNetwork(uid, gid, vn_template); + vn = new VirtualNetwork(uid, gid, uname, gname, vn_template); // Check for duplicates vn->get_template_attribute("NAME", name); From 348e0aaebc10b233583b4b125b78f5d2993ef4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 11:41:27 +0200 Subject: [PATCH 24/75] Feature #687: Add mutex to AclManager --- include/AclManager.h | 26 ++++++++++++++++++++++++++ src/acl/AclManager.cc | 27 ++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index 3de8710902..c07886b2aa 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -112,6 +112,10 @@ public: private: + // ---------------------------------------- + // ACL rules management + // ---------------------------------------- + /** * ACL rules. Each rule is indexed by its 'user' long long attibute, * several rules can apply to the same user @@ -146,6 +150,28 @@ private: long long individual_obj_type, long long group_obj_type); + // ---------------------------------------- + // Mutex synchronization + // ---------------------------------------- + + pthread_mutex_t mutex; + + /** + * Function to lock the manager + */ + void lock() + { + pthread_mutex_lock(&mutex); + }; + + /** + * Function to unlock the manager + */ + void unlock() + { + pthread_mutex_unlock(&mutex); + }; + // ---------------------------------------- // DataBase implementation variables // ---------------------------------------- diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index efc5611ed9..d950a6075d 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -51,8 +51,7 @@ AclManager::AclManager(SqlDB * _db) : { ostringstream oss; - // TODO: - // pthread_mutex_init(&mutex, 0); + pthread_mutex_init(&mutex, 0); set_callback(static_cast (&AclManager::init_cb)); @@ -63,7 +62,6 @@ AclManager::AclManager(SqlDB * _db) : unset_callback(); } -; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -80,10 +78,16 @@ AclManager::~AclManager() { multimap::iterator it; + lock(); + for ( it = acl_rules.begin(); it != acl_rules.end(); it++ ) { delete it->second; } + + unlock(); + + pthread_mutex_destroy(&mutex); } /* -------------------------------------------------------------------------- */ @@ -191,6 +195,8 @@ bool AclManager::match_rules( pair::iterator, multimap::iterator> index; + lock(); + index = acl_rules.equal_range( user_req ); for ( it = index.first; it != index.second; it++) @@ -219,10 +225,12 @@ bool AclManager::match_rules( oss.str("Permission granted"); NebulaLog::log("ACL",Log::DEBUG,oss); + unlock(); return true; } } + unlock(); return false; } @@ -232,6 +240,8 @@ bool AclManager::match_rules( int AclManager::add_rule(long long user, long long resource, long long rights, string& error_str) { + lock(); + if (lastOID == INT_MAX) { lastOID = -1; @@ -278,6 +288,8 @@ int AclManager::add_rule(long long user, long long resource, long long rights, update_lastOID(); + unlock(); + return lastOID; @@ -305,6 +317,8 @@ error_common: delete rule; lastOID--; + unlock(); + return rc; } @@ -323,6 +337,8 @@ int AclManager::del_rule(int oid, string& error_str) int rc; bool found = false; + lock(); + // Check the rule exists found = acl_rules_oids.count(oid) > 0; @@ -332,6 +348,7 @@ int AclManager::del_rule(int oid, string& error_str) oss << "Rule " << oid << " does not exist"; error_str = oss.str(); + unlock(); return -1; } @@ -363,6 +380,7 @@ int AclManager::del_rule(int oid, string& error_str) NebulaLog::log("ACL",Log::ERROR,oss); + unlock(); return -1; } @@ -372,6 +390,8 @@ int AclManager::del_rule(int oid, string& error_str) if ( rc != 0 ) { error_str = "SQL DB error"; + + unlock(); return -1; } @@ -380,6 +400,7 @@ int AclManager::del_rule(int oid, string& error_str) acl_rules.erase( it ); acl_rules_oids.erase( oid ); + unlock(); return 0; } From 7520a50dd3cba9f2c18e7d26d4da4d812563e24b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 11:53:18 +0200 Subject: [PATCH 25/75] Feature #687: Add correctness check for ACL rule rights --- src/acl/AclRule.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index 24dd9b7e25..899256b826 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -163,6 +163,30 @@ bool AclRule::malformed(string& error_str) const oss << "wrong [resource] type"; } + // Check rights + + if ( rights == 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "wrong [rights], it cannot be 0"; + } + + if ( rights > 0x1FFLL ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "wrong [rights], it cannot be bigger than 0x1FF"; + } + if ( error ) { error_str = oss.str(); From 255c8ff886f6010a8eb35d09d5b1d8514413ad3b Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 30 Jun 2011 12:09:25 +0200 Subject: [PATCH 26/75] feature #687: user and group name are now stored in XML descriptions --- include/PoolObjectSQL.h | 14 ++++++---- src/image/Image.cc | 10 +++++-- src/rm/RequestManagerChown.cc | 51 ++++++++++++++++++++++++++--------- src/um/User.cc | 14 +++++----- src/vm/VirtualMachine.cc | 42 ++++++++++++++++------------- src/vm_template/VMTemplate.cc | 4 +++ src/vnm/VirtualNetwork.cc | 36 ++++++++++++++----------- 7 files changed, 112 insertions(+), 59 deletions(-) diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index b12b16107b..36df15280e 100644 --- a/include/PoolObjectSQL.h +++ b/include/PoolObjectSQL.h @@ -98,21 +98,25 @@ public: }; /** - * Changes the object's owner id + * Changes the object's owner * @param _uid New User ID + * @param _uname Name of the new user */ - void set_uid(int _uid) + void set_user(int _uid, const string& _uname) { - uid = _uid; + uid = _uid; + uname = _uname; } /** * Changes the object's group id * @param _gid New Group ID + * @param _gname Name of the new group */ - void set_gid(int _gid) + void set_group(int _gid, const string& _gname) { - gid = _gid; + gid = _gid; + gname = _gname; }; /* --------------------------------------------------------------------- */ diff --git a/src/image/Image.cc b/src/image/Image.cc index 1b77775f3f..a752546490 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -326,6 +326,8 @@ string& Image::to_xml(string& xml) const "" << oid << "" << "" << uid << "" << "" << gid << "" << + "" << uname << "" << + "" << gname << "" << "" << name << "" << "" << type << "" << "" << public_obj << "" << @@ -334,7 +336,7 @@ string& Image::to_xml(string& xml) const "" << source << "" << "" << state << "" << "" << running_vms << "" << - obj_template->to_xml(template_xml) << + obj_template->to_xml(template_xml) << ""; xml = oss.str(); @@ -357,9 +359,13 @@ int Image::from_xml(const string& xml) update_from_str(xml); // Get class base attributes - rc += xpath(oid, "/IMAGE/ID", -1); + rc += xpath(oid, "/IMAGE/ID", -1); rc += xpath(uid, "/IMAGE/UID", -1); rc += xpath(gid, "/IMAGE/GID", -1); + + rc += xpath(uname, "/IMAGE/UNAME", "not_found"); + rc += xpath(gname, "/IMAGE/GNAME", "not_found"); + rc += xpath(name, "/IMAGE/NAME", "not_found"); rc += xpath(int_type, "/IMAGE/TYPE", 0); diff --git a/src/rm/RequestManagerChown.cc b/src/rm/RequestManagerChown.cc index f2910aefe0..6e5c37b199 100644 --- a/src/rm/RequestManagerChown.cc +++ b/src/rm/RequestManagerChown.cc @@ -28,6 +28,9 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList) int noid = xmlrpc_c::value_int(paramList.getInt(2)); int ngid = xmlrpc_c::value_int(paramList.getInt(3)); + string nuname; + string ngname; + Nebula& nd = Nebula::instance(); GroupPool * gpool = nd.get_gpool(); UserPool * upool = nd.get_upool(); @@ -41,18 +44,36 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList) // ------------- Check new user and group id's --------------------- - if ( noid > -1 && upool->get(noid,false) == 0 ) + if ( noid > -1 ) { - failure_response(NO_EXISTS, + User * user; + + if ((user = upool->get(noid,true)) == 0) + { + failure_response(NO_EXISTS, get_error(object_name(AuthRequest::USER),noid)); - return; + return; + } + + nuname = user->get_name(); + + user->unlock(); } - if ( ngid > -1 && gpool->get(ngid,false) == 0 ) + if ( ngid > -1 ) { - failure_response(NO_EXISTS, + Group * group; + + if ((group = gpool->get(ngid,true)) == 0) + { + failure_response(NO_EXISTS, get_error(object_name(AuthRequest::GROUP),ngid)); - return; + return; + } + + ngname = group->get_name(); + + group->unlock(); } // ------------- Update the object --------------------- @@ -67,12 +88,12 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList) if ( noid != -1 ) { - object->set_uid(noid); + object->set_user(noid,nuname); } if ( ngid != -1 ) { - object->set_gid(ngid); + object->set_group(ngid,ngname); } pool->update(object); @@ -93,7 +114,7 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList) int ngid = xmlrpc_c::value_int(paramList.getInt(2)); int old_gid; - string str; + string ngname; Nebula& nd = Nebula::instance(); GroupPool * gpool = nd.get_gpool(); @@ -114,13 +135,18 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList) failure_response(XML_RPC_API,request_error("Wrong group ID","")); return; } - else if ( gpool->get(ngid,false) == 0 ) + + if ( (group = gpool->get(ngid,true)) == 0 ) { failure_response(NO_EXISTS, get_error(object_name(AuthRequest::GROUP),ngid)); return; } + ngname = group->get_name(); + + group->unlock(); + // ------------- Change users primary group --------------------- user = upool->get(oid,true); @@ -139,7 +165,7 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList) return; } - user->set_gid(ngid); + user->set_group(ngid,ngname); user->add_group(ngid); user->del_group(old_gid); @@ -154,7 +180,8 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList) if( group == 0 ) { - get_error(object_name(AuthRequest::GROUP),ngid); //TODO Rollback + failure_response(NO_EXISTS, + get_error(object_name(AuthRequest::GROUP),ngid));//TODO Rollback return; } diff --git a/src/um/User.cc b/src/um/User.cc index 3dd668b573..1a1d28aa6c 100644 --- a/src/um/User.cc +++ b/src/um/User.cc @@ -128,12 +128,13 @@ string& User::to_xml(string& xml) const oss << "" - "" << oid <<"" << - "" << gid <<"" << - "" << name <<"" << - "" << password <<"" << - "" << enabled_int <<"" << - collection_xml << + "" << oid <<"" << + "" << gid <<"" << + "" << gname <<"" << + "" << name <<"" << + "" << password <<""<< + "" << enabled_int <<"" << + collection_xml << ""; xml = oss.str(); @@ -155,6 +156,7 @@ int User::from_xml(const string& xml) rc += xpath(oid, "/USER/ID", -1); rc += xpath(gid, "/USER/GID", -1); + rc += xpath(gname, "/USER/GNAME", "not_found"); rc += xpath(name, "/USER/NAME", "not_found"); rc += xpath(password, "/USER/PASSWORD", "not_found"); rc += xpath(int_enabled, "/USER/ENABLED", 0); diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index ef8e3ba6b0..7d12824d81 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1155,6 +1155,8 @@ string& VirtualMachine::to_xml(string& xml) const << "" << oid << "" << "" << uid << "" << "" << gid << "" + << "" << uname << "" + << "" << gname << "" << "" << name << "" << "" << last_poll << "" << "" << state << "" @@ -1187,34 +1189,38 @@ int VirtualMachine::from_xml(const string &xml_str) { vector content; - int int_state; - int int_lcmstate; + int istate; + int ilcmstate; int rc = 0; // Initialize the internal XML object update_from_str(xml_str); // Get class base attributes - rc += xpath(oid, "/VM/ID", -1); - rc += xpath(uid, "/VM/UID", -1); - rc += xpath(gid, "/VM/GID", -1); - rc += xpath(name, "/VM/NAME", "not_found"); + rc += xpath(oid, "/VM/ID", -1); - rc += xpath(last_poll, "/VM/LAST_POLL",0); - rc += xpath(int_state, "/VM/STATE", 0); - rc += xpath(int_lcmstate,"/VM/LCM_STATE", 0); + rc += xpath(uid, "/VM/UID", -1); + rc += xpath(gid, "/VM/GID", -1); - rc += xpath(stime, "/VM/STIME", 0); - rc += xpath(etime, "/VM/ETIME", 0); - rc += xpath(deploy_id, "/VM/DEPLOY_ID",""); + rc += xpath(uname, "/VM/UNAME", "not_found"); + rc += xpath(gname, "/VM/GNAME", "not_found"); + rc += xpath(name, "/VM/NAME", "not_found"); - rc += xpath(memory, "/VM/MEMORY", 0); - rc += xpath(cpu, "/VM/CPU", 0); - rc += xpath(net_tx, "/VM/NET_TX", 0); - rc += xpath(net_rx, "/VM/NET_RX", 0); + rc += xpath(last_poll, "/VM/LAST_POLL", 0); + rc += xpath(istate, "/VM/STATE", 0); + rc += xpath(ilcmstate, "/VM/LCM_STATE", 0); - state = static_cast( int_state ); - lcm_state = static_cast( int_lcmstate ); + rc += xpath(stime, "/VM/STIME", 0); + rc += xpath(etime, "/VM/ETIME", 0); + rc += xpath(deploy_id, "/VM/DEPLOY_ID",""); + + rc += xpath(memory, "/VM/MEMORY", 0); + rc += xpath(cpu, "/VM/CPU", 0); + rc += xpath(net_tx, "/VM/NET_TX", 0); + rc += xpath(net_rx, "/VM/NET_RX", 0); + + state = static_cast(istate); + lcm_state = static_cast(ilcmstate); // Get associated classes ObjectXML::get_nodes("/VM/TEMPLATE", content); diff --git a/src/vm_template/VMTemplate.cc b/src/vm_template/VMTemplate.cc index a39f5c5638..94a7ce7230 100644 --- a/src/vm_template/VMTemplate.cc +++ b/src/vm_template/VMTemplate.cc @@ -192,6 +192,8 @@ string& VMTemplate::to_xml(string& xml) const << "" << oid << "" << "" << uid << "" << "" << gid << "" + << "" << uname << "" + << "" << gname << "" << "" << name << "" << "" << public_obj << "" << "" << regtime << "" @@ -218,6 +220,8 @@ int VMTemplate::from_xml(const string& xml) rc += xpath(oid, "/VMTEMPLATE/ID", -1); rc += xpath(uid, "/VMTEMPLATE/UID", -1); rc += xpath(gid, "/VMTEMPLATE/GID", -1); + rc += xpath(uname, "/VMTEMPLATE/UNAME", "not_found"); + rc += xpath(gname, "/VMTEMPLATE/GNAME", "not_found"); rc += xpath(name, "/VMTEMPLATE/NAME", "not_found"); rc += xpath(public_obj, "/VMTEMPLATE/PUBLIC", 0); rc += xpath(regtime, "/VMTEMPLATE/REGTIME", 0); diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index 43f10ae834..7dab044d06 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -516,12 +516,14 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const os << "" << - "" << oid << "" << - "" << uid << "" << - "" << gid << "" << - "" << name << "" << - "" << type << "" << - "" << bridge << ""; + "" << oid << "" << + "" << uid << "" << + "" << gid << "" << + "" << uname << "" << + "" << gname << "" << + "" << name << "" << + "" << type << "" << + "" << bridge << ""; if (!phydev.empty()) { @@ -533,7 +535,7 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const os << "" << vlan_id << ""; } - os << "" << public_obj << "" << + os << "" << public_obj << "" << ""<< total_leases << ""<< obj_template->to_xml(template_xml); @@ -563,18 +565,20 @@ int VirtualNetwork::from_xml(const string &xml_str) update_from_str(xml_str); // Get class base attributes - rc += xpath(oid, "/VNET/ID", -1); - rc += xpath(uid, "/VNET/UID", -1); - rc += xpath(gid, "/VNET/GID", -1); - rc += xpath(name, "/VNET/NAME", "not_found"); - rc += xpath(int_type, "/VNET/TYPE", -1); - rc += xpath(bridge, "/VNET/BRIDGE", "not_found"); - rc += xpath(public_obj, "/VNET/PUBLIC", 0); + rc += xpath(oid, "/VNET/ID", -1); + rc += xpath(uid, "/VNET/UID", -1); + rc += xpath(gid, "/VNET/GID", -1); + rc += xpath(uname, "/VNET/UNAME", "not_found"); + rc += xpath(gname, "/VNET/GNAME", "not_found"); + rc += xpath(name, "/VNET/NAME", "not_found"); + rc += xpath(int_type, "/VNET/TYPE", -1); + rc += xpath(bridge, "/VNET/BRIDGE", "not_found"); + rc += xpath(public_obj, "/VNET/PUBLIC", 0); xpath(phydev, "/VNET/PHYDEV", ""); - xpath(vlan_id, "/VNET/VLAN_ID", ""); + xpath(vlan_id, "/VNET/VLAN_ID",""); - type = static_cast( int_type ); + type = static_cast(int_type); // Get associated classes ObjectXML::get_nodes("/VNET/TEMPLATE", content); From f2f9c267cbf27df607c7eb9edec8816a90ac81a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 15:17:58 +0200 Subject: [PATCH 27/75] Feature #687: Let users in the oneadmin group manage ACL rules --- include/RequestManagerAcl.h | 13 ++++--------- src/acl/AclManager.cc | 7 +++++++ src/rm/Request.cc | 2 ++ src/rm/RequestManagerAcl.cc | 15 +++------------ 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/include/RequestManagerAcl.h b/include/RequestManagerAcl.h index fce48369a6..364cd9ea08 100644 --- a/include/RequestManagerAcl.h +++ b/include/RequestManagerAcl.h @@ -35,6 +35,7 @@ protected: :Request(method_name,params,help) { auth_object = AuthRequest::ACL; + auth_op = AuthRequest::MANAGE; }; ~RequestManagerAcl(){}; @@ -58,9 +59,7 @@ public: RequestManagerAcl("AclAddRule", "Adds a new ACL rule", "A:ssss") - { - // TODO: auth_op ? - }; + {}; ~AclAddRule(){}; @@ -77,9 +76,7 @@ public: RequestManagerAcl("AclDelRule", "Deletes an existing ACL rule", "A:si") - { - // TODO: auth_op ? - }; + {}; ~AclDelRule(){}; @@ -96,9 +93,7 @@ public: RequestManagerAcl("AclInfo", "Returns the ACL rule set", "A:s") - { - // TODO: auth_op ? - }; + {}; ~AclInfo(){}; diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index d950a6075d..23a847e3c8 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -18,6 +18,7 @@ #include "AclManager.h" #include "NebulaLog.h" +#include "GroupPool.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -105,6 +106,12 @@ const bool AclManager::authorize(int uid, const set &user_groups, bool auth = false; + // Only oneadmin, or someone in the oneadmin group can manage acl rules + if ( obj_type == AuthRequest::ACL ) + { + return ( uid == 0 || user_groups.count( GroupPool::ONEADMIN_ID ) == 1 ); + } + // Build masks for request long long user_req; long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; diff --git a/src/rm/Request.cc b/src/rm/Request.cc index 19f3584012..2a32ee6a64 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -171,6 +171,8 @@ string Request::object_name(AuthRequest::Object ob) return "virtual machine template"; case AuthRequest::GROUP: return "group"; + case AuthRequest::ACL: + return "ACL"; default: return "-"; } diff --git a/src/rm/RequestManagerAcl.cc b/src/rm/RequestManagerAcl.cc index aa30f041e1..676d54ce89 100644 --- a/src/rm/RequestManagerAcl.cc +++ b/src/rm/RequestManagerAcl.cc @@ -55,11 +55,8 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList) string error_msg; - // TODO: Only oneadmin can manage ACL - if ( uid != 0 ) + if ( basic_authorization(-1) == false ) { - failure_response(AUTHORIZATION, - authorization_error("Only oneadmin can manage ACL rules")); return; } @@ -89,11 +86,8 @@ void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList) string error_msg; - // TODO: Only oneadmin can manage ACL - if ( uid != 0 ) + if ( basic_authorization(-1) == false ) { - failure_response(AUTHORIZATION, - authorization_error("Only oneadmin can manage ACL rules")); return; } @@ -121,11 +115,8 @@ void AclInfo::request_execute(xmlrpc_c::paramList const& paramList) ostringstream oss; int rc; - // TODO: Only oneadmin can manage ACL - if ( uid != 0 ) + if ( basic_authorization(-1) == false ) { - failure_response(AUTHORIZATION, - authorization_error("Only oneadmin can manage ACL rules")); return; } From 19d3db124ea92455efbc60ae43cdbb01914bc68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tino=20V=C3=A1zquez?= Date: Thu, 30 Jun 2011 15:48:08 +0200 Subject: [PATCH 28/75] Feature #687: ACL string syntax for oneacl --- src/cli/etc/oneacl.yaml | 22 +++++++----- src/cli/one_helper/oneacl_helper.rb | 53 ++++++++++++++++++++++++--- src/cli/oneacl | 27 +++----------- src/oca/ruby/OpenNebula/Acl.rb | 55 ++++++++++++----------------- src/oca/ruby/OpenNebula/AclPool.rb | 12 +++---- 5 files changed, 93 insertions(+), 76 deletions(-) diff --git a/src/cli/etc/oneacl.yaml b/src/cli/etc/oneacl.yaml index e53a1bad8e..19402950a1 100644 --- a/src/cli/etc/oneacl.yaml +++ b/src/cli/etc/oneacl.yaml @@ -1,25 +1,31 @@ --- +:ID: + :desc: To which resource owner the rule applies to + :size: 5 + :right: true + :USER: :desc: To which resource owner the rule applies to - :size: 4 + :size: 8 :right: true -:RESOURCE_VHNIUTG: +:RES_VHNIUTG: :desc: Which resource the rule applies to - :size: 16 + :size: 11 :RID: :desc: Resource ID - :size: 4 + :size: 5 :right: true -:OPERATION_CDUMIPpTW: +:OPE_CDUMIPpTW: :desc: Operation to which the rule applies - :size: 19 + :size: 13 :right: true :default: +- :ID - :USER -- :RESOURCE_VHNIUTG +- :RES_VHNIUTG - :RID -- :OPERATION_CDUMIPpTW +- :OPE_CDUMIPpTW diff --git a/src/cli/one_helper/oneacl_helper.rb b/src/cli/one_helper/oneacl_helper.rb index 916d4be256..da721f8d2d 100644 --- a/src/cli/one_helper/oneacl_helper.rb +++ b/src/cli/one_helper/oneacl_helper.rb @@ -24,6 +24,43 @@ class OneAclHelper < OpenNebulaHelper::OneHelper def self.conf_file "oneacl.yaml" end + + def add_rule(options, arg0, arg1=nil, arg2=nil) + aclp = OpenNebula::AclPool.new( OpenNebula::Client.new() ) + + if arg2 + rc = aclp.addrule( arg0, arg1, arg2 ) + else + rc = aclp.addrule_with_str( arg0 ) + end + + if OpenNebula.is_error?(rc) + [-1, rc.message] + else + if !rc + puts "Rule added" if options[:verbose] + return 0 + end + return [-1, rc[:users].message] if OpenNebula.is_error?(rc[:users]) + return [-1, rc[:resources].message] if OpenNebula.is_error?( + rc[:resources]) + return [-1, rc[:rights].message] if OpenNebula.is_error?( + rc[:rights]) + end + end + + def delete_rule(id) + acl = OpenNebula::AclPool.new( OpenNebula::Client.new() ) + + rc = acl.delrule( id ) + + if OpenNebula.is_error?(rc) + [-1, rc.message] + else + puts "Rule deleted" if options[:verbose] + 0 + end + end private @@ -92,27 +129,33 @@ class OneAclHelper < OpenNebulaHelper::OneHelper config_file=self.class.table_conf table=CLIHelper::ShowTable.new(config_file, self) do + column :ID, "Rule Identifier", + :size=>5 do |d| + d['ID'] + end + column :USER, "To which resource owner the rule applies to", - :size=>4 do |d| + :size=>8 do |d| d['STRING'].split(" ")[0] end - column :RESOURCE_VHNIUTG, "Resource to which the rule applies" do |d| + column :RES_VHNIUTG, "Resource to which the rule applies" do |d| OneAclHelper::resource_mask d['STRING'].split(" ")[1] end - column :RID, "Resource ID", :right, :size=>4 do |d| + column :RID, "Resource ID", :right, :size=>8 do |d| d['STRING'].split(" ")[1].split("/")[1] end - column :OPERATION_CDUMIPpTW, "Operation to which the rule applies" do |d| + column :OPE_CDUMIPpTW, "Operation to which the rule applies" do |d| OneAclHelper::right_mask d['STRING'].split(" ")[2] end - default :USER, :RESOURCE_VHNIUTG, :RID, :OPERATION_CDUMIPpTW + default :ID, :USER, :RESOURCE_VHNIUTG, :RID, :OPERATION_CDUMIPpTW end table.show(pool, options) end + end \ No newline at end of file diff --git a/src/cli/oneacl b/src/cli/oneacl index d4001ffac1..d291668361 100755 --- a/src/cli/oneacl +++ b/src/cli/oneacl @@ -54,17 +54,8 @@ cmd = CommandParser::CmdParser.new(ARGV) do Adds a new ACL rule EOT - command :addrule, addrule_desc, :user, :resource, :rights do - acl = OpenNebula::AclPool.new( OpenNebula::Client.new() ) - - rc = acl.addrule( args[0], args[1], args[2] ) - - if OpenNebula.is_error?(rc) - [-1, rc.message] - else - puts "Rule added" if options[:verbose] - 0 - end + command :addrule, addrule_desc, [:user,:rulestr], [:resource, nil], [:rights, nil] do + helper.add_rule(options, args[0], args[1], args[2] ) end delrule_desc = <<-EOT.unindent @@ -72,17 +63,7 @@ cmd = CommandParser::CmdParser.new(ARGV) do EOT command :delrule, delrule_desc, :id do - acl = OpenNebula::Acl.new( OpenNebula::Client.new() ) - - rc = acl.delrule( args[0] ) - - if OpenNebula.is_error?(rc) - [-1, rc.message] - else - puts "Rule deleted" if options[:verbose] - 0 - end - + helper.delete_rule( args[0] ) end list_desc = <<-EOT.unindent @@ -90,6 +71,6 @@ cmd = CommandParser::CmdParser.new(ARGV) do EOT command :list, list_desc,:options=>OpenNebulaHelper::XML do - helper.list_pool(options) + helper.list_pool( options ) end end diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index 52698f1d9a..7347ca72fc 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -72,28 +72,16 @@ module OpenNebula } - def initialize(rule_xml=nil) + def initialize(rule_str=nil) @content = { - :users => 0, - :resources => 0, - :rights => 0 + :users => 0, + :resources => 0, + :rights => 0 } - parse_rule(rule_xml) + parse_rule(rule_str) if rule_str end - def initialize(users,resources,rights, str) - str=str.split(" ") - - @content = { - :users => users, - :resources => resources, - :rights => rights, - :users_str => str.size==3?str[0]:0, - :resources_str => str.size==3?str[1]:0, - :rights_str => str.size==3?str[2]:0 - } - end def set_hex_rule(users,resources,rights) set_hex_users users @@ -114,21 +102,22 @@ module OpenNebula end def set_users(users) - @content[:users] = users.to_s(10) + @content[:users] = users.to_i.to_s(10) end def set_resources(resources) - @content[:resources] = resources.to_s(10) + @content[:resources] = resources.to_i.to_s(10) end def set_rights(rights) - @content[:rights] = rights.to_s(10) - end + @content[:rights] = rights.to_i.to_s(10) + end + def parse_rule(rule_str) begin rule_str = rule_str.split(" ") parse_users(rule_str[0]) - parse_resource(rule_str[1]) + parse_resources(rule_str[1]) parse_rights(rule_str[2]) rescue Exception => e @content[:users] = OpenNebula::Error.new(e.message) @@ -153,15 +142,13 @@ module OpenNebula return end - resources[0].each{ |resource| + resources[0].split("+").each{ |resource| next if !RESOURCES[resource.upcase] - - @content[:resources] = @content[:resources] - + RESOURCES[resource.upcase] + @content[:resources] = @content[:resources] + RESOURCES[resource.upcase].to_i } - + @content[:resources] = @content[:resources] + - calculate_user(resources[1]) + calculate_users(resources[1]).to_i @content[:resources] = @content[:resources].to_s(16) rescue Exception => e @@ -179,7 +166,7 @@ module OpenNebula @content[:rights] = @content[:rights] + RIGHTS[right.upcase] } - @content[:rights] = @content[:rights].to_s(16) + @content[:rights] = @content[:rights].to_i.to_s(16) rescue Exception => e @content[:rights] = OpenNebula::Error.new(e.message) end @@ -187,20 +174,22 @@ module OpenNebula def calculate_users(users_str) - if users == "*" + if users_str == "*" return USERS["ALL"] end - value = 0 + value = 0 - case users[0..0] + case users_str[0..0] when "#" value = USERS["UID"] when "@" value = USERS["GID"] end + + users_value = users_str[1..-1].to_i + value - return value + users[1..-1].to_i + return users_value.to_i.to_s(16) end def users diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/OpenNebula/AclPool.rb index 8b49b898c5..3f77fa7764 100644 --- a/src/oca/ruby/OpenNebula/AclPool.rb +++ b/src/oca/ruby/OpenNebula/AclPool.rb @@ -68,12 +68,14 @@ module OpenNebula # Adds a new ACL rule. # - # +rule+ Rule class - def addrule_with_class(rule) + # +rule+ Rule tring + def addrule_with_str(rule_str) + rule = Acl.new rule_str + return rule.error if rule.is_error? rc = @client.call( ACL_POOL_METHODS[:addrule], - rule.user, + rule.users, rule.resources, rule.rights ) @@ -98,10 +100,6 @@ module OpenNebula return rc end - ####################################################################### - # Helpers - ####################################################################### - private end From d813946556ca15fdff056db8bfa36d3a2f2792ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 16:04:56 +0200 Subject: [PATCH 29/75] Feature #687: Add method AclRule::from_xml --- include/AclRule.h | 9 +++++++++ include/ObjectXML.h | 14 ++++++++++++++ src/acl/AclRule.cc | 26 ++++++++++++++++++++++++++ src/xml/ObjectXML.cc | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) diff --git a/include/AclRule.h b/include/AclRule.h index ebcc11b317..c8ea53bd9a 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -74,6 +74,15 @@ public: */ string& to_xml(string& xml) const; + /** + * Rebuilds the rule from an xml formatted string + * + * @param xml_str The xml-formatted string + * + * @return 0 on success, -1 otherwise + */ + int from_xml(const string &xml_str); + /** * Returns the 32 less significant bits of the user long long attribute * diff --git a/include/ObjectXML.h b/include/ObjectXML.h index 72fa91d878..53919577fc 100644 --- a/include/ObjectXML.h +++ b/include/ObjectXML.h @@ -94,6 +94,20 @@ public: int xpath(unsigned int& value, const char * xpath_expr, const unsigned int& def); + /** + * Gets and sets a xpath attribute, if the attribute is not found a default + * is used + * @param value to set + * @param xpath_expr of the xml element + * @param def default value if the element is not found + * @param hex if true, the contents of the element are expected to be in + * hexadecimal instead of decimal + * + * @return -1 if default was set + */ + long long xpath(long long& value, const char * xpath_expr, + const long long& def, bool hex=true); + /** * Gets and sets a xpath attribute, if the attribute is not found a default * is used diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index 899256b826..f94f4013e3 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -16,6 +16,7 @@ #include "AclRule.h" #include "AuthManager.h" +#include "ObjectXML.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -315,3 +316,28 @@ string& AclRule::to_xml(string& xml) const /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +int AclRule::from_xml(const string &xml_str) +{ + int rc = 0; + + string tmp_error; + + ObjectXML xml_obj(xml_str); + + rc += xml_obj.xpath(oid , "/ACL/ID" , 0); + rc += xml_obj.xpath(user , "/ACL/USER" , 0); + rc += xml_obj.xpath(resource, "/ACL/RESOURCE", 0); + rc += xml_obj.xpath(rights , "/ACL/RIGHTS" , 0); + rc += xml_obj.xpath(str , "/ACL/STRING" , ""); + + if ( (rc != 0) || malformed(tmp_error) ) + { + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/xml/ObjectXML.cc b/src/xml/ObjectXML.cc index 657e889398..3f61ab7358 100644 --- a/src/xml/ObjectXML.cc +++ b/src/xml/ObjectXML.cc @@ -222,6 +222,47 @@ int ObjectXML::xpath(unsigned int& value, const char * xpath_expr, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +long long ObjectXML::xpath(long long& value, const char * xpath_expr, + const long long& def, bool hex) +{ + vector values; + int rc = 0; + + values = (*this)[xpath_expr]; + + if (values.empty() == true) + { + value = def; + rc = -1; + } + else + { + istringstream iss; + + iss.str(values[0]); + + if ( hex ) + { + iss >> hex >> value; + } + else + { + iss >> dec >> value; + } + + if (iss.fail() == true) + { + value = def; + rc = -1; + } + } + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int ObjectXML::xpath(time_t& value, const char * xpath_expr, const time_t& def) { int int_val; From bc29eaca98b8c0dec54da69bb2122f466488a4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 17:43:06 +0200 Subject: [PATCH 30/75] Feature #687: Let users use and see public objects in their group --- src/authm/AuthManager.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index be132d650f..f4d68b789d 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -78,6 +78,15 @@ void AuthRequest::add_auth(Object ob, { auth = true; } + else if ( pub && ( gids.count( ob_gid ) == 1 ) && + (op == USE || op == INSTANTIATE || op == INFO ) && + (ob == NET || ob == IMAGE || ob == TEMPLATE) + ) + { + // Users are authorized to use or see information of NET, IMAGE, and + // TEMPLATE objects in their group + auth = true; + } else { Nebula& nd = Nebula::instance(); From 5ae5d8530111817f19824e4d8d9201729236a32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 18:03:06 +0200 Subject: [PATCH 31/75] Feature #687: Let users in the oneadmin group perform any operation, instead of only manage ACL rules --- src/acl/AclManager.cc | 6 ------ src/authm/AuthManager.cc | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index 23a847e3c8..a10c71661a 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -106,12 +106,6 @@ const bool AclManager::authorize(int uid, const set &user_groups, bool auth = false; - // Only oneadmin, or someone in the oneadmin group can manage acl rules - if ( obj_type == AuthRequest::ACL ) - { - return ( uid == 0 || user_groups.count( GroupPool::ONEADMIN_ID ) == 1 ); - } - // Build masks for request long long user_req; long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index f4d68b789d..680c7ca954 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -74,7 +74,7 @@ void AuthRequest::add_auth(Object ob, // Authorize the request for self authorization // ------------------------------------------------------------------------- - if ( uid == 0 ) + if ( uid == 0 || gids.count( GroupPool::ONEADMIN_ID ) == 1 ) { auth = true; } From dc0a1edff5f7af48379be3da92290b2728e5c342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 30 Jun 2011 19:43:36 +0200 Subject: [PATCH 32/75] Feature #687: Better handling of requests that don't have oid or gid --- include/AclRule.h | 4 ++++ src/acl/AclManager.cc | 44 +++++++++++++++++++++++++++++++++++++++---- src/acl/AclRule.cc | 15 +++++++++++++-- src/rm/Request.cc | 13 ++++--------- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/include/AclRule.h b/include/AclRule.h index c8ea53bd9a..a3d3c98a41 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -35,6 +35,10 @@ public: static const long long GROUP_ID; static const long long ALL_ID; + // NONE_ID can never be used in a rule. It is useful to create masks that + // will never match any existing rule + static const long long NONE_ID; + AclRule(int _oid, long long _user, long long _resource, long long _rights): oid(_oid), user(_user), resource(_resource), rights(_rights) { diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index a10c71661a..ef5649f8e0 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -108,8 +108,28 @@ const bool AclManager::authorize(int uid, const set &user_groups, // Build masks for request long long user_req; - long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; - long long resource_gid_req = obj_type + AclRule::GROUP_ID + obj_gid; + long long resource_oid_req; + + if ( obj_id >= 0 ) + { + resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; + } + else + { + resource_oid_req = AclRule::NONE_ID; + } + + long long resource_gid_req; + + if ( obj_gid >= 0 ) + { + resource_gid_req = obj_type + AclRule::GROUP_ID + obj_gid; + } + else + { + resource_gid_req = AclRule::NONE_ID; + } + long long resource_all_req = obj_type + AclRule::ALL_ID; long long rights_req = op; @@ -120,10 +140,26 @@ const bool AclManager::authorize(int uid, const set &user_groups, ( obj_type | AclRule::GROUP_ID | 0xFFFFFFFF ); + // Create a temporal rule, to log the request - AclRule request_rule(-1, AclRule::INDIVIDUAL_ID + uid, resource_oid_req, + long long log_resource; + + if ( obj_id >= 0 ) + { + log_resource = resource_oid_req; + } + else if ( obj_gid >= 0 ) + { + log_resource = resource_gid_req; + } + else + { + log_resource = resource_all_req; + } + + AclRule log_rule(-1, AclRule::INDIVIDUAL_ID + uid, log_resource, rights_req); - oss << "Request " << request_rule.to_str(); + oss << "Request " << log_rule.to_str(); NebulaLog::log("ACL",Log::DEBUG,oss); diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index f94f4013e3..57c1b38d32 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -25,6 +25,8 @@ const long long AclRule::INDIVIDUAL_ID = 0x100000000LL; const long long AclRule::GROUP_ID = 0x200000000LL; const long long AclRule::ALL_ID = 0x400000000LL; +const long long AclRule::NONE_ID = 0x1000000000000000LL; + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -211,10 +213,14 @@ void AclRule::build_str() { oss << "#" << user_id(); } - else + else if ( (user & ALL_ID) != 0 ) { oss << "*"; } + else + { + oss << "??"; + } oss << " "; @@ -254,10 +260,15 @@ void AclRule::build_str() { oss << "#" << resource_id(); } - else + else if ( (resource & ALL_ID) != 0 ) { oss << "*"; } + else + { + oss << "??"; + } + oss << " "; diff --git a/src/rm/Request.cc b/src/rm/Request.cc index 2a32ee6a64..55d94d0f18 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -55,21 +55,16 @@ bool Request::basic_authorization(int oid) { PoolObjectSQL * object; - bool pub; - int ouid; - int ogid; + bool pub = false; + int ouid = 0; + int ogid = -1; if ( uid == 0 ) { return true; } - if ( oid == -1 ) - { - ouid = 0; - pub = false; - } - else + if ( oid >= 0 ) { object = pool->get(oid,true); From 1b656b3b29e5d8c173eeabe6153e42581a8232ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 1 Jul 2011 12:54:31 +0200 Subject: [PATCH 33/75] Feature #687: Additional check for new ACL rules --- include/RequestManagerPoolInfoFilter.h | 6 +++--- src/acl/AclRule.cc | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h index 102d24845d..17ef3b89ef 100644 --- a/include/RequestManagerPoolInfoFilter.h +++ b/include/RequestManagerPoolInfoFilter.h @@ -41,9 +41,9 @@ protected: /* -------------------------------------------------------------------- */ - static const int ALL; /**< Secify all objects in the pool (-2) */ - static const int MINE; /**< Secify user's objects in the pool (-3)*/ - static const int MINE_GROUP; /**< Secify users + group objects (-1) */ + static const int ALL; /**< Specify all objects in the pool (-2) */ + static const int MINE; /**< Specify user's objects in the pool (-3)*/ + static const int MINE_GROUP; /**< Specify users + group objects (-1) */ /* -------------------------------------------------------------------- */ diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index 57c1b38d32..b09479814f 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -65,6 +65,17 @@ bool AclRule::malformed(string& error_str) const oss << "[user] GROUP (@) and ALL (*) bits are exclusive"; } + if ( (user & 0x700000000LL) == 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[user] is missing one of the INDIVIDUAL, GROUP or ALL bits"; + } + if ( user_id() < 0 ) { if ( error ) @@ -122,6 +133,17 @@ bool AclRule::malformed(string& error_str) const oss << "[resource] GROUP (@) and ALL (*) bits are exclusive"; } + if ( (resource & 0x700000000LL) == 0 ) + { + if ( error ) + { + oss << "; "; + } + + error = true; + oss << "[resource] is missing one of the INDIVIDUAL, GROUP or ALL bits"; + } + if ( resource_id() < 0 ) { if ( error ) From 32a7699c5a6d86b984ab7191ad4880397710ffd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 1 Jul 2011 14:30:48 +0200 Subject: [PATCH 34/75] Feature #687: Fix oneacl delete --- src/cli/one_helper/oneacl_helper.rb | 4 ++-- src/cli/oneacl | 2 +- src/oca/ruby/OpenNebula/AclPool.rb | 11 +++-------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/cli/one_helper/oneacl_helper.rb b/src/cli/one_helper/oneacl_helper.rb index da721f8d2d..6d920ab909 100644 --- a/src/cli/one_helper/oneacl_helper.rb +++ b/src/cli/one_helper/oneacl_helper.rb @@ -49,7 +49,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper end end - def delete_rule(id) + def delete_rule(options, id) acl = OpenNebula::AclPool.new( OpenNebula::Client.new() ) rc = acl.delrule( id ) @@ -151,7 +151,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper OneAclHelper::right_mask d['STRING'].split(" ")[2] end - default :ID, :USER, :RESOURCE_VHNIUTG, :RID, :OPERATION_CDUMIPpTW + default :ID, :USER, :RES_VHNIUTG, :RID, :OPE_CDUMIPpTW end table.show(pool, options) diff --git a/src/cli/oneacl b/src/cli/oneacl index d291668361..30bcd8819c 100755 --- a/src/cli/oneacl +++ b/src/cli/oneacl @@ -63,7 +63,7 @@ cmd = CommandParser::CmdParser.new(ARGV) do EOT command :delrule, delrule_desc, :id do - helper.delete_rule( args[0] ) + helper.delete_rule( options, args[0] ) end list_desc = <<-EOT.unindent diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/OpenNebula/AclPool.rb index 3f77fa7764..e42b68759d 100644 --- a/src/oca/ruby/OpenNebula/AclPool.rb +++ b/src/oca/ruby/OpenNebula/AclPool.rb @@ -86,14 +86,9 @@ module OpenNebula # Deletes an existing ACL rule. # - # +user+ A hex number, e.g. 0x100000001 - # +resource+ A hex number, e.g. 0x2100000001 - # +rights+ A hex number, e.g. 0x10 - def delrule(user, resource, rights) - rc = @client.call( ACL_POOL_METHODS[:delrule], - user, - resource, - rights ) + # +id+ An existing ACL rule ID + def delrule(id) + rc = @client.call( ACL_POOL_METHODS[:delrule], id.to_i ) rc = nil if !OpenNebula.is_error?(rc) From 27288cfc0ea96b2f1ae25b03a1363b91ca7bddfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 1 Jul 2011 16:10:00 +0200 Subject: [PATCH 35/75] Feature #687: Better default rules in AuthManager, takes into account the object's owner --- src/authm/AuthManager.cc | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index 680c7ca954..cc751b295a 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -74,19 +74,28 @@ void AuthRequest::add_auth(Object ob, // Authorize the request for self authorization // ------------------------------------------------------------------------- - if ( uid == 0 || gids.count( GroupPool::ONEADMIN_ID ) == 1 ) + // There are some default conditions that grant permission without + // consulting the ACL manager + if ( + // User is oneadmin, or is in the oneadmin group + uid == 0 || + gids.count( GroupPool::ONEADMIN_ID ) == 1 || + + // User is the owner of the object, for certain operations + ( owner == uid && + ( op == DELETE || op == USE || op == MANAGE || + op == INFO || op == INSTANTIATE ) + ) || + + // Object is public and user is in its group, for certain operations + ( pub && ( gids.count( ob_gid ) == 1 ) && + (op == USE || op == INSTANTIATE || op == INFO ) && + (ob == NET || ob == IMAGE || ob == TEMPLATE) + ) + ) { auth = true; } - else if ( pub && ( gids.count( ob_gid ) == 1 ) && - (op == USE || op == INSTANTIATE || op == INFO ) && - (ob == NET || ob == IMAGE || ob == TEMPLATE) - ) - { - // Users are authorized to use or see information of NET, IMAGE, and - // TEMPLATE objects in their group - auth = true; - } else { Nebula& nd = Nebula::instance(); From 2b90f0237700bb5da0ef6603d66dc832cd6abd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 1 Jul 2011 17:33:37 +0200 Subject: [PATCH 36/75] Feature #687: Bug in RequestManagerPoolInfoFilter: each request has a different operation, they can't share the common auth_op attribute --- include/Request.h | 21 +++++++++++++++++++-- include/RequestManagerPoolInfoFilter.h | 4 +--- src/rm/Request.cc | 4 ++-- src/rm/RequestManagerPoolInfoFilter.cc | 8 +++++--- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/Request.h b/include/Request.h index 4a7d7121df..c4cb137a02 100644 --- a/include/Request.h +++ b/include/Request.h @@ -95,11 +95,28 @@ protected: * from the request. The function gets the object from the pool to get * the public attribute and its owner. The authorization is based on * object and type of operation for the request. - * @param oid of the object. + * @param oid of the object, can be -1 for objects to be created, or + * pools. * * @return true if the user is authorized. */ - bool basic_authorization(int oid); + bool basic_authorization(int oid) + { + return basic_authorization(oid, auth_op); + }; + + /** + * Performs a basic authorization for this request using the uid/gid + * from the request. The function gets the object from the pool to get + * the public attribute and its owner. The authorization is based on + * object and type of operation for the request. + * @param oid of the object, can be -1 for objects to be created, or + * pools. + * @param op operation of the request. + * + * @return true if the user is authorized. + */ + bool basic_authorization(int oid, AuthRequest::Operation op); /** * Actual Execution method for the request. Must be implemented by the diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h index 17ef3b89ef..fd7147d1fe 100644 --- a/include/RequestManagerPoolInfoFilter.h +++ b/include/RequestManagerPoolInfoFilter.h @@ -33,9 +33,7 @@ protected: RequestManagerPoolInfoFilter(const string& method_name, const string& help) :Request(method_name,"A:si",help) - { - auth_op = AuthRequest::INFO_POOL; - }; + {}; ~RequestManagerPoolInfoFilter(){}; diff --git a/src/rm/Request.cc b/src/rm/Request.cc index 55d94d0f18..f9079206ce 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -51,7 +51,7 @@ void Request::execute( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -bool Request::basic_authorization(int oid) +bool Request::basic_authorization(int oid, AuthRequest::Operation op) { PoolObjectSQL * object; @@ -83,7 +83,7 @@ bool Request::basic_authorization(int oid) AuthRequest ar(uid, group_ids); - ar.add_auth(auth_object, oid, ogid, auth_op, ouid, pub); + ar.add_auth(auth_object, oid, ogid, op, ouid, pub); if (UserPool::authorize(ar) == -1) { diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc index 88a4fe2647..a2dfd0ed4b 100644 --- a/src/rm/RequestManagerPoolInfoFilter.cc +++ b/src/rm/RequestManagerPoolInfoFilter.cc @@ -38,6 +38,8 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa int rc; + AuthRequest::Operation request_op = AuthRequest::INFO_POOL; + if ( filter_flag < MINE ) { failure_response(XML_RPC_API, request_error("Incorrect filter_flag","")); @@ -48,7 +50,7 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa { case MINE: where_string << "UID=" << uid; - auth_op = AuthRequest::INFO_POOL_MINE; + request_op = AuthRequest::INFO_POOL_MINE; break; case ALL: @@ -56,7 +58,7 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa case MINE_GROUP: where_string << "UID=" << uid << " OR GID=" << gid; - auth_op = AuthRequest::INFO_POOL_MINE; + request_op = AuthRequest::INFO_POOL_MINE; break; default: @@ -64,7 +66,7 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa break; } - if ( basic_authorization(-1) == false ) + if ( basic_authorization(-1, request_op) == false ) { return; } From c1ff6fe3aecb6e0bd7e6faed70197a0abf05de48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 1 Jul 2011 18:09:14 +0200 Subject: [PATCH 37/75] Feature #687: Remove trailing spaces --- src/oca/ruby/OpenNebula/Acl.rb | 122 ++++++++++++++--------------- src/oca/ruby/OpenNebula/AclPool.rb | 20 ++--- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index 7347ca72fc..ae481b1e50 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -39,15 +39,15 @@ module OpenNebula # INFO_POOL_MINE # INSTANTIATE # CHOWN - class Acl - + class Acl + USERS = { "UID" => 4294967296, "GID" => 8589934592, "ALL" => 17179869184 - } - - + } + + RESOURCES = { "VM" => 68719476736, "HOST" => 137438953472, @@ -58,61 +58,61 @@ module OpenNebula "GROUP" => 4398046511104, "ACL" => 8796093022208 } - - RIGHTS = { - "CREATE" => 1, # Auth. to create an object - "DELETE" => 2, # Auth. to delete an object - "USE" => 4, # Auth. to use an object - "MANAGE" => 8, # Auth. to manage an object - "INFO" => 16, # Auth. to view an object - "INFO_POOL" => 32, # Auth. to view any object in the pool - "INFO_POOL_MINE"=> 64, # Auth. to view user and/or group objects + + RIGHTS = { + "CREATE" => 1, # Auth. to create an object + "DELETE" => 2, # Auth. to delete an object + "USE" => 4, # Auth. to use an object + "MANAGE" => 8, # Auth. to manage an object + "INFO" => 16, # Auth. to view an object + "INFO_POOL" => 32, # Auth. to view any object in the pool + "INFO_POOL_MINE"=> 64, # Auth. to view user and/or group objects "INSTANTIATE" => 128,# Auth. to instantiate a VM from a TEMPLATE - "CHOWN" => 256 # Auth. to change ownership of an object + "CHOWN" => 256 # Auth. to change ownership of an object } - - + + def initialize(rule_str=nil) @content = { :users => 0, :resources => 0, :rights => 0 } - + parse_rule(rule_str) if rule_str end - - + + def set_hex_rule(users,resources,rights) set_hex_users users set_hex_resources resources set_hex_rights rights end - + def set_hex_users(users) @content[:users] = users end - + def set_hex_resources(resources) @content[:resources] = resources end - + def set_hex_rights(rights) @content[:rights] = rights - end - + end + def set_users(users) @content[:users] = users.to_i.to_s(10) end - + def set_resources(resources) @content[:resources] = resources.to_i.to_s(10) end - + def set_rights(rights) @content[:rights] = rights.to_i.to_s(10) - end - + end + def parse_rule(rule_str) begin rule_str = rule_str.split(" ") @@ -123,19 +123,19 @@ module OpenNebula @content[:users] = OpenNebula::Error.new(e.message) end end - + def parse_users(users) begin - @content[:users] = calculate_users(users) + @content[:users] = calculate_users(users) rescue Exception => e @content[:resources] = OpenNebula::Error.new(e.message) end end - + def parse_resources(resources) begin resources = resources.split("/") - + if resources.size != 2 @content[:resources] = OpenNebula::Error.new( "Resource #{resources} not well formed") @@ -145,75 +145,75 @@ module OpenNebula resources[0].split("+").each{ |resource| next if !RESOURCES[resource.upcase] @content[:resources] = @content[:resources] + RESOURCES[resource.upcase].to_i - } + } - @content[:resources] = @content[:resources] + + @content[:resources] = @content[:resources] + calculate_users(resources[1]).to_i - - @content[:resources] = @content[:resources].to_s(16) + + @content[:resources] = @content[:resources].to_s(16) rescue Exception => e @content[:resources] = OpenNebula::Error.new(e.message) - end + end end - + def parse_rights(rights) begin rights = rights.split("+") - + rights.each{ |right| next if !RIGHTS[right.upcase] - + @content[:rights] = @content[:rights] + RIGHTS[right.upcase] } - - @content[:rights] = @content[:rights].to_i.to_s(16) + + @content[:rights] = @content[:rights].to_i.to_s(16) rescue Exception => e @content[:rights] = OpenNebula::Error.new(e.message) - end + end end - - + + def calculate_users(users_str) if users_str == "*" return USERS["ALL"] - end - - value = 0 - + end + + value = 0 + case users_str[0..0] when "#" value = USERS["UID"] when "@" value = USERS["GID"] end - + users_value = users_str[1..-1].to_i + value - + return users_value.to_i.to_s(16) end - + def users @content[:users] end - + def resources @content[:resources] end - + def rights @content[:rights] end - + def is_error? - OpenNebula.is_error?(@content[:users]) || - OpenNebula.is_error?(@content[:resources]) || + OpenNebula.is_error?(@content[:users]) || + OpenNebula.is_error?(@content[:resources]) || OpenNebula.is_error?(@content[:rights]) || @content[:users] == 0 || @content[:resources] == 0 || - @content[:rights] == 0 + @content[:rights] == 0 end - - def error + + def error @content.each{ |part| return part if OpenNebula.is_error?(part) } diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/OpenNebula/AclPool.rb index e42b68759d..e7c773a8a3 100644 --- a/src/oca/ruby/OpenNebula/AclPool.rb +++ b/src/oca/ruby/OpenNebula/AclPool.rb @@ -34,7 +34,7 @@ module OpenNebula def initialize(client) super('ACL_POOL','ACL',client) end - + def factory(element_xml) acl=REXML::Document.new(element_xml).root OpenNebula::Acl.new(acl['USER'], acl['RESOURCE'], acl['RIGHTS']) @@ -56,27 +56,27 @@ module OpenNebula # +resource+ A hex number, e.g. 0x2100000001 # +rights+ A hex number, e.g. 0x10 def addrule(user, resource, rights) - rc = @client.call( ACL_POOL_METHODS[:addrule], - user, - resource, + rc = @client.call( ACL_POOL_METHODS[:addrule], + user, + resource, rights ) rc = nil if !OpenNebula.is_error?(rc) return rc end - + # Adds a new ACL rule. # # +rule+ Rule tring def addrule_with_str(rule_str) rule = Acl.new rule_str - + return rule.error if rule.is_error? - - rc = @client.call( ACL_POOL_METHODS[:addrule], - rule.users, - rule.resources, + + rc = @client.call( ACL_POOL_METHODS[:addrule], + rule.users, + rule.resources, rule.rights ) rc = nil if !OpenNebula.is_error?(rc) From a091e52ffbf26f3543671812d4ae4d431a6250f2 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 1 Jul 2011 18:54:02 +0200 Subject: [PATCH 38/75] feature #687: Redo of commit 2b90f0237700bb5da0ef6603d66dc832cd6abd12 --- src/rm/RequestManagerPoolInfoFilter.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc index 2049eb785a..b3875a2dc2 100644 --- a/src/rm/RequestManagerPoolInfoFilter.cc +++ b/src/rm/RequestManagerPoolInfoFilter.cc @@ -45,7 +45,6 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa set::iterator it; ostringstream oss; - bool empty = true; ostringstream where_string; @@ -59,6 +58,8 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa int rc; + AuthRequest::Operation request_op; + // ------------------------------------------ // User ID filter // ------------------------------------------ @@ -74,10 +75,11 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa case MINE: uid_filter << "uid = " << uid; - auth_op = AuthRequest::INFO_POOL_MINE; + request_op = AuthRequest::INFO_POOL_MINE; break; case ALL: + request_op = AuthRequest::INFO_POOL; break; case MINE_GROUP: @@ -89,11 +91,13 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa where_string << " OR gid = " << *it; } - auth_op = AuthRequest::INFO_POOL_MINE; + request_op = AuthRequest::INFO_POOL_MINE; break; default: uid_filter << "uid = " << filter_flag; + + request_op = AuthRequest::INFO_POOL; break; } @@ -180,7 +184,7 @@ void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& pa // Authorize & get the pool // ------------------------------------------ - if ( basic_authorization(-1) == false ) + if ( basic_authorization(-1, request_op) == false ) { return; } From 896385e77b43c32e03785913b7eb671359e94ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 1 Jul 2011 19:05:17 +0200 Subject: [PATCH 39/75] Feature #687: Fix oneacl addrule parser --- src/oca/ruby/OpenNebula/Acl.rb | 105 ++++++++++------------------- src/oca/ruby/OpenNebula/AclPool.rb | 17 ++--- 2 files changed, 41 insertions(+), 81 deletions(-) diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index ae481b1e50..708a0b5d0f 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -42,37 +42,36 @@ module OpenNebula class Acl USERS = { - "UID" => 4294967296, - "GID" => 8589934592, - "ALL" => 17179869184 + "UID" => 0x100000000, + "GID" => 0x200000000, + "ALL" => 0x400000000 + } + RESOURCES = + { + "VM" => 0x1000000000, + "HOST" => 0x2000000000, + "NET" => 0x4000000000, + "IMAGE" => 0x8000000000, + "USER" => 0x10000000000, + "TEMPLATE" => 0x20000000000, + "GROUP" => 0x40000000000 } - - RESOURCES = { - "VM" => 68719476736, - "HOST" => 137438953472, - "NET" => 274877906944, - "IMAGE" => 549755813888, - "USER" => 1099511627776, - "TEMPLATE" => 2199023255552, - "GROUP" => 4398046511104, - "ACL" => 8796093022208 + RIGHTS = + { + "CREATE" => 0x1, # Auth. to create an object + "DELETE" => 0x2, # Auth. to delete an object + "USE" => 0x4, # Auth. to use an object + "MANAGE" => 0x8, # Auth. to manage an object + "INFO" => 0x10, # Auth. to view an object + "INFO_POOL" => 0x20, # Auth. to view any object in the pool + "INFO_POOL_MINE"=> 0x40, # Auth. to view user and/or group objects + "INSTANTIATE" => 0x80, # Auth. to instantiate a VM from a TEMPLATE + "CHOWN" => 0x100 # Auth. to change ownership of an object } - RIGHTS = { - "CREATE" => 1, # Auth. to create an object - "DELETE" => 2, # Auth. to delete an object - "USE" => 4, # Auth. to use an object - "MANAGE" => 8, # Auth. to manage an object - "INFO" => 16, # Auth. to view an object - "INFO_POOL" => 32, # Auth. to view any object in the pool - "INFO_POOL_MINE"=> 64, # Auth. to view user and/or group objects - "INSTANTIATE" => 128,# Auth. to instantiate a VM from a TEMPLATE - "CHOWN" => 256 # Auth. to change ownership of an object - } - - def initialize(rule_str=nil) + # Content stores numbers @content = { :users => 0, :resources => 0, @@ -82,37 +81,6 @@ module OpenNebula parse_rule(rule_str) if rule_str end - - def set_hex_rule(users,resources,rights) - set_hex_users users - set_hex_resources resources - set_hex_rights rights - end - - def set_hex_users(users) - @content[:users] = users - end - - def set_hex_resources(resources) - @content[:resources] = resources - end - - def set_hex_rights(rights) - @content[:rights] = rights - end - - def set_users(users) - @content[:users] = users.to_i.to_s(10) - end - - def set_resources(resources) - @content[:resources] = resources.to_i.to_s(10) - end - - def set_rights(rights) - @content[:rights] = rights.to_i.to_s(10) - end - def parse_rule(rule_str) begin rule_str = rule_str.split(" ") @@ -144,13 +112,11 @@ module OpenNebula resources[0].split("+").each{ |resource| next if !RESOURCES[resource.upcase] - @content[:resources] = @content[:resources] + RESOURCES[resource.upcase].to_i + @content[:resources] += RESOURCES[resource.upcase] } - @content[:resources] = @content[:resources] + - calculate_users(resources[1]).to_i + @content[:resources] += calculate_users(resources[1]) - @content[:resources] = @content[:resources].to_s(16) rescue Exception => e @content[:resources] = OpenNebula::Error.new(e.message) end @@ -163,10 +129,9 @@ module OpenNebula rights.each{ |right| next if !RIGHTS[right.upcase] - @content[:rights] = @content[:rights] + RIGHTS[right.upcase] + @content[:rights] += RIGHTS[right.upcase] } - @content[:rights] = @content[:rights].to_i.to_s(16) rescue Exception => e @content[:rights] = OpenNebula::Error.new(e.message) end @@ -189,19 +154,19 @@ module OpenNebula users_value = users_str[1..-1].to_i + value - return users_value.to_i.to_s(16) + return users_value end - def users - @content[:users] + def users_hex_str + @content[:users].to_i.to_s(16) end - def resources - @content[:resources] + def resources_hex_str + @content[:resources].to_i.to_s(16) end - def rights - @content[:rights] + def rights_hex_str + @content[:rights].to_i.to_s(16) end def is_error? diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/OpenNebula/AclPool.rb index e7c773a8a3..9c012a61b8 100644 --- a/src/oca/ruby/OpenNebula/AclPool.rb +++ b/src/oca/ruby/OpenNebula/AclPool.rb @@ -52,9 +52,9 @@ module OpenNebula # Adds a new ACL rule. # - # +user+ A hex number, e.g. 0x100000001 - # +resource+ A hex number, e.g. 0x2100000001 - # +rights+ A hex number, e.g. 0x10 + # +user+ A string containing a hex number, e.g. 0x100000001 + # +resource+ A string containing a hex number, e.g. 0x2100000001 + # +rights+ A string containing a hex number, e.g. 0x10 def addrule(user, resource, rights) rc = @client.call( ACL_POOL_METHODS[:addrule], user, @@ -74,14 +74,9 @@ module OpenNebula return rule.error if rule.is_error? - rc = @client.call( ACL_POOL_METHODS[:addrule], - rule.users, - rule.resources, - rule.rights ) - - rc = nil if !OpenNebula.is_error?(rc) - - return rc + return addrule( rule.users_hex_str, + rule.resources_hex_str, + rule.rights_hex_str ) end # Deletes an existing ACL rule. From ff7e79207f544a9ce3663b8d3b26905cbb545c87 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 2 Jul 2011 19:11:22 +0200 Subject: [PATCH 40/75] feature #687: Scheduler uses the new filter function --- include/RequestManagerPoolInfoFilter.h | 2 +- src/scheduler/src/pool/VirtualMachinePoolXML.cc | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h index b671086347..738c05c6b6 100644 --- a/include/RequestManagerPoolInfoFilter.h +++ b/include/RequestManagerPoolInfoFilter.h @@ -67,7 +67,7 @@ public: VirtualMachinePoolInfo(): RequestManagerPoolInfoFilter("VirtualMachinePoolInfo", "Returns the virtual machine instances pool", - "A:siii") + "A:siiii") { Nebula& nd = Nebula::instance(); pool = nd.get_vmpool(); diff --git a/src/scheduler/src/pool/VirtualMachinePoolXML.cc b/src/scheduler/src/pool/VirtualMachinePoolXML.cc index 2cb47da06d..f81e359a65 100644 --- a/src/scheduler/src/pool/VirtualMachinePoolXML.cc +++ b/src/scheduler/src/pool/VirtualMachinePoolXML.cc @@ -64,13 +64,15 @@ int VirtualMachinePoolXML::load_info(xmlrpc_c::value &result) { try { - client->call(client->get_endpoint(), // serverUrl - "one.vmpool.info", // methodName - "sii", // arguments format - &result, // resultP - client->get_oneauth().c_str(), // auth string - -2, // VM from all users - 1); // in pending state + client->call(client->get_endpoint(), // serverUrl + "one.vmpool.info", // methodName + "siiii", // arguments format + &result, // resultP + client->get_oneauth().c_str(), // auth string + -2, // VM from all users + -1, // start_id (none) + -1, // end_id (none) + 1); // in pending state return 0; } catch (exception const& e) From 95cc8c31d5f8887f3ec50c3f91eee9029f4998d2 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 01:57:39 +0200 Subject: [PATCH 41/75] feature #687: Potentiall access to freed memory in Object_XML::get_nodes. Nodes must be disposed when not needed by the calling function --- include/ObjectXML.h | 14 ++++++++++++++ src/group/Group.cc | 4 +++- src/host/Host.cc | 7 +++++-- src/image/Image.cc | 5 ++++- src/um/User.cc | 3 ++- src/vm/VirtualMachine.cc | 8 ++++++-- src/vm_template/VMTemplate.cc | 4 +++- src/vnm/VirtualNetwork.cc | 6 ++++-- src/xml/ObjectXML.cc | 3 ++- src/xml/test/ObjectXMLTest.cc | 1 + 10 files changed, 44 insertions(+), 11 deletions(-) diff --git a/include/ObjectXML.h b/include/ObjectXML.h index 53919577fc..d370270226 100644 --- a/include/ObjectXML.h +++ b/include/ObjectXML.h @@ -138,6 +138,20 @@ public: */ int get_nodes(const char * xpath_expr, vector& content); + /** + * Frees a vector of XMLNodes, as returned by the get_nodes function + * @param content the vector of xmlNodePtr + */ + void free_nodes(vector& content) + { + vector::iterator it; + + for (it = content.begin(); it < content.end(); it++) + { + xmlFreeNode(*it); + } + }; + /** * Updates the object representation with a new XML document. Previous * XML resources are freed diff --git a/src/group/Group.cc b/src/group/Group.cc index 3b710bc7d6..acae4034d3 100644 --- a/src/group/Group.cc +++ b/src/group/Group.cc @@ -129,7 +129,7 @@ int Group::from_xml(const string& xml) // Get associated classes ObjectXML::get_nodes("/GROUP/USERS", content); - if( content.size() < 1 ) + if (content.empty()) { return -1; } @@ -137,6 +137,8 @@ int Group::from_xml(const string& xml) // Set of IDs rc += ObjectCollection::from_xml_node(content[0]); + ObjectXML::free_nodes(content); + if (rc != 0) { return -1; diff --git a/src/host/Host.cc b/src/host/Host.cc index 062c456024..32e98ad3fc 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -240,24 +240,27 @@ int Host::from_xml(const string& xml) // Get associated classes ObjectXML::get_nodes("/HOST/HOST_SHARE", content); - if( content.size() < 1 ) + if (content.empty()) { return -1; } rc += host_share.from_xml_node( content[0] ); + ObjectXML::free_nodes(content); content.clear(); ObjectXML::get_nodes("/HOST/TEMPLATE", content); - if( content.size() < 1 ) + if( content.empty()) { return -1; } rc += obj_template->from_xml_node( content[0] ); + ObjectXML::free_nodes(content); + if (rc != 0) { return -1; diff --git a/src/image/Image.cc b/src/image/Image.cc index a752546490..b02a3f7d8a 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -382,13 +382,16 @@ int Image::from_xml(const string& xml) // Get associated classes ObjectXML::get_nodes("/IMAGE/TEMPLATE", content); - if( content.size() < 1 ) + + if (content.empty()) { return -1; } rc += obj_template->from_xml_node(content[0]); + ObjectXML::free_nodes(content); + if (rc != 0) { return -1; diff --git a/src/um/User.cc b/src/um/User.cc index 1a1d28aa6c..7250be3fb3 100644 --- a/src/um/User.cc +++ b/src/um/User.cc @@ -166,7 +166,7 @@ int User::from_xml(const string& xml) // Get associated classes ObjectXML::get_nodes("/USER/GROUPS", content); - if( content.size() < 1 ) + if (content.empty()) { return -1; } @@ -174,6 +174,7 @@ int User::from_xml(const string& xml) // Set of IDs rc += ObjectCollection::from_xml_node(content[0]); + ObjectXML::free_nodes(content); if (rc != 0) { diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index b73c8253ab..6d5e0da844 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1251,7 +1251,7 @@ int VirtualMachine::from_xml(const string &xml_str) // Get associated classes ObjectXML::get_nodes("/VM/TEMPLATE", content); - if( content.size() < 1 ) + if (content.empty()) { return -1; } @@ -1260,16 +1260,20 @@ int VirtualMachine::from_xml(const string &xml_str) rc += obj_template->from_xml_node(content[0]); // Last history entry + ObjectXML::free_nodes(content); content.clear(); + ObjectXML::get_nodes("/VM/HISTORY_RECORDS/HISTORY", content); - if( !content.empty() ) + if (!content.empty()) { history = new History(oid); rc += history->from_xml_node(content[0]); history_records.resize(history->seq + 1); history_records[history->seq] = history; + + ObjectXML::free_nodes(content); } if (rc != 0) diff --git a/src/vm_template/VMTemplate.cc b/src/vm_template/VMTemplate.cc index 94a7ce7230..8df3b1da1f 100644 --- a/src/vm_template/VMTemplate.cc +++ b/src/vm_template/VMTemplate.cc @@ -229,7 +229,7 @@ int VMTemplate::from_xml(const string& xml) // Get associated classes ObjectXML::get_nodes("/VMTEMPLATE/TEMPLATE", content); - if( content.size() < 1 ) + if (content.empty()) { return -1; } @@ -237,6 +237,8 @@ int VMTemplate::from_xml(const string& xml) // Template contents rc += obj_template->from_xml_node(content[0]); + ObjectXML::free_nodes(content); + if (rc != 0) { return -1; diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index 7dab044d06..d2f25e8dc2 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -583,13 +583,15 @@ int VirtualNetwork::from_xml(const string &xml_str) // Get associated classes ObjectXML::get_nodes("/VNET/TEMPLATE", content); - if( content.size() < 1 ) + if (content.empty()) { return -1; } // Virtual Network template - rc += obj_template->from_xml_node( content[0] ); + rc += obj_template->from_xml_node(content[0]); + + ObjectXML::free_nodes(content); if (rc != 0) { diff --git a/src/xml/ObjectXML.cc b/src/xml/ObjectXML.cc index 3f61ab7358..8e30594b9f 100644 --- a/src/xml/ObjectXML.cc +++ b/src/xml/ObjectXML.cc @@ -328,10 +328,11 @@ int ObjectXML::get_nodes (const char * xpath_expr, vector& content) for(int i = 0; i < size; ++i) { - cur = ns->nodeTab[i]; + cur = xmlCopyNode(ns->nodeTab[i],1); if ( cur == 0 || cur->type != XML_ELEMENT_NODE ) { + xmlFreeNode(cur); continue; } diff --git a/src/xml/test/ObjectXMLTest.cc b/src/xml/test/ObjectXMLTest.cc index 5b96f94397..fd538203d3 100644 --- a/src/xml/test/ObjectXMLTest.cc +++ b/src/xml/test/ObjectXMLTest.cc @@ -161,6 +161,7 @@ public: CPPUNIT_ASSERT(results.size() == 1); CPPUNIT_ASSERT(results[0] == "A_hostname"); + obj.free_nodes(vms); } catch(runtime_error& re) { From 72a26d476f299da22f1d551fcf1a4e360a120340 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 03:27:21 +0200 Subject: [PATCH 42/75] feature #687: Made ObjectCollection::from_xml_node more efficient --- src/pool/ObjectCollection.cc | 46 ++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/pool/ObjectCollection.cc b/src/pool/ObjectCollection.cc index ec8da0934c..ba41fa621d 100644 --- a/src/pool/ObjectCollection.cc +++ b/src/pool/ObjectCollection.cc @@ -21,32 +21,38 @@ int ObjectCollection::from_xml_node(const xmlNodePtr node) { - ObjectXML xml(node); - int rc = 0; - int id; + xmlNodePtr cur_node = 0; + istringstream iss; + int id; + int rc = 0; - vector values; - vector::iterator it; - istringstream iss; - - string xpath_expr = "/" + collection_name + "/ID"; - - values = xml[xpath_expr.c_str()]; - - for ( it = values.begin() ; it < values.end(); it++ ) - { - iss.str(*it); - iss >> dec >> id; - - if ( iss.fail() ) + for (cur_node = node->children; cur_node != 0; cur_node = cur_node->next) + { + if ((cur_node->type == XML_ELEMENT_NODE) && + (cur_node->children != 0) && + ((cur_node->children->type == XML_TEXT_NODE ) || + (cur_node->children->type == XML_CDATA_SECTION_NODE))) { - rc = -1; + iss.clear(); + iss.str(reinterpret_cast(cur_node->children->content)); + iss >> dec >> id; + + if ( iss.fail() ) + { + rc = -1; + break; + } + else + { + collection_set.insert(id); + } } else { - collection_set.insert(id); + rc = -1; + break; } - } + } return rc; }; From 9c46bb4131db32d5b68f46bad38984e69275a1a2 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 04:16:35 +0200 Subject: [PATCH 43/75] feature #687: The scheduler now loads the pool of users --- src/scheduler/include/HostPoolXML.h | 4 ++-- src/scheduler/include/PoolXML.h | 4 +++- src/scheduler/include/Scheduler.h | 8 ++++++++ src/scheduler/src/pool/SConstruct | 2 ++ src/scheduler/src/sched/Scheduler.cc | 12 ++++++++++++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/scheduler/include/HostPoolXML.h b/src/scheduler/include/HostPoolXML.h index deead4b2f8..8160262df6 100644 --- a/src/scheduler/include/HostPoolXML.h +++ b/src/scheduler/include/HostPoolXML.h @@ -49,9 +49,9 @@ protected: return get_nodes("/HOST_POOL/HOST[STATE<3]", content); }; - virtual void add_object(xmlNodePtr node); + void add_object(xmlNodePtr node); - virtual int load_info(xmlrpc_c::value &result); + int load_info(xmlrpc_c::value &result); }; #endif /* HOST_POOL_XML_H_ */ diff --git a/src/scheduler/include/PoolXML.h b/src/scheduler/include/PoolXML.h index e206524de8..4acc8e3f51 100644 --- a/src/scheduler/include/PoolXML.h +++ b/src/scheduler/include/PoolXML.h @@ -53,7 +53,7 @@ public: flush(); // ------------------------------------------------------------------------- - // Load the ids (to get an updated list of hosts) + // Load the ids (to get an updated list of the pool) // ------------------------------------------------------------------------- xmlrpc_c::value result; @@ -97,6 +97,8 @@ public: add_object(nodes[i]); } + free_nodes(nodes); + return 0; }; diff --git a/src/scheduler/include/Scheduler.h b/src/scheduler/include/Scheduler.h index 6cd9886af7..5fd1ae6365 100644 --- a/src/scheduler/include/Scheduler.h +++ b/src/scheduler/include/Scheduler.h @@ -18,6 +18,7 @@ #define SCHEDULER_H_ #include "Log.h" +#include "UserPoolXML.h" #include "HostPoolXML.h" #include "VirtualMachinePoolXML.h" #include "SchedulerPolicy.h" @@ -48,6 +49,7 @@ protected: int _machines_limit, int _dispatch_limit, int _host_dispatch_limit): hpool(0), vmpool(0), + upool(0), timer(_timer), url(_url), machines_limit(_machines_limit), @@ -71,6 +73,11 @@ protected: delete vmpool; } + if ( upool != 0) + { + delete upool; + } + if ( client != 0) { delete client; @@ -83,6 +90,7 @@ protected: HostPoolXML * hpool; VirtualMachinePoolXML * vmpool; + UserPoolXML * upool; // --------------------------------------------------------------- // Scheduler Policies diff --git a/src/scheduler/src/pool/SConstruct b/src/scheduler/src/pool/SConstruct index 31fe496bf4..0eb31942d5 100644 --- a/src/scheduler/src/pool/SConstruct +++ b/src/scheduler/src/pool/SConstruct @@ -21,6 +21,8 @@ Import('sched_env') lib_name='scheduler_pool' source_files=[ + 'UserPoolXML.cc', + 'UserXML.cc', 'HostPoolXML.cc', 'HostXML.cc', 'VirtualMachinePoolXML.cc', diff --git a/src/scheduler/src/sched/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc index 7bd288d11c..6b22e106f3 100644 --- a/src/scheduler/src/sched/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -121,6 +121,7 @@ void Scheduler::start() hpool = new HostPoolXML(client); vmpool = new VirtualMachinePoolXML(client, machines_limit); + upool = new UserPoolXML(client); // ----------------------------------------------------------- // Load scheduler policies @@ -228,6 +229,17 @@ int Scheduler::set_up_pools() return rc; } + //-------------------------------------------------------------------------- + //Cleans the cache and get the pending VMs + //-------------------------------------------------------------------------- + + rc = upool->set_up(); + + if ( rc != 0 ) + { + return rc; + } + //-------------------------------------------------------------------------- //Get the matching hosts for each VM //-------------------------------------------------------------------------- From 2a1221676007ac227703c8a222e81ff3ab5f1fd7 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 04:19:43 +0200 Subject: [PATCH 44/75] feature #687: UserXML for the Scheduler --- src/scheduler/include/UserPoolXML.h | 57 +++++++++++++++++ src/scheduler/include/UserXML.h | 53 ++++++++++++++++ src/scheduler/src/pool/UserPoolXML.cc | 90 +++++++++++++++++++++++++++ src/scheduler/src/pool/UserXML.cc | 74 ++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 src/scheduler/include/UserPoolXML.h create mode 100644 src/scheduler/include/UserXML.h create mode 100644 src/scheduler/src/pool/UserPoolXML.cc create mode 100644 src/scheduler/src/pool/UserXML.cc diff --git a/src/scheduler/include/UserPoolXML.h b/src/scheduler/include/UserPoolXML.h new file mode 100644 index 0000000000..44d151c71c --- /dev/null +++ b/src/scheduler/include/UserPoolXML.h @@ -0,0 +1,57 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + + +#ifndef USER_POOL_XML_H_ +#define USER_POOL_XML_H_ + +#include "PoolXML.h" +#include "UserXML.h" + +using namespace std; + +class UserPoolXML : public PoolXML +{ +public: + + UserPoolXML(Client* client):PoolXML(client){}; + + int set_up(); + + /** + * Gets an object from the pool + * @param oid the object unique identifier + * + * @return a pointer to the object, 0 in case of failure + */ + UserXML * get(int oid) const + { + return static_cast(PoolXML::get(oid)); + }; + +protected: + + int get_suitable_nodes(vector& content) + { + return get_nodes("/USER_POOL/USER[ENABLED=1]", content); + }; + + void add_object(xmlNodePtr node); + + int load_info(xmlrpc_c::value &result); +}; + +#endif /* HOST_POOL_XML_H_ */ diff --git a/src/scheduler/include/UserXML.h b/src/scheduler/include/UserXML.h new file mode 100644 index 0000000000..56e01040da --- /dev/null +++ b/src/scheduler/include/UserXML.h @@ -0,0 +1,53 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + + +#ifndef USER_XML_H_ +#define USER_XML_H_ + +#include "ObjectXML.h" +#include + +using namespace std; + +class UserXML : public ObjectXML +{ +public: + UserXML(const string &xml_doc):ObjectXML(xml_doc) + { + init_attributes(); + }; + + UserXML(const xmlNodePtr node):ObjectXML(node) + { + init_attributes(); + }; + + int get_uid() + { + return oid; + }; + +private: + int oid; + int gid; + + set group_ids; + + void init_attributes(); +}; + +#endif /* USER_XML_H_ */ diff --git a/src/scheduler/src/pool/UserPoolXML.cc b/src/scheduler/src/pool/UserPoolXML.cc new file mode 100644 index 0000000000..04252e45cf --- /dev/null +++ b/src/scheduler/src/pool/UserPoolXML.cc @@ -0,0 +1,90 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "UserPoolXML.h" + + +int UserPoolXML::set_up() +{ + ostringstream oss; + int rc; + + rc = PoolXML::set_up(); + + if ( rc == 0 ) + { + oss.str(""); + oss << "Users (enabled):"; + + map::iterator it; + + for (it=objects.begin();it!=objects.end();it++) + { + oss << " " << it->first; + } + + NebulaLog::log("HOST",Log::DEBUG,oss); + } + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void UserPoolXML::add_object(xmlNodePtr node) +{ + if ( node == 0 || node->children == 0 ) + { + NebulaLog::log("USER",Log::ERROR, + "XML Node does not represent a valid User"); + + return; + } + + UserXML* user = new UserXML(node); + + objects.insert(pair(user->get_uid(), user)); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int UserPoolXML::load_info(xmlrpc_c::value &result) +{ + try + { + client->call(client->get_endpoint(), // serverUrl + "one.userpool.info", // methodName + "s", // arguments format + &result, // resultP + client->get_oneauth().c_str()); // argument + return 0; + } + catch (exception const& e) + { + ostringstream oss; + oss << "Exception raised: " << e.what(); + + NebulaLog::log("USER", Log::ERROR, oss); + + return -1; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + diff --git a/src/scheduler/src/pool/UserXML.cc b/src/scheduler/src/pool/UserXML.cc new file mode 100644 index 0000000000..95cfb108d0 --- /dev/null +++ b/src/scheduler/src/pool/UserXML.cc @@ -0,0 +1,74 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include "UserXML.h" +#include + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void UserXML::init_attributes() +{ + vector content; + + oid = atoi(((*this)["/USER/ID"] )[0].c_str() ); + gid = atoi(((*this)["/USER/GID"] )[0].c_str() ); + + get_nodes("/USER/GROUPS",content); + + if (!content.empty()) + { + xmlNodePtr cur_node = 0; + istringstream iss; + int id; + + for (cur_node = content[0]->children; + cur_node != 0; + cur_node = cur_node->next) + { + if ((cur_node->type == XML_ELEMENT_NODE) && + (cur_node->children != 0) && + ((cur_node->children->type == XML_TEXT_NODE ) || + (cur_node->children->type == XML_CDATA_SECTION_NODE))) + { + iss.clear(); + iss.str(reinterpret_cast(cur_node->children->content)); + iss >> dec >> id; + + if ( iss.fail() ) + { + //TODO Print a warning message + break; + } + else + { + group_ids.insert(id); + } + } + else + { + //TODO Print a warning message + break; + } + } + } + + free_nodes(content); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + From facdf35009fde8d54e3b604e20ca87ad6851f3cd Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 04:56:05 +0200 Subject: [PATCH 45/75] feature #687: Place holder for ACL integration ready --- src/scheduler/include/UserXML.h | 5 +++ src/scheduler/include/VirtualMachineXML.h | 7 ++++ src/scheduler/src/pool/VirtualMachineXML.cc | 3 +- src/scheduler/src/sched/Scheduler.cc | 45 +++++++++++++++++++-- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/scheduler/include/UserXML.h b/src/scheduler/include/UserXML.h index 56e01040da..ef791274a0 100644 --- a/src/scheduler/include/UserXML.h +++ b/src/scheduler/include/UserXML.h @@ -41,6 +41,11 @@ public: return oid; }; + set get_groups() + { + return group_ids; + }; + private: int oid; int gid; diff --git a/src/scheduler/include/VirtualMachineXML.h b/src/scheduler/include/VirtualMachineXML.h index ed2ad44b7c..5a6baec137 100644 --- a/src/scheduler/include/VirtualMachineXML.h +++ b/src/scheduler/include/VirtualMachineXML.h @@ -46,6 +46,11 @@ public: return oid; }; + int get_uid() const + { + return uid; + }; + /** * Adds a new share to the map of suitable shares to start this VM * @param hid of the selected host @@ -138,6 +143,8 @@ protected: */ int oid; + int uid; + int memory; float cpu; diff --git a/src/scheduler/src/pool/VirtualMachineXML.cc b/src/scheduler/src/pool/VirtualMachineXML.cc index d64ede4c47..ce0cdb4667 100644 --- a/src/scheduler/src/pool/VirtualMachineXML.cc +++ b/src/scheduler/src/pool/VirtualMachineXML.cc @@ -22,7 +22,8 @@ void VirtualMachineXML::init_attributes() { vector result; - oid = atoi(((*this)["/VM/ID"] )[0].c_str() ); + oid = atoi(((*this)["/VM/ID"] )[0].c_str()); + uid = atoi(((*this)["/VM/UID"])[0].c_str()); result = ((*this)["/VM/TEMPLATE/MEMORY"]); if (result.size() > 0) diff --git a/src/scheduler/src/sched/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc index 6b22e106f3..0ea7eae18f 100644 --- a/src/scheduler/src/sched/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -230,7 +230,7 @@ int Scheduler::set_up_pools() } //-------------------------------------------------------------------------- - //Cleans the cache and get the pending VMs + //Cleans the cache and get the users //-------------------------------------------------------------------------- rc = upool->set_up(); @@ -240,6 +240,14 @@ int Scheduler::set_up_pools() return rc; } + //-------------------------------------------------------------------------- + //Cleans the cache and get the ACLs + //-------------------------------------------------------------------------- + + //TODO + // 1.- one.acl.list + // 2.- from_xml + //-------------------------------------------------------------------------- //Get the matching hosts for each VM //-------------------------------------------------------------------------- @@ -258,6 +266,7 @@ void Scheduler::match() int vm_memory; int vm_cpu; int vm_disk; + int uid; string reqs; HostXML * host; @@ -266,6 +275,9 @@ void Scheduler::match() char * error; bool matched; + UserXML * user; + set gids; + int rc; map::const_iterator vm_it; @@ -280,8 +292,9 @@ void Scheduler::match() vm = static_cast(vm_it->second); reqs = vm->get_requirements(); + uid = vm->get_uid(); - for (h_it=hosts.begin(); h_it != hosts.end(); h_it++) + for (h_it=hosts.begin(), matched=false; h_it != hosts.end(); h_it++) { host = static_cast(h_it->second); @@ -310,12 +323,38 @@ void Scheduler::match() { matched = true; } + + if ( matched == false ) + { + continue; + } + + // ----------------------------------------------------------------- + // Check host capacity + // ----------------------------------------------------------------- + + user = upool->get(uid); + matched = false; + + if ( user != 0 ) + { + set groups = user->get_groups(); + //TODO Authorization test for this user on this host + // 1.- user = uid + // 2.- gid + // 3.- groups + // 4.- DEPLOY on host->get_hid + } + else + { + //TODO Log debug info (user not authorized)? + continue; + } if ( matched == false ) { continue; } - // ----------------------------------------------------------------- // Check host capacity // ----------------------------------------------------------------- From c844ccb2cd522e812c0646f28527ee6fad58175f Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 13:12:00 +0200 Subject: [PATCH 46/75] feature #687: Comments and formatting for AclRule. Removed uneeded includes --- include/AclManager.h | 2 ++ include/AclRule.h | 49 +++++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index c07886b2aa..af9216de1a 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -20,6 +20,8 @@ #include "AuthManager.h" #include "AclRule.h" +#include "SqlDB.h" + using namespace std; /** diff --git a/include/AclRule.h b/include/AclRule.h index a3d3c98a41..91b21e5697 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -18,8 +18,7 @@ #define ACL_RULE_H_ #include - -#include "ObjectSQL.h" +#include using namespace std; @@ -31,15 +30,18 @@ class AclRule { public: + // ------------------------------------------------------------------------ static const long long INDIVIDUAL_ID; + static const long long GROUP_ID; + static const long long ALL_ID; + // ------------------------------------------------------------------------ - // NONE_ID can never be used in a rule. It is useful to create masks that - // will never match any existing rule - static const long long NONE_ID; - - AclRule(int _oid, long long _user, long long _resource, long long _rights): + AclRule(int _oid, + long long _user, + long long _resource, + long long _rights): oid(_oid), user(_user), resource(_resource), rights(_rights) { build_str(); @@ -47,9 +49,9 @@ public: bool operator ==(const AclRule& other) const { - return (user == other.user && + return (user == other.user && resource == other.resource && - rights == other.rights); + rights == other.rights); }; /** @@ -130,6 +132,9 @@ public: }; private: + // NONE_ID can never be used in a rule. It is useful to create masks that + // will never match any existing rule + static const long long NONE_ID; friend class AclManager; @@ -139,27 +144,43 @@ private: int oid; /** - * 64 bit integer holding a user ID in the 32 less significant bits, - * and a flag indicating the kind of ID in the other 32 + * 64 bit integer holding a user compound: + * + * 32 bits 32 bits + * +-----------------------+-----------------------+ + * | Type (user,group,all) | user/group ID | + * +-----------------------+-----------------------+ */ long long user; /** - * 64 bit integer holding an object ID in the 32 less significant bits, - * and flags indicanting the kind of ID and object in the other 32 + * 64 bit integer holding a resource compound + * + * 32 bits 32 bits + * +-----------------------+-----------------------+ + * | Type (VM, Host...) | resource ID | + * +-----------------------+-----------------------+ */ long long resource; /** * 64 bit integer containing the rights flags + * + * 64 bits + * +-----------------------------------------------+ + * | Actions (MANAGE, CREATE, USE, DELETE... | + * +-----------------------------------------------+ */ long long rights; /** - * Human readable representation + * Human readable representation of the rule */ string str; + /** + * Builds the human representation of the ACL + */ void build_str(); }; From 84a19e69adcf2ac0000eef2d415f955ac7a6ff84 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 14:13:43 +0200 Subject: [PATCH 47/75] feature #687: Minor changes in the ACL module --- include/AclManager.h | 23 ++++----- include/AuthManager.h | 16 +++--- src/acl/AclManager.cc | 103 ++++++++++++++++++++++++--------------- src/acl/AclRule.cc | 6 +-- src/authm/AuthManager.cc | 4 +- 5 files changed, 87 insertions(+), 65 deletions(-) diff --git a/include/AclManager.h b/include/AclManager.h index af9216de1a..bff6f519ba 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -56,12 +56,12 @@ public: * @param op The operation to be authorized * @return true if the authorization is granted by any rule */ - const bool authorize(int uid, const set &user_groups, - AuthRequest::Object obj_type, int obj_id, int obj_gid, - AuthRequest::Operation op); - - /* ---------------------------------------------------------------------- */ - + const bool authorize(int uid, + const set& user_groups, + AuthRequest::Object obj_type, + int obj_id, + int obj_gid, + AuthRequest::Operation op); /** * Adds a new rule to the ACL rule set * @@ -75,11 +75,10 @@ public: * -2 if the rule is malformed, * -3 if the DB insert failed */ - int add_rule(long long user, long long resource, long long rights, - string& error_str); - - /* ---------------------------------------------------------------------- */ - + int add_rule(long long user, + long long resource, + long long rights, + string& error_str); /** * Deletes a rule from the ACL rule set * @@ -103,8 +102,6 @@ public: _db->exec(oss); }; - /* ---------------------------------------------------------------------- */ - /** * Dumps the rule set in XML format. * @param oss The output stream to dump the rule set contents diff --git a/include/AuthManager.h b/include/AuthManager.h index d8d5f6c206..d86d984f22 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -311,14 +311,14 @@ public: */ enum Object { - VM = 0x1000000000LL, - HOST = 0x2000000000LL, - NET = 0x4000000000LL, - IMAGE = 0x8000000000LL, - USER = 0x10000000000LL, - TEMPLATE = 0x20000000000LL, - GROUP = 0x40000000000LL, - ACL = 0x80000000000LL + VM = 0x0000001000000000LL, + HOST = 0x0000002000000000LL, + NET = 0x0000004000000000LL, + IMAGE = 0x0000008000000000LL, + USER = 0x0000010000000000LL, + TEMPLATE = 0x0000020000000000LL, + GROUP = 0x0000040000000000LL, + ACL = 0x0000080000000000LL }; static string Object_to_str(Object ob) diff --git a/src/acl/AclManager.cc b/src/acl/AclManager.cc index ef5649f8e0..5d6f3f1d3e 100644 --- a/src/acl/AclManager.cc +++ b/src/acl/AclManager.cc @@ -47,8 +47,7 @@ int AclManager::init_cb(void *nil, int num, char **values, char **names) /* -------------------------------------------------------------------------- */ -AclManager::AclManager(SqlDB * _db) : - db(_db), lastOID(-1) +AclManager::AclManager(SqlDB * _db) : db(_db), lastOID(-1) { ostringstream oss; @@ -94,8 +93,12 @@ AclManager::~AclManager() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -const bool AclManager::authorize(int uid, const set &user_groups, - AuthRequest::Object obj_type, int obj_id, int obj_gid, +const bool AclManager::authorize( + int uid, + const set& user_groups, + AuthRequest::Object obj_type, + int obj_id, + int obj_gid, AuthRequest::Operation op) { ostringstream oss; @@ -112,7 +115,7 @@ const bool AclManager::authorize(int uid, const set &user_groups, if ( obj_id >= 0 ) { - resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id; + resource_oid_req = obj_type | AclRule::INDIVIDUAL_ID | obj_id; } else { @@ -123,25 +126,24 @@ const bool AclManager::authorize(int uid, const set &user_groups, if ( obj_gid >= 0 ) { - resource_gid_req = obj_type + AclRule::GROUP_ID + obj_gid; + resource_gid_req = obj_type | AclRule::GROUP_ID | obj_gid; } else { resource_gid_req = AclRule::NONE_ID; } - long long resource_all_req = obj_type + AclRule::ALL_ID; - long long rights_req = op; + long long resource_all_req = obj_type | AclRule::ALL_ID; + long long rights_req = op; - long long individual_obj_type = - ( obj_type | AclRule::INDIVIDUAL_ID | 0xFFFFFFFF ); + long long resource_oid_mask = + ( obj_type | AclRule::INDIVIDUAL_ID | 0x00000000FFFFFFFFLL ); - long long group_obj_type = - ( obj_type | AclRule::GROUP_ID | 0xFFFFFFFF ); + long long resource_gid_mask = + ( obj_type | AclRule::GROUP_ID | 0x00000000FFFFFFFFLL ); // Create a temporal rule, to log the request - long long log_resource; if ( obj_id >= 0 ) @@ -157,46 +159,65 @@ const bool AclManager::authorize(int uid, const set &user_groups, log_resource = resource_all_req; } - AclRule log_rule(-1, AclRule::INDIVIDUAL_ID + uid, log_resource, - rights_req); + AclRule log_rule(-1, + AclRule::INDIVIDUAL_ID | uid, + log_resource, + rights_req); + oss << "Request " << log_rule.to_str(); NebulaLog::log("ACL",Log::DEBUG,oss); - + // --------------------------------------------------- // Look for rules that apply to everyone + // --------------------------------------------------- user_req = AclRule::ALL_ID; - auth = match_rules(user_req, resource_oid_req, resource_gid_req, - resource_all_req, rights_req, individual_obj_type, group_obj_type); - + auth = match_rules(user_req, + resource_oid_req, + resource_gid_req, + resource_all_req, + rights_req, + resource_oid_mask, + resource_gid_mask); if ( auth == true ) { return true; } + // --------------------------------------------------- // Look for rules that apply to the individual user id - user_req = AclRule::INDIVIDUAL_ID + uid; - - auth = match_rules(user_req, resource_oid_req, resource_gid_req, - resource_all_req, rights_req, individual_obj_type, group_obj_type); + // --------------------------------------------------- + user_req = AclRule::INDIVIDUAL_ID | uid; + auth = match_rules(user_req, + resource_oid_req, + resource_gid_req, + resource_all_req, + rights_req, + resource_oid_mask, + resource_gid_mask); if ( auth == true ) { return true; } - + // ---------------------------------------------------------- // Look for rules that apply to each one of the user's groups + // ---------------------------------------------------------- set::iterator g_it; for (g_it = user_groups.begin(); g_it != user_groups.end(); g_it++) { - user_req = AclRule::GROUP_ID + *g_it; + user_req = AclRule::GROUP_ID | *g_it; - auth = match_rules(user_req, resource_oid_req, resource_gid_req, - resource_all_req, rights_req, individual_obj_type, - group_obj_type); + auth = match_rules(user_req, + resource_oid_req, + resource_gid_req, + resource_all_req, + rights_req, + resource_oid_mask, + resource_gid_mask); if ( auth == true ) { @@ -204,7 +225,6 @@ const bool AclManager::authorize(int uid, const set &user_groups, } } - oss.str("No more rules, permission not granted "); NebulaLog::log("ACL",Log::DEBUG,oss); @@ -220,8 +240,8 @@ bool AclManager::match_rules( long long resource_gid_req, long long resource_all_req, long long rights_req, - long long individual_obj_type, - long long group_obj_type) + long long resource_oid_mask, + long long resource_gid_mask) { bool auth; @@ -251,10 +271,10 @@ bool AclManager::match_rules( ( it->second->resource == resource_all_req ) || // Or rule's object type and group object ID match - ( ( it->second->resource & group_obj_type ) == resource_gid_req ) + ( ( it->second->resource & resource_gid_mask ) == resource_gid_req ) || // Or rule's object type and individual object ID match - ( ( it->second->resource & individual_obj_type ) == resource_oid_req ) + ( ( it->second->resource & resource_oid_mask ) == resource_oid_req ) ); if ( auth == true ) @@ -262,12 +282,12 @@ bool AclManager::match_rules( oss.str("Permission granted"); NebulaLog::log("ACL",Log::DEBUG,oss); - unlock(); - return true; + break; } } unlock(); + return false; } @@ -493,11 +513,10 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names) iss.clear(); } - // TODO: Use add_rule() instead, to check possible errors, or assume - // that anything that was stored into the DB is trustworthy? - AclRule * rule = new AclRule(oid, rule_values[0], rule_values[1], - rule_values[2]); - + AclRule * rule = new AclRule(oid, + rule_values[0], + rule_values[1], + rule_values[2]); oss << "Loading ACL Rule " << rule->to_str(); NebulaLog::log("ACL",Log::DDEBUG,oss); @@ -573,6 +592,8 @@ int AclManager::dump(ostringstream& oss) map::iterator it; string xml; + lock(); + oss << ""; for ( it = acl_rules_oids.begin() ; it != acl_rules_oids.end(); it++ ) @@ -582,6 +603,8 @@ int AclManager::dump(ostringstream& oss) oss << ""; + unlock(); + return 0; } diff --git a/src/acl/AclRule.cc b/src/acl/AclRule.cc index b09479814f..91ebf218f5 100644 --- a/src/acl/AclRule.cc +++ b/src/acl/AclRule.cc @@ -21,9 +21,9 @@ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -const long long AclRule::INDIVIDUAL_ID = 0x100000000LL; -const long long AclRule::GROUP_ID = 0x200000000LL; -const long long AclRule::ALL_ID = 0x400000000LL; +const long long AclRule::INDIVIDUAL_ID = 0x0000000100000000LL; +const long long AclRule::GROUP_ID = 0x0000000200000000LL; +const long long AclRule::ALL_ID = 0x0000000400000000LL; const long long AclRule::NONE_ID = 0x1000000000000000LL; diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index cc751b295a..43cdf67c74 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -68,7 +68,7 @@ void AuthRequest::add_auth(Object ob, oss << Operation_to_str(op) << ":"; - oss << owner << ":" << pub; + oss << owner << ":"; // ------------------------------------------------------------------------- // Authorize the request for self authorization @@ -104,6 +104,8 @@ void AuthRequest::add_auth(Object ob, auth = aclm->authorize(uid, gids, ob, ob_id_int, ob_gid, op); } + oss << auth; // Store the ACL authorization result in the request + self_authorize = self_authorize && auth; auths.push_back(oss.str()); From d60c98345b5f6bcee0d7fbeebd8aaaafd09ef62d Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 3 Jul 2011 22:52:21 +0200 Subject: [PATCH 48/75] feature #687: DeleteRule returns the oid of the rule. AclManager initialized in constructor --- include/RequestManagerAcl.h | 15 +++++++++------ src/rm/RequestManagerAcl.cc | 19 +++---------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/include/RequestManagerAcl.h b/include/RequestManagerAcl.h index 364cd9ea08..fdb75e6539 100644 --- a/include/RequestManagerAcl.h +++ b/include/RequestManagerAcl.h @@ -36,6 +36,9 @@ protected: { auth_object = AuthRequest::ACL; auth_op = AuthRequest::MANAGE; + + Nebula& nd = Nebula::instance(); + aclm = nd.get_aclm(); }; ~RequestManagerAcl(){}; @@ -57,8 +60,8 @@ class AclAddRule : public RequestManagerAcl public: AclAddRule(): RequestManagerAcl("AclAddRule", - "Adds a new ACL rule", - "A:ssss") + "Adds a new ACL rule", + "A:ssss") {}; ~AclAddRule(){}; @@ -74,8 +77,8 @@ class AclDelRule : public RequestManagerAcl public: AclDelRule(): RequestManagerAcl("AclDelRule", - "Deletes an existing ACL rule", - "A:si") + "Deletes an existing ACL rule", + "A:si") {}; ~AclDelRule(){}; @@ -91,8 +94,8 @@ class AclInfo: public RequestManagerAcl public: AclInfo(): RequestManagerAcl("AclInfo", - "Returns the ACL rule set", - "A:s") + "Returns the ACL rule set", + "A:s") {}; ~AclInfo(){}; diff --git a/src/rm/RequestManagerAcl.cc b/src/rm/RequestManagerAcl.cc index 676d54ce89..827e841c7d 100644 --- a/src/rm/RequestManagerAcl.cc +++ b/src/rm/RequestManagerAcl.cc @@ -31,7 +31,6 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList) resource = xmlrpc_c::value_i8(paramList.getI8(2)); rights = xmlrpc_c::value_i8(paramList.getI8(3)); */ - long long user; long long resource; long long rights; @@ -49,10 +48,6 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList) iss.str( xmlrpc_c::value_string(paramList.getString(3)) ); iss >> hex >> rights; - - Nebula& nd = Nebula::instance(); - aclm = nd.get_aclm(); - string error_msg; if ( basic_authorization(-1) == false ) @@ -62,7 +57,6 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList) int rc = aclm->add_rule(user, resource, rights, error_msg); - if ( rc < 0 ) { failure_response(INTERNAL, request_error(error_msg, "")); @@ -79,11 +73,7 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList) void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList) { - int oid = xmlrpc_c::value_int(paramList.getInt(1)); - - Nebula& nd = Nebula::instance(); - aclm = nd.get_aclm(); - + int oid = xmlrpc_c::value_int(paramList.getInt(1)); string error_msg; if ( basic_authorization(-1) == false ) @@ -99,7 +89,7 @@ void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList) return; } - success_response(""); + success_response(oid); return; } @@ -109,9 +99,6 @@ void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList) void AclInfo::request_execute(xmlrpc_c::paramList const& paramList) { - Nebula& nd = Nebula::instance(); - aclm = nd.get_aclm(); - ostringstream oss; int rc; @@ -128,7 +115,7 @@ void AclInfo::request_execute(xmlrpc_c::paramList const& paramList) return; } - success_response( oss.str() ); + success_response(oss.str()); return; } From 1e9050a819acfc43f89a2bf6fc1ed562722ab099 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 4 Jul 2011 00:57:40 +0200 Subject: [PATCH 49/75] feature #687: Fix compilation for pool tests --- src/image/test/ImagePoolTest.cc | 9 +++++++- src/lcm/test/LifeCycleManagerTest.cc | 16 +++++++++++++-- src/pool/test/TestPoolSQL.h | 2 +- src/um/test/UserPoolTest.cc | 24 +++++++++++++--------- src/vm/test/SConstruct | 1 + src/vm/test/VirtualMachinePoolTest.cc | 2 +- src/vm_template/test/VMTemplatePoolTest.cc | 2 +- src/vnm/test/SConstruct | 1 + src/vnm/test/VirtualNetworkPoolTest.cc | 2 +- 9 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/image/test/ImagePoolTest.cc b/src/image/test/ImagePoolTest.cc index d7745bd474..7a59fdfa27 100644 --- a/src/image/test/ImagePoolTest.cc +++ b/src/image/test/ImagePoolTest.cc @@ -25,6 +25,10 @@ using namespace std; const int uids[] = {0,1,2}; +const char* unames[] = {"one","two","three"}; +const char* gnames[] = {"oneadmin","oneadmin","users"}; + + const string names[] = {"Image one", "Second Image", "The third image"}; const string templates[] = @@ -106,7 +110,10 @@ public: if( rc == 0 ) { - return ImagePool::allocate(uid, 1, img_template, oid, err); + string uname = unames[uid]; + string gname = gnames[uid]; + + return ImagePool::allocate(uid, 1, uname, gname, img_template, oid, err); } else { diff --git a/src/lcm/test/LifeCycleManagerTest.cc b/src/lcm/test/LifeCycleManagerTest.cc index 33ec6ea6ed..414be71a67 100644 --- a/src/lcm/test/LifeCycleManagerTest.cc +++ b/src/lcm/test/LifeCycleManagerTest.cc @@ -24,6 +24,9 @@ using namespace std; const int uids[] = {123, 261, 123}; const int gids[] = {150, 164, 175}; +const char* unames[] = {"one", "two", "three"}; +const char* gnames[] = {"oneadmin", "oneadmin", "users"}; + const string names[] = {"VM one", "Second VM", "VM 3"}; const string templates[] = @@ -186,8 +189,17 @@ private: if( rc == 0 ) { - return vmpool->allocate(uids[index], gids[index], vm_template, &oid, - err, false); + string uname = unames[index]; + string gname = gnames[index]; + + return vmpool->allocate(uids[index], + gids[index], + uname, + gname, + vm_template, + &oid, + err, + false); } else { diff --git a/src/pool/test/TestPoolSQL.h b/src/pool/test/TestPoolSQL.h index d9eac8a5c2..9dd86a041d 100644 --- a/src/pool/test/TestPoolSQL.h +++ b/src/pool/test/TestPoolSQL.h @@ -30,7 +30,7 @@ class TestObjectSQL : public PoolObjectSQL { public: //OBJECT ATTRIBUTES - TestObjectSQL(int n=-1, string t="default"):PoolObjectSQL(-1,"",0,0,0),number(n),text(t){}; + TestObjectSQL(int n=-1, string t="default"):PoolObjectSQL(-1,"",0,0,"","",0),number(n),text(t){}; ~TestObjectSQL(){}; diff --git a/src/um/test/UserPoolTest.cc b/src/um/test/UserPoolTest.cc index c90dd971cb..ad60f7e3fa 100644 --- a/src/um/test/UserPoolTest.cc +++ b/src/um/test/UserPoolTest.cc @@ -97,7 +97,7 @@ protected: int oid; string err; - return ((UserPool*)pool)->allocate(&oid, 0, usernames[index], + return ((UserPool*)pool)->allocate(&oid, 0, usernames[index],"oneadmin", passwords[index], true, err); }; @@ -187,24 +187,28 @@ public: bool rc; int oid, gid; + set groups; + string uname, gname; // There is an initial user, created with the one_auth file: // one_user_test:password string session="one_user_test:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"; - rc = user_pool->authenticate( session, oid, gid ); + rc = user_pool->authenticate( session, oid, gid, uname, gname, groups ); CPPUNIT_ASSERT( rc == true ); CPPUNIT_ASSERT( oid == 0 ); - CPPUNIT_ASSERT( oid == 0 ); + CPPUNIT_ASSERT( gid == 0 ); + CPPUNIT_ASSERT( uname == "one_user_test" ); + CPPUNIT_ASSERT( gname == "oneadmin" ); session = "one_user_test:wrong_password"; - rc = user_pool->authenticate( session, oid, gid ); + rc = user_pool->authenticate( session, oid, gid , uname, gname, groups ); CPPUNIT_ASSERT( rc == false ); CPPUNIT_ASSERT( oid == -1 ); CPPUNIT_ASSERT( gid == -1 ); session = "unknown_user:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"; - rc = user_pool->authenticate( session, oid, gid ); + rc = user_pool->authenticate( session, oid, gid, uname, gname, groups ); CPPUNIT_ASSERT( rc == false ); CPPUNIT_ASSERT( oid == -1 ); CPPUNIT_ASSERT( gid == -1 ); @@ -293,17 +297,17 @@ public: UserPool * up = static_cast(pool); // Allocate a user. - rc = up->allocate(&oid, 0,usernames[0], passwords[0], true, err); + rc = up->allocate(&oid, 0,usernames[0], "oneadmin",passwords[0], true, err); CPPUNIT_ASSERT( oid == 1 ); CPPUNIT_ASSERT( oid == rc ); // Try to allocate twice the same user, should fail - rc = up->allocate(&oid, 0,usernames[0], passwords[0], true, err); + rc = up->allocate(&oid, 0,usernames[0], "oneadmin", passwords[0], true, err); CPPUNIT_ASSERT( rc == -1 ); CPPUNIT_ASSERT( oid == rc ); // Try again, with different password - rc = up->allocate(&oid, 0, usernames[0], passwords[1], true, err); + rc = up->allocate(&oid, 0, usernames[0], "oneadmin", passwords[1], true, err); CPPUNIT_ASSERT( rc == -1 ); CPPUNIT_ASSERT( oid == rc ); } @@ -318,7 +322,7 @@ public: for(int i=0; i<5; i++) { - ((UserPool*)pool)->allocate(&oid, 0, d_names[i], d_pass[i], true, err); + ((UserPool*)pool)->allocate(&oid, 0, d_names[i], "oneadmin", d_pass[i], true, err); } ostringstream oss; @@ -345,7 +349,7 @@ public: for(int i=0; i<5; i++) { - ((UserPool*)pool)->allocate(&oid, 0, d_names[i], d_pass[i], true, err); + ((UserPool*)pool)->allocate(&oid, 0, d_names[i], "oneadmin",d_pass[i], true, err); } // Note: second parameter of dump is the WHERE constraint. The "order diff --git a/src/vm/test/SConstruct b/src/vm/test/SConstruct index 7876b88735..fe0a76e259 100644 --- a/src/vm/test/SConstruct +++ b/src/vm/test/SConstruct @@ -23,6 +23,7 @@ env.Prepend(LIBS=[ 'nebula_vnm', 'nebula_authm', 'nebula_acl', + 'nebula_group', 'nebula_template', 'nebula_pool', 'nebula_xml', diff --git a/src/vm/test/VirtualMachinePoolTest.cc b/src/vm/test/VirtualMachinePoolTest.cc index 6e636d0065..b3122614dc 100644 --- a/src/vm/test/VirtualMachinePoolTest.cc +++ b/src/vm/test/VirtualMachinePoolTest.cc @@ -105,7 +105,7 @@ public: if( rc == 0 ) { - return VirtualMachinePool::allocate(uid, 1, vm_template, + return VirtualMachinePool::allocate(uid, 1, "the_user", "users",vm_template, oid, err, on_hold); } else diff --git a/src/vm_template/test/VMTemplatePoolTest.cc b/src/vm_template/test/VMTemplatePoolTest.cc index b70ff0b4a8..e6a8921888 100644 --- a/src/vm_template/test/VMTemplatePoolTest.cc +++ b/src/vm_template/test/VMTemplatePoolTest.cc @@ -78,7 +78,7 @@ public: if( rc == 0 ) { - return VMTemplatePool::allocate(uid, 0,template_contents, oid, err); + return VMTemplatePool::allocate(uid, 0,"the_user","oneadmin",template_contents, oid, err); } else { diff --git a/src/vnm/test/SConstruct b/src/vnm/test/SConstruct index d645885a0b..0854a0e939 100644 --- a/src/vnm/test/SConstruct +++ b/src/vnm/test/SConstruct @@ -22,6 +22,7 @@ env.Prepend(LIBS=[ 'nebula_vnm', 'nebula_authm', 'nebula_acl', + 'nebula_group', 'nebula_template', 'nebula_pool', 'nebula_xml', diff --git a/src/vnm/test/VirtualNetworkPoolTest.cc b/src/vnm/test/VirtualNetworkPoolTest.cc index 05e7227242..ef14d38149 100644 --- a/src/vnm/test/VirtualNetworkPoolTest.cc +++ b/src/vnm/test/VirtualNetworkPoolTest.cc @@ -111,7 +111,7 @@ public: if( rc == 0 ) { - return VirtualNetworkPool::allocate(uid, 0, vn_template, oid, err); + return VirtualNetworkPool::allocate(uid, 0,"the_user","oneadmin", vn_template, oid, err); } else { From 655d9f4a297b2dae5c495795d20d7c27caf79a3e Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 4 Jul 2011 01:28:07 +0200 Subject: [PATCH 50/75] feature #687: Fixes tests after UNAME/GNAME elements were added --- src/image/test/ImagePoolTest.cc | 11 +++++------ src/um/test/UserPoolTest.cc | 4 ++-- src/vm/test/VirtualMachinePoolTest.cc | 20 ++++++++++---------- src/vnm/test/VirtualNetworkPoolTest.cc | 14 +++++++------- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/image/test/ImagePoolTest.cc b/src/image/test/ImagePoolTest.cc index 7a59fdfa27..c190a08f1d 100644 --- a/src/image/test/ImagePoolTest.cc +++ b/src/image/test/ImagePoolTest.cc @@ -53,20 +53,19 @@ const string templates[] = const string xmls[] = { - "001Image one0010000000000-40", + "001oneoneadminImage one0010000000000-40", - "111Second Image0100000000000-40", + "111twooneadminSecond Image0100000000000-40", - "021The third image0000000000000-40" + "021threeusersThe third image0000000000000-40" }; // This xml dump result has the STIMEs modified to 0000000000 const string xml_dump = -"001Image one0010000000000-40111Second Image0100000000000-40221The third image0000000000000-40"; +"001oneoneadminImage one0010000000000-40111twooneadminSecond Image0100000000000-40221threeusersThe third image0000000000000-40"; const string xml_dump_where = -"001Image one0010000000000-40111Second Image0100000000000-40"; - +"001oneoneadminImage one0010000000000-40111twooneadminSecond Image0100000000000-40"; /* ************************************************************************* */ /* ************************************************************************* */ diff --git a/src/um/test/UserPoolTest.cc b/src/um/test/UserPoolTest.cc index ad60f7e3fa..344b9eb2f2 100644 --- a/src/um/test/UserPoolTest.cc +++ b/src/um/test/UserPoolTest.cc @@ -31,10 +31,10 @@ const string usernames[] = { "A user", "B user", "C user", "D user", "E user" }; const string passwords[] = { "A pass", "B pass", "C pass", "D pass", "E pass" }; const string dump_result = - "00one_user_test5baa61e4c9b93f3f0682250b6cf8331b7ee68fd81010ap1020a namepass1030a_namepassword1040another namesecret1050user123410"; + "00oneadminone_user_test5baa61e4c9b93f3f0682250b6cf8331b7ee68fd81010oneadminap1020oneadmina namepass1030oneadmina_namepassword1040oneadminanother namesecret1050oneadminuser123410"; const string dump_where_result = - "10ap1020a namepass1030a_namepassword1040another namesecret10"; + "10oneadminap1020oneadmina namepass1030oneadmina_namepassword1040oneadminanother namesecret10"; #include "NebulaTest.h" diff --git a/src/vm/test/VirtualMachinePoolTest.cc b/src/vm/test/VirtualMachinePoolTest.cc index b3122614dc..5bcd6c1e7d 100644 --- a/src/vm/test/VirtualMachinePoolTest.cc +++ b/src/vm/test/VirtualMachinePoolTest.cc @@ -46,21 +46,21 @@ const string templates[] = const string xmls[] = { - "01231VM one001231the_userusersVM one010000000000000000", - "12611Second VM0" + "12611the_userusersSecond VM0" "1000000000000<" "/ETIME>0000", - "01231VM one001231the_userusersVM one010000000000000000