Skip to content

narvisoftware/protego-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Protego Core

red?icon=feather alert triangle&scale=1
Important
Work in progress

TODO:

  • create javadoc for public API

  • full coverage with unit tests

  • create release (for jitpack.io) and publish it to maven central

This project is a simple implementation of an authorization mechanism. It can be named an Attribute Based Authorization Control (ABAC) or simply a Policy Rule Based Authorization.

This is not a fancy enterprise level, distributed and centralised authorisation mechanism. It is a simple-to-use framework as it should be any other.

The story is that while I was looking for an authorization implementation, I’ve found RBAC (Role Based Authorization Control). That was somewhere on 2009/2010. At that time, RBAC was already a standard (NIST RBAC).

At that time, Spring Security was a mess. An implementation of Access Control Lists (ACL) following no standards.

If I mentioned ACLs, the rbac standard follows the capability lists approach of implementing the Lampson’s access control matrix. RBAC comes with multiple optional levels of functionality (RBAC0 to RBAC3).

In the years that followed, I’ve implemented the RBAC model on multiple project. I’ve implemented only RBAC0, but with the addition of "dynamic evaluation of permissions". That means that in order to avoid the role "explosion", the permissions are evaluated at runtime based on user’s and resource attributes.

We cannot create a role for each combination of user and resource attributes. For example a access rule can be: "User can READ patient’s records if it is a doctor, the patient have an appointment to the doctor and can only access records related to the medicine branch that the doctor is part of. But this only during the working hours of the doctor." This can be done, of course, only if we evaluate the rule at runtime based of the attributes of the doctor, of the user and of the medical records.

Here I need to mention to be aware what represents security concerns and what is business flow.

However, after some implementation of RBAC0 + "Dynamic Permissions", I’ve realised that there is no real need for roles. And if we name these permissions "Policy Rules", there is a simple implementation of what it supposed to be ABAC. I’ve once implemented a Domain Specific Language for such Policy Rules, but is just simpler to implement them in Java.

I’ve found very disappointing that NIST ABAC (Attribute-Based Access Control) is very complicated (ine the book Attribute-Based Access Control from Amazon. I guess that the reason to be so complicated it is to be able to answer to the two questions:

  1. On what resources user X has access?

  2. What users can access resource Y?

Well, this framework cannot answer to neither one. RBAC can answer to the first question (and not the second).

orange?icon=feather alert triangle&scale=1

To keep things simple and to contradict Nassim Taleb who wrote on Antifragile that "Technothinkers love precision at the expense of applicability", there are no negative permissions or better said: policy rules cannot explicitly deny access. This is in concordance with NIST RBAC. The poly rule can permit something or just withold his vote. And also there are no roles. Because I didn’t find any real use of roles when using attribute-based authorization.

Terminology

Names used:
  1. user - user that performs an action

  2. permission - a protected resource and an action to be conducted on that resource

    1. protected resource - an object that is the subject of a user’s action.

    2. action - action to be conducted against a protected resource (READ/WRITE etc.).

  3. subject - computer process acting on behalf of a user

  4. policy rule - a piece of code that permit or not the permission that the user is trying to obtain.

Example

To better understand the framework here is an example. Let’s take the previous one:

"User can READ patient’s records if it is a doctor, the patient have an appointment to the doctor and can only access records related to the medicine branch that the doctor is part of. But this only during the working hours of the doctor."

The implementations used in the code are from protego-basic.

Init the framework:

PolicyRulesProvider policyRulesProvider = new BasicPolicyRuleProvider();
PolicyEvaluator.registerProviders(policyRulesProvider);

Store the authenticated user:

private static final ScopedValue<User> AUTHENTICATED_USER = ScopedValue.newInstance();
...
User authenticatedUser = authenticate(credentials);
ScopedValue.where(AUTHENTICATED_USER, authenticatedUser).run(() -> service.processRequest(pacientRecord));

Test the access:

AllowSameBranchPermission allowSameBranchPermission = new AllowSameBranchPermission(READ, somePacientRecord);
PolicyEvaluator.evaluatePermission(allowSameBranchPermission);

The permission:

public class AllowSameBranchPermission<CrudAction, PacientRecord> extends Permission {
  public AllowSameBranchPermission(PacientRecord protectedResource, CrudAction action) {
    super(protectedResource, action);
  }
}

And the policy rule:

public class AllowSameBranchPolicyRule implements PolicyRule {

  @Override
  public boolean hasPermission(Permission permission) {
    if (!(permission instanceof AllowSameBranchPermission)) {
      return false;
    }
    //the doctor is the subject
    User authenticatedUser = AUTHENTICATED_USER.get();
    if (!authenticatedUser.isDoctor()) {
      return false;
    }
    // only read is allowed
    if (permission.getAction() != CrudAction.READ) {
      return false;
    }
    // has an appointment today
    if (!permission.getProtectedResource().getOwner().hasAppointemnt(authenticatedUser, LocalDate.now())) {
      return false;
    }
    //the medical record belongs to the same medicine branch
    if (authenticatedUser.asDoctor().getSpeciality() != permission.getProtectedResource().getSpeciality()) {
      return false;
    }
    //the doctor is at work
    if (!authenticatedUser.getTodaysWorkingHoursInterval().includes(Instant.now())) {
      return false;
    }
    return true;
  }
}

gray?icon=feather alert circle&scale=1

Important
Vulnerability aspects

I can identify two:

  1. a PolicyRulesProvider implementation can be build unsafely by being tricked to load malicious PolicyRule classes. For example, a PolicyRulesProvider can load all PolicyRule subclasses from classpath. But into an open source library used by the application, someone can add a PolicyRule that permit everything to a specific username for example.

    1. to avoid this, in the implementation project (protego-basic), the BasicPolicyRuleProvider verifies the signatures of each PolicyRule

    2. the PolicyEvaluator can be initialized only once.

    3. I use Java Platform Module System (JPMS) in order to forbid illegal changes to private variables that store the policy rules.

  2. a PolicyRule can have bugs and unintendedly respond with PERMIT.

    1. as a result, each PolicyRule implementations must be fully tested with all edge cases.

License

This project is licensed under the MIT License - see the License.adoc file for details.

About

An ABAC security model

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages