Creating User Roles for ACEs
Describes how to create and use roles for access control.
A role is a label attached to a set of users and 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 them. This configuration file is
located at /opt/mapr/conf
and should be identical across all
clusters.
The structure of the configuration file is shown below. Roles end with
:
and 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
The above example file states that there are two roles from
which to choose while 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 file system layer to pick up the new
role: $ /opt/mapr/server/mrconfig dbrolescache
invalidate
Run this command on all the nodes whenever a change is needed in the roles configuration file.
Developer InformationThe functions that the libmapr_roles_refimpl.so
exposes are found in
the extensibility implementation. If 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 the boolean value of that role to
true
. If the HashTable does not find a user ID or if any errors
occur, such as Role not found
, it sets the boolean value to
false
.
A cleanup method 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 become 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 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 until the class that is calling it is destructed.
Invoke Shared Library from MFS
The TablePermissions
class opens and closes the shared library. During
class initialization, the name of the shared library that 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 with the cleanup
method and are variables that can be called.
TablePermissions
contains two methods that can be called to access the
shared library: - The
GetSecurityMembership
method. This method takes three 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. This 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.