1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

Merge branch 'feature-687' of git.opennebula.org:one into feature-687

This commit is contained in:
Carlos Martín 2011-07-05 19:28:42 +02:00
commit fa2477a79f
17 changed files with 341 additions and 105 deletions

View File

@ -32,7 +32,12 @@ class AclManager : public Callbackable
public:
AclManager(SqlDB * _db);
~AclManager();
AclManager():db(0),lastOID(0)
{
pthread_mutex_init(&mutex, 0);
};
virtual ~AclManager();
/**
* Loads the ACL rule set from the DB
@ -75,10 +80,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);
virtual int add_rule(long long user,
long long resource,
long long rights,
string& error_str);
/**
* Deletes a rule from the ACL rule set
*
@ -86,7 +91,7 @@ public:
* @param error_str Returns the error reason, if any
* @return 0 on success
*/
int del_rule(int oid, string& error_str);
virtual int del_rule(int oid, string& error_str);
/* ---------------------------------------------------------------------- */
/* DB management */
@ -102,9 +107,9 @@ public:
* @param oss The output stream to dump the rule set contents
* @return 0 on success
*/
int dump(ostringstream& oss);
virtual int dump(ostringstream& oss);
private:
protected:
// ----------------------------------------
// ACL rules management
@ -121,6 +126,8 @@ private:
*/
map<int, AclRule *> acl_rules_oids;
private:
/**
* Gets all rules that apply to the user_req and, if any of them grants
* permission, returns true.

View File

@ -19,6 +19,7 @@
#include <set>
#include <string>
#include <libxml/tree.h>
using namespace std;
@ -83,11 +84,10 @@ public:
/**
* Rebuilds the rule from an xml formatted string
*
* @param xml_str The xml-formatted string
*
* @param node xml node for the ACL rule
* @return 0 on success, -1 otherwise
*/
int from_xml(const string &xml_str);
int from_xml(xmlNodePtr node);
/**
* Returns the 32 less significant bits of the user long long attribute
@ -131,6 +131,20 @@ public:
return resource & 0xFFFFFFFF00000000LL;
};
// ------------------------------------------------------------------------
// Functions needed by the Scheduler ACL engine
// ------------------------------------------------------------------------
long long get_user() const
{
return user;
}
long long get_oid() const
{
return oid;
}
private:
// NONE_ID can never be used in a rule. It is useful to create masks that
// will never match any existing rule

View File

@ -94,20 +94,6 @@ 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

View File

@ -340,7 +340,6 @@ int AclManager::add_rule(long long user, long long resource, long long rights,
goto error_malformed;
}
rc = insert(rule);
if ( rc != 0 )

View File

@ -350,27 +350,54 @@ string& AclRule::to_xml(string& xml) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclRule::from_xml(const string &xml_str)
int AclRule::from_xml(xmlNodePtr node)
{
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) )
for (xmlNodePtr acl = node->children ; acl != 0 ; acl = acl->next)
{
return -1;
if ( acl->type != XML_ELEMENT_NODE )
{
rc = -1;
break;
}
xmlNodePtr elem = acl->children;
if ( elem->type != XML_TEXT_NODE )
{
rc = -1;
break;
}
string name = reinterpret_cast<const char*>(acl->name);
istringstream iss(reinterpret_cast<const char*>(elem->content));
if (name == "ID")
{
iss >> oid;
}
else if (name == "USER")
{
iss >> hex >> user;
}
else if (name == "RESOURCE")
{
iss >> hex >> resource;
}
else if (name == "RIGHTS")
{
iss >> hex >> rights;
}
else if (name == "STRING")
{
str = iss.str();
}
}
return 0;
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -35,10 +35,10 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
end
if OpenNebula.is_error?(rc)
[-1, rc.message]
return [-1, rc.message]
else
if !rc
puts "Rule added" if options[:verbose]
if rc.class == Fixnum
puts "Rule added with ID #{rc}" if options[:verbose]
return 0
end
return [-1, rc[:users].message] if OpenNebula.is_error?(rc[:users])

View File

@ -54,7 +54,7 @@ cmd = CommandParser::CmdParser.new(ARGV) do
Adds a new ACL rule
EOT
command :addrule, addrule_desc, [:user,:rulestr], [:resource, nil], [:rights, nil] do
command :create, addrule_desc, [:user,:rulestr], [:resource, nil], [:rights, nil] do
helper.add_rule(options, args[0], args[1], args[2] )
end
@ -62,7 +62,7 @@ cmd = CommandParser::CmdParser.new(ARGV) do
Deletes an existing ACL rule
EOT
command :delrule, delrule_desc, :id do
command :delete, delrule_desc, :id do
helper.delete_rule( options, args[0] )
end

View File

@ -111,7 +111,9 @@ module OpenNebula
end
resources[0].split("+").each{ |resource|
next if !RESOURCES[resource.upcase]
if !RESOURCES[resource.upcase]
raise "Resource #{resource} malformed."
end
@content[:resources] += RESOURCES[resource.upcase]
}
@ -127,7 +129,7 @@ module OpenNebula
rights = rights.split("+")
rights.each{ |right|
next if !RIGHTS[right.upcase]
raise "Right #{right} malformed." if !RIGHTS[right.upcase]
@content[:rights] += RIGHTS[right.upcase]
}

View File

@ -56,14 +56,10 @@ module OpenNebula
# +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],
return @client.call( ACL_POOL_METHODS[:addrule],
user,
resource,
rights )
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
# Adds a new ACL rule.

View File

@ -0,0 +1,83 @@
/* -------------------------------------------------------------------------- */
/* 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_XML_H_
#define ACL_XML_H_
#include "AclManager.h"
#include "Client.h"
using namespace std;
/**
* This class manages the ACL rules and the authorization engine
*/
class AclXML : public AclManager
{
public:
AclXML(Client * _client):AclManager(), client(_client){};
virtual ~AclXML(){};
/**
* Loads the ACL rule set from the DB
* @return 0 on success.
*/
int set_up();
private:
/* ---------------------------------------------------------------------- */
/* Re-implement DB public functions not used in scheduler */
/* ---------------------------------------------------------------------- */
int start()
{
return -1;
}
int add_rule(long long user,
long long resource,
long long rights,
string& error_str)
{
return -1;
};
int del_rule(int oid, string& error_str)
{
return -1;
};
int dump(ostringstream& oss)
{
return -1;
};
Client * client;
/**
* Loads the ACL rule set from its XML representation:
* as obtained by a dump call
*
* @param xml_str string with the XML document for the ACL
* @return 0 on success.
*/
int load_rules(const string& xml_str);
void flush_rules();
};
#endif /*ACL_XML_H*/

