[PROPOSAL] to accept BRBAC into the Apache Incubator = Abstract =
Pluggable, Scalable and Fastest possible approach for Role Based Access Control (RBAC) based on binary arithmetic and basic Linux style permissions. = Proposal = BRBAC aims to become the default free, readymade and configurable access control plugin for enterprise applications, spring-web like frameworks, hadoop infrastructure and new era big data applications. BRBAC is a very simple binary concept which can easily be implemented in all programming languages and can be applied for access control in most complex and simple permission scenarios. It may scale easily from single user to lacks of users and from single entity to lacks of entities with same performance. A maximum of 3-5 classes with 20-30 lines of code are more than sufficient to implement BRBAC in any enterprise application. Permissions need to be stored separately as binary numbers (8 bit integers or bit-sets) on a per entity, per user or per role basis. Please visit wiki page for more details ( https://github.com/muktalabs/brbac/wiki) = Background = In enterprise applications, Access needs to be controlled where an Operation is being performed on an Entity by an authenticated User. Hence, access control in enterprise applications has some basic aspects == User == Authenticated user has fixed set of permissions to perform certain operations in an enterprise level application. Based on these permissions, user is allowed or denied to perform various operations in the application. Thus, permissions are always stored on a per user basis. == Entity / Model == Generally, enterprise applications have many entity classes. Each entity allows certain operations by some roles and denies certain operations to some roles / users. To control this behavior, permissions also need to be stored on a per entity basis. == Operation / Action == CRUD = Create, Read, Update, Delete. Every entity in the application is subject to the CRUD operations. There can be more operations but CRUD is the most basic and most common set of operations. Since entities have different behavior for different operations by different users, permissions also need to be stored on a per operation basis. == Role / Level == Another such aspect is Role. Each User has a Role in the system, based on the role, he /she is assigned Permissions to perform Operations on Entities. Common RBAC systems store permissions for a Role and each User is assigned one or more Roles as per requirements. == Context == If the entity is created by an admin level user, it should not be editable / deletable by lower permissions. Keeping it simple for now, we shall look after context in the next version of BRBAC. = Rationale = An application needs to store and evaluate permissions on a per User, per Entity and per Operation basis. Most of the times this data takes up-to 5 tables to store the RBAC permissions. Selecting permissions for user from database also consumes time while user attempts to perform some operation. Sometimes the time taken to check permission is more than time taken to perform required operation. Thus the current approaches for RBAC seems inefficient in TIME and STORAGE. Now since databases are storing petabytes of data in raw binary formats (hbase, cassandra) and applications are supporting hundred lacks of users, if a big data application requires access control, the RBAC should also be fast and scalable enough to support the volume and performance. == How BRBAC works == Binary arithmetic is known for vast in scalability, smallest in memory and fastest in speed. BRBAC uses separate bits to store permissions on User, Entity and Operation level. Permission bits of User, Operation and Entity are bitwise ANDed together to see if the operation is allowed or denied for the user. In BRBAC, long (8 bytes number) data type is used to store CRUD permission bits on various levels / roles for Operations, User and Entities. Since CRUD are 4 different operations, 1 hexadecimal number (4 bits) are used to store permission mask for 1 role. If number of operations are more than 4, a bigger number (6 bits or 8 bits) should be used to store permissions. To keep it simple and manageable by hexadecimal numbers, we recommend to use 4 or 8 bits. We are assuming 4 roles i.e. Admin, Supervisor, Operator and Guest which seems sufficient for all general purpose applications… so 4 hexadecimal numbers are used to store permissions e.g. 0x44EF. If number of Roles increase, that many number of hexadecimal digits are also increased in permission mask. If application has 8 roles, the mask would be e.g. 0x44ECCEFF. == 1’s = permissive, 0’s = restrictive == More number of 1’s make BRBAC more permissive and more number of 0’s make BRBAC more restrictive. Controlling the number of 1’s and 0’s at the specific locations is the key point in management of BRBAC. User’s permission mask 0x44EF or 0100-0100-1110-1111, provides this user full access on guest level, Create, Read and Update access on Operator level and Read access on Admin and Supervisor level. Thus this user becomes an Operator level user who can read all Entities in the system. By Entity’s permission mask 0xFEC4 or 1111-1110-1100-0100, this entity allows full access to Admin level, Create, Read and Update access to Supervisor level, Create and Read access to Operator level and Read only access to the Guest level. = Example = An example of checking CRUD permissions is described below where User has a permission mask of 0x44EF and entity has a permission mask of 0xFEC4: == Create == Create action / operation has 1 on the 3rd bit and 0 on the remaining bits of each hexadecimal digit. Thus, the action / permission mask becomes 0x8888 in hexadecimal or 1000-1000-1000-1000 in binary. When it binary ANDed with User’s permission mask 0x44EF or 0100-0100-1110-1111, and Entity’s permission mask 0xFEC4 or 1111-1110-1100-0100, it gives 1 on the 8th bit (0000-0000-1000-0000). Since the result of binary AND is non zero, Create access is hereby granted to the User for the Entity. Since highest 1 is seen on Operator level / Role, the User can Create Entity as an Operator. See example image ( https://github.com/muktalabs/brbac/blob/master/docs/brbac_concept_create.png ) == Read == Read action / operation has 1 on the 2nd bit and 0 on the remaining bits of each hexadecimal digit. Thus, the action / permission mask becomes 0x4444 in hexadecimal or 0100-0100-0100-0100 in binary. When it binary ANDed with User’s permission mask 0x44EF or 0100-0100-1110-1111, and Entity’s permission mask 0xFEC4 or 1111-1110-1100-0100, it gives 1’s on the 2nd, 6th, 10th and 14th bits (0100-0100-0100-0100). Since the result of binary AND is non zero, Read access is hereby granted to the User for the Entity. Since highest 1 is seen on Admin level / Role, the User can Read Entity as an Admin. See example image ( https://github.com/muktalabs/brbac/blob/master/docs/brbac_concept_read.png) == Update == Update action / operation has 1 on the 1st bit and 0 on the remaining bits of each hexadecimal digit. Thus, the action / permission mask becomes 0x2222 in hexadecimal or 0010-0010-0010-0010 in binary. When it binary ANDed with User’s permission mask 0x44EF or 0100-0100-1110-1111, and Entity’s permission mask 0xFEC4 or 1111-1110-1100-0100, it gives 0’s on all the bits (0000-0000-0000-0000). Since the result of binary AND is zero, Update access is hereby denied to the User for the Entity. See example image ( https://github.com/muktalabs/brbac/blob/master/docs/brbac_concept_update.png ) == Delete == Delete action / operation has 1 on the 0th bit and 0 on the remaining bits of each hexadecimal digit. Thus, the action / permission mask becomes 0x1111 in hexadecimal or 0001-0001-0001-0001 in binary. When it binary ANDed with User’s permission mask 0x44EF or 0100-0100-1110-1111, and Entity’s permission mask 0xFEC4 or 1111-1110-1100-0100, it gives 0’s on all the bits (0000-0000-0000-0000). Since the result of binary AND is zero, Delete access is hereby denied to the User for the Entity. See example image ( https://github.com/muktalabs/brbac/blob/master/docs/brbac_concept_delete.png ) = Initial Goals = 1. Initial goal is to create a simple Java maven project which can be added as a plugin to any maven project. Code for this plugin is 80% ready and has been tested for access control in our spring mvc applications. Some brainstorming and guidance is needed for deciding the project structure for an independent release. 2. Next goal is to provide a simple API to configure the binary permission flags on User, Entity and Role levels. API needs to be provided to add and define new operations. A robust mechanism needs to be designed carefully where adding new permission flags does not corrupt the existing settings. 3. Collaborative brainstorming is also needed to plan plugin based approaches for storage of binary permissions on per Entity and per User basis which can provide easiest integration with existing applications. = Current Status = A very basic POC level code is written, tested and open-sourced. This code directly hard codes the permissions in complex hexadecimal format (e.g. 0xFFE4). Brainstorming and efforts are needed to simplify the configuration of permissions so that API user does have to directly edit hexadecimal codes. == Meritocracy == We are open to collaborate with and respect the committers and we agree that active committers should be members of project management committee (PMC). == Community == The need for Role Based Access Control in enterprise applications is tremendous and lacks a universal default pluggable API thus providing the potential for a large community == Core Developers == The developers Upendra Jariya and Douglas Johnson are aged software professionals, both having interest in open source community and both have invested hard earned time in developing open source software. == Alignment == Apache is the best suitable place for hosting BRBAC because all leading open source projects already belong to Apache. We aim to propose BRBAC as RBAC plugin to existing Apache projects including apache-commons, spring-security, spring-web, struts, hadoop etc. = Known Risks = API need to be carefully designed to define and modify the permissions. This API should support migration from present to future versions of BRBAC without loss of functionality. Since the storage will be binary and disjoint, adding new Roles or New Operations should not impact existing Roles / permissions of the application by giving or denying access to the wrong User. == Relationships with Other Apache Products == BRBAC will likely be used by apache-commons, spring-security, spring-mvc, struts, hadoop and will support Apache commons logging. = Documentation = Project documentation is available on wiki page at: https://github.com/muktalabs/brbac/wiki = Initial Source = Source code for BRBAC is available online @ https://github.com/muktalabs/brbac under open source Apache 2.0 license. It requires very less code to integrate BRBAC into any existing or new application. For the sake of illustration, some important code snippets are as following: == Crud Action == There can be 100 ways to store action / operation codes. We have chosen enum as per suitability in our application. package com.muktalabs.brbac; public enum CrudAction { CREATE (0x8888), READ (0x4444), UPDATE (0x2222), DELETE (0x1111), DISABLED (0x0000); private final long mask; CrudAction(long mask){ this.mask = mask; } public long getMask() { return mask; } public static CrudAction get(String straction) { if(straction == null){ return DISABLED; } switch(straction.toUpperCase()) { case "CREATE" : return CREATE; case "READ" : return READ; case "UPDATE" : return UPDATE; case "DELETE" : return DELETE; case "DISABLED" : default : return DISABLED; } } } == Entity == For easiest implementation, we have directly associated different permission mask to each Entity using annotation. Since Entity’s permission mask does not change in most general cases, Annotation fits best in most requirements. import com.muktalabs.brbac.CrudPermission; @CrudPermission(permission=0xFEC4) public class Employee extends Model { } == Crud Permission == This is the source code for customized @CrudPermission annotation. This annotation has a default value of 0x4444 i.e. by default, the entity allows Read access to all the Users. The permission attribute can be overridden for each entity by @CrudPermission(permission=0xFEC4) package com.muktalabs.brbac; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) //on class level public @interface CrudPermission { long permission() default 0x4444; // Read permission to all } == Base Controller == In most enterprise web applications, controllers are used to check login and check access permissions. This BaseController is the base class of all Controllers which defines the checkPermission method. This checkPermission() method need to be invoked from all controller methods. Aspect pointcuts can also be used to make a call to checkPermission method. package com.muktalabs.brbac.controller; import java.util.logging.Logger; import com.muktalabs.brbac.CrudAction; import com.muktalabs.brbac.CrudPermission; import com.muktalabs.brbac.model.Model; import com.muktalabs.brbac.model.User; public class BaseController { private static final Logger logger = Logger.getLogger(BaseController.class.getName()); public boolean checkPermission(Class<? extends Model> entity, CrudAction action, User user) { CrudPermission entityPerms = entity.getAnnotation(CrudPermission.class); // Get permissions on entity long entityMask = entityPerms.permission(); // Get permissions for user String userPermStr = user.getPermission(); long userPerm = Long.decode(userPermStr); // Get permissions required to perform the action long actionMask = action.getMask(); // Binary AND the 3 Masks long result = entityMask & userPerm & actionMask; // Done. If result is non-zero, user has the permission if (result > 0) { // TODO: Context: Here, in case of update/ delete, if saved entity has // greater roleMask, than current user's roleMask, do not allow. // Scale: Also use 0xFFFF000000000000 format. return true; } else { throw new RuntimeException("Insufficient priviliges to perform this operation. " + "Please contact your system administrator."); } } } = Source and Intellectual Property Submission Plan = The initial source code is already available in Apache 2.0 license on a github public URL. Still, if separate IPR submission is required, we will follow the instructions from Apache Incubator. = External Dependencies = NONE as of now. = Required Resources = == Mailing lists == priv...@brbac.incubator.apache.org d...@brbac.incubator.apache.org comm...@brbac.incubator.apache.org us...@brbac.incubator.apache.org == Git Repository == https://git-wip-us.apache.org/repos/asf/incubator-brbac.git == Issue Tracking == JIRA: Apache BRBAC (BRBAC) == Wiki == Confluence: Apache BRBAC (BRBAC) = Initial Committers = Upendra Jariya (upendra dot jariya at gmail dot com), Douglas Johnson (doug4j at gmail dot com), Gourav Dodia (gouravkumardodia at gmail dot com) Willing developers are most invited to participate in BRBAC development == Affiliations == None as of now. = Sponsors = == Champion / Mentors == Yet to be searched for, will start searching after initial project acceptance. == Sponsoring Entity == Mukta InfoTech (www.muktainfotech.org) Clyrity (www.clyrity.com) Apache Incubator is requested to take the sponsorship of this project. Thanks & Regards, *Upendra Jariya <https://in.linkedin.com/in/upendrajariya>* Freelance Consultant, *Mukta InfoTech* <http://www.muktainfotech.org/> Email: upendra.jar...@gmail.com Phone: +919406614355