Creating User Roles for ACEs
A role is a label attached to a set of users, which defines a common task, or set of
behaviors for those users. Roles enable you to use functionality similar to Unix groups for
your users, without requiring you to alter the existing group hierarchy of your system.
Role names can be up to 64 characters long, and cannot use the :
,
&
, |
, or !
characters.
Standard Reference Implementation
User InformationThe standard reference implementation is a library called
libmapr_roles_refimpl.so
. This library is located at
/opt/mapr/server/permissions
. This library opens a configuration
file named m7_permissions_roles_refimpl.conf
, which should contain a
list of all the roles, and the users associated with those given roles. This
configuration file is located at /opt/mapr/conf
, and should be
identical across all clusters.
The structure of the configuration file is as
follows. Roles end with :
, while user names are written on each
subsequent line. For example:
Role_1:
user_a
user_b
Role_2:
user_b
user_c
user_d
#comment
This
example file states that there are two roles to choose from when assigning permissions -
Role_1
and Role_2
. The users located under
Role_1
are user_a
and user_b
.
Role_2
contains user_b
, user_c
,
and user_d
. Blank lines, and lines beginning with # are
ignored.
Assume a table has permissions r:Role_2
.
user_b
has access to this table, while user_a
does
not have access.
After adding a new role to the
m7_permissions_roles_refimpl.conf
file, you must issue the following
command to enable the MapR-FS layer to pick up the new
role: $ /opt/mapr/server/mrconfig dbrolescache
invalidate
Run this command on all the nodes, whenever there is a change in the roles configuration file.
Developer InformationThe functions that the libmapr_roles_refimpl.so
exposes, are found in
the extensibility implementation. When the library is called initially through
GetSecurityMembership
, it parses the
m7_permissions_roles_refimpl.conf
file, and loads it into memory.
All user names are read, and parsed into user IDs (uid_t). If a user ID is not found,
the ID is skipped.
The library uses a HashTable. The roles are the keys. The values are a Binary tree of user IDs.
Each call checks the given user ID and role.
The HashTable keys off the role, and then searches the Binary Tree for the user ID. If
the HashTable finds a user ID, it sets that role boolean value to true
.
If the HashTable does not find a userI D, or if any errors occur, such as Role
not found
, it sets the boolean value to false
.
There
is also a cleanup method which frees the memory allocated to the HashTable, along with
all of its children. If the GetSecurityMembership
method is called
again, the library reloads the configuration file, and loads all the values into memory.
Extensible Implementation
If users decide not to use the reference implementation, they can replace the shared
library with their own. In the mfs.conf
file, add a parameter that
specifies the name of the file.
If the
name of the file is changed, then MFS searches
/opt/mapr/server/permissions
for the new file. If the file is found,
it is loaded into memory. If not, then all roles evaluate to false
.
The user's shared library should contain two functions specified under the
mapr::fs
namespace:
extern "C"
void GetSecurityMembership(uid_t uid, const char *roles[], int numRoles, bool truthValue[]) {
}
extern "C"
void cleanup() {
}
GetSecurityMembership
takes the given user ID along with a list of
all the roles, the amount of roles in the array, and an array of all the results, as
booleans.
Users must code their own implementation of populating the truthValue
array with either true
or false
. The
truthValue
array has the same length as numRoles
, and is initialized.
Do not modify any other variables.
Use the cleanup
method to reset the shared library to an initialized state. This
method resets all values, and frees memory, since the shared library is not closed, till
the class calling it, gets destructed.
Invoke Shared Library from MFS
The TablePermissions
class handles opening, and closing the shared
library. During class initialization, the name of the shared library, which is read from
the mfs.conf
, file is passed to the constructor. The constructor loads
the shared library into memory, using the LoadSO
method from
filterutils.cc
. The constructor also loads the
GetSecurityMembership
method, along with the cleanup
method, as
variables that can be called.
TablePermissions
contains two methods that can be called, to access the shared library:
- The
GetSecurityMembership
method takes 3 arguments - the user ID, the array of roles, and the amount of roles in the array. This method returns aRolePermission
structure, which contains all the same data, as well as the boolean of the successful roles for that given user ID. To evaluate the user roles, pass thisRolePermission
structure to theTablePermission::checkTablePermissions
method. - The
cleanup
method calls thecleanup
method in the shared library. This method takes no arguments.
The entity that allocates the RolePermission
structure into memory, also needs to deallocate this structure.
Deallocating the TablePermissions
class, calls the cleanup
method, and closes the shared library.