1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-10 01:17:40 +03:00

Feature #2653: Add zone id to each ACL rule

This commit is contained in:
Carlos Martín 2014-01-21 12:52:25 +01:00
parent 16915c4326
commit cf31d91abd
13 changed files with 250 additions and 38 deletions

View File

@ -74,6 +74,7 @@ public:
* @param user 64 bit ID and flags
* @param resource 64 bit ID and flags
* @param rights 64 bit flags
* @param zone 64 bit flags
* @param error_str Returns the error reason, if any
*
* @return the oid assigned to the rule on success,
@ -84,6 +85,7 @@ public:
virtual int add_rule(long long user,
long long resource,
long long rights,
long long zone,
string& error_str);
/**
* Deletes a rule from the ACL rule set
@ -100,6 +102,7 @@ public:
* @param user 64 bit ID and flags
* @param resource 64 bit ID and flags
* @param rights 64 bit flags
* @param zone 64 bit flags
*
* @param error_str Returns the error reason, if any
* @return 0 on success
@ -107,6 +110,7 @@ public:
virtual int del_rule(long long user,
long long resource,
long long rights,
long long zone,
string& error_str);
/**
@ -271,6 +275,13 @@ private:
long long resource_req,
long long resource_mask);
// TODO
int get_zone_id() const
{
return 10;
};
// ----------------------------------------
// Mutex synchronization
// ----------------------------------------

View File

@ -47,7 +47,7 @@ public:
/**
* Creates an empty ACL rule
*/
AclRule():oid(0), user(0), resource(0), rights(0), str("") {};
AclRule():oid(0), user(0), resource(0), rights(0), zone(0), str("") {};
/**
* Main ACL rule constructor
@ -55,8 +55,10 @@ public:
AclRule(int _oid,
long long _user,
long long _resource,
long long _rights):
oid(_oid), user(_user), resource(_resource), rights(_rights)
long long _rights,
long long _zone):
oid(_oid), user(_user), resource(_resource),
rights(_rights), zone(_zone)
{
build_str();
};
@ -64,16 +66,17 @@ public:
/**
* Set the fields of the ACL, and updates its representation
*/
void set(int _oid,
long long _user,
long long _resource,
long long _rights)
long long _rights,
long long _zone)
{
oid = _oid;
user = _user;
resource = _resource;
rights = _rights;
zone = _zone;
build_str();
};
@ -85,7 +88,8 @@ public:
{
return (user == other.user &&
resource == other.resource &&
rights == other.rights);
rights == other.rights &&
zone == other.zone);
};
/**
@ -164,6 +168,16 @@ public:
return resource & 0xFFFFFFFF00000000LL;
};
/**
* Returns the 32 less significant bits of the zone long long attribute
*
* @return the zone ID
*/
int zone_id() const
{
return zone;
};
// ------------------------------------------------------------------------
// Functions needed by the Scheduler ACL engine
// ------------------------------------------------------------------------
@ -220,6 +234,16 @@ private:
*/
long long rights;
/**
* 64 bit integer holding a zone compound:
*
* 32 bits 32 bits
* +-----------------------+-----------------------+
* | Type (individual,all) | zone ID |
* +-----------------------+-----------------------+
*/
long long zone;
/**
* Human readable representation of the rule
*/

View File