View File

@ -23,6 +23,7 @@
#include "VirtualMachinePoolXML.h"
#include "SchedulerPolicy.h"
#include "ActionManager.h"
#include "AclXML.h"
using namespace std;
@ -50,6 +51,7 @@ protected:
hpool(0),
vmpool(0),
upool(0),
acls(0),
timer(_timer),
url(_url),
machines_limit(_machines_limit),
@ -78,6 +80,11 @@ protected:
delete upool;
}
if ( acls != 0)
{
delete acls;
}
if ( client != 0)
{
delete client;
@ -91,6 +98,7 @@ protected:
HostPoolXML * hpool;
VirtualMachinePoolXML * vmpool;
UserPoolXML * upool;
AclXML * acls;
// ---------------------------------------------------------------
// Scheduler Policies

View File

@ -41,7 +41,12 @@ public:
return oid;
};
set<int> get_groups()
int get_gid()
{
return gid;
};
const set<int>& get_groups()
{
return group_ids;
};

View File

@ -0,0 +1,114 @@
/* -------------------------------------------------------------------------- */
/* 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 "AclXML.h"
#include "ObjectXML.h"
#include <vector>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclXML::set_up()
{
xmlrpc_c::value result;
try
{
client->call(client->get_endpoint(), // serverUrl
"one.acl.info", // methodName
"s", // arguments format
&result, // resultP
client->get_oneauth().c_str());// argument
vector<xmlrpc_c::value> values =
xmlrpc_c::value_array(result).vectorValueValue();
bool success = xmlrpc_c::value_boolean(values[0]);
string message = xmlrpc_c::value_string(values[1]);
if( !success )
{
ostringstream oss;
oss << "ONE returned error while retrieving the acls:" << endl;
oss << message;
NebulaLog::log("ACL", Log::ERROR, oss);
return -1;
}
flush_rules();
load_rules(message);
return 0;
}
catch (exception const& e)
{
ostringstream oss;
oss << "Exception raised: " << e.what();
NebulaLog::log("ACL", Log::ERROR, oss);
return -1;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclXML::load_rules(const string& xml_str)
{
ObjectXML acl_xml(xml_str);
vector<xmlNodePtr> rules;
vector<xmlNodePtr>::iterator it;
acl_xml.get_nodes("/ACL_POOL/ACL",rules);
for (it = rules.begin(); it != rules.end() ; it++)
{
AclRule * rule = new AclRule(0,0,0,0);
int rc = rule->from_xml(*it);
if ( rc == 0 )
{
acl_rules.insert( make_pair(rule->get_user(), rule) );
acl_rules_oids.insert( make_pair(rule->get_oid(), rule) );
}
}
acl_xml.free_nodes(rules);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclXML::flush_rules()
{
multimap<long long, AclRule *>::iterator it;
for ( it = acl_rules.begin(); it != acl_rules.end(); it++ )
{
delete it->second;
}
acl_rules.clear();
acl_rules_oids.clear();
}

View File

@ -21,6 +21,7 @@ Import('sched_env')
lib_name='scheduler_pool'
source_files=[
'AclXML.cc',
'UserPoolXML.cc',
'UserXML.cc',
'HostPoolXML.cc',

View File

@ -32,6 +32,7 @@ sched_env.Prepend(LIBS=[
'scheduler_pool',
'nebula_log',
'scheduler_client',
'nebula_acl',
'nebula_xml',
'nebula_common',
'crypto',

View File

@ -122,6 +122,7 @@ void Scheduler::start()
hpool = new HostPoolXML(client);
vmpool = new VirtualMachinePoolXML(client, machines_limit);
upool = new UserPoolXML(client);
acls = new AclXML(client);
// -----------------------------------------------------------
// Load scheduler policies
@ -244,9 +245,12 @@ int Scheduler::set_up_pools()
//Cleans the cache and get the ACLs
//--------------------------------------------------------------------------
//TODO
// 1.- one.acl.list
// 2.- from_xml
rc = acls->set_up();
if ( rc != 0 )
{
return rc;
}
//--------------------------------------------------------------------------
//Get the matching hosts for each VM
@ -326,11 +330,17 @@ void Scheduler::match()
if ( matched == false )
{
ostringstream oss;
oss << "Host " << host->get_hid() <<
" filtered out. It does not fullfil REQUIREMENTS.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
continue;
}
// -----------------------------------------------------------------
// Check host capacity
// Check if user is authorized
// -----------------------------------------------------------------
user = upool->get(uid);
@ -338,21 +348,35 @@ void Scheduler::match()
if ( user != 0 )
{
set<int> 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
const set<int> groups = user->get_groups();
if ( uid == 0 || user->get_gid() == 0 )
{
matched = true;
}
else
{
matched = acls->authorize(uid,
groups,
AuthRequest::HOST,
host->get_hid(),
-1,
AuthRequest::USE);
}
}
else
{
//TODO Log debug info (user not authorized)?
continue;
}
if ( matched == false )
{
ostringstream oss;
oss << "Host " << host->get_hid() <<
" filtered out. User is not authorized to use it.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
continue;
}
// -----------------------------------------------------------------
@ -370,6 +394,16 @@ void Scheduler::match()
vm->add_host(host->get_hid());
}
}
else
{
ostringstream oss;
oss << "Host " << host->get_hid() <<
" filtered out. It does not have enough capacity.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
}
}
}
}

View File

@ -222,47 +222,6 @@ 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<string> 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;