mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-30 22:50:10 +03:00
Feature #687: Add oid to ACL Rules, one.acl.delrule now expects that ID. Modify XML to look similar to a pool
This commit is contained in:
parent
3543b4c209
commit
165a8fb74b
@ -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<long long, AclRule*> acl_rules;
|
||||
|
||||
/**
|
||||
* Rules indexed by oid. Stores the same rules as acl_rules
|
||||
*/
|
||||
map<int, AclRule *> 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*/
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -14,6 +14,8 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include <climits>
|
||||
|
||||
#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<Callbackable::Callback> (&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<int> &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<long long, AclRule *>::iterator it;
|
||||
pair<multimap<long long, AclRule *>::iterator,
|
||||
multimap<long long, AclRule *>::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<long long, AclRule *>::iterator it;
|
||||
map<int, AclRule *>::iterator it;
|
||||
string xml;
|
||||
|
||||
oss << "<ACL>";
|
||||
oss << "<ACL_POOL>";
|
||||
|
||||
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 << "</ACL>";
|
||||
oss << "</ACL_POOL>";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -276,12 +276,13 @@ string& AclRule::to_xml(string& xml) const
|
||||
ostringstream oss;
|
||||
|
||||
oss <<
|
||||
"<RULE>"
|
||||
"<ACL>"
|
||||
"<ID>" << oid << "</ID>" <<
|
||||
"<USER>" << hex << user << "</USER>" <<
|
||||
"<RESOURCE>" << hex << resource << "</RESOURCE>" <<
|
||||
"<RIGHTS>" << hex << rights << "</RIGHTS>" <<
|
||||
"<STRING>" << str << "</STRING>" <<
|
||||
"</RULE>";
|
||||
"</ACL>";
|
||||
|
||||
xml = oss.str();
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user