@ -357,6 +357,12 @@ public:
return hostname;
};
// TODO
int get_zone_id()
{
return 10;
};
/**
* Returns the version of oned
* @return the version

View File

@ -25,10 +25,11 @@
const char * AclManager::table = "acl";
const char * AclManager::db_names = "oid, user, resource, rights";
const char * AclManager::db_names = "oid, user, resource, rights, zone";
const char * AclManager::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
"acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, rights BIGINT)";
"acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, "
"rights BIGINT, zone BIGINT)";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -77,6 +78,7 @@ AclManager::AclManager(SqlDB * _db) : db(_db), lastOID(-1)
PoolObjectSQL::IMAGE |
PoolObjectSQL::TEMPLATE,
AuthRequest::CREATE,
AclRule::ALL_ID,
error_str);
// Users in USERS can deploy VMs in any HOST
@ -86,12 +88,14 @@ AclManager::AclManager(SqlDB * _db) : db(_db), lastOID(-1)
AclRule::ALL_ID |
PoolObjectSQL::HOST,
AuthRequest::MANAGE,
AclRule::ALL_ID,
error_str);
add_rule(AclRule::ALL_ID,
AclRule::ALL_ID |
PoolObjectSQL::DOCUMENT,
AuthRequest::CREATE,
AclRule::ALL_ID,
error_str);
}
@ -219,7 +223,8 @@ const bool AclManager::authorize(
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req);
rights_req,
AclRule::INDIVIDUAL_ID | get_zone_id());
oss << "Request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
@ -389,6 +394,10 @@ bool AclManager::match_rules(
pair<multimap<long long, AclRule *>::iterator,
multimap<long long, AclRule *>::iterator> index;
long long zone_oid_mask = AclRule::INDIVIDUAL_ID | 0x00000000FFFFFFFFLL;
long long zone_req = AclRule::INDIVIDUAL_ID | get_zone_id();
long long zone_all_req = AclRule::ALL_ID;
index = rules.equal_range( user_req );
for ( it = index.first; it != index.second; it++)
@ -398,6 +407,14 @@ bool AclManager::match_rules(
NebulaLog::log("ACL",Log::DDEBUG,oss);
auth =
(
// Rule applies in any Zone
( ( it->second->zone & zone_all_req ) == zone_all_req )
||
// Rule applies in this Zone
( ( it->second->zone & zone_oid_mask ) == zone_req )
)
&&
// Rule grants the requested rights
( ( it->second->rights & rights_req ) == rights_req )
&&
@ -431,7 +448,7 @@ bool AclManager::match_rules(
/* -------------------------------------------------------------------------- */
int AclManager::add_rule(long long user, long long resource, long long rights,
string& error_str)
long long zone, string& error_str)
{
lock();
@ -440,7 +457,7 @@ int AclManager::add_rule(long long user, long long resource, long long rights,
lastOID = -1;
}
AclRule * rule = new AclRule(++lastOID, user, resource, rights);
AclRule * rule = new AclRule(++lastOID, user, resource, rights, zone);
ostringstream oss;
int rc;
@ -604,11 +621,12 @@ int AclManager::del_rule(
long long user,
long long resource,
long long rights,
long long zone,
string& error_str)
{
lock();
AclRule * rule = new AclRule(-1, user, resource, rights);
AclRule * rule = new AclRule(-1, user, resource, rights, zone);
int oid = -1;
bool found = false;
@ -796,6 +814,10 @@ void AclManager::reverse_search(int uid,
long long resource_cid_mask =
( obj_type | AclRule::CLUSTER_ID );
long long zone_oid_req =
AclRule::INDIVIDUAL_ID | get_zone_id();
long long zone_all_req = AclRule::ALL_ID;
// Create a temporal rule, to log the request
long long log_resource;
@ -805,7 +827,8 @@ void AclManager::reverse_search(int uid,
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req);
rights_req,
zone_oid_req);
oss << "Reverse search request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
@ -841,8 +864,15 @@ void AclManager::reverse_search(int uid,
for ( it = index.first; it != index.second; it++)
{
// Rule grants the requested rights
if ( ( it->second->rights & rights_req ) == rights_req )
// Rule grants the requested rights
if ( ( ( it->second->rights & rights_req ) == rights_req )
&&
// Rule applies in this zone or in all zones
( ( it->second->zone == zone_oid_req )
||
( it->second->zone == zone_all_req )
)
)
{
oss.str("");
oss << "> Rule " << it->second->to_str();
@ -919,11 +949,12 @@ void AclManager::update_lastOID()
int AclManager::select_cb(void *nil, int num, char **values, char **names)
{
if ( (num != 4) ||
if ( (num != 5) ||
(!values[0]) ||
(!values[1]) ||
(!values[2]) ||
(!values[3]) )
(!values[3]) ||
(!values[4]) )
{
return -1;
}
@ -935,7 +966,7 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names)
long long rule_values[3];
for ( int i = 0; i < 3; i++ )
for ( int i = 0; i < 4; i++ )
{
iss.str( values[i+1] );
@ -952,7 +983,8 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names)
AclRule * rule = new AclRule(oid,
rule_values[0],
rule_values[1],
rule_values[2]);
rule_values[2],
rule_values[3]);
oss << "Loading ACL Rule " << rule->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
@ -996,7 +1028,8 @@ int AclManager::insert(AclRule * rule, SqlDB * db)
<< rule->oid << ","
<< rule->user << ","
<< rule->resource << ","
<< rule->rights << ")";
<< rule->rights << ","
<< rule->zone << ")";
rc = db->exec(oss);

View File

@ -240,6 +240,59 @@ bool AclRule::malformed(string& error_str) const
oss << "wrong [rights], it cannot be bigger than 0xF";
}
// Check zone
if ( (zone & GROUP_ID) != 0 )
{
error = true;
oss << "[zone] GROUP (@) bit is not supported";
}
if ( (zone & INDIVIDUAL_ID) != 0 && (zone & ALL_ID) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[zone] INDIVIDUAL (#) and ALL (*) bits are exclusive";
}
if ( (zone & 0x700000000LL) == 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[zone] is missing one of the INDIVIDUAL or ALL bits";
}
if ( zone_id() < 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[zone] ID cannot be negative";
}
if ( (zone & ALL_ID) != 0 && zone_id() != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "when using the ALL bit, [zone] ID must be 0";
}
if ( error )
{
error_str = oss.str();
@ -331,6 +384,21 @@ void AclRule::build_str()
}
}
oss << " ";
if ( (zone & INDIVIDUAL_ID) != 0 )
{
oss << "#" << zone_id();
}
else if ( (zone & ALL_ID) != 0 )
{
oss << "*";
}
else
{
oss << "??";
}
str = oss.str();
}
@ -347,6 +415,7 @@ string& AclRule::to_xml(string& xml) const
"<USER>" << hex << user << "</USER>" <<
"<RESOURCE>" << hex << resource << "</RESOURCE>" <<
"<RIGHTS>" << hex << rights << "</RIGHTS>" <<
"<ZONE>" << hex << zone << "</ZONE>" <<
"<STRING>" << str << "</STRING>" <<
"</ACL>";
@ -397,6 +466,10 @@ int AclRule::from_xml(xmlNodePtr node)
{
iss >> hex >> rights;
}
else if (name == "ZONE")
{
iss >> hex >> zone;
}
else if (name == "STRING")
{
str = iss.str();

View File

@ -18,6 +18,11 @@
:size: 5
:right: true
:ZONE:
:desc: Zone ID
:size: 5
:right: true
:OPE_UMAC:
:desc: Operation to which the rule applies
:size: 8
@ -28,4 +33,5 @@
- :USER
- :RES_VHNIUTGDCO
- :RID
- :ZONE
- :OPE_UMAC

View File

@ -116,12 +116,16 @@ private
d['STRING'].split(" ")[1].split("/")[1]
end
column :ZONE, "Zone ID", :right, :size=>5 do |d|
d['STRING'].split(" ")[3]
end
column :OPE_UMAC,
"Operation to which the rule applies", :size =>8 do |d|
OneAclHelper::right_mask d['STRING'].split(" ")[2]
end
default :ID, :USER, :RES_VHNIUTGDCO, :RID, :OPE_UMAC
default :ID, :USER, :RES_VHNIUTGDCO, :RID, :ZONE, :OPE_UMAC
end
table

View File

@ -69,10 +69,10 @@ cmd = CommandParser::CmdParser.new(ARGV) do
if OpenNebula.is_error?(new_args)
next -1, new_args.message
end
when 3
when 3, 4
new_args=args
else
next -1, "Wrong number of arguments, must be 1 or 3"
next -1, "Wrong number of arguments, must be 1 or 4"
end
helper.create_resource(options) do |rule|

View File

@ -99,14 +99,24 @@ module OpenNebula
# A string containing a hex number, e.g. 0x2100000001
# @param rights [String]
# A string containing a hex number, e.g. 0x10
# @param zone [String]
# A string containing a hex number, e.g. 0x100000001
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def allocate(user, resource, rights)
return super( AclPool::ACL_POOL_METHODS[:addrule],
user,
resource,
rights )
def allocate(user, resource, rights, zone=nil)
if !zone.nil?
return super( AclPool::ACL_POOL_METHODS[:addrule],
user,
resource,
rights,
zone )
else
return super( AclPool::ACL_POOL_METHODS[:addrule],
user,
resource,
rights)
end
end
# Deletes the Acl rule
@ -138,7 +148,7 @@ module OpenNebula
rule_str = rule_str.split(" ")
if rule_str.length != 3
if rule_str.length != 3 && rule_str.length != 4
return OpenNebula::Error.new(
"String needs three components: User, Resource, Rights")
end
@ -147,6 +157,10 @@ module OpenNebula
ret << parse_resources(rule_str[1])
ret << parse_rights(rule_str[2])
if rule_str.length > 3
ret << parse_zone(rule_str[3])
end
errors=ret.map do |arg|
if OpenNebula.is_error?(arg)
arg.message
@ -230,6 +244,19 @@ private
end
end
# Converts a string in the form [#<id>, *] to a hex. number
#
# @param zone [String] Zone component string
#
# @return [String] A string containing a hex number
def self.parse_zone(zone)
begin
return calculate_ids(zone).to_i.to_s(16)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
end
# Calculates the numeric value for a String containing an individual
# (#<id>), group (@<id>) or all (*) ID component
#

View File

@ -22,12 +22,16 @@ void PoolObjectAuth::get_acl_rules(AclRule& owner_rule,
AclRule& group_rule,
AclRule& other_rule) const
{
long long perm_user, perm_resource, perm_rights;
long long perm_user, perm_resource, perm_rights, perm_zone;
perm_resource = obj_type | AclRule::INDIVIDUAL_ID | oid;
// TODO
//perm_zone = AclRule::INDIVIDUAL_ID | Nebula::instance().get_zone_id();
perm_zone = AclRule::INDIVIDUAL_ID | 10;
// -------------------------------------------------------------------------
// Rule "#uid ob_type/#oid user_rights"
// Rule "#uid ob_type/#oid user_rights #zone"
// -------------------------------------------------------------------------
perm_user = AclRule::INDIVIDUAL_ID | uid;
@ -48,7 +52,7 @@ void PoolObjectAuth::get_acl_rules(AclRule& owner_rule,
perm_rights = perm_rights | AuthRequest::ADMIN;
}
owner_rule.set(0, perm_user, perm_resource, perm_rights);
owner_rule.set(0, perm_user, perm_resource, perm_rights, perm_zone);
// -------------------------------------------------------------------------
// Rule "@gid ob_type/#oid group_rights"
@ -72,7 +76,7 @@ void PoolObjectAuth::get_acl_rules(AclRule& owner_rule,
perm_rights = perm_rights | AuthRequest::ADMIN;
}
group_rule.set(0, perm_user, perm_resource, perm_rights);
group_rule.set(0, perm_user, perm_resource, perm_rights, perm_zone);
// -------------------------------------------------------------------------
// Rule "* ob_type/#oid others_rights"
@ -96,6 +100,6 @@ void PoolObjectAuth::get_acl_rules(AclRule& owner_rule,
perm_rights = perm_rights | AuthRequest::ADMIN;
}
other_rule.set(0, perm_user, perm_resource, perm_rights);
other_rule.set(0, perm_user, perm_resource, perm_rights, perm_zone);
};

View File

@ -35,6 +35,7 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList,
long long user;
long long resource;
long long rights;
long long zone;
istringstream iss;
@ -49,6 +50,17 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList,
iss.str( xmlrpc_c::value_string(paramList.getString(3)) );
iss >> hex >> rights;
if ( paramList.size() > 4 )
{
iss.clear();
iss.str( xmlrpc_c::value_string(paramList.getString(4)) );
iss >> hex >> zone;
}
else
{
zone = AclRule::INDIVIDUAL_ID | Nebula::instance().get_zone_id();
}
string error_msg;
if ( basic_authorization(-1, att) == false )
@ -56,7 +68,7 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList,
return;
}
int rc = aclm->add_rule(user, resource, rights, error_msg);
int rc = aclm->add_rule(user, resource, rights, zone, error_msg);
if ( rc < 0 )
{

View File

@ -218,6 +218,9 @@ int GroupAddProvider::edit_acl_rules(
AuthRequest::MANAGE,
AclRule::INDIVIDUAL_ID |
zone_id,
error_msg);
// @<gid> DATASTORE+NET/%<cid> USE
@ -231,6 +234,9 @@ int GroupAddProvider::edit_acl_rules(
AuthRequest::USE,
AclRule::INDIVIDUAL_ID |
zone_id,
error_msg);
if (rc != 0)
@ -269,7 +275,7 @@ int GroupDelProvider::edit_acl_rules(
mask_prefix = AclRule::CLUSTER_ID | cluster_id;
}
// @<gid> HOST/%<cid> MANAGE
// @<gid> HOST/%<cid> MANAGE #<zid>
rc += aclm->del_rule(
AclRule::GROUP_ID |
group_id,
@ -279,9 +285,12 @@ int GroupDelProvider::edit_acl_rules(
AuthRequest::MANAGE,
AclRule::INDIVIDUAL_ID |
zone_id,
error_msg);
// @<gid> DATASTORE+NET/%<cid> USE
// @<gid> DATASTORE+NET/%<cid> USE #<zid>
rc += aclm->del_rule(
AclRule::GROUP_ID |
group_id,
@ -292,6 +301,9 @@ int GroupDelProvider::edit_acl_rules(
AuthRequest::USE,
AclRule::INDIVIDUAL_ID |
zone_id,
error_msg);
if (rc != 0)

View File

@ -81,7 +81,7 @@ int AclXML::load_rules(const string& xml_str)
for (it = rules.begin(); it != rules.end() ; it++)
{
AclRule * rule = new AclRule(0,0,0,0);
AclRule * rule = new AclRule(0,0,0,0,0);
int rc = rule->from_xml(*it);
if ( rc == 0 )