mirror of
https://github.com/OpenNebula/one.git
synced 2025-02-22 17:57:46 +03:00
Feature #687: Add DB persistence to ACL rules
This commit is contained in:
parent
94d1615e58
commit
c1a0fa6f7d
@ -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<int> &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<long long, AclRule*> 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<long long, AclRule*> 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*/
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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<long long, AclRule *>::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<long long, AclRule *>::iterator it;
|
||||
pair<multimap<long long, AclRule *>::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<long long, AclRule *>::iterator it;
|
||||
pair<multimap<long long, AclRule *>::iterator,
|
||||
multimap<long long, AclRule *>::iterator> index;
|
||||
multimap<long long, AclRule *>::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<Callbackable::Callback>(&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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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 <<
|
||||
"<RULE>"
|
||||
"<USER>" << hex << user << "</USER>" <<
|
||||
"<RESOURCE>" << hex << resource << "</RESOURCE>" <<
|
||||
"<RIGHTS>" << hex << rights << "</RIGHTS>" <<
|
||||
"<USER>" << hex << user << "</USER>" <<
|
||||
"<RESOURCE>" << hex << resource << "</RESOURCE>" <<
|
||||
"<RIGHTS>" << hex << rights << "</RIGHTS>" <<
|
||||
|
||||
// TODO: Element DEBUG contains a human friendly string
|
||||
"<DEBUG>" << to_str() << "</DEBUG>" <<
|
||||
|
||||
"</RULE>";
|
||||
// TODO: Element DEBUG contains a human friendly string
|
||||
"<DEBUG>" << to_str() << "</DEBUG>" <<
|
||||
"</RULE>";
|
||||
|
||||
xml = oss.str();
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user